Commit 6c1e6612 authored by Chris Allegretta's avatar Chris Allegretta
Browse files

- General - Added multiple-line regex support. Format in .nanorc is...

- General - Added multiple-line regex support.  Format in .nanorc is start=regex end=regex.  Cleaned up nanorc:parse_colors(), added parse_next_regex(), changes to edit_add in winio.c(), changes to colortype, cleaning up some old cruft


git-svn-id: svn://svn.savannah.gnu.org/nano/trunk/nano@1021 35c25a1d-7b9e-4130-9fde-d3aeb78583b8
No related merge requests found
Showing with 319 additions and 204 deletions
+319 -204
...@@ -7,6 +7,10 @@ CVS code - ...@@ -7,6 +7,10 @@ CVS code -
- Better partial word checking code. New function - Better partial word checking code. New function
search.c:is_whole_word(), changes to findnextstr(), search.c:is_whole_word(), changes to findnextstr(),
and nano.c:do_int_spell_fix() (Rocco Corsi). and nano.c:do_int_spell_fix() (Rocco Corsi).
- Added multiple-line regex support. Format in .nanorc is
start="regex" end="regex". Cleaned up nanorc:parse_colors(),
added parse_next_regex(), changes to edit_add in winio.c(),
changes to colortype, cleaning up some old cruft.
- color.c: - color.c:
do_colorinit() do_colorinit()
- Moved some comments and braces around so color can work - Moved some comments and braces around so color can work
...@@ -39,6 +43,7 @@ CVS code - ...@@ -39,6 +43,7 @@ CVS code -
General General
- Took silly variables being passed everywhere like lineno and - Took silly variables being passed everywhere like lineno and
filename and made them static variables. filename and made them static variables.
- Re-indented.
rcfile_error() rcfile_error()
- Now automatically prpends the "error in line blah at foo" - Now automatically prpends the "error in line blah at foo"
message to error messages. message to error messages.
......
...@@ -122,12 +122,12 @@ typedef struct rcoption { ...@@ -122,12 +122,12 @@ typedef struct rcoption {
#define COLORSTRNUM 16 #define COLORSTRNUM 16
typedef struct colortype { typedef struct colortype {
int fg; int fg; /* fg color */
int bg; int bg; /* bg color */
int bright; int bright; /* Is this color A_BOLD? */
int pairnum; int pairnum; /* Color pair number used for this fg/bg */
char *start; char *start; /* Start (or all) of the regex string */
char *end; char *end; /* End of the regex string */
struct colortype *next; struct colortype *next;
} colortype; } colortype;
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
# set fill -8 # set fill -8
# Use this tab size instead of the default # Use this tab size instead of the default
# set tabsize 8 # set tabsize 4
# Use this spelling checker instead of the default one # Use this spelling checker instead of the default one
# set speller aspell # set speller aspell
...@@ -58,23 +58,25 @@ ...@@ -58,23 +58,25 @@
# #
# Color setup # Color setup
# Format: color foreground,background regex [regex...] # Format: color foreground,background "regex" ["regex"...]
# #
# Legal colors are: white, black, red, blue, green, yellow, purple, cyan # Legal colors are: white, black, red, blue, green, yellow, purple, cyan
# You may use the prefix "bright" to mean a stronger color highlight # You may use the prefix "bright" to mean a stronger color highlight
# #
# To use multi-line regexes use the start="regex" end="regex" format.
#
# If your system supports transparency, not specifying a background # If your system supports transparency, not specifying a background
# color will use a transparent color. If you don't want this, be sure # color will use a transparent color. If you don't want this, be sure
# to set the background color to black or white. # to set the background color to black or white.
# #
#color brightred float\ char\ int\ void\ NULL [A-Z_]\{2,\} static #color brightred "float " "char " "int " "void " "NULL" "[A-Z_]\{2,\}"
#color brightred [\ ]struct ^struct if\ while[\ \n\(] do[\ \n\(] else[\ \n] case\ switch\ break; #color brightred "static" "const" "[\ ]struct" "^struct" "if " "while[\ \n\(]"
#color brightcyan #define #include #ifn*def #endif #elif #else #color brightred "do[\ \n\(]" "else[\ \n]" "case " "switch " "break;"
#color brightcyan "#define" "#include" "#ifn*def" "#endif" "#elif" "#else"
# You will in general want your comments and strings to come last, because #You will in general want your comments and strings to come last, becase
# syntax highlighting rules will be applied in the order they are read in #syntax highlighting rules will be applied in the order they are read in
#color brightyellow <.*> ".*" #color brightyellow "<.*[^=\ ]*>" "\".*\""
#color brightblue /\*.**/ #color brightblue "//.*"
# multi-line comment hack #color brightblue start="/\*.*" end="\*/"
#color brightblue /\*.* [^\/][^\*]*\*\/ ^.*\*+*\**$ ^\ *\*\{1,\}\/$ \/\/.*
...@@ -40,37 +40,37 @@ ...@@ -40,37 +40,37 @@
#endif #endif
#ifndef DISABLE_WRAPJUSTIFY #ifndef DISABLE_WRAPJUSTIFY
#define NUM_RCOPTS 19 #define NUM_RCOPTS 19
#else #else
#define NUM_RCOPTS 18 #define NUM_RCOPTS 18
#endif #endif
/* Static stuff for the nanorc file */ /* Static stuff for the nanorc file */
rcoption rcopts[NUM_RCOPTS] = rcoption rcopts[NUM_RCOPTS] = {
{ {"regexp", USE_REGEXP},
{"regexp", USE_REGEXP}, {"const", CONSTUPDATE},
{"const", CONSTUPDATE}, {"autoindent", AUTOINDENT},
{"autoindent", AUTOINDENT}, {"cut", CUT_TO_END},
{"cut", CUT_TO_END}, {"nofollow", FOLLOW_SYMLINKS},
{"nofollow", FOLLOW_SYMLINKS}, {"mouse", USE_MOUSE},
{"mouse", USE_MOUSE}, {"operatingdir", 0},
{"operatingdir", 0}, {"pico", PICO_MODE},
{"pico", PICO_MODE}, {"tabsize", 0},
{"tabsize", 0},
#ifndef DISABLE_WRAPJUSTIFY #ifndef DISABLE_WRAPJUSTIFY
{"fill", 0}, {"fill", 0},
#endif #endif
{"speller", 0}, {"speller", 0},
{"tempfile", TEMP_OPT}, {"tempfile", TEMP_OPT},
{"view", VIEW_MODE}, {"view", VIEW_MODE},
{"nowrap", NO_WRAP}, {"nowrap", NO_WRAP},
{"nohelp", NO_HELP}, {"nohelp", NO_HELP},
{"suspend", SUSPEND}, {"suspend", SUSPEND},
{"multibuffer", MULTIBUFFER}, {"multibuffer", MULTIBUFFER},
{"smooth", SMOOTHSCROLL}, {"smooth", SMOOTHSCROLL},
{"keypad", ALT_KEYPAD}}; {"keypad", ALT_KEYPAD}
};
static int errors = 0; static int errors = 0;
static int lineno = 0; static int lineno = 0;
...@@ -89,8 +89,7 @@ void rcfile_error(char *msg, ...) ...@@ -89,8 +89,7 @@ void rcfile_error(char *msg, ...)
va_end(ap); va_end(ap);
fprintf(stderr, _("\nPress return to continue starting nano\n")); fprintf(stderr, _("\nPress return to continue starting nano\n"));
while (getchar() != '\n') while (getchar() != '\n');
;
} }
...@@ -113,12 +112,27 @@ void rcfile_msg(char *msg, ...) ...@@ -113,12 +112,27 @@ void rcfile_msg(char *msg, ...)
/* Parse the next word from the string. Returns NULL if we hit EOL */ /* Parse the next word from the string. Returns NULL if we hit EOL */
char *parse_next_word(char *ptr) char *parse_next_word(char *ptr)
{ {
char *prev = " "; while (*ptr != ' ' && *ptr != '\t' && *ptr != '\n' && *ptr != '\0')
ptr++;
if (*ptr == '\0')
return NULL;
/* Null terminate and advance ptr */
*ptr++ = 0;
while ((*ptr != ' ' || *prev == '\\') while ((*ptr == ' ' || *ptr == '\t') && *ptr != '\0')
&& *ptr != '\t' && *ptr != '\n' && *ptr != '\0') { ptr++;
return ptr;
}
char *parse_next_regex(char *ptr)
{
char prev = ' ';
while ((*ptr != '"' || prev == '\\') && *ptr != '\n' && *ptr != '\0') {
prev = *ptr;
ptr++; ptr++;
prev = ptr;
} }
if (*ptr == '\0') if (*ptr == '\0')
...@@ -131,6 +145,7 @@ char *parse_next_word(char *ptr) ...@@ -131,6 +145,7 @@ char *parse_next_word(char *ptr)
ptr++; ptr++;
return ptr; return ptr;
} }
int colortoint(char *colorname, int *bright) int colortoint(char *colorname, int *bright)
...@@ -175,11 +190,10 @@ int colortoint(char *colorname, int *bright) ...@@ -175,11 +190,10 @@ int colortoint(char *colorname, int *bright)
#ifdef ENABLE_COLOR #ifdef ENABLE_COLOR
/* Parse the color stuff into the colorstrings array */ /* Parse the color stuff into the colorstrings array */
void parse_colors(FILE *rcstream, char *buf, char *ptr) void parse_colors(FILE * rcstream, char *buf, char *ptr)
{ {
int i = 0, fg, bg, bright = 0, loopdone = 0; int fg, bg, bright = 0;
int expectend = 0; /* Do we expect an end= line? */ int expectend = 0; /* Do we expect an end= line? */
char prev = '\\';
char *tmp = NULL, *beginning, *fgstr, *bgstr; char *tmp = NULL, *beginning, *fgstr, *bgstr;
colortype *tmpcolor = NULL; colortype *tmpcolor = NULL;
...@@ -203,36 +217,30 @@ void parse_colors(FILE *rcstream, char *buf, char *ptr) ...@@ -203,36 +217,30 @@ void parse_colors(FILE *rcstream, char *buf, char *ptr)
/* Now the fun part, start adding regexps to individual strings /* Now the fun part, start adding regexps to individual strings
in the colorstrings array, woo! */ in the colorstrings array, woo! */
while (*ptr != '\0') {
while (*ptr == ' ')
ptr++;
if (*ptr == '\n' || *ptr == '\0')
break;
if (!strncasecmp(ptr, "start=", 6)) { if (!strncasecmp(ptr, "start=", 6)) {
ptr += 6; ptr += 6;
expectend = 1; expectend = 1;
} }
i = 0; if (*ptr != '"') {
beginning = ptr; rcfile_error(_("regex strings must begin and end with a \" character\n"));
while (*ptr != '\0' && !loopdone) {
switch (*ptr) {
case '\n':
*ptr = ' ';
case ' ':
if (prev != '\\') {
/* This is the end of the regex, uh I guess.
Add it to the colorstrings array for this color */
if (i == 0) {
rcfile_error(_("regex length must be > 0"));
continue; continue;
} }
ptr++;
tmp = NULL; beginning = ptr;
tmp = charalloc(i + 1); ptr = parse_next_regex(ptr);
strncpy(tmp, beginning, i);
tmp[i] = '\0';
/* Get rid of the leading space */ tmp = NULL;
ptr = parse_next_word(ptr); tmp = mallocstrcpy(tmp, beginning);
if (ptr == NULL)
return;
if (colorstrings == NULL) { if (colorstrings == NULL) {
colorstrings = nmalloc(sizeof(colortype)); colorstrings = nmalloc(sizeof(colortype));
...@@ -242,16 +250,16 @@ void parse_colors(FILE *rcstream, char *buf, char *ptr) ...@@ -242,16 +250,16 @@ void parse_colors(FILE *rcstream, char *buf, char *ptr)
colorstrings->start = tmp; colorstrings->start = tmp;
colorstrings->next = NULL; colorstrings->next = NULL;
tmpcolor = colorstrings; tmpcolor = colorstrings;
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, "Starting a new colorstring for fg %d bg %d\n", fg, bg); fprintf(stderr,
"Starting a new colorstring for fg %d bg %d\n",
fg, bg);
fprintf(stderr, "string val=%s\n", tmp); fprintf(stderr, "string val=%s\n", tmp);
#endif #endif
} else { } else {
for (tmpcolor = colorstrings; tmpcolor->next != NULL; for (tmpcolor = colorstrings;
tmpcolor = tmpcolor->next) tmpcolor->next != NULL; tmpcolor = tmpcolor->next);
;
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, "Adding new entry for fg %d bg %d\n", fg, bg); fprintf(stderr, "Adding new entry for fg %d bg %d\n", fg, bg);
fprintf(stderr, "string val=%s\n", tmp); fprintf(stderr, "string val=%s\n", tmp);
...@@ -266,48 +274,42 @@ void parse_colors(FILE *rcstream, char *buf, char *ptr) ...@@ -266,48 +274,42 @@ void parse_colors(FILE *rcstream, char *buf, char *ptr)
tmpcolor = tmpcolor->next; tmpcolor = tmpcolor->next;
} }
i = 0;
beginning = ptr;
if (expectend)
loopdone = 1;
break;
}
/* Else drop through to the default case */
default:
i++;
prev = *ptr;
ptr++;
break;
}
}
if (expectend) { if (expectend) {
if (ptr == NULL || strncasecmp(ptr, "end=", 4)) { if (ptr == NULL || strncasecmp(ptr, "end=", 4)) {
rcfile_error( rcfile_error(_
_("\n\t\"start=\" requires a corresponding \"end=\"")); ("\n\t\"start=\" requires a corresponding \"end=\""));
return; return;
} }
ptr += 4; ptr += 4;
if (*ptr != '"') {
rcfile_error(_
("regex strings must begin and end with a \" character\n"));
continue;
}
ptr++;
beginning = ptr; beginning = ptr;
ptr = parse_next_word(ptr); ptr = parse_next_regex(ptr);
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, "For end part, beginning = \"%s\"\n", beginning); fprintf(stderr, "For end part, beginning = \"%s\"\n",
beginning);
#endif #endif
tmp = NULL; tmp = NULL;
tmp = mallocstrcpy(tmp, beginning); tmp = mallocstrcpy(tmp, beginning);
tmpcolor->end = tmp; tmpcolor->end = tmp;
} } else
tmpcolor->end = NULL;
}
} }
#endif /* ENABLE_COLOR */ #endif /* ENABLE_COLOR */
/* Parse the RC file, once it has been opened successfully */ /* Parse the RC file, once it has been opened successfully */
void parse_rcfile(FILE *rcstream) void parse_rcfile(FILE * rcstream)
{ {
char *buf, *ptr, *keyword, *option; char *buf, *ptr, *keyword, *option;
int set = 0, i; int set = 0, i;
...@@ -362,8 +364,7 @@ void parse_rcfile(FILE *rcstream) ...@@ -362,8 +364,7 @@ void parse_rcfile(FILE *rcstream)
rcopts[i].name); rcopts[i].name);
#endif #endif
if (set == 1 || rcopts[i].flag == FOLLOW_SYMLINKS) { if (set == 1 || rcopts[i].flag == FOLLOW_SYMLINKS) {
if ( if (!strcasecmp(rcopts[i].name, "operatingdir") ||
!strcasecmp(rcopts[i].name, "operatingdir") ||
!strcasecmp(rcopts[i].name, "tabsize") || !strcasecmp(rcopts[i].name, "tabsize") ||
#ifndef DISABLE_WRAPJUSTIFY #ifndef DISABLE_WRAPJUSTIFY
!strcasecmp(rcopts[i].name, "fill") || !strcasecmp(rcopts[i].name, "fill") ||
...@@ -376,7 +377,8 @@ void parse_rcfile(FILE *rcstream) ...@@ -376,7 +377,8 @@ void parse_rcfile(FILE *rcstream)
) { ) {
if (*ptr == '\n' || *ptr == '\0') { if (*ptr == '\n' || *ptr == '\0') {
rcfile_error(_("option %s requires an argument"), rcfile_error(_
("option %s requires an argument"),
rcopts[i].name); rcopts[i].name);
continue; continue;
} }
...@@ -386,34 +388,40 @@ void parse_rcfile(FILE *rcstream) ...@@ -386,34 +388,40 @@ void parse_rcfile(FILE *rcstream)
#ifndef DISABLE_WRAPJUSTIFY #ifndef DISABLE_WRAPJUSTIFY
if ((i = atoi(option)) < MIN_FILL_LENGTH) { if ((i = atoi(option)) < MIN_FILL_LENGTH) {
rcfile_error( rcfile_error(_
_("requested fill size %d too small"), i); ("requested fill size %d too small"),
} i);
else } else
fill = i; fill = i;
#endif #endif
} else if (!strcasecmp(rcopts[i].name, "tabsize")) { } else
if (!strcasecmp(rcopts[i].name, "tabsize"))
{
if ((i = atoi(option)) <= 0) { if ((i = atoi(option)) <= 0) {
rcfile_error( rcfile_error(_
_("requested tab size %d too small"), i); ("requested tab size %d too small"),
i);
} else { } else {
tabsize = i; tabsize = i;
} }
} else { } else {
#ifndef DISABLE_SPELLER #ifndef DISABLE_SPELLER
alt_speller = charalloc(strlen(option) + 1); alt_speller =
charalloc(strlen(option) + 1);
strcpy(alt_speller, option); strcpy(alt_speller, option);
#endif #endif
} }
} else } else
SET(rcopts[i].flag); SET(rcopts[i].flag);
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, _("set flag %d!\n"), rcopts[i].flag); fprintf(stderr, _("set flag %d!\n"),
rcopts[i].flag);
#endif #endif
} else { } else {
UNSET(rcopts[i].flag); UNSET(rcopts[i].flag);
#ifdef DEBUG #ifdef DEBUG
fprintf(stderr, _("unset flag %d!\n"), rcopts[i].flag); fprintf(stderr, _("unset flag %d!\n"),
rcopts[i].flag);
#endif #endif
} }
} }
...@@ -462,4 +470,3 @@ void do_rcfile(void) ...@@ -462,4 +470,3 @@ void do_rcfile(void)
#endif /* ENABLE_NANORC */ #endif /* ENABLE_NANORC */
...@@ -774,10 +774,10 @@ void edit_add(filestruct * fileptr, int yval, int start, int virt_cur_x, ...@@ -774,10 +774,10 @@ void edit_add(filestruct * fileptr, int yval, int start, int virt_cur_x,
#ifdef ENABLE_COLOR #ifdef ENABLE_COLOR
colortype *tmpcolor = NULL; colortype *tmpcolor = NULL;
int k, paintlen; int k, paintlen;
filestruct *e, *s;
regoff_t ematch, smatch;
#endif #endif
/* Just paint the string in any case (we'll add color or reverse on /* Just paint the string in any case (we'll add color or reverse on
just the text that needs it */ just the text that needs it */
mvwaddnstr(edit, yval, 0, &fileptr->data[start], mvwaddnstr(edit, yval, 0, &fileptr->data[start],
...@@ -788,6 +788,9 @@ void edit_add(filestruct * fileptr, int yval, int start, int virt_cur_x, ...@@ -788,6 +788,9 @@ void edit_add(filestruct * fileptr, int yval, int start, int virt_cur_x,
for (tmpcolor = colorstrings; tmpcolor != NULL; for (tmpcolor = colorstrings; tmpcolor != NULL;
tmpcolor = tmpcolor->next) { tmpcolor = tmpcolor->next) {
if (tmpcolor->end == NULL) {
/* First, highlight all single-line regexes */
k = start; k = start;
regcomp(&search_regexp, tmpcolor->start, 0); regcomp(&search_regexp, tmpcolor->start, 0);
while (!regexec(&search_regexp, &fileptr->data[k], 1, while (!regexec(&search_regexp, &fileptr->data[k], 1,
...@@ -817,7 +820,6 @@ void edit_add(filestruct * fileptr, int yval, int start, int virt_cur_x, ...@@ -817,7 +820,6 @@ void edit_add(filestruct * fileptr, int yval, int start, int virt_cur_x,
&fileptr->data[k + regmatches[0].rm_so], &fileptr->data[k + regmatches[0].rm_so],
paintlen); paintlen);
} }
if (tmpcolor->bright) if (tmpcolor->bright)
...@@ -825,7 +827,106 @@ void edit_add(filestruct * fileptr, int yval, int start, int virt_cur_x, ...@@ -825,7 +827,106 @@ void edit_add(filestruct * fileptr, int yval, int start, int virt_cur_x,
wattroff(edit, COLOR_PAIR(tmpcolor->pairnum)); wattroff(edit, COLOR_PAIR(tmpcolor->pairnum));
k += regmatches[0].rm_eo; k += regmatches[0].rm_eo;
}
} }
/* Now, if there's an 'end' somewhere below, and a 'start'
somewhere above, things get really fun. We have to look
down for an end, make sure there's not a start before
the end after us, and then look up for a start,
and see if there's an end after the start, before us :) */
else {
s = fileptr;
while (s != NULL) {
regcomp(&search_regexp, tmpcolor->start, 0);
if (!regexec
(&search_regexp, s->data, 1, regmatches, 0))
break;
s = s->prev;
}
if (s != NULL) {
/* We found a start, mark it */
smatch = regmatches[0].rm_so;
e = s;
while (e != NULL && e != fileptr) {
regcomp(&search_regexp, tmpcolor->end, 0);
if (!regexec
(&search_regexp, e->data, 1, regmatches, 0))
break;
e = e->next;
}
if (e != fileptr)
continue; /* There's an end before us */
else { /* Keep looking for an end */
while (e != NULL) {
regcomp(&search_regexp, tmpcolor->end, 0);
if (!regexec
(&search_regexp, e->data, 1, regmatches,
0))
break;
e = e->next;
}
if (e == NULL)
continue; /* There's no start before the end :) */
else { /* Okay, we found an end, mark it! */
ematch = regmatches[0].rm_eo;
while (e != NULL) {
regcomp(&search_regexp, tmpcolor->end, 0);
if (!regexec
(&search_regexp, e->data, 1,
regmatches, 0))
break;
e = e->next;
}
if (e == NULL)
continue; /* No end, oh well :) */
/* Didn't find another end, we must be in the
middle of a highlighted bit */
if (tmpcolor->bright)
wattron(edit, A_BOLD);
wattron(edit, COLOR_PAIR(tmpcolor->pairnum));
if (s == fileptr && e == fileptr)
mvwaddnstr(edit, yval, start + smatch,
&fileptr->data[start + smatch],
ematch - smatch);
else if (s == fileptr)
mvwaddnstr(edit, yval, start + smatch,
&fileptr->data[start + smatch],
COLS - smatch);
else if (e == fileptr)
mvwaddnstr(edit, yval, start,
&fileptr->data[start],
ematch - start);
else
mvwaddnstr(edit, yval, start,
&fileptr->data[start],
COLS);
if (tmpcolor->bright)
wattroff(edit, A_BOLD);
wattroff(edit, COLOR_PAIR(tmpcolor->pairnum));
}
}
/* Else go to the next string, yahoo! =) */
}
}
} }
#endif /* ENABLE_COLOR */ #endif /* ENABLE_COLOR */
#ifndef NANO_SMALL #ifndef NANO_SMALL
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment