From b5905134eaaeba0be072e9e7492cc0c6ce06e8ab Mon Sep 17 00:00:00 2001 From: Mark-Weston Date: Sun, 29 Apr 2018 00:28:06 +0300 Subject: [PATCH] Add "atends" configuration setting With this setting on, Ctrl+Right and Shift+Ctrl+Right go to the end of a word instead of the beginning, and Ctrl+Down and Shift+Ctrl+Down goes to the end of a block instead of the beginning. Ctrl+Right and Shift+Ctrl+Right behaves this way on leafpad, geany, micro, bluefish, chromium, firefox and myriad of other applications. The new behaviour of Ctrl+Down and Shift+Ctrl+Down comes from applying the same logic for blocks instead of words. Signed-off-by: Mark-Weston --- doc/nanorc.5 | 4 +++ src/browser.c | 4 +-- src/global.c | 24 ++++++------- src/move.c | 96 +++++++++++++++++++++++++++++++++++++++++---------- src/nano.c | 2 +- src/nano.h | 3 +- src/proto.h | 8 +++-- src/rcfile.c | 1 + src/text.c | 4 +-- 9 files changed, 107 insertions(+), 39 deletions(-) diff --git a/doc/nanorc.5 b/doc/nanorc.5 index 6a931f96..bebbd6d5 100644 --- a/doc/nanorc.5 +++ b/doc/nanorc.5 @@ -62,6 +62,10 @@ NOT enable this option unless you are sure you need it. When soft line wrapping is enabled, make it wrap lines at blank characters (tabs and spaces) instead of always at the edge of the screen. .TP +.B set atends +Make Ctrl+Right and Shift+Ctrl+Right move at the end of words. +Make Ctrl+Down and Shift+Ctrl+Down move at the end of blocks. +.TP .B set autoindent Use auto-indentation. .TP diff --git a/src/browser.c b/src/browser.c index 9d8ed49e..8bc33931 100644 --- a/src/browser.c +++ b/src/browser.c @@ -193,10 +193,10 @@ char *do_browser(char *path) } else if (func == do_down) { if (selected + width <= filelist_len - 1) selected += width; - } else if (func == do_prev_block) { + } else if (func == do_prev_block_void) { selected = ((selected / (editwinrows * width)) * editwinrows * width) + selected % width; - } else if (func == do_next_block) { + } else if (func == do_next_block_void) { selected = ((selected / (editwinrows * width)) * editwinrows * width) + selected % width + editwinrows * width - width; diff --git a/src/global.c b/src/global.c index 22495a62..e6cd7043 100644 --- a/src/global.c +++ b/src/global.c @@ -872,9 +872,9 @@ void shortcut_init(void) N_("Scroll Down"), WITHORSANS(scrolldown_gist), BLANKAFTER, VIEW); #endif - add_to_funcs(do_prev_block, MMAIN, + add_to_funcs(do_prev_block_void, MMAIN, N_("Prev Block"), WITHORSANS(prevblock_gist), TOGETHER, VIEW); - add_to_funcs(do_next_block, MMAIN, + add_to_funcs(do_next_block_void, MMAIN, N_("Next Block"), WITHORSANS(nextblock_gist), TOGETHER, VIEW); #ifdef ENABLE_JUSTIFY add_to_funcs(do_para_begin_void, MMAIN|MWHEREIS, @@ -1055,9 +1055,9 @@ void shortcut_init(void) N_("Left Column"), WITHORSANS(browserlefthand_gist), TOGETHER, VIEW); add_to_funcs(do_next_word_void, MBROWSER, N_("Right Column"), WITHORSANS(browserrighthand_gist), TOGETHER, VIEW); - add_to_funcs(do_prev_block, MBROWSER, + add_to_funcs(do_prev_block_void, MBROWSER, N_("Top Row"), WITHORSANS(browsertoprow_gist), TOGETHER, VIEW); - add_to_funcs(do_next_block, MBROWSER, + add_to_funcs(do_next_block_void, MBROWSER, N_("Bottom Row"), WITHORSANS(browserbottomrow_gist), BLANKAFTER, VIEW); #endif #endif /* ENABLE_BROWSER */ @@ -1194,18 +1194,18 @@ void shortcut_init(void) if (using_utf8()) { add_to_sclist(MMAIN|MHELP|MBROWSER, "\xE2\x96\xb2", KEY_UP, do_up, 0); add_to_sclist(MMAIN|MHELP|MBROWSER, "\xE2\x96\xbc", KEY_DOWN, do_down, 0); - add_to_sclist(MMAIN|MBROWSER, "^\xE2\x96\xb2", CONTROL_UP, do_prev_block, 0); - add_to_sclist(MMAIN|MBROWSER, "^\xE2\x96\xbc", CONTROL_DOWN, do_next_block, 0); + add_to_sclist(MMAIN|MBROWSER, "^\xE2\x96\xb2", CONTROL_UP, do_prev_block_void, 0); + add_to_sclist(MMAIN|MBROWSER, "^\xE2\x96\xbc", CONTROL_DOWN, do_next_block_void, 0); } else #endif { add_to_sclist(MMAIN|MHELP|MBROWSER, "Up", KEY_UP, do_up, 0); add_to_sclist(MMAIN|MHELP|MBROWSER, "Down", KEY_DOWN, do_down, 0); - add_to_sclist(MMAIN|MBROWSER, "^Up", CONTROL_UP, do_prev_block, 0); - add_to_sclist(MMAIN|MBROWSER, "^Down", CONTROL_DOWN, do_next_block, 0); + add_to_sclist(MMAIN|MBROWSER, "^Up", CONTROL_UP, do_prev_block_void, 0); + add_to_sclist(MMAIN|MBROWSER, "^Down", CONTROL_DOWN, do_next_block_void, 0); } - add_to_sclist(MMAIN, "M-7", 0, do_prev_block, 0); - add_to_sclist(MMAIN, "M-8", 0, do_next_block, 0); + add_to_sclist(MMAIN, "M-7", 0, do_prev_block_void, 0); + add_to_sclist(MMAIN, "M-8", 0, do_next_block_void, 0); #ifdef ENABLE_JUSTIFY add_to_sclist(MMAIN, "M-(", 0, do_para_begin_void, 0); add_to_sclist(MMAIN, "M-9", 0, do_para_begin_void, 0); @@ -1575,9 +1575,9 @@ sc *strtosc(const char *input) else if (!strcasecmp(input, "end")) s->func = do_end; else if (!strcasecmp(input, "prevblock")) - s->func = do_prev_block; + s->func = do_prev_block_void; else if (!strcasecmp(input, "nextblock")) - s->func = do_next_block; + s->func = do_next_block_void; else if (!strcasecmp(input, "pageup") || !strcasecmp(input, "prevpage")) s->func = do_page_up; diff --git a/src/move.c b/src/move.c index d4dd718f..c5024daa 100644 --- a/src/move.c +++ b/src/move.c @@ -253,18 +253,44 @@ void do_prev_block(void) edit_redraw(was_current, CENTERING); } -/* Move to the next block of text. */ -void do_next_block(void) +/* Move to the next block of text. + * If at_ends is TRUE then stop at block ends instead of beginnings. */ +void do_next_block(bool at_ends) { filestruct *was_current = openfile->current; bool is_white = white_string(openfile->current->data); bool seen_white = is_white; - /* Skip forward until first nonblank line after some blank line(s). */ - while (openfile->current->next != NULL && (!seen_white || is_white)) { - openfile->current = openfile->current->next; - is_white = white_string(openfile->current->data); - seen_white = seen_white || is_white; + /* If we are looking for the end of a block, go there */ + if (at_ends) { + if (white_string(openfile->current->data)) { + while (openfile->current->next != NULL + && white_string(openfile->current->next->data)) { + openfile->current = openfile->current->next; + } + while (openfile->current->next != NULL + && !white_string(openfile->current->next->data)) { + openfile->current = openfile->current->next; + } + if (openfile->current->next != NULL) { + openfile->current = openfile->current->next; + } + } else { + while (openfile->current->next != NULL + && !white_string(openfile->current->next->data)) { + openfile->current = openfile->current->next; + } + if (openfile->current->next != NULL) { + openfile->current = openfile->current->next; + } + } + } else { + /* Skip forward until first nonblank line after some blank line(s). */ + while (openfile->current->next != NULL && (!seen_white || is_white)) { + openfile->current = openfile->current->next; + is_white = white_string(openfile->current->data); + seen_white = seen_white || is_white; + } } openfile->current_x = 0; @@ -303,6 +329,7 @@ void do_prev_word(bool allow_punct, bool update_screen) step_forward = TRUE; break; } + } if (step_forward) @@ -316,13 +343,15 @@ void do_prev_word(bool allow_punct, bool update_screen) /* Move to the next word. If allow_punct is TRUE, treat punctuation * as part of a word. When requested, update the screen afterwards. + * If at_ends is TRUE, move to the end of the word instead of the beginning. * Return TRUE if we started on a word, and FALSE otherwise. */ -bool do_next_word(bool allow_punct, bool update_screen) +bool do_next_word(bool at_ends, bool allow_punct, bool update_screen) { filestruct *was_current = openfile->current; bool started_on_word = is_word_mbchar(openfile->current->data + openfile->current_x, allow_punct); bool seen_space = !started_on_word; + bool seen_word = started_on_word; /* Move forward until we reach the start of a word. */ while (TRUE) { @@ -340,13 +369,28 @@ bool do_next_word(bool allow_punct, bool update_screen) openfile->current_x); } - /* If this is not a word character, then it's a separator; else - * if we've already seen a separator, then it's a word start. */ - if (!is_word_mbchar(openfile->current->data + openfile->current_x, - allow_punct)) - seen_space = TRUE; - else if (seen_space) - break; + if (!at_ends) { + /* If this is not a word character, then it's a separator; else + * if we've already seen a separator, then it's a word start. */ + if (!is_word_mbchar(openfile->current->data + openfile->current_x, + allow_punct)) + seen_space = TRUE; + else if (seen_space) + break; + } else { + if (!is_word_mbchar(openfile->current->data + openfile->current_x, + allow_punct)) { + if (seen_word) { + break; + } else { + seen_space = TRUE; + } + } else { + if (seen_space) { + seen_word = true; + } + } + } } if (update_screen) @@ -356,18 +400,34 @@ bool do_next_word(bool allow_punct, bool update_screen) return started_on_word; } +/* Move to the previous block in the file and update the screen afterwards. + * If AT_ENDS flag is set, stop at block ends too. */ +void do_prev_block_void(void) +{ + do_prev_block(); +} + +/* Move to the next block in the file and update the screen afterwards. + * If AT_ENDS flag is set, stop at block ends too. */ +void do_next_block_void(void) +{ + do_next_block(ISSET(AT_ENDS)); +} + /* Move to the previous word in the file, treating punctuation as part of a - * word if the WORD_BOUNDS flag is set, and update the screen afterwards. */ + * word if the WORD_BOUNDS flag is set, and update the screen afterwards. + * If AT_ENDS flag is set, stop at word ends too. */ void do_prev_word_void(void) { do_prev_word(ISSET(WORD_BOUNDS), TRUE); } /* Move to the next word in the file, treating punctuation as part of a word - * if the WORD_BOUNDS flag is set, and update the screen afterwards. */ + * if the WORD_BOUNDS flag is set, and update the screen afterwards. + * If AT_ENDS flag is set, stop at word ends too. */ void do_next_word_void(void) { - do_next_word(ISSET(WORD_BOUNDS), TRUE); + do_next_word(ISSET(AT_ENDS), ISSET(WORD_BOUNDS), TRUE); } /* Move to the beginning of the current line (or softwrapped chunk). diff --git a/src/nano.c b/src/nano.c index 09aacfbb..ed17f06c 100644 --- a/src/nano.c +++ b/src/nano.c @@ -1599,7 +1599,7 @@ bool wanted_to_move(void (*func)(void)) #ifdef ENABLE_JUSTIFY func == do_para_begin_void || func == do_para_end_void || #endif - func == do_prev_block || func == do_next_block || + func == do_prev_block_void || func == do_next_block_void || func == do_page_up || func == do_page_down || func == to_first_line || func == to_last_line; } diff --git a/src/nano.h b/src/nano.h index 17a52369..a378a60a 100644 --- a/src/nano.h +++ b/src/nano.h @@ -543,7 +543,8 @@ enum SHOW_CURSOR, LINE_NUMBERS, NO_PAUSES, - AT_BLANKS + AT_BLANKS, + AT_ENDS }; /* Flags for the menus in which a given function should be present. */ diff --git a/src/proto.h b/src/proto.h index f2c51f93..fe641b81 100644 --- a/src/proto.h +++ b/src/proto.h @@ -378,11 +378,13 @@ void do_para_begin_void(void); void do_para_end_void(void); #endif void do_prev_block(void); -void do_next_block(void); -void do_prev_word(bool allow_punct, bool update_screen); -bool do_next_word(bool allow_punct, bool update_screen); +void do_next_block(bool at_ends); +void do_prev_word( bool allow_punct, bool update_screen); +bool do_next_word(bool at_ends, bool allow_punct, bool update_screen); void do_prev_word_void(void); void do_next_word_void(void); +void do_prev_block_void(void); +void do_next_block_void(void); void do_home(void); void do_end(void); void do_up(void); diff --git a/src/rcfile.c b/src/rcfile.c index afa172ec..0f1bf4d5 100644 --- a/src/rcfile.c +++ b/src/rcfile.c @@ -112,6 +112,7 @@ static const rcoption rcopts[] = { {"whitespace", 0}, {"wordbounds", WORD_BOUNDS}, {"wordchars", 0}, + {"atends", AT_ENDS}, #endif #ifdef ENABLE_COLOR {"titlecolor", 0}, diff --git a/src/text.c b/src/text.c index 7f0bdb33..e306c5b5 100644 --- a/src/text.c +++ b/src/text.c @@ -209,7 +209,7 @@ void do_cutword(bool backward) if (backward) do_prev_word(ISSET(WORD_BOUNDS), FALSE); else - do_next_word(ISSET(WORD_BOUNDS), FALSE); + do_next_word(ISSET(AT_ENDS), ISSET(WORD_BOUNDS), FALSE); /* Set the mark at the start of that word. */ openfile->mark = openfile->current; @@ -3459,7 +3459,7 @@ void do_wordlinechar_count(void) * count whenever we're on a word just before moving. */ while (openfile->current != openfile->filebot || openfile->current->data[openfile->current_x] != '\0') { - if (do_next_word(TRUE, FALSE)) + if (do_next_word(FALSE, TRUE, FALSE)) words++; } -- 2.17.0