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 <axxisd@gmail.com>
master
David Lawrence Ramsey 2017-03-07 10:36:43 -06:00 committed by Benno Schulenberg
parent aa04ad4f83
commit bb4d0d548a
7 changed files with 50 additions and 6 deletions

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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. */

View File

@ -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},

View File

@ -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. */
/* 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;

View File

@ -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:]]*$)"