Code

Fix unbind behavoir
[tig.git] / tig.c
diff --git a/tig.c b/tig.c
index cd3428cc38c29f783bdbc12800f3dd5ad26d86bf..47daba930c2831d267ad6665e3d0660a8027c719 100644 (file)
--- a/tig.c
+++ b/tig.c
@@ -1166,7 +1166,8 @@ enum request {
 #define REQ_(req, help) REQ_##req
 
        /* Offset all requests to avoid conflicts with ncurses getch values. */
-       REQ_OFFSET = KEY_MAX + 1,
+       REQ_UNKNOWN = KEY_MAX + 1,
+       REQ_OFFSET,
        REQ_INFO
 
 #undef REQ_GROUP
@@ -1198,7 +1199,7 @@ get_request(const char *name)
                if (enum_equals(req_info[i], name, namelen))
                        return req_info[i].request;
 
-       return REQ_NONE;
+       return REQ_UNKNOWN;
 }
 
 
@@ -1404,7 +1405,7 @@ struct keybinding {
        enum request request;
 };
 
-static const struct keybinding default_keybindings[] = {
+static struct keybinding default_keybindings[] = {
        /* View switching */
        { 'm',          REQ_VIEW_MAIN },
        { 'd',          REQ_VIEW_DIFF },
@@ -1520,6 +1521,14 @@ add_keybinding(enum keymap keymap, enum request request, int key)
                die("Failed to allocate keybinding");
        table->data[table->size].alias = key;
        table->data[table->size++].request = request;
+
+       if (request == REQ_NONE && keymap == KEYMAP_GENERIC) {
+               int i;
+
+               for (i = 0; i < ARRAY_SIZE(default_keybindings); i++)
+                       if (default_keybindings[i].alias == key)
+                               default_keybindings[i].request = REQ_NONE;
+       }
 }
 
 /* Looks for a key binding first in the given map, then in the generic map, and
@@ -2005,7 +2014,7 @@ option_bind_command(int argc, const char *argv[])
        }
 
        request = get_request(argv[2]);
-       if (request == REQ_NONE) {
+       if (request == REQ_UNKNOWN) {
                static const struct enum_map obsolete[] = {
                        ENUM_MAP("cherry-pick",         REQ_NONE),
                        ENUM_MAP("screen-resize",       REQ_NONE),
@@ -2020,9 +2029,9 @@ option_bind_command(int argc, const char *argv[])
                        return ERR;
                }
        }
-       if (request == REQ_NONE && *argv[2]++ == '!')
+       if (request == REQ_UNKNOWN && *argv[2]++ == '!')
                request = add_run_request(keymap, key, argc - 2, argv + 2);
-       if (request == REQ_NONE) {
+       if (request == REQ_UNKNOWN) {
                config_msg = "Unknown request name";
                return ERR;
        }
@@ -2160,7 +2169,22 @@ static char ref_commit[SIZEOF_REF]       = "HEAD";
 static char ref_head[SIZEOF_REF]       = "HEAD";
 static char ref_branch[SIZEOF_REF]     = "";
 
+enum view_type {
+       VIEW_MAIN,
+       VIEW_DIFF,
+       VIEW_LOG,
+       VIEW_TREE,
+       VIEW_BLOB,
+       VIEW_BLAME,
+       VIEW_BRANCH,
+       VIEW_HELP,
+       VIEW_PAGER,
+       VIEW_STATUS,
+       VIEW_STAGE,
+};
+
 struct view {
+       enum view_type type;    /* View type */
        const char *name;       /* View name */
        const char *cmd_env;    /* Command line set via environment */
        const char *id;         /* Points to either of ref_{head,commit,blob} */
@@ -2169,6 +2193,7 @@ struct view {
 
        enum keymap keymap;     /* What keymap does this view have */
        bool git_dir;           /* Whether the view requires a git directory. */
+       bool refresh;           /* Whether the view supports refreshing. */
 
        char ref[SIZEOF_REF];   /* Hovered commit reference */
        char vid[SIZEOF_REF];   /* View ID. Set to id member when updating. */
@@ -2245,29 +2270,27 @@ static struct view_ops status_ops;
 static struct view_ops tree_ops;
 static struct view_ops branch_ops;
 
-#define VIEW_STR(name, env, ref, ops, map, git) \
-       { name, #env, ref, ops, map, git }
-
-#define VIEW_(id, name, ops, git, ref) \
-       VIEW_STR(name, TIG_##id##_CMD, ref, ops, KEYMAP_##id, git)
+#define VIEW_STR(type, name, env, ref, ops, map, git, refresh) \
+       { type, name, #env, ref, ops, map, git, refresh }
 
+#define VIEW_(id, name, ops, git, refresh, ref) \
+       VIEW_STR(VIEW_##id, name, TIG_##id##_CMD, ref, ops, KEYMAP_##id, git, refresh)
 
 static struct view views[] = {
-       VIEW_(MAIN,   "main",   &main_ops,   TRUE,  ref_head),
-       VIEW_(DIFF,   "diff",   &diff_ops,   TRUE,  ref_commit),
-       VIEW_(LOG,    "log",    &log_ops,    TRUE,  ref_head),
-       VIEW_(TREE,   "tree",   &tree_ops,   TRUE,  ref_commit),
-       VIEW_(BLOB,   "blob",   &blob_ops,   TRUE,  ref_blob),
-       VIEW_(BLAME,  "blame",  &blame_ops,  TRUE,  ref_commit),
-       VIEW_(BRANCH, "branch", &branch_ops, TRUE,  ref_head),
-       VIEW_(HELP,   "help",   &help_ops,   FALSE, ""),
-       VIEW_(PAGER,  "pager",  &pager_ops,  FALSE, "stdin"),
-       VIEW_(STATUS, "status", &status_ops, TRUE,  ""),
-       VIEW_(STAGE,  "stage",  &stage_ops,  TRUE,  ""),
+       VIEW_(MAIN,   "main",   &main_ops,   TRUE,  TRUE,  ref_head),
+       VIEW_(DIFF,   "diff",   &diff_ops,   TRUE,  FALSE, ref_commit),
+       VIEW_(LOG,    "log",    &log_ops,    TRUE,  TRUE,  ref_head),
+       VIEW_(TREE,   "tree",   &tree_ops,   TRUE,  FALSE, ref_commit),
+       VIEW_(BLOB,   "blob",   &blob_ops,   TRUE,  FALSE, ref_blob),
+       VIEW_(BLAME,  "blame",  &blame_ops,  TRUE,  FALSE, ref_commit),
+       VIEW_(BRANCH, "branch", &branch_ops, TRUE,  TRUE,  ref_head),
+       VIEW_(HELP,   "help",   &help_ops,   FALSE, FALSE, ""),
+       VIEW_(PAGER,  "pager",  &pager_ops,  FALSE, FALSE, "stdin"),
+       VIEW_(STATUS, "status", &status_ops, TRUE,  TRUE,  ""),
+       VIEW_(STAGE,  "stage",  &stage_ops,  TRUE,  TRUE,  ""),
 };
 
 #define VIEW(req)      (&views[(req) - REQ_OFFSET - 1])
-#define VIEW_REQ(view) ((view) - views + REQ_OFFSET + 1)
 
 #define foreach_view(view, i) \
        for (i = 0; i < ARRAY_SIZE(views) && (view = &views[i]); i++)
@@ -2275,6 +2298,8 @@ static struct view views[] = {
 #define view_is_displayed(view) \
        (view == display[0] || view == display[1])
 
+#define view_has_parent(view, child_type, parent_type) \
+       (view->type == child_type && view->parent && view->parent->type == parent_type)
 
 static inline void
 set_view_attr(struct view *view, enum line_type type)
@@ -2543,7 +2568,7 @@ update_view_title(struct view *view)
 
        assert(view_is_displayed(view));
 
-       if (view != VIEW(REQ_VIEW_STATUS) && view->lines) {
+       if (view->type != VIEW_STATUS && view->lines) {
                unsigned int view_lines = view->offset + view->height;
                unsigned int lines = view->lines
                                   ? MIN(view_lines, view->lines) * 100 / view->lines
@@ -3322,7 +3347,7 @@ update_view(struct view *view)
                /* Keep the displayed view in sync with line number scaling. */
                if (digits != view->digits) {
                        view->digits = digits;
-                       if (opt_line_number || view == VIEW(REQ_VIEW_BLAME))
+                       if (opt_line_number || view->type == VIEW_BLAME)
                                redraw = TRUE;
                }
        }
@@ -3559,11 +3584,7 @@ view_driver(struct view *view, enum request request)
        if (request > REQ_NONE) {
                open_run_request(request);
                /* FIXME: When all views can refresh always do this. */
-               if (view == VIEW(REQ_VIEW_STATUS) ||
-                   view == VIEW(REQ_VIEW_MAIN) ||
-                   view == VIEW(REQ_VIEW_LOG) ||
-                   view == VIEW(REQ_VIEW_BRANCH) ||
-                   view == VIEW(REQ_VIEW_STAGE))
+               if (view->refresh)
                        request = REQ_REFRESH;
                else
                        return TRUE;
@@ -3651,16 +3672,11 @@ view_driver(struct view *view, enum request request)
        case REQ_PREVIOUS:
                request = request == REQ_NEXT ? REQ_MOVE_DOWN : REQ_MOVE_UP;
 
-               if ((view == VIEW(REQ_VIEW_DIFF) &&
-                    view->parent == VIEW(REQ_VIEW_MAIN)) ||
-                  (view == VIEW(REQ_VIEW_DIFF) &&
-                    view->parent == VIEW(REQ_VIEW_BLAME)) ||
-                  (view == VIEW(REQ_VIEW_STAGE) &&
-                    view->parent == VIEW(REQ_VIEW_STATUS)) ||
-                  (view == VIEW(REQ_VIEW_BLOB) &&
-                    view->parent == VIEW(REQ_VIEW_TREE)) ||
-                  (view == VIEW(REQ_VIEW_MAIN) &&
-                    view->parent == VIEW(REQ_VIEW_BRANCH))) {
+               if (view_has_parent(view, VIEW_DIFF, VIEW_MAIN) ||
+                   view_has_parent(view, VIEW_DIFF, VIEW_BLAME) ||
+                   view_has_parent(view, VIEW_STAGE, VIEW_STATUS) ||
+                   view_has_parent(view, VIEW_BLOB, VIEW_TREE) ||
+                   view_has_parent(view, VIEW_MAIN, VIEW_BRANCH)) {
                        int line;
 
                        view = view->parent;
@@ -3742,8 +3758,7 @@ view_driver(struct view *view, enum request request)
                break;
 
        case REQ_STOP_LOADING:
-               for (i = 0; i < ARRAY_SIZE(views); i++) {
-                       view = &views[i];
+               foreach_view(view, i) {
                        if (view->pipe)
                                report("Stopped loading the %s view", view->name),
                        end_update(view, TRUE);
@@ -4036,7 +4051,7 @@ add_pager_refs(struct view *view, struct line *line)
 
        list = get_ref_list(commit_id);
        if (!list) {
-               if (view == VIEW(REQ_VIEW_DIFF))
+               if (view->type == VIEW_DIFF)
                        goto try_add_describe_ref;
                return;
        }
@@ -4053,7 +4068,7 @@ add_pager_refs(struct view *view, struct line *line)
                        is_tag = TRUE;
        }
 
-       if (!is_tag && view == VIEW(REQ_VIEW_DIFF)) {
+       if (!is_tag && view->type == VIEW_DIFF) {
 try_add_describe_ref:
                /* Add <tag>-g<commit_id> "fake" reference. */
                if (!add_describe_ref(buf, &bufpos, commit_id, sep))
@@ -4079,8 +4094,8 @@ pager_read(struct view *view, char *data)
                return FALSE;
 
        if (line->type == LINE_COMMIT &&
-           (view == VIEW(REQ_VIEW_DIFF) ||
-            view == VIEW(REQ_VIEW_LOG)))
+           (view->type == VIEW_DIFF ||
+            view->type == VIEW_LOG))
                add_pager_refs(view, line);
 
        return TRUE;
@@ -4095,8 +4110,8 @@ pager_request(struct view *view, enum request request, struct line *line)
                return request;
 
        if (line->type == LINE_COMMIT &&
-          (view == VIEW(REQ_VIEW_LOG) ||
-           view == VIEW(REQ_VIEW_PAGER))) {
+          (view->type == VIEW_LOG ||
+           view->type == VIEW_PAGER)) {
                open_view(view, REQ_VIEW_DIFF, OPEN_SPLIT);
                split = 1;
        }
@@ -4129,7 +4144,7 @@ pager_select(struct view *view, struct line *line)
        if (line->type == LINE_COMMIT) {
                char *text = (char *)line->data + STRING_SIZE("commit ");
 
-               if (view != VIEW(REQ_VIEW_PAGER))
+               if (view->type != VIEW_PAGER)
                        string_copy_rev(view->ref, text);
                string_copy_rev(ref_commit, text);
        }
@@ -7803,6 +7818,10 @@ main(int argc, const char *argv[])
                /* Some low-level request handling. This keeps access to
                 * status_win restricted. */
                switch (request) {
+               case REQ_NONE:
+                       report("Unknown key, press %s for help",
+                              get_key(view->keymap, REQ_VIEW_HELP));
+                       break;
                case REQ_PROMPT:
                {
                        char *cmd = read_prompt(":");