new feature: add the option --wordchars, to set extra word characters

This allows the user to specify which other characters, besides the
default alphanumeric ones, should be considered as part of a word, so
that word operations like Ctrl+Left and Ctrl+Right will pass them by.

Using this option overrides the option --wordbounds.

This fulfills https://savannah.gnu.org/bugs/?47283.
master
Benno Schulenberg 2016-06-30 18:02:45 +02:00
parent d88423eaae
commit 6f12992cea
10 changed files with 74 additions and 14 deletions

View File

@ -148,9 +148,14 @@ keystroke instead of 25. Note that \fB\-c\fP overrides this.
Show the current version number and exit. Show the current version number and exit.
.TP .TP
.BR \-W ", " \-\-wordbounds .BR \-W ", " \-\-wordbounds
Detect word boundaries more accurately by treating punctuation Detect word boundaries differently by treating punctuation
characters as part of a word. characters as part of a word.
.TP .TP
.BR "\-X ""\fIcharacters\fB""" ", " "\-\-wordchars=""" \fIcharacters """
Specify which other characters (besides the normal alphanumeric ones)
should be considered as part of a word. This overrides option
\fB\-W\fR (\fB\-\-wordbounds\fR).
.TP
.BR \-Y\ \fIname\fR ", " \-\-syntax= \fIname .BR \-Y\ \fIname\fR ", " \-\-syntax= \fIname
Specify the name of the syntax highlighting to use from among the ones Specify the name of the syntax highlighting to use from among the ones
defined in the \fInanorc\fP files. defined in the \fInanorc\fP files.

View File

@ -253,8 +253,13 @@ Set the two characters used to indicate the presence of tabs and
spaces. They must be single-column characters. spaces. They must be single-column characters.
.TP .TP
.B set wordbounds .B set wordbounds
Detect word boundaries more accurately by treating punctuation Detect word boundaries differently by treating punctuation
characters as parts of words. characters as parts of words.
.TP
.B set wordchars \fIstring\fP
Specify which other characters (besides the normal alphanumeric ones)
should be considered as parts of words. This overrides the option
\fBwordbounds\fR.
.SH SYNTAX HIGHLIGHTING .SH SYNTAX HIGHLIGHTING
Coloring the different syntactic elements of a file Coloring the different syntactic elements of a file

View File

@ -178,10 +178,15 @@
## The default otherwise: ## The default otherwise:
# set whitespace ">." # set whitespace ">."
## Detect word boundaries more accurately by treating punctuation ## Detect word boundaries differently by treating punctuation
## characters as parts of words. ## characters as parts of words.
# set wordbounds # set wordbounds
## The characters (besides alphanumeric ones) that should be considered
## as parts of words. This option does not have a default value. When
## set, it overrides option 'set wordbounds'.
# set wordchars "<_>."
## Paint the interface elements of nano. ## Paint the interface elements of nano.
## This is an example; by default there are no colors. ## This is an example; by default there are no colors.

View File

@ -231,9 +231,15 @@ Show the current version number and exit.
@item -W @item -W
@itemx --wordbounds @itemx --wordbounds
Detect word boundaries more accurately by treating punctuation Detect word boundaries differently by treating punctuation
characters as parts of words. characters as parts of words.
@item -X "@var{characters}"
@itemx --wordchars="@var{characters}"
Specify which other characters (besides the normal alphanumeric ones)
should be considered as parts of words. This overrides option
@option{-W} (@option{--wordbounds}).
@item -Y @var{name} @item -Y @var{name}
@itemx --syntax=@var{name} @itemx --syntax=@var{name}
Specify a specific syntax from the nanorc files to use for highlighting. Specify a specific syntax from the nanorc files to use for highlighting.
@ -831,9 +837,14 @@ spaces. They must be single-column characters. The default pair
for a UTF-8 locale is @t{"»·"}, and for other locales @t{">."}. for a UTF-8 locale is @t{"»·"}, and for other locales @t{">."}.
@item set wordbounds @item set wordbounds
Detect word boundaries more accurately by treating punctuation Detect word boundaries differently by treating punctuation
characters as part of a word. characters as part of a word.
@item set wordchars "@var{string}"
Specify which other characters (besides the normal alphanumeric ones)
should be considered as parts of words. This overrides the option
@code{wordbounds}.
@end table @end table
@node Syntax Highlighting @node Syntax Highlighting

View File

@ -183,15 +183,26 @@ bool is_punct_mbchar(const char *c)
return ispunct((unsigned char)*c); return ispunct((unsigned char)*c);
} }
/* Return TRUE for a multibyte character found in a word (currently only /* Return TRUE when the given multibyte character c is a word-forming
* an alphanumeric or punctuation character, and only the latter if * character (that is: alphanumeric, or specified in wordchars, or
* allow_punct is TRUE) and FALSE otherwise. */ * punctuation when allow_punct is TRUE), and FALSE otherwise. */
bool is_word_mbchar(const char *c, bool allow_punct) bool is_word_mbchar(const char *c, bool allow_punct)
{ {
assert(c != NULL); assert(c != NULL);
return is_alnum_mbchar(c) || (allow_punct ? is_punct_mbchar(c) : if (is_alnum_mbchar(c))
FALSE); return TRUE;
if (word_chars != NULL && *word_chars != '\0') {
char *symbol = charalloc(MB_CUR_MAX + 1);
int symlen = parse_mbchar(c, symbol, NULL);
symbol[symlen] = '\0';
return (strstr(word_chars, symbol) != NULL);
}
return (allow_punct && is_punct_mbchar(c));
} }
/* Return the visible representation of control character c. */ /* Return the visible representation of control character c. */

View File

@ -124,6 +124,9 @@ size_t quotelen;
#endif #endif
#endif #endif
char *word_chars = NULL;
/* Nonalphanumeric characters that also form words. */
bool nodelay_mode = FALSE; bool nodelay_mode = FALSE;
/* Are we checking for a cancel wile doing something? */ /* Are we checking for a cancel wile doing something? */
@ -1669,6 +1672,7 @@ void thanks_for_all_the_fish(void)
delwin(edit); delwin(edit);
delwin(bottomwin); delwin(bottomwin);
free(word_chars);
#ifndef DISABLE_JUSTIFY #ifndef DISABLE_JUSTIFY
free(quotestr); free(quotestr);
#ifdef HAVE_REGEX_H #ifdef HAVE_REGEX_H

View File

@ -860,6 +860,8 @@ void usage(void)
#ifndef NANO_TINY #ifndef NANO_TINY
print_opt("-W", "--wordbounds", print_opt("-W", "--wordbounds",
N_("Detect word boundaries more accurately")); N_("Detect word boundaries more accurately"));
print_opt("-X", "--wordchars",
N_("Which other characters are word parts"));
#endif #endif
#ifndef DISABLE_COLOR #ifndef DISABLE_COLOR
if (!ISSET(RESTRICTED)) if (!ISSET(RESTRICTED))
@ -1995,6 +1997,7 @@ int main(int argc, char **argv)
{"smooth", 0, NULL, 'S'}, {"smooth", 0, NULL, 'S'},
{"quickblank", 0, NULL, 'U'}, {"quickblank", 0, NULL, 'U'},
{"wordbounds", 0, NULL, 'W'}, {"wordbounds", 0, NULL, 'W'},
{"wordchars", 1, NULL, 'X'},
{"autoindent", 0, NULL, 'i'}, {"autoindent", 0, NULL, 'i'},
{"cut", 0, NULL, 'k'}, {"cut", 0, NULL, 'k'},
{"unix", 0, NULL, 'u'}, {"unix", 0, NULL, 'u'},
@ -2040,11 +2043,11 @@ int main(int argc, char **argv)
while ((optchr = while ((optchr =
#ifdef HAVE_GETOPT_LONG #ifdef HAVE_GETOPT_LONG
getopt_long(argc, argv, getopt_long(argc, argv,
"ABC:DEFGHIKLNOPQ:RST:UVWY:abcdefghijklmno:pqr:s:tuvwxz$", "ABC:DEFGHIKLNOPQ:RST:UVWX:Y:abcdefghijklmno:pqr:s:tuvwxz$",
long_options, NULL) long_options, NULL)
#else #else
getopt(argc, argv, getopt(argc, argv,
"ABC:DEFGHIKLNOPQ:RST:UVWY:abcdefghijklmno:pqr:s:tuvwxz$") "ABC:DEFGHIKLNOPQ:RST:UVWX:Y:abcdefghijklmno:pqr:s:tuvwxz$")
#endif #endif
) != -1) { ) != -1) {
switch (optchr) { switch (optchr) {
@ -2146,6 +2149,9 @@ int main(int argc, char **argv)
case 'W': case 'W':
SET(WORD_BOUNDS); SET(WORD_BOUNDS);
break; break;
case 'X':
word_chars = mallocstrcpy(word_chars, optarg);
break;
#endif #endif
#ifndef DISABLE_COLOR #ifndef DISABLE_COLOR
case 'Y': case 'Y':
@ -2279,6 +2285,7 @@ int main(int argc, char **argv)
#endif #endif
#ifndef NANO_TINY #ifndef NANO_TINY
char *backup_dir_cpy = backup_dir; char *backup_dir_cpy = backup_dir;
char *word_chars_cpy = word_chars;
#endif #endif
#ifndef DISABLE_JUSTIFY #ifndef DISABLE_JUSTIFY
char *quotestr_cpy = quotestr; char *quotestr_cpy = quotestr;
@ -2297,6 +2304,7 @@ int main(int argc, char **argv)
#endif #endif
#ifndef NANO_TINY #ifndef NANO_TINY
backup_dir = NULL; backup_dir = NULL;
word_chars = NULL;
#endif #endif
#ifndef DISABLE_JUSTIFY #ifndef DISABLE_JUSTIFY
quotestr = NULL; quotestr = NULL;
@ -2327,6 +2335,10 @@ int main(int argc, char **argv)
free(backup_dir); free(backup_dir);
backup_dir = backup_dir_cpy; backup_dir = backup_dir_cpy;
} }
if (word_chars_cpy != NULL) {
free(word_chars);
word_chars = word_chars_cpy;
}
#endif #endif
#ifndef DISABLE_JUSTIFY #ifndef DISABLE_JUSTIFY
if (quotestr_cpy != NULL) { if (quotestr_cpy != NULL) {

View File

@ -91,7 +91,10 @@ extern size_t quotelen;
#endif #endif
#endif /* !DISABLE_JUSTIFY */ #endif /* !DISABLE_JUSTIFY */
extern char *word_chars;
extern bool nodelay_mode; extern bool nodelay_mode;
extern char *answer; extern char *answer;
extern ssize_t tabsize; extern ssize_t tabsize;

View File

@ -102,6 +102,7 @@ static const rcoption rcopts[] = {
{"unix", MAKE_IT_UNIX}, {"unix", MAKE_IT_UNIX},
{"whitespace", 0}, {"whitespace", 0},
{"wordbounds", WORD_BOUNDS}, {"wordbounds", WORD_BOUNDS},
{"wordchars", 0},
#endif #endif
#ifndef DISABLE_COLOR #ifndef DISABLE_COLOR
{"titlecolor", 0}, {"titlecolor", 0},
@ -1177,6 +1178,9 @@ void parse_rcfile(FILE *rcstream
if (strcasecmp(rcopts[i].name, "backupdir") == 0) if (strcasecmp(rcopts[i].name, "backupdir") == 0)
backup_dir = option; backup_dir = option;
else else
if (strcasecmp(rcopts[i].name, "wordchars") == 0)
word_chars = option;
else
#endif #endif
#ifndef DISABLE_SPELLER #ifndef DISABLE_SPELLER
if (strcasecmp(rcopts[i].name, "speller") == 0) if (strcasecmp(rcopts[i].name, "speller") == 0)

View File

@ -294,8 +294,8 @@ bool is_separate_word(size_t position, size_t length, const char *buf)
* word isn't a non-punctuation "word" character, and if we're at * word isn't a non-punctuation "word" character, and if we're at
* the end of the line or the character after the word isn't a * the end of the line or the character after the word isn't a
* non-punctuation "word" character, we have a whole word. */ * non-punctuation "word" character, we have a whole word. */
retval = (position == 0 || !is_word_mbchar(before, FALSE)) && retval = (position == 0 || !is_alnum_mbchar(before)) &&
(word_end == strlen(buf) || !is_word_mbchar(after, FALSE)); (word_end == strlen(buf) || !is_alnum_mbchar(after));
free(before); free(before);
free(after); free(after);