Code

Add specialized open methods for each view
[tig.git] / tig.c
diff --git a/tig.c b/tig.c
index f022f17a974b2424f32e6c729a191f6672ac2792..c971ff754476630cbb858e6f9659ebf081cd9a19 100644 (file)
--- a/tig.c
+++ b/tig.c
@@ -1115,7 +1115,7 @@ parse_string(char *opt, const char *arg, size_t optsize)
 static enum option_code
 parse_args(const char ***args, const char *argv[])
 {
-       if (!argv_copy(args, argv))
+       if (*args == NULL && !argv_copy(args, argv))
                return OPT_ERR_OUT_OF_MEMORY;
        return OPT_OK;
 }
@@ -1127,15 +1127,15 @@ option_set_command(int argc, const char *argv[])
        if (argc < 3)
                return OPT_ERR_WRONG_NUMBER_OF_ARGUMENTS;
 
-       if (!opt_blame_argv && !strcmp(argv[0], "blame-options"))
+       if (strcmp(argv[1], "="))
+               return OPT_ERR_NO_VALUE_ASSIGNED;
+
+       if (!strcmp(argv[0], "blame-options"))
                return parse_args(&opt_blame_argv, argv + 2);
 
        if (argc != 3)
                return OPT_ERR_WRONG_NUMBER_OF_ARGUMENTS;
 
-       if (strcmp(argv[1], "="))
-               return OPT_ERR_NO_VALUE_ASSIGNED;
-
        if (!strcmp(argv[0], "show-author"))
                return parse_enum(&opt_author, argv[2], author_map);
 
@@ -1378,7 +1378,6 @@ enum view_type {
 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} */
 
        struct view_ops *ops;   /* View operations */
@@ -1430,13 +1429,19 @@ struct view {
        time_t update_secs;
 };
 
+enum open_flags {
+       OPEN_DEFAULT = 0,       /* Use default view switching. */
+       OPEN_SPLIT = 1,         /* Split current view. */
+       OPEN_RELOAD = 4,        /* Reload view even if it is the current. */
+       OPEN_REFRESH = 16,      /* Refresh view using previous command. */
+       OPEN_PREPARED = 32,     /* Open already prepared command. */
+};
+
 struct view_ops {
        /* What type of content being displayed. Used in the title bar. */
        const char *type;
-       /* Default command arguments. */
-       const char **argv;
        /* Open and reads in all view content. */
-       bool (*open)(struct view *view);
+       bool (*open)(struct view *view, enum open_flags flags);
        /* Read one line; updates view->line. */
        bool (*read)(struct view *view, char *data);
        /* Draw one line; @lineno must be < view->height. */
@@ -1447,8 +1452,6 @@ struct view_ops {
        bool (*grep)(struct view *view, struct line *line);
        /* Select line */
        void (*select)(struct view *view, struct line *line);
-       /* Prepare view for loading */
-       bool (*prepare)(struct view *view);
 };
 
 static struct view_ops blame_ops;
@@ -1463,11 +1466,11 @@ static struct view_ops status_ops;
 static struct view_ops tree_ops;
 static struct view_ops branch_ops;
 
-#define VIEW_STR(type, name, env, ref, ops, map, git) \
-       { type, name, #env, ref, ops, map, git }
+#define VIEW_STR(type, name, ref, ops, map, git) \
+       { type, name, ref, ops, map, git }
 
 #define VIEW_(id, name, ops, git, ref) \
-       VIEW_STR(VIEW_##id, name, TIG_##id##_CMD, ref, ops, KEYMAP_##id, git)
+       VIEW_STR(VIEW_##id, name, ref, ops, KEYMAP_##id, git)
 
 static struct view views[] = {
        VIEW_(MAIN,   "main",   &main_ops,   TRUE,  ref_head),
@@ -1514,6 +1517,8 @@ set_view_attr(struct view *view, enum line_type type)
        }
 }
 
+#define VIEW_MAX_LEN(view) ((view)->width + (view)->yoffset - (view)->col)
+
 static int
 draw_chars(struct view *view, enum line_type type, const char *string,
           int max_len, bool use_tilde)
@@ -1585,18 +1590,18 @@ draw_text(struct view *view, enum line_type type, const char *string)
        do {
                size_t pos = string_expand(text, sizeof(text), string, opt_tab_size);
 
-               view->col += draw_chars(view, type, text, view->width + view->yoffset - view->col, TRUE);
+               view->col += draw_chars(view, type, text, VIEW_MAX_LEN(view), TRUE);
                string += pos;
-       } while (*string && view->width + view->yoffset > view->col);
+       } while (*string && VIEW_MAX_LEN(view) > 0);
 
-       return view->width + view->yoffset <= view->col;
+       return VIEW_MAX_LEN(view) <= 0;
 }
 
 static bool
 draw_graphic(struct view *view, enum line_type type, const chtype graphic[], size_t size, bool separator)
 {
        size_t skip = view->yoffset > view->col ? view->yoffset - view->col : 0;
-       int max = view->width + view->yoffset - view->col;
+       int max = VIEW_MAX_LEN(view);
        int i;
 
        if (max < size)
@@ -1615,13 +1620,13 @@ draw_graphic(struct view *view, enum line_type type, const chtype graphic[], siz
                view->col++;
        }
 
-       return view->width + view->yoffset <= view->col;
+       return VIEW_MAX_LEN(view) <= 0;
 }
 
 static bool
 draw_field(struct view *view, enum line_type type, const char *text, int len, bool trim)
 {
-       int max = MIN(view->width + view->yoffset - view->col, len);
+       int max = MIN(VIEW_MAX_LEN(view), len);
        int col;
 
        if (text)
@@ -1631,7 +1636,7 @@ draw_field(struct view *view, enum line_type type, const char *text, int len, bo
 
        view->col += col;
        view->col += draw_space(view, LINE_DEFAULT, max - col, max - col);
-       return view->width + view->yoffset <= view->col;
+       return VIEW_MAX_LEN(view) <= 0;
 }
 
 static bool
@@ -1681,7 +1686,7 @@ draw_lineno(struct view *view, unsigned int lineno)
 {
        char number[10];
        int digits3 = view->digits < 3 ? 3 : view->digits;
-       int max = MIN(view->width + view->yoffset - view->col, digits3);
+       int max = MIN(VIEW_MAX_LEN(view), digits3);
        char *text = NULL;
        chtype separator = opt_line_graphics ? ACS_VLINE : '|';
 
@@ -2521,18 +2526,20 @@ prepare_update_file(struct view *view, const char *name)
 }
 
 static bool
-begin_update(struct view *view, bool refresh)
+begin_update(struct view *view, const char *dir, const char **argv, enum open_flags flags)
 {
+       bool reload = !!(flags & (OPEN_RELOAD | OPEN_REFRESH | OPEN_PREPARED));
+       bool refresh = flags & (OPEN_REFRESH | OPEN_PREPARED);
+
+       if (!reload && !strcmp(view->vid, view->id))
+               return TRUE;
+
        if (view->pipe)
                end_update(view, TRUE);
 
        if (!refresh) {
-               if (view->ops->prepare) {
-                       if (!view->ops->prepare(view))
-                               return FALSE;
-               } else if (!prepare_io(view, NULL, view->ops->argv, TRUE)) {
+               if (!prepare_io(view, dir, argv, TRUE))
                        return FALSE;
-               }
 
                /* Put the current ref_* value to the view title ref
                 * member. This is needed by the blob view. Most other
@@ -2550,6 +2557,12 @@ begin_update(struct view *view, bool refresh)
        return TRUE;
 }
 
+static bool
+view_open(struct view *view, enum open_flags flags)
+{
+       return begin_update(view, NULL, NULL, flags);
+}
+
 static bool
 update_view(struct view *view)
 {
@@ -2686,14 +2699,6 @@ add_line_format(struct view *view, enum line_type type, const char *fmt, ...)
  * View opening
  */
 
-enum open_flags {
-       OPEN_DEFAULT = 0,       /* Use default view switching. */
-       OPEN_SPLIT = 1,         /* Split current view. */
-       OPEN_RELOAD = 4,        /* Reload view even if it is the current. */
-       OPEN_REFRESH = 16,      /* Refresh view using previous command. */
-       OPEN_PREPARED = 32,     /* Open already prepared command. */
-};
-
 static void
 open_view(struct view *prev, enum request request, enum open_flags flags)
 {
@@ -2739,16 +2744,11 @@ open_view(struct view *prev, enum request request, enum open_flags flags)
        if (view->ops->open) {
                if (view->pipe)
                        end_update(view, TRUE);
-               if (!view->ops->open(view)) {
+               if (!view->ops->open(view, flags)) {
                        report("Failed to load %s view", view->name);
                        return;
                }
                restore_view_position(view);
-
-       } else if ((reload || strcmp(view->vid, view->id)) &&
-                  !begin_update(view, flags & (OPEN_REFRESH | OPEN_PREPARED))) {
-               report("Failed to load %s view", view->name);
-               return;
        }
 
        if (split && prev->lineno - prev->offset >= prev->height) {
@@ -3332,8 +3332,7 @@ pager_select(struct view *view, struct line *line)
 
 static struct view_ops pager_ops = {
        "line",
-       NULL,
-       NULL,
+       view_open,
        pager_read,
        pager_draw,
        pager_request,
@@ -3341,9 +3340,15 @@ static struct view_ops pager_ops = {
        pager_select,
 };
 
-static const char *log_argv[SIZEOF_ARG] = {
-       "git", "log", "--no-color", "--cc", "--stat", "-n100", "%(head)", NULL
-};
+static bool
+log_open(struct view *view, enum open_flags flags)
+{
+       static const char *log_argv[] = {
+               "git", "log", "--no-color", "--cc", "--stat", "-n100", "%(head)", NULL
+       };
+
+       return begin_update(view, NULL, log_argv, flags);
+}
 
 static enum request
 log_request(struct view *view, enum request request, struct line *line)
@@ -3360,8 +3365,7 @@ log_request(struct view *view, enum request request, struct line *line)
 
 static struct view_ops log_ops = {
        "line",
-       log_argv,
-       NULL,
+       log_open,
        pager_read,
        pager_draw,
        log_request,
@@ -3369,11 +3373,17 @@ static struct view_ops log_ops = {
        pager_select,
 };
 
-static const char *diff_argv[SIZEOF_ARG] = {
-       "git", "show", "--pretty=fuller", "--no-color", "--root",
-               "--patch-with-stat", "--find-copies-harder", "-C",
-               "%(diffargs)", "%(commit)", "--", "%(fileargs)", NULL
-};
+static bool
+diff_open(struct view *view, enum open_flags flags)
+{
+       static const char *diff_argv[] = {
+               "git", "show", "--pretty=fuller", "--no-color", "--root",
+                       "--patch-with-stat", "--find-copies-harder", "-C",
+                       "%(diffargs)", "%(commit)", "--", "%(fileargs)", NULL
+       };
+
+       return begin_update(view, NULL, diff_argv, flags);
+}
 
 static bool
 diff_read(struct view *view, char *data)
@@ -3404,8 +3414,7 @@ diff_read(struct view *view, char *data)
 
 static struct view_ops diff_ops = {
        "line",
-       diff_argv,
-       NULL,
+       diff_open,
        diff_read,
        pager_draw,
        pager_request,
@@ -3501,7 +3510,7 @@ help_open_keymap(struct view *view, enum keymap keymap)
 }
 
 static bool
-help_open(struct view *view)
+help_open(struct view *view, enum open_flags flags)
 {
        enum keymap keymap;
 
@@ -3535,7 +3544,6 @@ help_request(struct view *view, enum request request, struct line *line)
 
 static struct view_ops help_ops = {
        "line",
-       NULL,
        help_open,
        NULL,
        pager_draw,
@@ -3972,8 +3980,12 @@ tree_select(struct view *view, struct line *line)
 }
 
 static bool
-tree_prepare(struct view *view)
+tree_open(struct view *view, enum open_flags flags)
 {
+       static const char *tree_argv[] = {
+               "git", "ls-tree", "%(commit)", "%(directory)", NULL
+       };
+
        if (view->lines == 0 && opt_prefix[0]) {
                char *pos = opt_prefix;
 
@@ -3994,25 +4006,29 @@ tree_prepare(struct view *view)
                opt_path[0] = 0;
        }
 
-       return prepare_io(view, opt_cdup, view->ops->argv, TRUE);
+       return begin_update(view, opt_cdup, tree_argv, flags);
 }
 
-static const char *tree_argv[SIZEOF_ARG] = {
-       "git", "ls-tree", "%(commit)", "%(directory)", NULL
-};
-
 static struct view_ops tree_ops = {
        "file",
-       tree_argv,
-       NULL,
+       tree_open,
        tree_read,
        tree_draw,
        tree_request,
        tree_grep,
        tree_select,
-       tree_prepare,
 };
 
+static bool
+blob_open(struct view *view, enum open_flags flags)
+{
+       static const char *blob_argv[] = {
+               "git", "cat-file", "blob", "%(blob)", NULL
+       };
+
+       return begin_update(view, NULL, blob_argv, flags);
+}
+
 static bool
 blob_read(struct view *view, char *line)
 {
@@ -4033,14 +4049,9 @@ blob_request(struct view *view, enum request request, struct line *line)
        }
 }
 
-static const char *blob_argv[SIZEOF_ARG] = {
-       "git", "cat-file", "blob", "%(blob)", NULL
-};
-
 static struct view_ops blob_ops = {
        "line",
-       blob_argv,
-       NULL,
+       blob_open,
        blob_read,
        pager_draw,
        blob_request,
@@ -4076,7 +4087,7 @@ struct blame {
 };
 
 static bool
-blame_open(struct view *view)
+blame_open(struct view *view, enum open_flags flags)
 {
        char path[SIZEOF_STR];
        size_t i;
@@ -4484,7 +4495,6 @@ blame_select(struct view *view, struct line *line)
 
 static struct view_ops blame_ops = {
        "line",
-       NULL,
        blame_open,
        blame_read,
        blame_draw,
@@ -4641,7 +4651,7 @@ branch_open_visitor(void *data, const struct ref *ref)
 }
 
 static bool
-branch_open(struct view *view)
+branch_open(struct view *view, enum open_flags flags)
 {
        const char *branch_log[] = {
                "git", "log", "--no-color", "--pretty=raw",
@@ -4687,7 +4697,6 @@ branch_select(struct view *view, struct line *line)
 
 static struct view_ops branch_ops = {
        "branch",
-       NULL,
        branch_open,
        branch_read,
        branch_draw,
@@ -4939,7 +4948,7 @@ status_update_onbranch(void)
  * info using git-diff-files(1), and finally untracked files using
  * git-ls-files(1). */
 static bool
-status_open(struct view *view)
+status_open(struct view *view, enum open_flags flags)
 {
        reset_view(view);
 
@@ -5454,7 +5463,6 @@ status_grep(struct view *view, struct line *line)
 
 static struct view_ops status_ops = {
        "file",
-       NULL,
        status_open,
        NULL,
        status_draw,
@@ -5692,8 +5700,7 @@ stage_request(struct view *view, enum request request, struct line *line)
 
 static struct view_ops stage_ops = {
        "line",
-       NULL,
-       NULL,
+       view_open,
        pager_read,
        pager_draw,
        stage_request,
@@ -5784,11 +5791,17 @@ struct commit {
        struct graph_canvas graph;      /* Ancestry chain graphics. */
 };
 
-static const char *main_argv[SIZEOF_ARG] = {
-       "git", "log", "--no-color", "--pretty=raw", "--parents",
-               "--topo-order", "%(diffargs)", "%(revargs)",
-               "--", "%(fileargs)", NULL
-};
+static bool
+main_open(struct view *view, enum open_flags flags)
+{
+       static const char *main_argv[] = {
+               "git", "log", "--no-color", "--pretty=raw", "--parents",
+                       "--topo-order", "%(diffargs)", "%(revargs)",
+                       "--", "%(fileargs)", NULL
+       };
+
+       return begin_update(view, NULL, main_argv, flags);
+}
 
 static bool
 main_draw(struct view *view, struct line *line, unsigned int lineno)
@@ -5991,8 +6004,7 @@ main_select(struct view *view, struct line *line)
 
 static struct view_ops main_ops = {
        "commit",
-       main_argv,
-       NULL,
+       main_open,
        main_read,
        main_draw,
        main_request,
@@ -6874,7 +6886,6 @@ main(int argc, const char *argv[])
        const char *codeset = "UTF-8";
        enum request request = parse_options(argc, argv);
        struct view *view;
-       size_t i;
 
        signal(SIGINT, quit);
        signal(SIGPIPE, SIG_IGN);
@@ -6911,16 +6922,6 @@ main(int argc, const char *argv[])
        if (load_refs() == ERR)
                die("Failed to load refs.");
 
-       foreach_view (view, i) {
-               if (getenv(view->cmd_env))
-                       warn("Use of the %s environment variable is deprecated,"
-                            " use options or TIG_DIFF_ARGS instead",
-                            view->cmd_env);
-               if (!argv_from_env(view->ops->argv, view->cmd_env))
-                       die("Too many arguments in the `%s` environment variable",
-                           view->cmd_env);
-       }
-
        init_display();
 
        while (view_driver(display[current_view], request)) {