Make keybinding reference more dynamic
[tig] / tig.c
diff --git a/tig.c b/tig.c
index f5b9b8c..45e47b9 100644 (file)
--- a/tig.c
+++ b/tig.c
@@ -12,7 +12,7 @@
  */
 
 #ifndef        VERSION
-#define VERSION        "tig-0.6"
+#define VERSION        "tig-0.6.git"
 #endif
 
 #ifndef DEBUG
@@ -269,6 +269,9 @@ sq_quote(char buf[SIZEOF_STR], size_t bufsize, const char *src)
        }
        BUFPUT('\'');
 
+       if (bufsize < SIZEOF_STR)
+               buf[bufsize] = 0;
+
        return bufsize;
 }
 
@@ -867,7 +870,7 @@ get_key(enum request request)
        static char buf[BUFSIZ];
        static char key_char[] = "'X'";
        size_t pos = 0;
-       char *sep = "    ";
+       char *sep = "";
        int i;
 
        buf[pos] = 0;
@@ -1258,8 +1261,8 @@ static struct view views[] = {
        VIEW_(LOG,   "log",   &pager_ops, ref_head),
        VIEW_(TREE,  "tree",  &tree_ops,  ref_commit),
        VIEW_(BLOB,  "blob",  &blob_ops,  ref_blob),
-       VIEW_(HELP,  "help",  &pager_ops, "static"),
-       VIEW_(PAGER, "pager", &pager_ops, "static"),
+       VIEW_(HELP,  "help",  &pager_ops, ""),
+       VIEW_(PAGER, "pager", &pager_ops, ""),
 };
 
 #define VIEW(req) (&views[(req) - REQ_OFFSET - 1])
@@ -1622,7 +1625,8 @@ move_view(struct view *view, enum request request)
        }
 
        if (!view_is_displayed(view)) {
-               view->offset += steps;
+               view->offset += scroll_steps;
+               assert(0 <= view->offset && view->offset < view->lines);
                view->ops->select(view, &view->line[view->lineno]);
                return;
        }
@@ -1779,17 +1783,21 @@ begin_update(struct view *view)
        if (opt_cmd[0]) {
                string_copy(view->cmd, opt_cmd);
                opt_cmd[0] = 0;
-               /* When running random commands, the view ref could have become
-                * invalid so clear it. */
-               view->ref[0] = 0;
+               /* When running random commands, initially show the
+                * command in the title. However, it maybe later be
+                * overwritten if a commit line is selected. */
+               string_copy(view->ref, view->cmd);
 
        } else if (view == VIEW(REQ_VIEW_TREE)) {
                const char *format = view->cmd_env ? view->cmd_env : view->cmd_fmt;
+               char path[SIZEOF_STR];
 
                if (strcmp(view->vid, view->id))
-                       opt_path[0] = 0;
+                       opt_path[0] = path[0] = 0;
+               else if (sq_quote(path, 0, opt_path) >= sizeof(path))
+                       return FALSE;
 
-               if (!string_format(view->cmd, format, id, opt_path))
+               if (!string_format(view->cmd, format, id, path))
                        return FALSE;
 
        } else {
@@ -1797,6 +1805,12 @@ begin_update(struct view *view)
 
                if (!string_format(view->cmd, format, id, id, id, id, id))
                        return FALSE;
+
+               /* Put the current ref_* value to the view title ref
+                * member. This is needed by the blob view. Most other
+                * views sets it automatically after loading because the
+                * first line is a commit line. */
+               string_copy(view->ref, id);
        }
 
        /* Special case for the pager view. */
@@ -1927,6 +1941,12 @@ update_view(struct view *view)
                if (redraw_from > 0)
                        redraw_from--;
 
+               /* Since revision graph visualization requires knowledge
+                * about the parent commit, it causes a further one-off
+                * needed to be redrawn for incremental updates. */
+               if (redraw_from > 0 && opt_rev_graph)
+                       redraw_from--;
+
                /* Incrementally draw avoids flickering. */
                redraw_view_from(view, redraw_from);
        }
@@ -1956,6 +1976,24 @@ end:
        return FALSE;
 }
 
+static struct line *
+add_line_text(struct view *view, char *data, enum line_type type)
+{
+       struct line *line = &view->line[view->lines];
+
+       if (!data)
+               return NULL;
+
+       line->data = strdup(data);
+       if (!line->data)
+               return NULL;
+
+       line->type = type;
+       view->lines++;
+
+       return line;
+}
+
 
 /*
  * View opening
@@ -1980,22 +2018,22 @@ static void open_help_view(struct view *view)
                return;
        }
 
-       view->ops->read(view, "Quick reference for tig keybindings:");
+       add_line_text(view, "Quick reference for tig keybindings:", LINE_DEFAULT);
 
        for (i = 0; i < ARRAY_SIZE(req_info); i++) {
                char *key;
 
                if (!req_info[i].request) {
-                       view->ops->read(view, "");
-                       view->ops->read(view, req_info[i].help);
+                       add_line_text(view, "", LINE_DEFAULT);
+                       add_line_text(view, req_info[i].help, LINE_DEFAULT);
                        continue;
                }
 
                key = get_key(req_info[i].request);
-               if (!string_format(buf, "%-25s %s", key, req_info[i].help))
+               if (!string_format(buf, "    %-25s %s", key, req_info[i].help))
                        continue;
 
-               view->ops->read(view, buf);
+               add_line_text(view, buf, LINE_DEFAULT);
        }
 }
 
@@ -2110,7 +2148,8 @@ view_driver(struct view *view, enum request request)
 
        case REQ_VIEW_BLOB:
                if (!ref_blob[0]) {
-                       report("No file chosen, press 't' to open tree view");
+                       report("No file chosen, press %s to open tree view",
+                              get_key(REQ_VIEW_TREE));
                        break;
                }
                /* Fall-through */
@@ -2387,30 +2426,21 @@ try_add_describe_ref:
        if (!realloc_lines(view, view->line_size + 1))
                return;
 
-       line = &view->line[view->lines];
-       line->data = strdup(buf);
-       if (!line->data)
-               return;
-
-       line->type = LINE_PP_REFS;
-       view->lines++;
+       add_line_text(view, buf, LINE_PP_REFS);
 }
 
 static bool
 pager_read(struct view *view, char *data)
 {
-       struct line *line = &view->line[view->lines];
+       struct line *line;
 
        if (!data)
                return TRUE;
 
-       line->data = strdup(data);
-       if (!line->data)
+       line = add_line_text(view, data, get_line_type(data));
+       if (!line)
                return FALSE;
 
-       line->type = get_line_type(line->data);
-       view->lines++;
-
        if (line->type == LINE_COMMIT &&
            (view == VIEW(REQ_VIEW_DIFF) ||
             view == VIEW(REQ_VIEW_LOG)))
@@ -2464,10 +2494,11 @@ static void
 pager_select(struct view *view, struct line *line)
 {
        if (line->type == LINE_COMMIT) {
-               char *text = line->data;
+               char *text = line->data + STRING_SIZE("commit ");
 
-               string_copy(view->ref, text + STRING_SIZE("commit "));
-               string_copy(ref_commit, view->ref);
+               if (view != VIEW(REQ_VIEW_PAGER))
+                       string_copy(view->ref, text);
+               string_copy(ref_commit, text);
        }
 }
 
@@ -2528,21 +2559,18 @@ tree_read(struct view *view, char *text)
 
        if (first_read) {
                /* Add path info line */
-               if (string_format(buf, "Directory path /%s", opt_path) &&
-                   realloc_lines(view, view->line_size + 1) &&
-                   pager_read(view, buf))
-                       view->line[view->lines - 1].type = LINE_DEFAULT;
-               else
+               if (!string_format(buf, "Directory path /%s", opt_path) ||
+                   !realloc_lines(view, view->line_size + 1) ||
+                   !add_line_text(view, buf, LINE_DEFAULT))
                        return FALSE;
 
                /* Insert "link" to parent directory. */
-               if (*opt_path &&
-                   string_format(buf, TREE_UP_FORMAT, view->ref) &&
-                   realloc_lines(view, view->line_size + 1) &&
-                   pager_read(view, buf))
-                       view->line[view->lines - 1].type = LINE_TREE_DIR;
-               else if (*opt_path)
-                       return FALSE;
+               if (*opt_path) {
+                       if (!string_format(buf, TREE_UP_FORMAT, view->ref) ||
+                           !realloc_lines(view, view->line_size + 1) ||
+                           !add_line_text(view, buf, LINE_TREE_DIR))
+                               return FALSE;
+               }
        }
 
        /* Strip the path part ... */
@@ -2581,14 +2609,13 @@ tree_read(struct view *view, char *text)
                return TRUE;
        }
 
-       if (!pager_read(view, text))
+       if (!add_line_text(view, text, type))
                return FALSE;
 
        /* Move the current line to the first tree entry. */
        if (first_read)
                view->lineno++;
 
-       view->line[view->lines - 1].type = type;
        return TRUE;
 }
 
@@ -2646,15 +2673,10 @@ tree_enter(struct view *view, struct line *line)
 static void
 tree_select(struct view *view, struct line *line)
 {
-       char *text = line->data;
-
-       text += STRING_SIZE("100644 blob ");
+       char *text = line->data + STRING_SIZE("100644 blob ");
 
        if (line->type == LINE_TREE_FILE) {
                string_ncopy(ref_blob, text, 40);
-               /* Also update the blob view's ref, since all there must always
-                * be in sync. */
-               string_copy(VIEW(REQ_VIEW_BLOB)->ref, ref_blob);
 
        } else if (line->type != LINE_TREE_DIR) {
                return;
@@ -2675,12 +2697,7 @@ static struct view_ops tree_ops = {
 static bool
 blob_read(struct view *view, char *line)
 {
-       bool state = pager_read(view, line);
-
-       if (state == TRUE)
-               view->line[view->lines - 1].type = LINE_DEFAULT;
-
-       return state;
+       return add_line_text(view, line, LINE_DEFAULT);
 }
 
 static struct view_ops blob_ops = {