diff options
Diffstat (limited to 'match.c')
| -rw-r--r-- | match.c | 69 |
1 files changed, 36 insertions, 33 deletions
@@ -844,37 +844,46 @@ match_t *get_named_capture(match_t *m, const char *name, size_t namelen) return NULL; } -void fprint_match(FILE *out, const char *file_start, match_t *m) +static inline void fputc_safe(FILE *out, char c, print_options_t *opts) +{ + (void)fputc(c, out); + if (c == '\n' && opts && opts->on_nl) { + opts->on_nl(out); + if (opts->replace_color) fprintf(out, "%s", opts->replace_color); + } +} + +void fprint_match(FILE *out, const char *file_start, match_t *m, print_options_t *opts) { if (m->pat->type == BP_REPLACE) { const char *text = m->pat->args.replace.text; const char *end = &text[m->pat->args.replace.len]; + if (opts && opts->replace_color) fprintf(out, "%s", opts->replace_color); // TODO: clean up the line numbering code for (const char *r = text; r < end; ) { // Capture substitution if (*r == '@' && r+1 < end && r[1] != '@') { - ++r; - + const char *next = r+1; // Retrieve the capture value: match_t *cap = NULL; - if (isdigit(*r)) { - int n = (int)strtol(r, (char**)&r, 10); + if (isdigit(*next)) { + int n = (int)strtol(next, (char**)&next, 10); cap = get_numbered_capture(m->children[0], n); } else { - const char *name = r, *end = after_name(r); + const char *name = next, *end = after_name(next); if (end > name) { cap = get_named_capture(m->children[0], name, (size_t)(end - name)); - r = end; - if (r < m->end && *r == ';') ++r; + next = end; + if (next < m->end && *next == ';') ++next; } } if (cap != NULL) { - fprint_match(out, file_start, cap); + fprint_match(out, file_start, cap, opts); + if (opts && opts->replace_color) fprintf(out, "%s", opts->replace_color); + r = next; continue; - } else { - --r; } } @@ -887,30 +896,19 @@ void fprint_match(FILE *out, const char *file_start, match_t *m) // the replacement text contains newlines, this may get weird. const char *line_start = m->start; while (line_start > file_start && line_start[-1] != '\n') --line_start; - char denter = *line_start == '\t' ? '\t' : ' '; - fputc('\n', out); - if (denter == ' ' || denter == '\t') { - for (const char *p = line_start; p && *p == denter && p < m->start; ++p) - fputc(denter, out); - } + fputc_safe(out, '\n', opts); + for (const char *p = line_start; p < m->start && (*p == ' ' || *p == '\t'); ++p) + fputc(*p, out); continue; } - const char *start = r; - char c = unescapechar(r, &r); - if (r > start) (void)fputc(c, out); - else (void)fputc('\\', out); - continue; - } else if (*r == '\n') { - (void)fputc('\n', out); - ++r; - continue; + fputc_safe(out, unescapechar(r, &r), opts); } else { - (void)fputc(*r, out); + fputc_safe(out, *r, opts); ++r; - continue; } } } else { + if (opts && opts->match_color) fprintf(out, "%s", opts->match_color); const char *prev = m->start; for (int i = 0; m->children && m->children[i]; i++) { match_t *child = m->children[i]; @@ -918,13 +916,18 @@ void fprint_match(FILE *out, const char *file_start, match_t *m) if (!(prev <= child->start && child->start <= m->end && prev <= child->end && child->end <= m->end)) continue; - if (child->start > prev) - fwrite(prev, sizeof(char), (size_t)(child->start - prev), out); - fprint_match(out, file_start, child); + if (child->start > prev) { + if (opts && opts->fprint_between) opts->fprint_between(out, prev, child->start, opts->match_color); + else fwrite(prev, sizeof(char), (size_t)(child->start - prev), out); + } + fprint_match(out, file_start, child, opts); + if (opts && opts->match_color) fprintf(out, "%s", opts->match_color); prev = child->end; } - if (m->end > prev) - fwrite(prev, sizeof(char), (size_t)(m->end - prev), out); + if (m->end > prev) { + if (opts && opts->fprint_between) opts->fprint_between(out, prev, m->end, opts->match_color); + else fwrite(prev, sizeof(char), (size_t)(m->end - prev), out); + } } } |
