index 9250cd7013e7c26b8187ce09c2ead6233bc61f87..3ae55f23d78d87b0f2ad3bcec9d9f8591862913f 100644 (file)
--- a/tig.c
+++ b/tig.c
static const char **opt_diff_argv = NULL;
static const char **opt_rev_argv = NULL;
static const char **opt_file_argv = NULL;
static const char **opt_diff_argv = NULL;
static const char **opt_rev_argv = NULL;
static const char **opt_file_argv = NULL;
+static const char **opt_blame_argv = NULL;
#define is_initial_commit() (!get_ref_head())
#define is_head_commit(rev) (!strcmp((rev), "HEAD") || (get_ref_head() && !strcmp(rev, get_ref_head()->id)))
#define is_initial_commit() (!get_ref_head())
#define is_head_commit(rev) (!strcmp((rev), "HEAD") || (get_ref_head() && !strcmp(rev, get_ref_head()->id)))
OPT_ERR_(NO_OPTION_VALUE, "No option value"), \
OPT_ERR_(NO_VALUE_ASSIGNED, "No value assigned"), \
OPT_ERR_(OBSOLETE_REQUEST_NAME, "Obsolete request name"), \
OPT_ERR_(NO_OPTION_VALUE, "No option value"), \
OPT_ERR_(NO_VALUE_ASSIGNED, "No value assigned"), \
OPT_ERR_(OBSOLETE_REQUEST_NAME, "Obsolete request name"), \
+ OPT_ERR_(OUT_OF_MEMORY, "Out of memory"), \
OPT_ERR_(TOO_MANY_OPTION_ARGUMENTS, "Too many option arguments"), \
OPT_ERR_(UNKNOWN_ATTRIBUTE, "Unknown attribute"), \
OPT_ERR_(UNKNOWN_COLOR, "Unknown color"), \
OPT_ERR_(TOO_MANY_OPTION_ARGUMENTS, "Too many option arguments"), \
OPT_ERR_(UNKNOWN_ATTRIBUTE, "Unknown attribute"), \
OPT_ERR_(UNKNOWN_COLOR, "Unknown color"), \
}
}
}
}
+static enum option_code
+parse_args(const char ***args, const char *argv[])
+{
+ if (*args == NULL && !argv_copy(args, argv))
+ return OPT_ERR_OUT_OF_MEMORY;
+ return OPT_OK;
+}
+
/* Wants: name = value */
static enum option_code
option_set_command(int argc, const char *argv[])
{
/* Wants: name = value */
static enum option_code
option_set_command(int argc, const char *argv[])
{
- if (argc != 3)
+ if (argc < 3)
return OPT_ERR_WRONG_NUMBER_OF_ARGUMENTS;
if (strcmp(argv[1], "="))
return OPT_ERR_NO_VALUE_ASSIGNED;
return OPT_ERR_WRONG_NUMBER_OF_ARGUMENTS;
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[0], "show-author"))
return parse_enum(&opt_author, argv[2], author_map);
if (!strcmp(argv[0], "show-author"))
return parse_enum(&opt_author, argv[2], author_map);
struct view {
enum view_type type; /* View type */
const char *name; /* View name */
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 */
const char *id; /* Points to either of ref_{head,commit,blob} */
struct view_ops *ops; /* View operations */
time_t update_secs;
};
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;
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. */
/* 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. */
/* Read one line; updates view->line. */
bool (*read)(struct view *view, char *data);
/* Draw one line; @lineno must be < view->height. */
bool (*grep)(struct view *view, struct line *line);
/* Select line */
void (*select)(struct view *view, struct line *line);
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;
};
static struct view_ops blame_ops;
static struct view_ops tree_ops;
static struct view_ops branch_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) \
#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),
static struct view views[] = {
VIEW_(MAIN, "main", &main_ops, TRUE, ref_head),
}
}
}
}
-static int
+#define VIEW_MAX_LEN(view) ((view)->width + (view)->yoffset - (view)->col)
+
+static bool
draw_chars(struct view *view, enum line_type type, const char *string,
int max_len, bool use_tilde)
{
draw_chars(struct view *view, enum line_type type, const char *string,
int max_len, bool use_tilde)
{
size_t skip = view->yoffset > view->col ? view->yoffset - view->col : 0;
if (max_len <= 0)
size_t skip = view->yoffset > view->col ? view->yoffset - view->col : 0;
if (max_len <= 0)
- return 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, skip, &col, max_len, &trimmed, use_tilde, opt_tab_size);
}
}
}
}
- return col;
+ view->col += col;
+ return VIEW_MAX_LEN(view) <= 0;
}
}
-static int
+static bool
draw_space(struct view *view, enum line_type type, int max, int spaces)
{
static char space[] = " ";
draw_space(struct view *view, enum line_type type, int max, int spaces)
{
static char space[] = " ";
- int col = 0;
spaces = MIN(max, spaces);
while (spaces > 0) {
int len = MIN(spaces, sizeof(space) - 1);
spaces = MIN(max, spaces);
while (spaces > 0) {
int len = MIN(spaces, sizeof(space) - 1);
- col += draw_chars(view, type, space, len, FALSE);
+ if (draw_chars(view, type, space, len, FALSE))
+ return TRUE;
spaces -= len;
}
spaces -= len;
}
- return col;
+ return VIEW_MAX_LEN(view) <= 0;
}
static bool
}
static bool
do {
size_t pos = string_expand(text, sizeof(text), string, opt_tab_size);
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);
+ if (draw_chars(view, type, text, VIEW_MAX_LEN(view), TRUE))
+ return TRUE;
string += pos;
string += pos;
- } while (*string && view->width + view->yoffset > view->col);
+ } while (*string);
- 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;
}
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)
int i;
if (max < size)
@@ -1599,23 +1622,20 @@ draw_graphic(struct view *view, enum line_type type, const chtype graphic[], siz
view->col++;
}
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)
{
}
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 col;
+ int max = MIN(VIEW_MAX_LEN(view), len);
+ int col = view->col;
- if (text)
- col = draw_chars(view, type, text, max - 1, trim);
- else
- col = draw_space(view, type, max - 1, max - 1);
+ if (!text)
+ return draw_space(view, type, max, max);
- view->col += col;
- view->col += draw_space(view, LINE_DEFAULT, max - col, max - col);
- return view->width + view->yoffset <= view->col;
+ return draw_chars(view, type, text, max - 1, trim)
+ || draw_space(view, LINE_DEFAULT, max - (view->col - col), max);
}
static bool
}
static bool
const char *date = mkdate(time, opt_date);
int cols = opt_date == DATE_SHORT ? DATE_SHORT_COLS : DATE_COLS;
const char *date = mkdate(time, opt_date);
int cols = opt_date == DATE_SHORT ? DATE_SHORT_COLS : DATE_COLS;
+ if (opt_date == DATE_NO)
+ return FALSE;
+
return draw_field(view, LINE_DATE, date, cols, FALSE);
}
return draw_field(view, LINE_DATE, date, cols, FALSE);
}
bool trim = opt_author_cols == 0 || opt_author_cols > 5;
bool abbreviate = opt_author == AUTHOR_ABBREVIATED || !trim;
bool trim = opt_author_cols == 0 || opt_author_cols > 5;
bool abbreviate = opt_author == AUTHOR_ABBREVIATED || !trim;
+ if (opt_author == AUTHOR_NO)
+ return FALSE;
+
if (abbreviate && author)
author = get_author_initials(author);
if (abbreviate && author)
author = get_author_initials(author);
{
char number[10];
int digits3 = view->digits < 3 ? 3 : view->digits;
{
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 : '|';
char *text = NULL;
chtype separator = opt_line_graphics ? ACS_VLINE : '|';
text = number;
}
if (text)
text = number;
}
if (text)
- view->col += draw_chars(view, LINE_LINE_NUMBER, text, max, TRUE);
+ draw_chars(view, LINE_LINE_NUMBER, text, max, TRUE);
else
else
- view->col += draw_space(view, LINE_LINE_NUMBER, max, digits3);
+ draw_space(view, LINE_LINE_NUMBER, max, digits3);
return draw_graphic(view, LINE_DEFAULT, &separator, 1, TRUE);
}
return draw_graphic(view, LINE_DEFAULT, &separator, 1, TRUE);
}
}
static void
}
static void
-maximize_view(struct view *view)
+maximize_view(struct view *view, bool redraw)
{
memset(display, 0, sizeof(display));
current_view = 0;
display[current_view] = view;
resize_display();
{
memset(display, 0, sizeof(display));
current_view = 0;
display[current_view] = view;
resize_display();
- redraw_display(FALSE);
- report("");
+ if (redraw) {
+ redraw_display(FALSE);
+ report("");
+ }
}
}
}
static bool
}
static bool
-format_argv(const char ***dst_argv, const char *src_argv[], bool replace, bool first)
+format_argv(const char ***dst_argv, const char *src_argv[], bool first)
{
char buf[SIZEOF_STR];
int argc;
{
char buf[SIZEOF_STR];
int argc;
@@ -2383,6 +2411,11 @@ format_argv(const char ***dst_argv, const char *src_argv[], bool replace, bool f
break;
continue;
break;
continue;
+ } else if (!strcmp(arg, "%(blameargs)")) {
+ if (!argv_append_array(dst_argv, opt_blame_argv))
+ break;
+ continue;
+
} else if (!strcmp(arg, "%(revargs)") ||
(first && !strcmp(arg, "%(commit)"))) {
if (!argv_append_array(dst_argv, opt_rev_argv))
} else if (!strcmp(arg, "%(revargs)") ||
(first && !strcmp(arg, "%(commit)"))) {
if (!argv_append_array(dst_argv, opt_rev_argv))
@@ -2395,7 +2428,7 @@ format_argv(const char ***dst_argv, const char *src_argv[], bool replace, bool f
int len = next - arg;
const char *value;
int len = next - arg;
const char *value;
- if (!next || !replace) {
+ if (!next) {
len = strlen(arg);
value = "";
len = strlen(arg);
value = "";
@@ -2410,7 +2443,7 @@ format_argv(const char ***dst_argv, const char *src_argv[], bool replace, bool f
if (!string_format_from(buf, &bufpos, "%.*s%s", len, arg, value))
return FALSE;
if (!string_format_from(buf, &bufpos, "%.*s%s", len, arg, value))
return FALSE;
- arg = next && replace ? strchr(next, ')') + 1 : NULL;
+ arg = next ? strchr(next, ')') + 1 : NULL;
}
if (!argv_append(dst_argv, buf))
}
if (!argv_append(dst_argv, buf))
}
static bool
}
static bool
-prepare_io(struct view *view, const char *dir, const char *argv[], bool replace)
-{
- view->dir = dir;
- return format_argv(&view->argv, argv, replace, !view->prev);
-}
-
-static bool
-prepare_update(struct view *view, const char *argv[], const char *dir)
+prepare_update(struct view *view, const char *dir, const char *argv[])
{
if (view->pipe)
{
if (view->pipe)
- end_update(view, TRUE);
- return prepare_io(view, dir, argv, FALSE);
+ io_done(view->pipe);
+ view->dir = dir;
+ return argv_copy(&view->argv, argv);
}
static bool
start_update(struct view *view, const char **argv, const char *dir)
{
}
static bool
start_update(struct view *view, const char **argv, const char *dir)
{
- if (view->pipe)
- io_done(view->pipe);
- return prepare_io(view, dir, argv, FALSE) &&
+ return prepare_update(view, dir, argv) &&
io_run(&view->io, IO_RD, dir, view->argv);
}
static bool
io_run(&view->io, IO_RD, dir, view->argv);
}
static bool
-prepare_update_file(struct view *view, const char *name)
+begin_update(struct view *view, const char *dir, const char **argv, enum open_flags flags)
{
{
- if (view->pipe)
- end_update(view, TRUE);
- argv_free(view->argv);
- return io_open(&view->io, "%s/%s", opt_cdup[0] ? opt_cdup : ".", name);
-}
+ 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;
-static bool
-begin_update(struct view *view, bool refresh)
-{
if (view->pipe)
end_update(view, TRUE);
if (!refresh) {
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)) {
+ view->dir = dir;
+ if (!format_argv(&view->argv, argv, !view->prev))
return FALSE;
return FALSE;
- }
/* Put the current ref_* value to the view title ref
* member. This is needed by the blob view. Most other
/* Put the current ref_* value to the view title ref
* member. This is needed by the blob view. Most other
return TRUE;
}
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)
{
static bool
update_view(struct view *view)
{
@@ -2665,23 +2690,63 @@ add_line_format(struct view *view, enum line_type type, const char *fmt, ...)
* View opening
*/
* 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
+load_view(struct view *view, enum open_flags flags)
+{
+ if (view->pipe)
+ end_update(view, TRUE);
+ if (!view->ops->open(view, flags)) {
+ report("Failed to load %s view", view->name);
+ return;
+ }
+ restore_view_position(view);
+
+ if (view->pipe && view->lines == 0) {
+ /* Clear the old view and let the incremental updating refill
+ * the screen. */
+ werase(view->win);
+ view->p_restore = flags & (OPEN_RELOAD | OPEN_REFRESH);
+ report("");
+ } else if (view_is_displayed(view)) {
+ redraw_view(view);
+ report("");
+ }
+}
+
+#define refresh_view(view) load_view(view, OPEN_REFRESH)
+
+static void
+split_view(struct view *prev, struct view *view)
+{
+ display[1] = view;
+ current_view = 1;
+ view->parent = prev;
+ resize_display();
+
+ if (prev->lineno - prev->offset >= prev->height) {
+ /* Take the title line into account. */
+ int lines = prev->lineno - prev->offset - prev->height + 1;
+
+ /* Scroll the view that was split if the current line is
+ * outside the new limited view. */
+ do_scroll_view(prev, lines);
+ }
+
+ if (view != prev && view_is_displayed(prev)) {
+ /* "Blur" the previous view. */
+ update_view_title(prev);
+ }
+}
static void
open_view(struct view *prev, enum request request, enum open_flags flags)
{
bool split = !!(flags & OPEN_SPLIT);
static void
open_view(struct view *prev, enum request request, enum open_flags flags)
{
bool split = !!(flags & OPEN_SPLIT);
- bool reload = !!(flags & (OPEN_RELOAD | OPEN_REFRESH | OPEN_PREPARED));
- bool nomaximize = !!(flags & OPEN_REFRESH);
+ bool reload = !!(flags & (OPEN_RELOAD | OPEN_PREPARED));
struct view *view = VIEW(request);
int nviews = displayed_views();
struct view *view = VIEW(request);
int nviews = displayed_views();
- struct view *base_view = display[0];
+
+ assert(flags ^ OPEN_REFRESH);
if (view == prev && nviews == 1 && !reload) {
report("Already in %s view", view->name);
if (view == prev && nviews == 1 && !reload) {
report("Already in %s view", view->name);
}
if (split) {
}
if (split) {
- display[1] = view;
- current_view = 1;
- view->parent = prev;
- } else if (!nomaximize) {
- /* Maximize the current view. */
- memset(display, 0, sizeof(display));
- current_view = 0;
- display[current_view] = view;
+ split_view(prev, view);
+ } else {
+ maximize_view(view, FALSE);
}
/* No prev signals that this is the first loaded view. */
}
/* No prev signals that this is the first loaded view. */
view->prev = prev;
}
view->prev = prev;
}
- /* Resize the view when switching between split- and full-screen,
- * or when switching between two different full-screen views. */
- if (nviews != displayed_views() ||
- (nviews == 1 && base_view != display[0]))
- resize_display();
-
- if (view->ops->open) {
- if (view->pipe)
- end_update(view, TRUE);
- if (!view->ops->open(view)) {
- 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;
- }
+ load_view(view, flags);
+}
- if (split && prev->lineno - prev->offset >= prev->height) {
- /* Take the title line into account. */
- int lines = prev->lineno - prev->offset - prev->height + 1;
+static void
+open_argv(struct view *prev, struct view *view, const char *argv[], const char *dir, enum open_flags flags)
+{
+ enum request request = view - views + REQ_OFFSET + 1;
- /* Scroll the view that was split if the current line is
- * outside the new limited view. */
- do_scroll_view(prev, lines);
+ if (!prepare_update(view, dir, argv)) {
+ report("Failed to open %s view: %s", view->name, io_strerror(&view->io));
+ } else {
+ open_view(prev, request, flags | OPEN_PREPARED);
}
}
+}
- if (prev && view != prev && split && view_is_displayed(prev)) {
- /* "Blur" the previous view. */
- update_view_title(prev);
- }
+static void
+open_file(struct view *prev, struct view *view, const char *file, enum open_flags flags)
+{
+ enum request request = view - views + REQ_OFFSET + 1;
+ const char *file_argv[] = { opt_cdup, file , NULL };
- if (view->pipe && view->lines == 0) {
- /* Clear the old view and let the incremental updating refill
- * the screen. */
- werase(view->win);
- view->p_restore = flags & (OPEN_RELOAD | OPEN_REFRESH);
- report("");
- } else if (view_is_displayed(view)) {
- redraw_view(view);
- report("");
+ if (view->pipe)
+ end_update(view, TRUE);
+ view->dir = opt_cdup;
+ if (!argv_copy(&view->argv, file_argv)) {
+ report("Failed to load %s: out of memory", file);
+ } else {
+ open_view(prev, request, flags | OPEN_PREPARED);
}
}
}
}
return;
}
return;
}
- if (format_argv(&argv, req->argv, TRUE, FALSE))
+ if (format_argv(&argv, req->argv, FALSE))
open_external_viewer(argv, NULL);
if (argv)
argv_free(argv);
open_external_viewer(argv, NULL);
if (argv)
argv_free(argv);
case REQ_MAXIMIZE:
if (displayed_views() == 2)
case REQ_MAXIMIZE:
if (displayed_views() == 2)
- maximize_view(view);
+ maximize_view(view, TRUE);
break;
case REQ_OPTIONS:
break;
case REQ_OPTIONS:
* view itself. Parents to closed view should never be
* followed. */
if (view->prev && view->prev != view) {
* view itself. Parents to closed view should never be
* followed. */
if (view->prev && view->prev != view) {
- maximize_view(view->prev);
+ maximize_view(view->prev, TRUE);
view->prev = view;
break;
}
view->prev = view;
break;
}
static struct view_ops pager_ops = {
"line",
static struct view_ops pager_ops = {
"line",
- NULL,
- NULL,
+ view_open,
pager_read,
pager_draw,
pager_request,
pager_read,
pager_draw,
pager_request,
pager_select,
};
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)
static enum request
log_request(struct view *view, enum request request, struct line *line)
switch (request) {
case REQ_REFRESH:
load_refs();
switch (request) {
case REQ_REFRESH:
load_refs();
- open_view(view, REQ_VIEW_LOG, OPEN_REFRESH);
+ refresh_view(view);
return REQ_NONE;
default:
return pager_request(view, request, line);
return REQ_NONE;
default:
return pager_request(view, request, line);
static struct view_ops log_ops = {
"line",
static struct view_ops log_ops = {
"line",
- log_argv,
- NULL,
+ log_open,
pager_read,
pager_draw,
log_request,
pager_read,
pager_draw,
log_request,
pager_select,
};
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)
static bool
diff_read(struct view *view, char *data)
static struct view_ops diff_ops = {
"line",
static struct view_ops diff_ops = {
"line",
- diff_argv,
- NULL,
+ diff_open,
diff_read,
pager_draw,
pager_request,
diff_read,
pager_draw,
pager_request,
}
static bool
}
static bool
-help_open(struct view *view)
+help_open(struct view *view, enum open_flags flags)
{
enum keymap keymap;
{
enum keymap keymap;
if (line->type == LINE_HELP_KEYMAP) {
help_keymap_hidden[line->other] =
!help_keymap_hidden[line->other];
if (line->type == LINE_HELP_KEYMAP) {
help_keymap_hidden[line->other] =
!help_keymap_hidden[line->other];
- view->p_restore = TRUE;
- open_view(view, REQ_VIEW_HELP, OPEN_REFRESH);
+ refresh_view(view);
}
return REQ_NONE;
}
return REQ_NONE;
static struct view_ops help_ops = {
"line",
static struct view_ops help_ops = {
"line",
- NULL,
help_open,
NULL,
pager_draw,
help_open,
NULL,
pager_draw,
if (draw_mode(view, entry->mode))
return TRUE;
if (draw_mode(view, entry->mode))
return TRUE;
- if (opt_author && draw_author(view, entry->author))
+ if (draw_author(view, entry->author))
return TRUE;
return TRUE;
- if (opt_date && draw_date(view, &entry->time))
+ if (draw_date(view, &entry->time))
return TRUE;
}
return TRUE;
}
}
static bool
}
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;
if (view->lines == 0 && opt_prefix[0]) {
char *pos = opt_prefix;
opt_path[0] = 0;
}
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",
static struct view_ops tree_ops = {
"file",
- tree_argv,
- NULL,
+ tree_open,
tree_read,
tree_draw,
tree_request,
tree_grep,
tree_select,
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)
{
static bool
blob_read(struct view *view, char *line)
{
}
}
}
}
-static const char *blob_argv[SIZEOF_ARG] = {
- "git", "cat-file", "blob", "%(blob)", NULL
-};
-
static struct view_ops blob_ops = {
"line",
static struct view_ops blob_ops = {
"line",
- blob_argv,
- NULL,
+ blob_open,
blob_read,
pager_draw,
blob_request,
blob_read,
pager_draw,
blob_request,
};
static bool
};
static bool
-blame_open(struct view *view)
+blame_open(struct view *view, enum open_flags flags)
{
char path[SIZEOF_STR];
size_t i;
{
char path[SIZEOF_STR];
size_t i;
{
if (!line) {
const char *blame_argv[] = {
{
if (!line) {
const char *blame_argv[] = {
- "git", "blame", "--incremental",
+ "git", "blame", "%(blameargs)", "--incremental",
*opt_ref ? opt_ref : "--incremental", "--", opt_file, NULL
};
*opt_ref ? opt_ref : "--incremental", "--", opt_file, NULL
};
time = &blame->commit->time;
}
time = &blame->commit->time;
}
- if (opt_date && draw_date(view, time))
+ if (draw_date(view, time))
return TRUE;
return TRUE;
- if (opt_author && draw_author(view, author))
+ if (draw_author(view, author))
return TRUE;
if (draw_field(view, LINE_BLAME_ID, id, ID_COLS, FALSE))
return TRUE;
if (draw_field(view, LINE_BLAME_ID, id, ID_COLS, FALSE))
string_copy(opt_file, blame->commit->filename);
if (blame->lineno)
view->lineno = blame->lineno;
string_copy(opt_file, blame->commit->filename);
if (blame->lineno)
view->lineno = blame->lineno;
- open_view(view, REQ_VIEW_BLAME, OPEN_REFRESH);
+ refresh_view(view);
}
break;
}
break;
string_copy_rev(opt_ref, blame->commit->parent_id);
string_copy(opt_file, blame->commit->parent_filename);
setup_blame_parent_line(view, blame);
string_copy_rev(opt_ref, blame->commit->parent_id);
string_copy(opt_file, blame->commit->parent_filename);
setup_blame_parent_line(view, blame);
- open_view(view, REQ_VIEW_BLAME, OPEN_REFRESH);
+ refresh_view(view);
}
break;
}
break;
diff_index_argv[7] = "/dev/null";
}
diff_index_argv[7] = "/dev/null";
}
- if (!prepare_update(diff, diff_index_argv, NULL)) {
- report("Failed to allocate diff command");
- break;
- }
- flags |= OPEN_PREPARED;
+ open_argv(view, diff, diff_index_argv, NULL, flags);
+ } else {
+ open_view(view, REQ_VIEW_DIFF, flags);
}
}
-
- open_view(view, REQ_VIEW_DIFF, flags);
if (VIEW(REQ_VIEW_DIFF)->pipe && !strcmp(blame->commit->id, NULL_ID))
string_copy_rev(VIEW(REQ_VIEW_DIFF)->ref, NULL_ID);
break;
if (VIEW(REQ_VIEW_DIFF)->pipe && !strcmp(blame->commit->id, NULL_ID))
string_copy_rev(VIEW(REQ_VIEW_DIFF)->ref, NULL_ID);
break;
static struct view_ops blame_ops = {
"line",
static struct view_ops blame_ops = {
"line",
- NULL,
blame_open,
blame_read,
blame_draw,
blame_open,
blame_read,
blame_draw,
struct branch *branch = line->data;
enum line_type type = branch->ref->head ? LINE_MAIN_HEAD : LINE_DEFAULT;
struct branch *branch = line->data;
enum line_type type = branch->ref->head ? LINE_MAIN_HEAD : LINE_DEFAULT;
- if (opt_date && draw_date(view, &branch->time))
+ if (draw_date(view, &branch->time))
return TRUE;
return TRUE;
- if (opt_author && draw_author(view, branch->author))
+ if (draw_author(view, branch->author))
return TRUE;
draw_text(view, type, branch->ref == &branch_all ? "All branches" : branch->ref->name);
return TRUE;
draw_text(view, type, branch->ref == &branch_all ? "All branches" : branch->ref->name);
switch (request) {
case REQ_REFRESH:
load_refs();
switch (request) {
case REQ_REFRESH:
load_refs();
- open_view(view, REQ_VIEW_BRANCH, OPEN_REFRESH);
+ refresh_view(view);
return REQ_NONE;
case REQ_TOGGLE_SORT_FIELD:
return REQ_NONE;
case REQ_TOGGLE_SORT_FIELD:
};
struct view *main_view = VIEW(REQ_VIEW_MAIN);
};
struct view *main_view = VIEW(REQ_VIEW_MAIN);
- if (!prepare_update(main_view, all_branches_argv, NULL))
- report("Failed to load view of all branches");
- else
- open_view(view, REQ_VIEW_MAIN, OPEN_PREPARED | OPEN_SPLIT);
+ open_argv(view, main_view, all_branches_argv, NULL, OPEN_SPLIT);
return REQ_NONE;
}
default:
return REQ_NONE;
}
default:
}
static bool
}
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",
{
const char *branch_log[] = {
"git", "log", "--no-color", "--pretty=raw",
static struct view_ops branch_ops = {
"branch",
static struct view_ops branch_ops = {
"branch",
- NULL,
branch_open,
branch_read,
branch_draw,
branch_open,
branch_read,
branch_draw,
* info using git-diff-files(1), and finally untracked files using
* git-ls-files(1). */
static bool
* 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);
{
reset_view(view);
return TRUE;
}
return TRUE;
}
-static enum request
-status_load_error(struct view *view, struct view *stage, const char *path)
-{
- if (displayed_views() == 2 || display[current_view] != view)
- maximize_view(view);
- report("Failed to load '%s': %s", path, io_strerror(&stage->io));
- return REQ_NONE;
-}
-
static enum request
status_enter(struct view *view, struct line *line)
{
static enum request
status_enter(struct view *view, struct line *line)
{
* path, so leave it empty. */
const char *newpath = status && status->status != 'U' ? status->new.name : NULL;
const char *info;
* path, so leave it empty. */
const char *newpath = status && status->status != 'U' ? status->new.name : NULL;
const char *info;
- enum open_flags split;
+ enum open_flags flags = view_is_displayed(view) ? OPEN_SPLIT : OPEN_DEFAULT;
struct view *stage = VIEW(REQ_VIEW_STAGE);
if (line->type == LINE_STAT_NONE ||
struct view *stage = VIEW(REQ_VIEW_STAGE);
if (line->type == LINE_STAT_NONE ||
"--", "/dev/null", newpath, NULL
};
"--", "/dev/null", newpath, NULL
};
- if (!prepare_update(stage, no_head_diff_argv, opt_cdup))
- return status_load_error(view, stage, newpath);
+ open_argv(view, stage, no_head_diff_argv, opt_cdup, flags);
} else {
const char *index_show_argv[] = {
"git", "diff-index", "--root", "--patch-with-stat",
} else {
const char *index_show_argv[] = {
"git", "diff-index", "--root", "--patch-with-stat",
oldpath, newpath, NULL
};
oldpath, newpath, NULL
};
- if (!prepare_update(stage, index_show_argv, opt_cdup))
- return status_load_error(view, stage, newpath);
+ open_argv(view, stage, index_show_argv, opt_cdup, flags);
}
if (status)
}
if (status)
"-C", "-M", "--", oldpath, newpath, NULL
};
"-C", "-M", "--", oldpath, newpath, NULL
};
- if (!prepare_update(stage, files_show_argv, opt_cdup))
- return status_load_error(view, stage, newpath);
+ open_argv(view, stage, files_show_argv, opt_cdup, flags);
if (status)
info = "Unstaged changes to %s";
else
if (status)
info = "Unstaged changes to %s";
else
return REQ_NONE;
}
return REQ_NONE;
}
- if (!prepare_update_file(stage, newpath))
- return status_load_error(view, stage, newpath);
+ open_file(view, stage, newpath, flags);
info = "Untracked file %s";
break;
info = "Untracked file %s";
break;
die("line type %d not handled in switch", line->type);
}
die("line type %d not handled in switch", line->type);
}
- split = view_is_displayed(view) ? OPEN_SPLIT : OPEN_DEFAULT;
- open_view(view, REQ_VIEW_STAGE, OPEN_PREPARED | split);
if (view_is_displayed(VIEW(REQ_VIEW_STAGE))) {
if (status) {
stage_status = *status;
if (view_is_displayed(VIEW(REQ_VIEW_STAGE))) {
if (status) {
stage_status = *status;
return request;
}
return request;
}
- open_view(view, REQ_VIEW_STATUS, OPEN_RELOAD);
+ refresh_view(view);
return REQ_NONE;
}
return REQ_NONE;
}
static struct view_ops status_ops = {
"file",
static struct view_ops status_ops = {
"file",
- NULL,
status_open,
NULL,
status_draw,
status_open,
NULL,
status_draw,
return request;
}
return request;
}
- VIEW(REQ_VIEW_STATUS)->p_restore = TRUE;
- open_view(view, REQ_VIEW_STATUS, OPEN_REFRESH);
+ refresh_view(view->parent);
/* Check whether the staged entry still exists, and close the
* stage view if it doesn't. */
/* Check whether the staged entry still exists, and close the
* stage view if it doesn't. */
return REQ_VIEW_CLOSE;
}
return REQ_VIEW_CLOSE;
}
- if (stage_line_type == LINE_STAT_UNTRACKED) {
- if (!suffixcmp(stage_status.new.name, -1, "/")) {
- report("Cannot display a directory");
- return REQ_NONE;
- }
-
- if (!prepare_update_file(view, stage_status.new.name)) {
- report("Failed to open file: %s", strerror(errno));
- return REQ_NONE;
- }
- }
- open_view(view, REQ_VIEW_STAGE, OPEN_REFRESH);
+ refresh_view(view);
return REQ_NONE;
}
static struct view_ops stage_ops = {
"line",
return REQ_NONE;
}
static struct view_ops stage_ops = {
"line",
- NULL,
- NULL,
+ view_open,
pager_read,
pager_draw,
stage_request,
pager_read,
pager_draw,
stage_request,
struct graph_canvas graph; /* Ancestry chain graphics. */
};
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)
static bool
main_draw(struct view *view, struct line *line, unsigned int lineno)
if (!commit->author)
return FALSE;
if (!commit->author)
return FALSE;
- if (opt_date && draw_date(view, &commit->time))
+ if (draw_date(view, &commit->time))
return TRUE;
return TRUE;
- if (opt_author && draw_author(view, commit->author))
+ if (draw_author(view, commit->author))
return TRUE;
if (opt_rev_graph && draw_graph(view, &commit->graph))
return TRUE;
if (opt_rev_graph && draw_graph(view, &commit->graph))
switch (request) {
case REQ_ENTER:
if (view_is_displayed(view) && display[0] != view)
switch (request) {
case REQ_ENTER:
if (view_is_displayed(view) && display[0] != view)
- maximize_view(view);
+ maximize_view(view, TRUE);
open_view(view, REQ_VIEW_DIFF, flags);
break;
case REQ_REFRESH:
load_refs();
open_view(view, REQ_VIEW_DIFF, flags);
break;
case REQ_REFRESH:
load_refs();
- open_view(view, REQ_VIEW_MAIN, OPEN_REFRESH);
+ refresh_view(view);
break;
default:
return request;
break;
default:
return request;
static struct view_ops main_ops = {
"commit",
static struct view_ops main_ops = {
"commit",
- main_argv,
- NULL,
+ main_open,
main_read,
main_draw,
main_request,
main_read,
main_draw,
main_request,
"\n"
"Usage: tig [options] [revs] [--] [paths]\n"
" or: tig show [options] [revs] [--] [paths]\n"
"\n"
"Usage: tig [options] [revs] [--] [paths]\n"
" or: tig show [options] [revs] [--] [paths]\n"
-" or: tig blame [rev] path\n"
+" or: tig blame [options] [rev] [--] path\n"
" or: tig status\n"
" or: tig < [git command output]\n"
"\n"
" or: tig status\n"
" or: tig < [git command output]\n"
"\n"
return REQ_VIEW_STATUS;
} else if (!strcmp(subcommand, "blame")) {
return REQ_VIEW_STATUS;
} else if (!strcmp(subcommand, "blame")) {
- if (argc <= 2 || argc > 4)
+ filter_rev_parse(&opt_file_argv, "--no-revs", "--no-flags", argv + 2);
+ filter_rev_parse(&opt_blame_argv, "--no-revs", "--flags", argv + 2);
+ filter_rev_parse(&opt_rev_argv, "--symbolic", "--revs-only", argv + 2);
+
+ if (!opt_file_argv || opt_file_argv[1] || (opt_rev_argv && opt_rev_argv[1]))
die("invalid number of options to blame\n\n%s", usage);
die("invalid number of options to blame\n\n%s", usage);
- i = 2;
- if (argc == 4) {
- string_ncopy(opt_ref, argv[i], strlen(argv[i]));
- i++;
+ if (opt_rev_argv) {
+ string_ncopy(opt_ref, opt_rev_argv[0], strlen(opt_rev_argv[0]));
}
}
- string_ncopy(opt_file, argv[i], strlen(argv[i]));
+ string_ncopy(opt_file, opt_file_argv[0], strlen(opt_file_argv[0]));
return REQ_VIEW_BLAME;
} else if (!strcmp(subcommand, "show")) {
return REQ_VIEW_BLAME;
} else if (!strcmp(subcommand, "show")) {
const char *codeset = "UTF-8";
enum request request = parse_options(argc, argv);
struct view *view;
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);
signal(SIGINT, quit);
signal(SIGPIPE, SIG_IGN);
if (load_refs() == ERR)
die("Failed to load refs.");
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)) {
init_display();
while (view_driver(display[current_view], request)) {
if (!argv_from_string(argv, &argc, cmd)) {
report("Too many arguments");
if (!argv_from_string(argv, &argc, cmd)) {
report("Too many arguments");
- } else if (!prepare_update(next, argv, NULL)) {
- report("Failed to format command");
} else {
} else {
- open_view(view, REQ_VIEW_PAGER, OPEN_PREPARED);
+ open_argv(view, next, argv, NULL, OPEN_DEFAULT);
}
}
}
}