Commit 85866344 authored by Mark-Weston's avatar Mark-Weston Committed by Benno Schulenberg
Browse files

new feature: an option to make the 'nextword' function stop at word ends


When 'afterends' is set and Ctrl+Right or Shift+Ctrl+Right is pressed,
nano will stop at the ends of words instead of their beginnings.
Signed-off-by: default avatarMark-Weston <markweston@cock.li>
Signed-off-by: default avatarBenno Schulenberg <bensberg@telfort.nl>
parent 4046dfca
Showing with 67 additions and 12 deletions
+67 -12
...@@ -250,6 +250,9 @@ Disable the hard-wrapping of long lines. This option conflicts with ...@@ -250,6 +250,9 @@ Disable the hard-wrapping of long lines. This option conflicts with
.BR \-x ", " \-\-nohelp .BR \-x ", " \-\-nohelp
Don't show the two help lines at the bottom of the screen. Don't show the two help lines at the bottom of the screen.
.TP .TP
.BR \-y ", " \-\-afterends
Make Ctrl+Right stop at word ends instead of beginnings.
.TP
.BR \-z ", " \-\-suspend .BR \-z ", " \-\-suspend
Enable the suspend ability. Enable the suspend ability.
.TP .TP
......
...@@ -392,6 +392,10 @@ is located at the very bottom of the editor. ...@@ -392,6 +392,10 @@ is located at the very bottom of the editor.
Note: When accessing the help system, Expert Mode is temporarily Note: When accessing the help system, Expert Mode is temporarily
disabled to display the help-system navigation keys. disabled to display the help-system navigation keys.
@item -y
@itemx --afterends
Make Ctrl+Right stop at word ends instead of beginnings.
@item -z @item -z
@itemx --suspend @itemx --suspend
Enable the ability to suspend @command{nano} using the system's suspend Enable the ability to suspend @command{nano} using the system's suspend
...@@ -689,6 +693,9 @@ The supported settings in a nanorc file are: ...@@ -689,6 +693,9 @@ The supported settings in a nanorc file are:
@table @code @table @code
@item set afterends
Make Ctrl+Right stop at word ends instead of beginnings.
@item set allow_insecure_backup @item set allow_insecure_backup
When backing up files, allow the backup to succeed even if its When backing up files, allow the backup to succeed even if its
permissions can't be (re)set due to special OS considerations. permissions can't be (re)set due to special OS considerations.
......
...@@ -53,6 +53,9 @@ match \fB"\fP, \fB'\fP, \fB)\fP, \fB>\fP, \fB]\fP, and \fB}\fP. ...@@ -53,6 +53,9 @@ match \fB"\fP, \fB'\fP, \fB)\fP, \fB>\fP, \fB]\fP, and \fB}\fP.
The supported commands and arguments are: The supported commands and arguments are:
.TP 3 .TP 3
.B set afterends
Make Ctrl+Right stop at word ends instead of beginnings.
.TP
.B set allow_insecure_backup .B set allow_insecure_backup
When backing up files, allow the backup to succeed even if its permissions When backing up files, allow the backup to succeed even if its permissions
can't be (re)set due to special OS considerations. You should can't be (re)set due to special OS considerations. You should
......
...@@ -15,6 +15,10 @@ ...@@ -15,6 +15,10 @@
## its end. For example, for the "brackets" option, ""')>]}" will match ## its end. For example, for the "brackets" option, ""')>]}" will match
## ", ', ), >, ], and }. ## ", ', ), >, ], and }.
## Make the 'nextword' function (Ctrl+Right) stop at word ends
## instead of at beginnings.
# set afterends
## When soft line wrapping is enabled, make it wrap lines at blanks ## When soft line wrapping is enabled, make it wrap lines at blanks
## (tabs and spaces) instead of always at the edge of the screen. ## (tabs and spaces) instead of always at the edge of the screen.
# set atblanks # set atblanks
......
...@@ -314,15 +314,17 @@ void do_prev_word(bool allow_punct, bool update_screen) ...@@ -314,15 +314,17 @@ void do_prev_word(bool allow_punct, bool update_screen)
edit_redraw(was_current, FLOWING); edit_redraw(was_current, FLOWING);
} }
/* Move to the next word. If allow_punct is TRUE, treat punctuation /* Move to the next word. If after_ends is TRUE, stop at the ends of words
* instead of their beginnings. If allow_punct is TRUE, treat punctuation
* as part of a word. When requested, update the screen afterwards. * as part of a word. When requested, update the screen afterwards.
* Return TRUE if we started on a word, and FALSE otherwise. */ * 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 after_ends, bool allow_punct, bool update_screen)
{ {
filestruct *was_current = openfile->current; filestruct *was_current = openfile->current;
bool started_on_word = is_word_mbchar(openfile->current->data + bool started_on_word = is_word_mbchar(openfile->current->data +
openfile->current_x, allow_punct); openfile->current_x, allow_punct);
bool seen_space = !started_on_word; bool seen_space = !started_on_word;
bool seen_word = started_on_word;
/* Move forward until we reach the start of a word. */ /* Move forward until we reach the start of a word. */
while (TRUE) { while (TRUE) {
...@@ -340,6 +342,18 @@ bool do_next_word(bool allow_punct, bool update_screen) ...@@ -340,6 +342,18 @@ bool do_next_word(bool allow_punct, bool update_screen)
openfile->current_x); openfile->current_x);
} }
#ifndef NANO_TINY
if (after_ends) {
/* If this is a word character, continue; else it's a separator,
* and if we've already seen a word, then it's a word end. */
if (is_word_mbchar(openfile->current->data + openfile->current_x,
allow_punct))
seen_word = TRUE;
else if (seen_word)
break;
} else
#endif
{
/* If this is not a word character, then it's a separator; else /* 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 we've already seen a separator, then it's a word start. */
if (!is_word_mbchar(openfile->current->data + openfile->current_x, if (!is_word_mbchar(openfile->current->data + openfile->current_x,
...@@ -347,6 +361,7 @@ bool do_next_word(bool allow_punct, bool update_screen) ...@@ -347,6 +361,7 @@ bool do_next_word(bool allow_punct, bool update_screen)
seen_space = TRUE; seen_space = TRUE;
else if (seen_space) else if (seen_space)
break; break;
}
} }
if (update_screen) if (update_screen)
...@@ -363,11 +378,12 @@ void do_prev_word_void(void) ...@@ -363,11 +378,12 @@ void do_prev_word_void(void)
do_prev_word(ISSET(WORD_BOUNDS), TRUE); do_prev_word(ISSET(WORD_BOUNDS), TRUE);
} }
/* Move to the next word in the file, treating punctuation as part of a word /* Move to the next word in the file. If the AFTER_ENDS flag is set, stop
* if the WORD_BOUNDS flag is set, and update the screen afterwards. */ * at word ends instead of beginnings. If the WORD_BOUNDS flag is set, treat
* punctuation as part of a word. Update the screen afterwards. */
void do_next_word_void(void) void do_next_word_void(void)
{ {
do_next_word(ISSET(WORD_BOUNDS), TRUE); do_next_word(ISSET(AFTER_ENDS), ISSET(WORD_BOUNDS), TRUE);
} }
/* Move to the beginning of the current line (or softwrapped chunk). /* Move to the beginning of the current line (or softwrapped chunk).
......
...@@ -888,6 +888,9 @@ void usage(void) ...@@ -888,6 +888,9 @@ void usage(void)
print_opt("-w", "--nowrap", N_("Don't hard-wrap long lines")); print_opt("-w", "--nowrap", N_("Don't hard-wrap long lines"));
#endif #endif
print_opt("-x", "--nohelp", N_("Don't show the two help lines")); print_opt("-x", "--nohelp", N_("Don't show the two help lines"));
#ifndef NANO_TINY
print_opt("-y", "--afterends", N_("Make Ctrl+Right stop at word ends"));
#endif
if (!ISSET(RESTRICTED)) if (!ISSET(RESTRICTED))
print_opt("-z", "--suspend", N_("Enable suspension")); print_opt("-z", "--suspend", N_("Enable suspension"));
#ifndef NANO_TINY #ifndef NANO_TINY
...@@ -2003,6 +2006,7 @@ int main(int argc, char **argv) ...@@ -2003,6 +2006,7 @@ int main(int argc, char **argv)
{"autoindent", 0, NULL, 'i'}, {"autoindent", 0, NULL, 'i'},
{"cutfromcursor", 0, NULL, 'k'}, {"cutfromcursor", 0, NULL, 'k'},
{"unix", 0, NULL, 'u'}, {"unix", 0, NULL, 'u'},
{"afterends", 0, NULL, 'y'},
{"softwrap", 0, NULL, '$'}, {"softwrap", 0, NULL, '$'},
#endif #endif
{NULL, 0, NULL, 0} {NULL, 0, NULL, 0}
...@@ -2061,7 +2065,7 @@ int main(int argc, char **argv) ...@@ -2061,7 +2065,7 @@ int main(int argc, char **argv)
while ((optchr = while ((optchr =
getopt_long(argc, argv, getopt_long(argc, argv,
"ABC:DEFGHIKLMNOPQ:RST:UVWX:Y:abcdefghijklmno:pqr:s:tuvwxz$", "ABC:DEFGHIKLMNOPQ:RST:UVWX:Y:abcdefghijklmno:pqr:s:tuvwxyz$",
long_options, NULL)) != -1) { long_options, NULL)) != -1) {
switch (optchr) { switch (optchr) {
case 'b': case 'b':
...@@ -2256,6 +2260,11 @@ int main(int argc, char **argv) ...@@ -2256,6 +2260,11 @@ int main(int argc, char **argv)
case 'x': case 'x':
SET(NO_HELP); SET(NO_HELP);
break; break;
#ifndef NANO_TINY
case 'y':
SET(AFTER_ENDS);
break;
#endif
case 'z': case 'z':
SET(SUSPEND); SET(SUSPEND);
break; break;
......
...@@ -543,7 +543,8 @@ enum ...@@ -543,7 +543,8 @@ enum
SHOW_CURSOR, SHOW_CURSOR,
LINE_NUMBERS, LINE_NUMBERS,
NO_PAUSES, NO_PAUSES,
AT_BLANKS AT_BLANKS,
AFTER_ENDS
}; };
/* Flags for the menus in which a given function should be present. */ /* Flags for the menus in which a given function should be present. */
......
...@@ -292,17 +292,28 @@ void do_statusbar_cut_text(void) ...@@ -292,17 +292,28 @@ void do_statusbar_cut_text(void)
void do_statusbar_next_word(void) void do_statusbar_next_word(void)
{ {
bool seen_space = !is_word_mbchar(answer + statusbar_x, FALSE); bool seen_space = !is_word_mbchar(answer + statusbar_x, FALSE);
bool seen_word = !seen_space;
/* Move forward until we reach the start of a word. */ /* Move forward until we reach either the end or the start of a word,
* depending on whether the AFTER_ENDS flag is set or not. */
while (answer[statusbar_x] != '\0') { while (answer[statusbar_x] != '\0') {
statusbar_x = move_mbright(answer, statusbar_x); statusbar_x = move_mbright(answer, statusbar_x);
if (ISSET(AFTER_ENDS)) {
/* If this is a word character, continue; else it's a separator,
* and if we've already seen a word, then it's a word end. */
if (is_word_mbchar(answer + statusbar_x, FALSE))
seen_word = TRUE;
else if (seen_word)
break;
} else {
/* If this is not a word character, then it's a separator; else /* 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 we've already seen a separator, then it's a word start. */
if (!is_word_mbchar(answer + statusbar_x, FALSE)) if (!is_word_mbchar(answer + statusbar_x, FALSE))
seen_space = TRUE; seen_space = TRUE;
else if (seen_space) else if (seen_space)
break; break;
}
} }
update_the_statusbar(); update_the_statusbar();
......
...@@ -380,7 +380,7 @@ void do_para_end_void(void); ...@@ -380,7 +380,7 @@ void do_para_end_void(void);
void do_prev_block(void); void do_prev_block(void);
void do_next_block(void); void do_next_block(void);
void do_prev_word(bool allow_punct, bool update_screen); void do_prev_word(bool allow_punct, bool update_screen);
bool do_next_word(bool allow_punct, bool update_screen); bool do_next_word(bool after_ends, bool allow_punct, bool update_screen);
void do_prev_word_void(void); void do_prev_word_void(void);
void do_next_word_void(void); void do_next_word_void(void);
void do_home(void); void do_home(void);
......
...@@ -88,6 +88,7 @@ static const rcoption rcopts[] = { ...@@ -88,6 +88,7 @@ static const rcoption rcopts[] = {
{"tempfile", TEMP_FILE}, {"tempfile", TEMP_FILE},
{"view", VIEW_MODE}, {"view", VIEW_MODE},
#ifndef NANO_TINY #ifndef NANO_TINY
{"afterends", AFTER_ENDS},
{"allow_insecure_backup", INSECURE_BACKUP}, {"allow_insecure_backup", INSECURE_BACKUP},
{"atblanks", AT_BLANKS}, {"atblanks", AT_BLANKS},
{"autoindent", AUTOINDENT}, {"autoindent", AUTOINDENT},
......
...@@ -209,7 +209,7 @@ void do_cutword(bool backward) ...@@ -209,7 +209,7 @@ void do_cutword(bool backward)
if (backward) if (backward)
do_prev_word(ISSET(WORD_BOUNDS), FALSE); do_prev_word(ISSET(WORD_BOUNDS), FALSE);
else else
do_next_word(ISSET(WORD_BOUNDS), FALSE); do_next_word(FALSE, ISSET(WORD_BOUNDS), FALSE);
/* Set the mark at the start of that word. */ /* Set the mark at the start of that word. */
openfile->mark = openfile->current; openfile->mark = openfile->current;
...@@ -3459,7 +3459,7 @@ void do_wordlinechar_count(void) ...@@ -3459,7 +3459,7 @@ void do_wordlinechar_count(void)
* count whenever we're on a word just before moving. */ * count whenever we're on a word just before moving. */
while (openfile->current != openfile->filebot || while (openfile->current != openfile->filebot ||
openfile->current->data[openfile->current_x] != '\0') { openfile->current->data[openfile->current_x] != '\0') {
if (do_next_word(TRUE, FALSE)) if (do_next_word(FALSE, TRUE, FALSE))
words++; words++;
} }
......
...@@ -7,7 +7,7 @@ comment "#" ...@@ -7,7 +7,7 @@ comment "#"
icolor brightred "^[[:space:]]*((un)?(bind|set)|include|syntax|header|magic|comment|linter|formatter|i?color|extendsyntax).*$" icolor brightred "^[[:space:]]*((un)?(bind|set)|include|syntax|header|magic|comment|linter|formatter|i?color|extendsyntax).*$"
# Keywords # Keywords
icolor brightgreen "^[[:space:]]*(set|unset)[[:space:]]+(allow_insecure_backup|atblanks|autoindent|backup|backwards|boldtext|casesensitive|constantshow|cutfromcursor|fill[[:space:]]+-?[[:digit:]]+|historylog|linenumbers|locking|morespace|mouse|multibuffer|noconvert|nohelp|nopauses|nonewlines|nowrap|positionlog|preserve|quickblank|quiet|rebinddelete|rebindkeypad|regexp|showcursor|smarthome|smooth|softwrap|suspend|tabsize[[:space:]]+[1-9][0-9]*|tabstospaces|tempfile|trimblanks|unix|view|wordbounds)\>" icolor brightgreen "^[[:space:]]*(set|unset)[[:space:]]+(afterends|allow_insecure_backup|atblanks|autoindent|backup|backwards|boldtext|casesensitive|constantshow|cutfromcursor|fill[[:space:]]+-?[[:digit:]]+|historylog|linenumbers|locking|morespace|mouse|multibuffer|noconvert|nohelp|nopauses|nonewlines|nowrap|positionlog|preserve|quickblank|quiet|rebinddelete|rebindkeypad|regexp|showcursor|smarthome|smooth|softwrap|suspend|tabsize[[:space:]]+[1-9][0-9]*|tabstospaces|tempfile|trimblanks|unix|view|wordbounds)\>"
icolor yellow "^[[:space:]]*set[[:space:]]+((error|function|key|number|selected|status|title)color)[[:space:]]+(bright)?(white|black|red|blue|green|yellow|magenta|cyan|normal)?(,(white|black|red|blue|green|yellow|magenta|cyan|normal))?\>" icolor yellow "^[[:space:]]*set[[:space:]]+((error|function|key|number|selected|status|title)color)[[:space:]]+(bright)?(white|black|red|blue|green|yellow|magenta|cyan|normal)?(,(white|black|red|blue|green|yellow|magenta|cyan|normal))?\>"
icolor brightgreen "^[[:space:]]*set[[:space:]]+(backupdir|brackets|errorcolor|functioncolor|keycolor|matchbrackets|numbercolor|operatingdir|punct|quotestr|selectedcolor|speller|statuscolor|titlecolor|whitespace|wordchars)[[:space:]]+" icolor brightgreen "^[[:space:]]*set[[:space:]]+(backupdir|brackets|errorcolor|functioncolor|keycolor|matchbrackets|numbercolor|operatingdir|punct|quotestr|selectedcolor|speller|statuscolor|titlecolor|whitespace|wordchars)[[:space:]]+"
icolor brightgreen "^[[:space:]]*bind[[:space:]]+((\^([[:alpha:]]|[]0-9\^_]|Space)|M-([[:alpha:]]|[]!"#$%&'()*+,./0-9:;<=>?@\^_`{|}~-]|Space))|F([1-9]|1[0-6])|Ins|Del)[[:space:]]+([[:alpha:]]+|".*")[[:space:]]+(all|main|search|replace(with)?|gotoline|writeout|insert|ext(ernal)?cmd|help|spell|linter|browser|whereisfile|gotodir)([[:space:]]+#|[[:space:]]*$)" icolor brightgreen "^[[:space:]]*bind[[:space:]]+((\^([[:alpha:]]|[]0-9\^_]|Space)|M-([[:alpha:]]|[]!"#$%&'()*+,./0-9:;<=>?@\^_`{|}~-]|Space))|F([1-9]|1[0-6])|Ins|Del)[[:space:]]+([[:alpha:]]+|".*")[[:space:]]+(all|main|search|replace(with)?|gotoline|writeout|insert|ext(ernal)?cmd|help|spell|linter|browser|whereisfile|gotodir)([[:space:]]+#|[[:space:]]*$)"
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment