From bef366c86f7b8d44f53127142fe41f9632bd5728 Mon Sep 17 00:00:00 2001 From: Jonas Fonseca Date: Sun, 14 Jun 2015 15:31:38 -0400 Subject: [PATCH] Highlight search results --- NEWS.adoc | 1 + doc/tigrc.5.adoc | 1 + include/tig/line.h | 3 ++- include/tig/string.h | 5 +++-- include/tig/view.h | 1 + src/draw.c | 43 ++++++++++++++++++++++++++++++++++++++++--- src/search.c | 7 +++++-- src/string.c | 8 ++++---- tigrc | 1 + 9 files changed, 58 insertions(+), 12 deletions(-) diff --git a/NEWS.adoc b/NEWS.adoc index b3861ab..e3a1fe9 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -16,6 +16,7 @@ Improvements: Add `set mailmap = yes` to `~/.tigrc` to enable. (GH #411) - See `contrib/vim.tigrc` for Vim-like keybindings. (GH #273, #351) - Add GitHub inspired file finder to search for and open any file. (GH #342) + - Highlight search results, configurable via `search-result` color. - Add `search` keymap for navigation file finder search results. - Populate `%(file)` with file names from diff stat. (GH #404) - `tig --merge` implies `--boundary` similar to gitk. diff --git a/doc/tigrc.5.adoc b/doc/tigrc.5.adoc index d0e3293..eeb4aef 100644 --- a/doc/tigrc.5.adoc +++ b/doc/tigrc.5.adoc @@ -909,6 +909,7 @@ setting the *default* color option. |status |The status window showing info messages. |title-focus |The title window for the current view. |title-blur |The title window of any backgrounded view. +|search-result |Highlighted search result. |delimiter |Delimiter shown for truncated lines. |header |The view header lines. Use 'status.header' to color the staged, unstaged, and untracked sections in the diff --git a/include/tig/line.h b/include/tig/line.h index f4411d0..387d28a 100644 --- a/include/tig/line.h +++ b/include/tig/line.h @@ -88,7 +88,8 @@ struct ref; _(PALETTE_11, ""), \ _(PALETTE_12, ""), \ _(PALETTE_13, ""), \ - _(GRAPH_COMMIT, "") + _(GRAPH_COMMIT, ""), \ + _(SEARCH_RESULT, "") enum line_type { #define DEFINE_LINE_ENUM(type, line) LINE_##type diff --git a/include/tig/string.h b/include/tig/string.h index 68312f4..cd91b91 100644 --- a/include/tig/string.h +++ b/include/tig/string.h @@ -114,9 +114,10 @@ unsigned long utf8_to_unicode(const char *string, size_t length); * trailing character, which can be useful when drawing a delimiter. * * Returns the number of bytes to output from string to satisfy max_width. */ -size_t utf8_length(const char **start, size_t skip, int *width, size_t max_width, int *trimmed, bool reserve, int tab_size); +size_t utf8_length(const char **start, int max_bytes, size_t skip, int *width, size_t max_width, int *trimmed, bool reserve, int tab_size); -int utf8_width_max(const char *text, int max); +int utf8_width_of(const char *text, int max_bytes, int max_width); +#define utf8_width_max(text, width) utf8_width_of(text, -1, width) #define utf8_width(text) utf8_width_max(text, -1) #endif diff --git a/include/tig/view.h b/include/tig/view.h index a19626d..ded803e 100644 --- a/include/tig/view.h +++ b/include/tig/view.h @@ -37,6 +37,7 @@ struct line { unsigned int commit_title:1; unsigned int no_commit_refs:1; unsigned int graph_indent:1; + unsigned int search_result:1; void *data; /* User data */ }; diff --git a/src/draw.c b/src/draw.c index 1276d63..5c3fb33 100644 --- a/src/draw.c +++ b/src/draw.c @@ -62,7 +62,7 @@ draw_chars(struct view *view, enum line_type type, const char *string, if (max_len <= 0) return VIEW_MAX_LEN(view) <= 0; - len = utf8_length(&string, skip, &col, max_len, &trimmed, use_tilde, opt_tab_size); + len = utf8_length(&string, -1, skip, &col, max_len, &trimmed, use_tilde, opt_tab_size); if (opt_iconv_out != ICONV_NONE) { string = encoding_iconv(opt_iconv_out, string, len); @@ -137,7 +137,7 @@ draw_text_overflow(struct view *view, const char *text, enum line_type type, const char *tmp = text; int text_width = 0; int trimmed = false; - size_t len = utf8_length(&tmp, 0, &text_width, max, &trimmed, false, 1); + size_t len = utf8_length(&tmp, -1, 0, &text_width, max, &trimmed, false, 1); if (draw_text_expanded(view, type, text, text_width, max < overflow)) return true; @@ -570,11 +570,43 @@ view_column_draw(struct view *view, struct line *line, unsigned int lineno) return true; } +static void +draw_view_line_search_result(struct view *view, unsigned int lineno) +{ + size_t bufsize = view->width * 4; + char *buf = malloc(bufsize); + regmatch_t pmatch[1]; + int i; + + if (!buf || mvwinnstr(view->win, lineno, 0, buf, bufsize) == ERR || + regexec(view->regex, buf, ARRAY_SIZE(pmatch), pmatch, 0)) { + free(buf); + return; + } + + for (i = 0; i < ARRAY_SIZE(pmatch); i++) { + regoff_t start = pmatch[i].rm_so; + + if (start == -1) + continue; + + mvwchgat(view->win, lineno, + utf8_width_of(buf, start, -1), + utf8_width_of(buf + start, pmatch[i].rm_eo - start, -1), + get_view_attr(view, LINE_SEARCH_RESULT), + get_view_color(view, LINE_SEARCH_RESULT), + NULL); + } + + free(buf); +} + bool draw_view_line(struct view *view, unsigned int lineno) { struct line *line; bool selected = (view->pos.offset + lineno == view->pos.lineno); + bool ok; /* FIXME: Disabled during code split. assert(view_is_displayed(view)); @@ -600,7 +632,12 @@ draw_view_line(struct view *view, unsigned int lineno) view->ops->select(view, line); } - return view->ops->draw(view, line, lineno); + ok = view->ops->draw(view, line, lineno); + + if (ok && line->search_result && view->regex) + draw_view_line_search_result(view, lineno); + + return ok; } void diff --git a/src/search.c b/src/search.c index d2e7a4a..c64b4cf 100644 --- a/src/search.c +++ b/src/search.c @@ -21,11 +21,10 @@ DEFINE_ALLOCATOR(realloc_unsigned_ints, unsigned int, 32) bool grep_text(struct view *view, const char *text[]) { - regmatch_t pmatch; size_t i; for (i = 0; text[i]; i++) - if (*text[i] && !regexec(view->regex, text[i], 1, &pmatch, 0)) + if (*text[i] && !regexec(view->regex, text[i], 0, NULL, 0)) return true; return false; } @@ -44,9 +43,13 @@ find_matches(struct view *view) if (!realloc_unsigned_ints(&view->matched_line, view->matched_lines, 1)) return false; + view->line[lineno].search_result = true; view->matched_line[view->matched_lines++] = lineno; } + /* Clear and show highlighted results. */ + redraw_view_from(view, 0); + return true; } diff --git a/src/string.c b/src/string.c index c9c9b40..9d3b986 100644 --- a/src/string.c +++ b/src/string.c @@ -304,10 +304,10 @@ utf8_to_unicode(const char *string, size_t length) * * Returns the number of bytes to output from string to satisfy max_width. */ size_t -utf8_length(const char **start, size_t skip, int *width, size_t max_width, int *trimmed, bool reserve, int tab_size) +utf8_length(const char **start, int max_chars, size_t skip, int *width, size_t max_width, int *trimmed, bool reserve, int tab_size) { const char *string = *start; - const char *end = strchr(string, '\0'); + const char *end = max_chars < 0 ? strchr(string, '\0') : string + max_chars; unsigned char last_bytes = 0; size_t last_ucwidth = 0; @@ -359,13 +359,13 @@ utf8_length(const char **start, size_t skip, int *width, size_t max_width, int * } int -utf8_width_max(const char *text, int max) +utf8_width_of(const char *text, int max_bytes, int max_width) { int text_width = 0; const char *tmp = text; int trimmed = false; - utf8_length(&tmp, 0, &text_width, max, &trimmed, false, 1); + utf8_length(&tmp, max_bytes, 0, &text_width, max_width, &trimmed, false, 1); return text_width; } diff --git a/tigrc b/tigrc index 79e667a..540d5c3 100644 --- a/tigrc +++ b/tigrc @@ -382,6 +382,7 @@ color palette-11 default default bold color palette-12 white default bold color palette-13 red default bold color graph-commit blue default +color search-result black yellow # Mappings for colors read from git configuration. # Set to "no" to disable. -- 2.11.4.GIT