Refactor current line activation to new select view operation
[tig] / tig.c
diff --git a/tig.c b/tig.c
index 44fcb1b..a6447bf 100644 (file)
--- a/tig.c
+++ b/tig.c
@@ -1192,7 +1192,7 @@ struct view {
 
        /* Searching */
        char grep[SIZEOF_STR];  /* Search string */
-       regex_t regex;          /* Pre-compiled regex */
+       regex_t *regex;         /* Pre-compiled regex */
 
        /* If non-NULL, points to the view that opened this view. If this view
         * is closed tig will switch back to the parent view. */
@@ -1220,6 +1220,8 @@ struct view_ops {
        bool (*enter)(struct view *view, struct line *line);
        /* Search for regex in a line. */
        bool (*grep)(struct view *view, struct line *line);
+       /* Select line */
+       void (*select)(struct view *view, struct line *line);
 };
 
 static struct view_ops pager_ops;
@@ -1255,12 +1257,19 @@ static struct view views[] = {
 static bool
 draw_view_line(struct view *view, unsigned int lineno)
 {
+       struct line *line;
+
        assert(view_is_displayed(view));
 
        if (view->offset + lineno >= view->lines)
                return FALSE;
 
-       return view->ops->draw(view, &view->line[view->offset + lineno], lineno);
+       line = &view->line[view->offset + lineno];
+
+       if (view->offset + lineno == view->lineno)
+               view->ops->select(view, line);
+
+       return view->ops->draw(view, line, lineno);
 }
 
 static void
@@ -1680,16 +1689,20 @@ search_view(struct view *view, enum request request, const char *search)
 {
        int regex_err;
 
-       if (*view->grep) {
-               regfree(&view->regex);
+       if (view->regex) {
+               regfree(view->regex);
                *view->grep = 0;
+       } else {
+               view->regex = calloc(1, sizeof(*view->regex));
+               if (!view->regex)
+                       return;
        }
 
-       regex_err = regcomp(&view->regex, search, REG_EXTENDED);
+       regex_err = regcomp(view->regex, search, REG_EXTENDED);
        if (regex_err != 0) {
                char buf[SIZEOF_STR] = "unknown error";
 
-               regerror(regex_err, &view->regex, buf, sizeof(buf));
+               regerror(regex_err, view->regex, buf, sizeof(buf));
                report("Search failed: %s", buf);
                return;
        }
@@ -2205,15 +2218,6 @@ pager_draw(struct view *view, struct line *line, unsigned int lineno)
        wmove(view->win, lineno, 0);
 
        if (view->offset + lineno == view->lineno) {
-               if (type == LINE_COMMIT) {
-                       string_copy(view->ref, text + 7);
-                       string_copy(ref_commit, view->ref);
-
-               } else if (type == LINE_TREE_DIR || type == LINE_TREE_FILE) {
-                       string_ncopy(view->ref, text + STRING_SIZE("100644 blob "), 40);
-                       string_copy(ref_blob, view->ref);
-               }
-
                type = LINE_CURSOR;
                wchgat(view->win, -1, 0, type, NULL);
        }
@@ -2333,10 +2337,14 @@ add_pager_refs(struct view *view, struct line *line)
 
        if (!is_tag && view == VIEW(REQ_VIEW_DIFF)) {
 try_add_describe_ref:
+               /* Add <tag>-g<commit_id> "fake" reference. */
                if (!add_describe_ref(buf, &bufpos, commit_id, sep))
                        return;
        }
 
+       if (bufpos == 0)
+               return;
+
        if (!realloc_lines(view, view->line_size + 1))
                return;
 
@@ -2404,18 +2412,30 @@ pager_grep(struct view *view, struct line *line)
        if (!*text)
                return FALSE;
 
-       if (regexec(&view->regex, text, 1, &pmatch, 0) == REG_NOMATCH)
+       if (regexec(view->regex, text, 1, &pmatch, 0) == REG_NOMATCH)
                return FALSE;
 
        return TRUE;
 }
 
+static void
+pager_select(struct view *view, struct line *line)
+{
+       if (line->type == LINE_COMMIT) {
+               char *text = line->data;
+
+               string_copy(view->ref, text + 7);
+               string_copy(ref_commit, view->ref);
+       }
+}
+
 static struct view_ops pager_ops = {
        "line",
        pager_draw,
        pager_read,
        pager_enter,
        pager_grep,
+       pager_select,
 };
 
 
@@ -2555,7 +2575,7 @@ tree_enter(struct view *view, struct line *line)
                        size_t origlen = pathlen;
                        char *basename = data + SIZEOF_TREE_ATTR;
 
-                       if (string_format_from(opt_path, &pathlen, "%s/", basename)) {
+                       if (!string_format_from(opt_path, &pathlen, "%s/", basename)) {
                                opt_path[origlen] = 0;
                                return TRUE;
                        }
@@ -2595,12 +2615,24 @@ tree_enter(struct view *view, struct line *line)
        return TRUE;
 }
 
+static void
+tree_select(struct view *view, struct line *line)
+{
+       if (line->type == LINE_TREE_DIR || line->type == LINE_TREE_FILE) {
+               char *text = line->data;
+
+               string_ncopy(view->ref, text + STRING_SIZE("100644 blob "), 40);
+               string_copy(ref_blob, view->ref);
+       }
+}
+
 static struct view_ops tree_ops = {
        "file",
        pager_draw,
        tree_read,
        tree_enter,
        pager_grep,
+       tree_select,
 };
 
 static bool
@@ -2620,6 +2652,7 @@ static struct view_ops blob_ops = {
        blob_read,
        pager_enter,
        pager_grep,
+       pager_select,
 };
 
 
@@ -2654,8 +2687,6 @@ main_draw(struct view *view, struct line *line, unsigned int lineno)
        wmove(view->win, lineno, col);
 
        if (view->offset + lineno == view->lineno) {
-               string_copy(view->ref, commit->id);
-               string_copy(ref_commit, view->ref);
                type = LINE_CURSOR;
                wattrset(view->win, get_line_attr(type));
                wchgat(view->win, -1, 0, type, NULL);
@@ -2880,19 +2911,29 @@ main_grep(struct view *view, struct line *line)
                        return FALSE;
                }
 
-               if (regexec(&view->regex, text, 1, &pmatch, 0) != REG_NOMATCH)
+               if (regexec(view->regex, text, 1, &pmatch, 0) != REG_NOMATCH)
                        return TRUE;
        }
 
        return FALSE;
 }
 
+static void
+main_select(struct view *view, struct line *line)
+{
+       struct commit *commit = line->data;
+
+       string_copy(view->ref, commit->id);
+       string_copy(ref_commit, view->ref);
+}
+
 static struct view_ops main_ops = {
        "commit",
        main_draw,
        main_read,
        main_enter,
        main_grep,
+       main_select,
 };