From: Chris Allegretta Date: Sun, 21 Sep 2008 23:02:30 +0000 (+0000) Subject: 2008-09-21 Chris Allegretta X-Git-Tag: v2.1.6~7 X-Git-Url: https://git.wh0rd.org/?a=commitdiff_plain;h=f30c1390c7cf32e76948547dbd8831cbd231530b;p=nano.git 2008-09-21 Chris Allegretta * rcfile.c, color.c, nano.h: Add new capability for matching a syntax type by the "header" (1st line) of a file being edited. Based on Savannah bug 24197 and inital proof of concept by Dave Geering git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@4328 35c25a1d-7b9e-4130-9fde-d3aeb78583b8 --- diff --git a/ChangeLog b/ChangeLog index e224a67f..5ea8c33b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2008-09-21 Chris Allegretta + * rcfile.c, color.c, nano.h: Add new capability for matching a syntax type by the "header" (1st line) + of a file being edited. Based on Savannah bug 24197 and inital proof of concept by Dave Geering + 2008-09-16 Chris Allegretta * text.c: Add support for undoing a text uncut. Split out the undo and redo of a text cut in order to avoid code duplication. diff --git a/doc/syntax/nanorc.nanorc b/doc/syntax/nanorc.nanorc index f63d770d..ae7baec3 100644 --- a/doc/syntax/nanorc.nanorc +++ b/doc/syntax/nanorc.nanorc @@ -5,7 +5,7 @@ syntax "nanorc" "\.?nanorc$" icolor brightwhite "^[[:space:]]*((un)?set|include|syntax|i?color).*$" ## Keywords icolor brightgreen "^[[:space:]]*(set|unset)[[:space:]]+(autoindent|backup|backupdir|backwards|boldtext|brackets|casesensitive|const|cut|fill|historylog|matchbrackets|morespace|mouse|multibuffer|noconvert|nofollow|nohelp|nonewlines|nowrap|operatingdir|preserve|punct)\>" "^[[:space:]]*(set|unset)[[:space:]]+(quickblank|quotestr|rebinddelete|rebindkeypad|regexp|smarthome|smooth|speller|suspend|tabsize|tabstospaces|tempfile|view|whitespace|wordbounds)\>" -icolor green "^[[:space:]]*(set|unset|include|syntax)\>" +icolor green "^[[:space:]]*(set|unset|include|syntax|header)\>" ## Colors icolor yellow "^[[:space:]]*i?color[[:space:]]*(bright)?(white|black|red|blue|green|yellow|magenta|cyan)?(,(white|black|red|blue|green|yellow|magenta|cyan))?\>" icolor magenta "^[[:space:]]*i?color\>" "\<(start|end)=" diff --git a/doc/syntax/perl.nanorc b/doc/syntax/perl.nanorc index 7bca4cd1..b5a56062 100644 --- a/doc/syntax/perl.nanorc +++ b/doc/syntax/perl.nanorc @@ -1,6 +1,7 @@ ## Here is an example for Perl. ## syntax "perl" "\.p[lm]$" +header "^#!.*/perl[-0-9._]*" color red "\<(accept|alarm|atan2|bin(d|mode)|c(aller|h(dir|mod|op|own|root)|lose(dir)?|onnect|os|rypt)|d(bm(close|open)|efined|elete|ie|o|ump)|e(ach|of|val|x(ec|ists|it|p))|f(cntl|ileno|lock|ork))\>" "\<(get(c|login|peername|pgrp|ppid|priority|pwnam|(host|net|proto|serv)byname|pwuid|grgid|(host|net)byaddr|protobynumber|servbyport)|([gs]et|end)(pw|gr|host|net|proto|serv)ent|getsock(name|opt)|gmtime|goto|grep|hex|index|int|ioctl|join)\>" "\<(keys|kill|last|length|link|listen|local(time)?|log|lstat|m|mkdir|msg(ctl|get|snd|rcv)|next|oct|open(dir)?|ord|pack|pipe|pop|printf?|push|q|qq|qx|rand|re(ad(dir|link)?|cv|do|name|quire|set|turn|verse|winddir)|rindex|rmdir|s|scalar|seek(dir)?)\>" "\<(se(lect|mctl|mget|mop|nd|tpgrp|tpriority|tsockopt)|shift|shm(ctl|get|read|write)|shutdown|sin|sleep|socket(pair)?|sort|spli(ce|t)|sprintf|sqrt|srand|stat|study|substr|symlink|sys(call|read|tem|write)|tell(dir)?|time|tr(y)?|truncate|umask)\>" "\<(un(def|link|pack|shift)|utime|values|vec|wait(pid)?|wantarray|warn|write)\>" color magenta "\<(continue|else|elsif|do|for|foreach|if|unless|until|while|eq|ne|lt|gt|le|ge|cmp|x|my|sub|use|package|can|isa)\>" icolor cyan start="[$@%]" end="( |[^0-9A-Z_]|-)" diff --git a/doc/syntax/sh.nanorc b/doc/syntax/sh.nanorc index f540f1b7..61098e37 100644 --- a/doc/syntax/sh.nanorc +++ b/doc/syntax/sh.nanorc @@ -1,6 +1,7 @@ ## Here is an example for Bourne shell scripts. ## syntax "sh" "\.sh$" +header "^#!.*/(ba|k|pdk|)sh[-0-9_]*" icolor brightgreen "^[0-9A-Z_]+\(\)" color green "\<(case|do|done|elif|else|esac|exit|fi|for|function|if|in|local|read|return|select|shift|then|time|until|while)\>" color green "(\{|\}|\(|\)|\;|\]|\[|`|\\|\$|<|>|!|=|&|\|)" diff --git a/src/color.c b/src/color.c index bbe46bd9..353a5baf 100644 --- a/src/color.c +++ b/src/color.c @@ -131,7 +131,7 @@ void color_update(void) /* If we didn't specify a syntax override string, or if we did and * there was no syntax by that name, get the syntax based on the - * file extension. */ + * file extension, and then look in the header. */ if (openfile->colorstrings == NULL) { for (tmpsyntax = syntaxes; tmpsyntax != NULL; tmpsyntax = tmpsyntax->next) { @@ -174,8 +174,51 @@ void color_update(void) } } } + + /* If we haven't matched anything yet, try the headers */ + if (openfile->colorstrings == NULL) { +#ifdef DEBUG + fprintf(stderr, "No match for file extensions, looking at headers...\n"); +#endif + for (tmpsyntax = syntaxes; tmpsyntax != NULL; + tmpsyntax = tmpsyntax->next) { + exttype *e; + + for (e = tmpsyntax->headers; e != NULL; e = e->next) { + bool not_compiled = (e->ext == NULL); + + /* e->ext_regex has already been checked for validity + * elsewhere. Compile its specified regex if we haven't + * already. */ + if (not_compiled) { + e->ext = (regex_t *)nmalloc(sizeof(regex_t)); + regcomp(e->ext, fixbounds(e->ext_regex), REG_EXTENDED); + } + + /* Set colorstrings if we matched the extension + * regex. */ +#ifdef DEBUG + fprintf(stderr, "Comparing header regex \"%s\" to fileage \"%s\"...\n", e->ext_regex, openfile->fileage->data); +#endif + if (regexec(e->ext, openfile->fileage->data, 0, NULL, 0) == 0) + openfile->colorstrings = tmpsyntax->color; + + if (openfile->colorstrings != NULL) + break; + + /* Decompile e->ext_regex's specified regex if we aren't + * going to use it. */ + if (not_compiled) { + regfree(e->ext); + free(e->ext); + e->ext = NULL; + } + } + } + } } + /* If we didn't get a syntax based on the file extension, and we * have a default syntax, use it. */ if (openfile->colorstrings == NULL && defcolor != NULL) diff --git a/src/nano.h b/src/nano.h index b286f0d0..c82122d6 100644 --- a/src/nano.h +++ b/src/nano.h @@ -242,6 +242,8 @@ typedef struct syntaxtype { /* The name of this syntax. */ exttype *extensions; /* The list of extensions that this syntax applies to. */ + exttype *headers; + /* Regexes to match on the 'header' (1st line) of the file */ colortype *color; /* The colors used in this syntax. */ struct syntaxtype *next; diff --git a/src/rcfile.c b/src/rcfile.c index 85fb9913..24ec588e 100644 --- a/src/rcfile.c +++ b/src/rcfile.c @@ -103,6 +103,8 @@ static char *nanorc = NULL; #ifdef ENABLE_COLOR static syntaxtype *endsyntax = NULL; /* The end of the list of syntaxes. */ +static exttype *endheader = NULL; + /* End of header list */ static colortype *endcolor = NULL; /* The end of the color list for the current syntax. */ #endif @@ -290,7 +292,9 @@ void parse_syntax(char *ptr) endsyntax->desc = mallocstrcpy(NULL, nameptr); endsyntax->color = NULL; endcolor = NULL; + endheader = NULL; endsyntax->extensions = NULL; + endsyntax->headers = NULL; endsyntax->next = NULL; #ifdef DEBUG @@ -715,6 +719,71 @@ void parse_colors(char *ptr, bool icase) } } } + +/* Parse the headers (1st line) of the file which may influence the regex used. */ +void parse_headers(char *ptr) +{ + char *h, *regstr; + + assert(ptr != NULL); + + if (syntaxes == NULL) { + rcfile_error( + N_("Cannot add a header regex without a syntax command")); + return; + } + + if (*ptr == '\0') { + rcfile_error(N_("Missing regex string")); + return; + } + + /* Now for the fun part. Start adding regexes to individual strings + * in the colorstrings array, woo! */ + while (ptr != NULL && *ptr != '\0') { + exttype *newheader; + /* The new color structure. */ + bool cancelled = FALSE; + /* The start expression was bad. */ + + if (*ptr != '"') { + rcfile_error( + N_("Regex strings must begin and end with a \" character")); + ptr = parse_next_regex(ptr); + continue; + } + + ptr++; + + regstr = ptr; + ptr = parse_next_regex(ptr); + if (ptr == NULL) + break; + + newheader = (exttype *)nmalloc(sizeof(exttype)); + + /* Save the regex string if it's valid */ + if (nregcomp(regstr, 0)) { + newheader->ext_regex = mallocstrcpy(NULL, regstr); + newheader->ext = NULL; + newheader->next = NULL; + +#ifdef DEBUG + fprintf(stderr, "Starting a new header entry: %s\n", newheader->ext_regex); +#endif + + if (endheader == NULL) { + endsyntax->headers = newheader; + } else { + endheader->next = newheader; + } + + endheader = newheader; + } else + free(newheader); + + } +} #endif /* ENABLE_COLOR */ /* Check whether the user has unmapped every shortcut for a @@ -812,7 +881,9 @@ void parse_rcfile(FILE *rcstream rcfile_error(N_("Syntax \"%s\" has no color commands"), endsyntax->desc); parse_syntax(ptr); - } else if (strcasecmp(keyword, "color") == 0) + } else if (strcasecmp(keyword, "header") == 0) + parse_headers(ptr); + else if (strcasecmp(keyword, "color") == 0) parse_colors(ptr, FALSE); else if (strcasecmp(keyword, "icolor") == 0) parse_colors(ptr, TRUE);