From bb4d0d548a9a95d8b9e166fc4e4ae07f5a11ec41 Mon Sep 17 00:00:00 2001 From: David Lawrence Ramsey Date: Tue, 7 Mar 2017 10:36:43 -0600 Subject: [PATCH] new feature: allow lines to be softwrapped at whitespace Extend get_softwrap_breakpoint() to break softwrapped lines on whitespace when a flag is set. This flag is controlled by the new rcfile option "atblanks". The '>' characters marking two-column characters at the edge of the screen are disabled when it's on. If get_softwrap_breakpoint() can't find whitespace in screen range, it will break the line on the screen edge. (In this case, a blank can be on the last column of the screen, but text can't, so that a blank on the last column doesn't become invisible and possibly break the display.) This fulfills https://savannah.gnu.org/bugs/index.php?49959. Requested-by: Nicholas Boel --- doc/nano.texi | 4 ++++ doc/nanorc.5 | 4 ++++ doc/sample.nanorc.in | 4 ++++ src/nano.h | 3 ++- src/rcfile.c | 1 + src/winio.c | 38 ++++++++++++++++++++++++++++++++++---- syntax/nanorc.nanorc | 2 +- 7 files changed, 50 insertions(+), 6 deletions(-) diff --git a/doc/nano.texi b/doc/nano.texi index 02140e0b..aad6b77a 100644 --- a/doc/nano.texi +++ b/doc/nano.texi @@ -657,6 +657,10 @@ 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 NOT enable this option unless you are sure you need it. +@item set atblanks +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. + @item set autoindent Use auto-indentation. diff --git a/doc/nanorc.5 b/doc/nanorc.5 index 9e4a983f..5671d570 100644 --- a/doc/nanorc.5 +++ b/doc/nanorc.5 @@ -57,6 +57,10 @@ 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 NOT enable this option unless you are sure you need it. .TP +.B set atblanks +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 autoindent Use auto-indentation. .TP diff --git a/doc/sample.nanorc.in b/doc/sample.nanorc.in index 07c706bc..fc66a1d4 100644 --- a/doc/sample.nanorc.in +++ b/doc/sample.nanorc.in @@ -20,6 +20,10 @@ ## versions of nano installed (e.g. your home directory is on NFS). # set quiet +## When soft line wrapping is enabled, make it wrap lines at blanks +## (tabs and spaces) instead of always at the edge of the screen. +# set atblanks + ## Use auto-indentation. # set autoindent diff --git a/src/nano.h b/src/nano.h index 113512f6..6c699209 100644 --- a/src/nano.h +++ b/src/nano.h @@ -521,7 +521,8 @@ enum JUSTIFY_TRIM, SHOW_CURSOR, LINE_NUMBERS, - NO_PAUSES + NO_PAUSES, + AT_BLANKS }; /* Flags for the menus in which a given function should be present. */ diff --git a/src/rcfile.c b/src/rcfile.c index 6d7a20be..8505e0c7 100644 --- a/src/rcfile.c +++ b/src/rcfile.c @@ -90,6 +90,7 @@ static const rcoption rcopts[] = { {"view", VIEW_MODE}, #ifndef NANO_TINY {"allow_insecure_backup", INSECURE_BACKUP}, + {"atblanks", AT_BLANKS}, {"autoindent", AUTOINDENT}, {"backup", BACKUP_FILE}, {"backupdir", 0}, diff --git a/src/winio.c b/src/winio.c index 8c1edcfd..414c30ce 100644 --- a/src/winio.c +++ b/src/winio.c @@ -2782,8 +2782,9 @@ int update_softwrapped_line(filestruct *fileptr) break; /* If the line is softwrapped before its last column, add a ">" just - * after its softwrap breakpoint. */ - if (to_col - from_col < editwincols) + * after its softwrap breakpoint, unless we're softwrapping at blanks + * and not in the middle of a word. */ + if (!ISSET(AT_BLANKS) && to_col - from_col < editwincols) mvwaddch(edit, row - 1, to_col - from_col, '>'); from_col = to_col; @@ -2993,12 +2994,20 @@ void edit_scroll(scroll_dir direction, int nrows) size_t get_softwrap_breakpoint(const char *text, size_t leftedge, bool *end_of_line) { + size_t index = 0; + /* Current index in text. */ size_t column = 0; /* Current column position in text. */ size_t prev_column = 0; /* Previous column position in text. */ size_t goal_column; /* Column of the last character where we can break the text. */ + bool found_blank = FALSE; + /* Did we find at least one blank? */ + size_t lastblank_index = 0; + /* Current index of the last blank in text. */ + size_t lastblank_column = 0; + /* Current column position of the last blank in text. */ int char_len = 0; /* Length of current character, in bytes. */ @@ -3007,13 +3016,26 @@ size_t get_softwrap_breakpoint(const char *text, size_t leftedge, while (*text != '\0' && column < leftedge) text += parse_mbchar(text, NULL, &column); - /* Use a full screen row for text. */ - goal_column = column + editwincols; + /* Use a full screen row for text, or, if we're softwrapping at blanks, use + * a full screen row less one column for text and reserve the last column + * for blanks. The latter case is to ensure that we have enough room for + * blanks exactly on the last column of the screen. */ + if (ISSET(AT_BLANKS) && editwincols > 2) + goal_column = column + (editwincols - 1); + else + goal_column = column + editwincols; while (*text != '\0' && column <= goal_column) { + if (ISSET(AT_BLANKS) && editwincols > 2 && is_blank_mbchar(text)) { + found_blank = TRUE; + lastblank_index = index; + lastblank_column = column; + } + prev_column = column; char_len = parse_mbchar(text, NULL, &column); text += char_len; + index += char_len; } /* If the text displays within goal_column, we've reached the end of the @@ -3023,6 +3045,14 @@ size_t get_softwrap_breakpoint(const char *text, size_t leftedge, return column; } + /* If we're softwrapping at blanks and we found at least one blank, move + * the pointer back to the last blank, step beyond it, and we're done. */ + if (found_blank) { + text = text - index + lastblank_index; + parse_mbchar(text, NULL, &lastblank_column); + return lastblank_column; + } + /* Otherwise, return the column of the last character before goal_column, * since we can't break the text anywhere else. */ return (editwincols > 2) ? prev_column : column - 1; diff --git a/syntax/nanorc.nanorc b/syntax/nanorc.nanorc index 2cf4e5f8..de293685 100644 --- a/syntax/nanorc.nanorc +++ b/syntax/nanorc.nanorc @@ -7,7 +7,7 @@ comment "#" icolor brightred "^[[:space:]]*((un)?(bind|set)|include|syntax|header|comment|magic|linter|i?color|extendsyntax).*$" # Keywords -icolor brightgreen "^[[:space:]]*(set|unset)[[:space:]]+(allow_insecure_backup|autoindent|backup|backwards|boldtext|casesensitive|constantshow|cut|fill[[:space:]]+-?[[:digit:]]+|historylog|justifytrim|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|unix|view|wordbounds)\>" +icolor brightgreen "^[[:space:]]*(set|unset)[[:space:]]+(allow_insecure_backup|atblanks|autoindent|backup|backwards|boldtext|casesensitive|constantshow|cut|fill[[:space:]]+-?[[:digit:]]+|historylog|justifytrim|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|unix|view|wordbounds)\>" icolor yellow "^[[:space:]]*set[[:space:]]+((function|key|number|status|title)color)[[:space:]]+(bright)?(white|black|red|blue|green|yellow|magenta|cyan)?(,(white|black|red|blue|green|yellow|magenta|cyan))?\>" icolor brightgreen "^[[:space:]]*set[[:space:]]+(backupdir|brackets|functioncolor|keycolor|matchbrackets|numbercolor|operatingdir|punct|quotestr|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:]]*$)"