new feature: a 'tabgives' command to define what the Tab key produces

The 'tabgives' command is syntax-specific and should be followed by a
string containing the character(s) that a single press of the <Tab> key
should produce -- most likely a single TAB or a small bunch of spaces,
but any string is allowed.  This overrides the 'tabstospaces' option.

When one wants to make sure <Tab> inserts always four spaces and never
a TAB when editing a Python file, one could add to one's nanorc:

  extendsyntax python tabgives "    "

where there are four spaces between the quotes.  And when one wants
to ensure, when editing a Makefile, that <Tab> always inserts a TAB
and never spaces, independent of what tabstospaces is set to, one
could add to one's nanorc:

  extendsyntax makefile tabgives "	"

where there is a literal TAB character between the quotes.

This fulfills https://savannah.gnu.org/bugs/?53661,
Requested-by: Andrew Pennebaker <andrew.pennebaker@gmail.com>
And addresses https://savannah.gnu.org/bugs/?54760.
Requested-by: Henry van Megen <hvanmegen@gmail.com>
And addresses part of https://savannah.gnu.org/bugs/?54775.
Requested-by: Dirkjan Ochtman <dirkjan@ochtman.nl>
master
Benno Schulenberg 2018-10-29 20:40:55 +01:00
parent 591d3170aa
commit 3644d51b97
4 changed files with 33 additions and 3 deletions

View File

@ -234,6 +234,8 @@ typedef struct syntaxtype {
/* The list of libmagic results that this syntax applies to. */ /* The list of libmagic results that this syntax applies to. */
char *linter; char *linter;
/* The command with which to lint this type of file. */ /* The command with which to lint this type of file. */
char *tab;
/* What the Tab key should produce; NULL for default behavior. */
#ifdef ENABLE_COMMENT #ifdef ENABLE_COMMENT
char *comment; char *comment;
/* The line comment prefix (and postfix) for this type of file. */ /* The line comment prefix (and postfix) for this type of file. */

View File

@ -333,6 +333,7 @@ void begin_new_syntax(char *ptr)
live_syntax->headers = NULL; live_syntax->headers = NULL;
live_syntax->magics = NULL; live_syntax->magics = NULL;
live_syntax->linter = NULL; live_syntax->linter = NULL;
live_syntax->tab = NULL;
#ifdef ENABLE_COMMENT #ifdef ENABLE_COMMENT
live_syntax->comment = mallocstrcpy(NULL, GENERAL_COMMENT_CHARACTER); live_syntax->comment = mallocstrcpy(NULL, GENERAL_COMMENT_CHARACTER);
#endif #endif
@ -947,6 +948,10 @@ bool parse_syntax_commands(char *keyword, char *ptr)
else if (strcasecmp(keyword, "comment") == 0) { else if (strcasecmp(keyword, "comment") == 0) {
#ifdef ENABLE_COMMENT #ifdef ENABLE_COMMENT
pick_up_name("comment", ptr, &live_syntax->comment); pick_up_name("comment", ptr, &live_syntax->comment);
#endif
} else if (strcasecmp(keyword, "tabgives") == 0) {
#ifdef ENABLE_COLOR
pick_up_name("tabgives", ptr, &live_syntax->tab);
#endif #endif
} else if (strcasecmp(keyword, "linter") == 0) } else if (strcasecmp(keyword, "linter") == 0)
pick_up_name("linter", ptr, &live_syntax->linter); pick_up_name("linter", ptr, &live_syntax->linter);
@ -1090,6 +1095,7 @@ void parse_rcfile(FILE *rcstream, bool just_syntax, bool intros_only)
} else if (intros_only && (strcasecmp(keyword, "color") == 0 || } else if (intros_only && (strcasecmp(keyword, "color") == 0 ||
strcasecmp(keyword, "icolor") == 0 || strcasecmp(keyword, "icolor") == 0 ||
strcasecmp(keyword, "comment") == 0 || strcasecmp(keyword, "comment") == 0 ||
strcasecmp(keyword, "tabgives") == 0 ||
strcasecmp(keyword, "linter") == 0)) { strcasecmp(keyword, "linter") == 0)) {
if (!opensyntax) if (!opensyntax)
jot_error(N_("A '%s' command requires a preceding " jot_error(N_("A '%s' command requires a preceding "

View File

@ -76,6 +76,11 @@ const char *invocation_error(const char *name)
* of spaces that a tab would normally take up. */ * of spaces that a tab would normally take up. */
void do_tab(void) void do_tab(void)
{ {
#ifdef ENABLE_COLOR
if (openfile->syntax && openfile->syntax->tab)
do_output(openfile->syntax->tab, strlen(openfile->syntax->tab), TRUE);
else
#endif
#ifndef NANO_TINY #ifndef NANO_TINY
if (ISSET(TABS_TO_SPACES)) { if (ISSET(TABS_TO_SPACES)) {
char *spaces = charalloc(tabsize + 1); char *spaces = charalloc(tabsize + 1);
@ -141,6 +146,11 @@ void do_indent(void)
indentation = charalloc(tabsize + 1); indentation = charalloc(tabsize + 1);
/* Set the indentation to either a bunch of spaces or a single tab. */ /* Set the indentation to either a bunch of spaces or a single tab. */
#ifdef ENABLE_COLOR
if (openfile->syntax && openfile->syntax->tab)
indentation = mallocstrcpy(indentation, openfile->syntax->tab);
else
#endif
if (ISSET(TABS_TO_SPACES)) { if (ISSET(TABS_TO_SPACES)) {
memset(indentation, ' ', tabsize); memset(indentation, ' ', tabsize);
indentation[tabsize] = '\0'; indentation[tabsize] = '\0';
@ -174,6 +184,18 @@ size_t length_of_white(const char *text)
{ {
size_t white_count = 0; size_t white_count = 0;
#ifdef ENABLE_COLOR
if (openfile->syntax && openfile->syntax->tab) {
size_t thelength = strlen(openfile->syntax->tab);
while (text[white_count] == openfile->syntax->tab[white_count])
if (++white_count == thelength)
return thelength;
white_count = 0;
}
#endif
while (TRUE) { while (TRUE) {
if (*text == '\t') if (*text == '\t')
return ++white_count; return ++white_count;

View File

@ -4,7 +4,7 @@ syntax nanorc "\.?nanorc$"
comment "#" comment "#"
# Possible errors and parameters # Possible errors and parameters
icolor brightred "^[[:space:]]*((un)?(bind|set)|include|syntax|header|magic|comment|linter|i?color|extendsyntax).*" icolor brightred "^[[:space:]]*((un)?(bind|set)|include|syntax|header|magic|comment|linter|tabgives|i?color|extendsyntax).*"
# Keywords # Keywords
icolor brightgreen "^[[:space:]]*(set|unset)[[:space:]]+(afterends|allow_insecure_backup|atblanks|autoindent|backup|backwards|boldtext|breaklonglines|casesensitive|constantshow|cutfromcursor|emptyline|finalnewline|historylog|jumpyscrolling|linenumbers|locking|morespace|mouse|multibuffer|noconvert|nohelp|nopauses|nonewlines|nowrap|positionlog|preserve|quickblank|quiet|rebinddelete|rebindkeypad|regexp|showcursor|smarthome|smooth|softwrap|suspend|tabstospaces|tempfile|trimblanks|unix|view|wordbounds|zap)\>" icolor brightgreen "^[[:space:]]*(set|unset)[[:space:]]+(afterends|allow_insecure_backup|atblanks|autoindent|backup|backwards|boldtext|breaklonglines|casesensitive|constantshow|cutfromcursor|emptyline|finalnewline|historylog|jumpyscrolling|linenumbers|locking|morespace|mouse|multibuffer|noconvert|nohelp|nopauses|nonewlines|nowrap|positionlog|preserve|quickblank|quiet|rebinddelete|rebindkeypad|regexp|showcursor|smarthome|smooth|softwrap|suspend|tabstospaces|tempfile|trimblanks|unix|view|wordbounds|zap)\>"
@ -13,9 +13,9 @@ icolor brightgreen "^[[:space:]]*set[[:space:]]+(backupdir|brackets|errorcolor|f
icolor brightgreen "^[[:space:]]*set[[:space:]]+(fill[[:space:]]+-?[[:digit:]]+|(guidestripe|tabsize)[[:space:]]+[1-9][0-9]*)\>" icolor brightgreen "^[[:space:]]*set[[:space:]]+(fill[[:space:]]+-?[[:digit:]]+|(guidestripe|tabsize)[[:space:]]+[1-9][0-9]*)\>"
icolor brightgreen "^[[:space:]]*bind[[:space:]]+((\^([[:alpha:]]|[]@\^_]|Space)|M-([[:alpha:]]|[]!"#$%&'()*+,./0-9:;<=>?@\^_`{|}~-]|Space))|F([1-9]|1[0-6])|Ins|Del)[[:space:]]+([[:alpha:]]+|".*")[[:space:]]+(all|main|search|replace(with)?|yesno|gotoline|writeout|insert|ext(ernal)?cmd|help|spell|linter|browser|whereisfile|gotodir)([[:space:]]+#|[[:space:]]*$)" icolor brightgreen "^[[:space:]]*bind[[:space:]]+((\^([[:alpha:]]|[]@\^_]|Space)|M-([[:alpha:]]|[]!"#$%&'()*+,./0-9:;<=>?@\^_`{|}~-]|Space))|F([1-9]|1[0-6])|Ins|Del)[[:space:]]+([[:alpha:]]+|".*")[[:space:]]+(all|main|search|replace(with)?|yesno|gotoline|writeout|insert|ext(ernal)?cmd|help|spell|linter|browser|whereisfile|gotodir)([[:space:]]+#|[[:space:]]*$)"
icolor brightgreen "^[[:space:]]*unbind[[:space:]]+((\^([[:alpha:]]|[]@\^_]|Space)|M-([[:alpha:]]|[]!"#$%&'()*+,./0-9:;<=>?@\^_`{|}~-]|Space))|F([1-9]|1[0-6])|Ins|Del)[[:space:]]+(all|main|search|replace(with)?|yesno|gotoline|writeout|insert|ext(ernal)?cmd|help|spell|linter|browser|whereisfile|gotodir)([[:space:]]+#|[[:space:]]*$)" icolor brightgreen "^[[:space:]]*unbind[[:space:]]+((\^([[:alpha:]]|[]@\^_]|Space)|M-([[:alpha:]]|[]!"#$%&'()*+,./0-9:;<=>?@\^_`{|}~-]|Space))|F([1-9]|1[0-6])|Ins|Del)[[:space:]]+(all|main|search|replace(with)?|yesno|gotoline|writeout|insert|ext(ernal)?cmd|help|spell|linter|browser|whereisfile|gotodir)([[:space:]]+#|[[:space:]]*$)"
icolor brightgreen "^[[:space:]]*extendsyntax[[:space:]]+[[:alpha:]]+[[:space:]]+(i?color|header|magic|comment|linter)[[:space:]]+.*" icolor brightgreen "^[[:space:]]*extendsyntax[[:space:]]+[[:alpha:]]+[[:space:]]+(i?color|header|magic|comment|linter|tabgives)[[:space:]]+.*"
icolor brightgreen "^[[:space:]]*(syntax|linter)[[:space:]]+[^[:blank:]]+" icolor brightgreen "^[[:space:]]*(syntax|linter)[[:space:]]+[^[:blank:]]+"
icolor green "^[[:space:]]*((un)?(bind|set)|include|syntax|header|magic|comment|linter|extendsyntax)\>" icolor green "^[[:space:]]*((un)?(bind|set)|include|syntax|header|magic|comment|linter|tabgives|extendsyntax)\>"
# Strings # Strings
color brightmagenta "([[:space:]]|(start|end)=)".+"([[:space:]]|$)" color brightmagenta "([[:space:]]|(start|end)=)".+"([[:space:]]|$)"