return isalnum(ch) || ch == '_';
}
+static void output_color(struct grep_opt *opt, const void *data, size_t size,
+ const char *color)
+{
+ if (opt->color && color && color[0]) {
+ opt->output(opt, color, strlen(color));
+ opt->output(opt, data, size);
+ opt->output(opt, GIT_COLOR_RESET, strlen(GIT_COLOR_RESET));
+ } else
+ opt->output(opt, data, size);
+}
+
+static void output_sep(struct grep_opt *opt, char sign)
+{
+ if (opt->null_following_name)
+ opt->output(opt, "\0", 1);
+ else
+ output_color(opt, &sign, 1, opt->color_sep);
+}
+
static void show_name(struct grep_opt *opt, const char *name)
{
- opt->output(opt, name, strlen(name));
+ output_color(opt, name, strlen(name), opt->color_filename);
opt->output(opt, opt->null_following_name ? "\0" : "\n", 1);
}
-
-static int fixmatch(const char *pattern, char *line, int ignore_case, regmatch_t *match)
+static int fixmatch(const char *pattern, char *line, char *eol,
+ int ignore_case, regmatch_t *match)
{
char *hit;
+
if (ignore_case)
hit = strcasestr(line, pattern);
else
- hit = strstr(line, pattern);
+ hit = memmem(line, eol - line, pattern, strlen(pattern));
if (!hit) {
match->rm_so = match->rm_eo = -1;
again:
if (p->fixed)
- hit = !fixmatch(p->pattern, bol, p->ignore_case, pmatch);
+ hit = !fixmatch(p->pattern, bol, eol, p->ignore_case, pmatch);
else
hit = !regexec(&p->regexp, bol, 1, pmatch, eflags);
const char *name, unsigned lno, char sign)
{
int rest = eol - bol;
- char sign_str[1];
+ char *line_color = NULL;
- sign_str[0] = sign;
if (opt->pre_context || opt->post_context) {
if (opt->last_shown == 0) {
- if (opt->show_hunk_mark)
- opt->output(opt, "--\n", 3);
- else
- opt->show_hunk_mark = 1;
- } else if (lno > opt->last_shown + 1)
- opt->output(opt, "--\n", 3);
+ if (opt->show_hunk_mark) {
+ output_color(opt, "--", 2, opt->color_sep);
+ opt->output(opt, "\n", 1);
+ }
+ } else if (lno > opt->last_shown + 1) {
+ output_color(opt, "--", 2, opt->color_sep);
+ opt->output(opt, "\n", 1);
+ }
}
opt->last_shown = lno;
- if (opt->null_following_name)
- sign_str[0] = '\0';
if (opt->pathname) {
- opt->output(opt, name, strlen(name));
- opt->output(opt, sign_str, 1);
+ output_color(opt, name, strlen(name), opt->color_filename);
+ output_sep(opt, sign);
}
if (opt->linenum) {
char buf[32];
snprintf(buf, sizeof(buf), "%d", lno);
- opt->output(opt, buf, strlen(buf));
- opt->output(opt, sign_str, 1);
+ output_color(opt, buf, strlen(buf), opt->color_lineno);
+ output_sep(opt, sign);
}
if (opt->color) {
regmatch_t match;
int ch = *eol;
int eflags = 0;
+ if (sign == ':')
+ line_color = opt->color_selected;
+ else if (sign == '-')
+ line_color = opt->color_context;
+ else if (sign == '=')
+ line_color = opt->color_function;
*eol = '\0';
while (next_match(opt, bol, eol, ctx, &match, eflags)) {
if (match.rm_so == match.rm_eo)
break;
- opt->output(opt, bol, match.rm_so);
- opt->output(opt, opt->color_match,
- strlen(opt->color_match));
- opt->output(opt, bol + match.rm_so,
- (int)(match.rm_eo - match.rm_so));
- opt->output(opt, GIT_COLOR_RESET,
- strlen(GIT_COLOR_RESET));
+ output_color(opt, bol, match.rm_so, line_color);
+ output_color(opt, bol + match.rm_so,
+ match.rm_eo - match.rm_so,
+ opt->color_match);
bol += match.rm_eo;
rest -= match.rm_eo;
eflags = REG_NOTBOL;
}
*eol = ch;
}
- opt->output(opt, bol, rest);
+ output_color(opt, bol, rest, line_color);
opt->output(opt, "\n", 1);
}
int hit;
regmatch_t m;
- if (p->fixed)
- hit = !fixmatch(p->pattern, bol, p->ignore_case, &m);
- else {
+ if (p->fixed) {
+ hit = !fixmatch(p->pattern, bol, bol + *left_p,
+ p->ignore_case, &m);
+ } else {
#ifdef REG_STARTEND
m.rm_so = 0;
m.rm_eo = *left_p;
!opt->name_only)
return 0;
- /* If we are showing hunk marks, we should not do it for the
- * first match. The synchronization problem we get for this
- * constraint is not yet solved, so we disable threading in
- * this case.
- */
- if (opt->pre_context || opt->post_context)
- return 0;
-
return 1;
}
enum grep_context ctx = GREP_CONTEXT_HEAD;
xdemitconf_t xecfg;
- opt->last_shown = 0;
-
if (!opt->output)
opt->output = std_output;
- if (buffer_is_binary(buf, size)) {
- switch (opt->binary) {
- case GREP_BINARY_DEFAULT:
+ if (opt->last_shown && (opt->pre_context || opt->post_context) &&
+ opt->output == std_output)
+ opt->show_hunk_mark = 1;
+ opt->last_shown = 0;
+
+ switch (opt->binary) {
+ case GREP_BINARY_DEFAULT:
+ if (buffer_is_binary(buf, size))
binary_match_only = 1;
- break;
- case GREP_BINARY_NOMATCH:
+ break;
+ case GREP_BINARY_NOMATCH:
+ if (buffer_is_binary(buf, size))
return 0; /* Assume unmatch */
- break;
- default:
- break;
- }
+ break;
+ case GREP_BINARY_TEXT:
+ break;
+ default:
+ die("bug: unknown binary handling mode");
}
memset(&xecfg, 0, sizeof(xecfg));
count++;
if (opt->status_only)
return 1;
+ if (opt->name_only) {
+ show_name(opt, name);
+ return 1;
+ }
+ if (opt->count)
+ goto next_line;
if (binary_match_only) {
opt->output(opt, "Binary file ", 12);
- opt->output(opt, name, strlen(name));
+ output_color(opt, name, strlen(name),
+ opt->color_filename);
opt->output(opt, " matches\n", 9);
return 1;
}
- if (opt->name_only) {
- show_name(opt, name);
- return 1;
- }
/* Hit at this line. If we haven't shown the
* pre-context lines, we would need to show them.
- * When asked to do "count", this still show
- * the context which is nonsense, but the user
- * deserves to get that ;-).
*/
if (opt->pre_context)
show_pre_context(opt, name, buf, bol, lno);
else if (opt->funcname)
show_funcname_line(opt, name, buf, bol, lno);
- if (!opt->count)
- show_line(opt, bol, eol, name, lno, ':');
+ show_line(opt, bol, eol, name, lno, ':');
last_hit = lno;
}
else if (last_hit &&
*/
if (opt->count && count) {
char buf[32];
- opt->output(opt, name, strlen(name));
- snprintf(buf, sizeof(buf), "%c%u\n",
- opt->null_following_name ? '\0' : ':', count);
+ output_color(opt, name, strlen(name), opt->color_filename);
+ output_sep(opt, ':');
+ snprintf(buf, sizeof(buf), "%u\n", count);
opt->output(opt, buf, strlen(buf));
+ return 1;
}
return !!last_hit;
}