aboutsummaryrefslogtreecommitdiff
path: root/match.c
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2021-09-23 20:51:04 -0700
committerBruce Hill <bruce@bruce-hill.com>2021-09-23 20:51:04 -0700
commit3a2492d584e3c7d4cada1386921d80ace33c1fd2 (patch)
treec644006290392edf5da2d3e85c41feef40d81f22 /match.c
parentfddba4c54f3ce21e711cc2cd931ce5c4cad660b9 (diff)
WIP: working line breaks, formatting, etc. All seems functional, but a
bit messy
Diffstat (limited to 'match.c')
-rw-r--r--match.c69
1 files changed, 36 insertions, 33 deletions
diff --git a/match.c b/match.c
index 29db8c6..870b4d0 100644
--- a/match.c
+++ b/match.c
@@ -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);
+ }
}
}