diff --git a/ChangeLog b/ChangeLog index e92ff323..0df0c6d2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -30,6 +30,11 @@ CVS code - titlebar(), statusbar(), onekey(), edit_draw(), do_replace_highlight(), nano.1, nanorc.5, nano.texi, and nanorc.sample. (DLR, suggested by Benno Schulenberg) + - Add the ability to use self-contained color syntaxes from + separate files, accessible in the nanorc via the "include" + command. New function parse_include(); changes to + parse_rcfile(), do_nanorc(), nanorc.5, and nanorc.sample. + (Victor Ananievsky, Brand Huntsman and DLR) - files.c: open_file() - Remove redundant wording in the error message when we try to @@ -49,14 +54,19 @@ CVS code - - Simplify the routine for closing the file just before we indicate success on the statusbar. (DLR) - rcfile.c: + parse_argument() + - Rename variable ptr_bak to ptr_save, for consistency. (DLR) + parse_colors() + - Check for a color command's not following a syntax line before + anything else. (DLR) do_rcfile() - Check for the rcfile's being a directory or device file and reject it if it is, for consistency with file handling elsewhere. (DLR) - Remove SYSCONFDIR #ifdef, as SYSCONFDIR should always be set. (DLR) - parse_argument() - - Rename variable ptr_bak to ptr_save, for consistency. (DLR) + - Change all rcfile error messages to refer to commands instead + of directives, for consistency with nanorc.5. (DLR) - doc/nano.1, doc/nanorc.5, doc/rnano.1, doc/nano.texi: - Update the copyright years to include 2006. (DLR) - Explicitly mention that all regexes should be extended regular diff --git a/doc/man/nanorc.5 b/doc/man/nanorc.5 index 8271a6a1..00a519ae 100644 --- a/doc/man/nanorc.5 +++ b/doc/man/nanorc.5 @@ -231,7 +231,11 @@ the first instance of \fIer\fP. .TP .B icolor \fIfgcolor\fP,\fIbgcolor\fP start="\fIsr\fP" end="\fIer\fP" Same as above, except that the expression matching is case insensitive. - +.TP +.B include "\fIsyntaxfile\fP" +Read in self-contained color syntaxes from \fIsyntaxfile\fP. Note that +\fIsyntaxfile\fP can only contain \fBsyntax\fP, \fBcolor\fP, and +\fBicolor\fP commands. .SH FILES .TP .I SYSCONFDIR/nanorc diff --git a/doc/nanorc.sample b/doc/nanorc.sample index d1de3e11..871ae143 100644 --- a/doc/nanorc.sample +++ b/doc/nanorc.sample @@ -356,7 +356,7 @@ ## # syntax "nanorc" "(\.|/|)nanorc$" ## highlight possible errors and parameters -# icolor brightwhite "^[[:space:]]*(set|unset|syntax|i?color).*$" +# icolor brightwhite "^[[:space:]]*(set|unset|include|syntax|i?color).*$" ## set, unset and syntax # icolor cyan "^[[: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|syntax)\>" diff --git a/src/proto.h b/src/proto.h index d6724726..582e94df 100644 --- a/src/proto.h +++ b/src/proto.h @@ -518,9 +518,14 @@ short color_to_short(const char *colorname, bool *bright); char *parse_next_regex(char *ptr); bool nregcomp(const char *regex, int eflags); void parse_syntax(char *ptr); +void parse_include(char *ptr); void parse_colors(char *ptr, bool icase); #endif -void parse_rcfile(FILE *rcstream); +void parse_rcfile(FILE *rcstream +#ifdef ENABLE_COLOR + , bool syntax_only +#endif + ); void do_rcfile(void); #endif diff --git a/src/rcfile.c b/src/rcfile.c index 68fa19d0..83d0ea5e 100644 --- a/src/rcfile.c +++ b/src/rcfile.c @@ -380,6 +380,66 @@ void parse_syntax(char *ptr) } } +/* Read and parse additional syntax files. */ +void parse_include(char *ptr) +{ + struct stat rcinfo; + FILE *rcstream; + char *option, *full_option, *nanorc_save = nanorc; + size_t lineno_save = lineno; + + option = ptr; + if (*option == '"') + option++; + ptr = parse_argument(ptr); + + /* Get the specified file's full path. */ + full_option = get_full_path(option); + + if (full_option == NULL) { + rcfile_error(_("Error reading %s: %s"), option, strerror(errno)); + goto cleanup_include; + } + + /* Don't open directories, character files, or block files. */ + if (stat(nanorc, &rcinfo) != -1) { + if (S_ISDIR(rcinfo.st_mode) || S_ISCHR(rcinfo.st_mode) || + S_ISBLK(rcinfo.st_mode)) { + rcfile_error(S_ISDIR(rcinfo.st_mode) ? + _("\"%s\" is a directory") : + _("\"%s\" is a device file"), nanorc); + goto cleanup_include; + } + } + + /* Open the new syntax file. */ + if ((rcstream = fopen(full_option, "rb")) == NULL) { + rcfile_error(_("Error reading %s: %s"), full_option, + strerror(errno)); + goto cleanup_include; + } + + /* Use the name and line number position of the new syntax file + * while parsing it, so we can know where any errors in it are. */ + nanorc = full_option; + lineno = 0; + + parse_rcfile(rcstream +#ifdef ENABLE_COLOR + , TRUE +#endif + ); + fclose(rcstream); + + /* We're done with the new syntax file. Restore the original + * filename and line number position. */ + nanorc = nanorc_save; + lineno = lineno_save; + + cleanup_include: + free(full_option); +} + /* Parse the color string in the line at ptr, and add it to the current * file's associated colors. If icase is TRUE, treat the color string * as case insensitive. */ @@ -391,6 +451,12 @@ void parse_colors(char *ptr, bool icase) assert(ptr != NULL); + if (syntaxes == NULL) { + rcfile_error( + N_("Cannot add a color command without a syntax line")); + return; + } + if (*ptr == '\0') { rcfile_error(N_("Missing color name")); return; @@ -429,12 +495,6 @@ void parse_colors(char *ptr, bool icase) } else fg = -1; - if (syntaxes == NULL) { - rcfile_error( - N_("Cannot add a color directive without a syntax line")); - return; - } - if (*ptr == '\0') { rcfile_error(N_("Missing regex string")); return; @@ -539,8 +599,13 @@ void parse_colors(char *ptr, bool icase) #endif /* ENABLE_COLOR */ /* Parse the rcfile, once it has been opened successfully at - * rcstream. */ -void parse_rcfile(FILE *rcstream) + * rcstream. If syntax_only is TRUE, only allow the file to contain + * color syntax commands: syntax, color, and icolor. */ +void parse_rcfile(FILE *rcstream +#ifdef ENABLE_COLOR + , bool syntax_only +#endif + ) { char *buf = NULL; ssize_t len; @@ -568,12 +633,34 @@ void parse_rcfile(FILE *rcstream) ptr = parse_next_word(ptr); /* Try to parse the keyword. */ - if (strcasecmp(keyword, "set") == 0) - set = 1; - else if (strcasecmp(keyword, "unset") == 0) - set = -1; + if (strcasecmp(keyword, "set") == 0) { #ifdef ENABLE_COLOR - else if (strcasecmp(keyword, "syntax") == 0) + if (syntax_only) + rcfile_error( + N_("Command %s not allowed in included file"), + keyword); + else +#endif + set = 1; + } else if (strcasecmp(keyword, "unset") == 0) { +#ifdef ENABLE_COLOR + if (syntax_only) + rcfile_error( + N_("Command %s not allowed in included file"), + keyword); + else +#endif + set = -1; + } +#ifdef ENABLE_COLOR + else if (strcasecmp(keyword, "include") == 0) { + if (syntax_only) + rcfile_error( + N_("Command %s not allowed in included file"), + keyword); + else + parse_include(ptr); + } else if (strcasecmp(keyword, "syntax") == 0) parse_syntax(ptr); else if (strcasecmp(keyword, "color") == 0) parse_colors(ptr, FALSE); @@ -773,7 +860,11 @@ void do_rcfile(void) /* Try to open the system-wide nanorc. */ rcstream = fopen(nanorc, "rb"); if (rcstream != NULL) - parse_rcfile(rcstream); + parse_rcfile(rcstream +#ifdef ENABLE_COLOR + , FALSE +#endif + ); #if defined(DISABLE_ROOTWRAP) && !defined(DISABLE_WRAPPING) /* We've already read SYSCONFDIR/nanorc, if it's there. If we're @@ -808,7 +899,11 @@ void do_rcfile(void) rcfile_error(N_("Error reading %s: %s"), nanorc, strerror(errno)); } else - parse_rcfile(rcstream); + parse_rcfile(rcstream +#ifdef ENABLE_COLOR + , FALSE +#endif + ); } free(nanorc);