index a82a4686e4696316a00eeb9473d8deb934df6e4b..ee0d0d63eb32833202af271a8134291c9c32f738 100644 (file)
--- a/tig.c
+++ b/tig.c
#define S_ISGITLINK(mode) (((mode) & S_IFMT) == 0160000)
/* Some ASCII-shorthands fitted into the ncurses namespace. */
+#define KEY_CTL(x) ((x) & 0x1f) /* KEY_CTL(A) == ^A == \1 */
#define KEY_TAB '\t'
#define KEY_RETURN '\r'
#define KEY_ESC 27
argv[0] = NULL;
}
+static size_t
+argv_size(const char **argv)
+{
+ int argc = 0;
+
+ while (argv && argv[argc])
+ argc++;
+
+ return argc;
+}
+
DEFINE_ALLOCATOR(argv_realloc, const char *, SIZEOF_ARG)
static bool
argv_append(const char ***argv, const char *arg)
{
- int argc = 0;
-
- while (*argv && (*argv)[argc])
- argc++;
+ size_t argc = argv_size(*argv);
if (!argv_realloc(argv, argc, 2))
return FALSE;
REQ_(MOVE_LAST_LINE, "Move cursor to last line"), \
\
REQ_GROUP("Scrolling") \
+ REQ_(SCROLL_FIRST_COL, "Scroll to the first line columns"), \
REQ_(SCROLL_LEFT, "Scroll two columns left"), \
REQ_(SCROLL_RIGHT, "Scroll two columns right"), \
REQ_(SCROLL_LINE_UP, "Scroll one line up"), \
REQ_(OPTIONS, "Open option menu"), \
REQ_(TOGGLE_LINENO, "Toggle line numbers"), \
REQ_(TOGGLE_DATE, "Toggle date display"), \
- REQ_(TOGGLE_DATE_SHORT, "Toggle short (date-only) dates"), \
REQ_(TOGGLE_AUTHOR, "Toggle author display"), \
REQ_(TOGGLE_REV_GRAPH, "Toggle revision graph visualization"), \
REQ_(TOGGLE_REFS, "Toggle reference display (tags/branches)"), \
static bool opt_line_graphics = TRUE;
static bool opt_rev_graph = FALSE;
static bool opt_show_refs = TRUE;
+static bool opt_untracked_dirs_content = TRUE;
static int opt_num_interval = 5;
static double opt_hscroll = 0.50;
static double opt_scale_split_view = 2.0 / 3.0;
static signed char opt_is_inside_work_tree = -1; /* set to TRUE or FALSE */
static char opt_editor[SIZEOF_STR] = "";
static FILE *opt_tty = NULL;
-static const char **opt_diff_args = NULL;
-static const char **opt_rev_args = NULL;
-static const char **opt_file_args = NULL;
+static const char **opt_diff_argv = NULL;
+static const char **opt_rev_argv = NULL;
+static const char **opt_file_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)))
{ KEY_TAB, REQ_VIEW_NEXT },
{ KEY_RETURN, REQ_ENTER },
{ KEY_UP, REQ_PREVIOUS },
+ { KEY_CTL('P'), REQ_PREVIOUS },
{ KEY_DOWN, REQ_NEXT },
+ { KEY_CTL('N'), REQ_NEXT },
{ 'R', REQ_REFRESH },
{ KEY_F(5), REQ_REFRESH },
{ 'O', REQ_MAXIMIZE },
{ KEY_HOME, REQ_MOVE_FIRST_LINE },
{ KEY_END, REQ_MOVE_LAST_LINE },
{ KEY_NPAGE, REQ_MOVE_PAGE_DOWN },
+ { KEY_CTL('D'), REQ_MOVE_PAGE_DOWN },
{ ' ', REQ_MOVE_PAGE_DOWN },
{ KEY_PPAGE, REQ_MOVE_PAGE_UP },
+ { KEY_CTL('U'), REQ_MOVE_PAGE_UP },
{ 'b', REQ_MOVE_PAGE_UP },
{ '-', REQ_MOVE_PAGE_UP },
/* Scrolling */
+ { '|', REQ_SCROLL_FIRST_COL },
{ KEY_LEFT, REQ_SCROLL_LEFT },
{ KEY_RIGHT, REQ_SCROLL_RIGHT },
{ KEY_IC, REQ_SCROLL_LINE_UP },
+ { KEY_CTL('Y'), REQ_SCROLL_LINE_UP },
{ KEY_DC, REQ_SCROLL_LINE_DOWN },
+ { KEY_CTL('E'), REQ_SCROLL_LINE_DOWN },
{ 'w', REQ_SCROLL_PAGE_UP },
{ 's', REQ_SCROLL_PAGE_DOWN },
{ 'z', REQ_STOP_LOADING },
{ 'v', REQ_SHOW_VERSION },
{ 'r', REQ_SCREEN_REDRAW },
+ { KEY_CTL('L'), REQ_SCREEN_REDRAW },
{ 'o', REQ_OPTIONS },
{ '.', REQ_TOGGLE_LINENO },
{ 'D', REQ_TOGGLE_DATE },
if (!strcasecmp(key_table[i].name, name))
return key_table[i].value;
+ if (strlen(name) == 2 && name[0] == '^' && isprint(*name))
+ return (int)name[1] & 0x1f;
if (strlen(name) == 1 && isprint(*name))
return (int) *name;
-
return ERR;
}
static const char *
get_key_name(int key_value)
{
- static char key_char[] = "'X'";
+ static char key_char[] = "'X'\0";
const char *seq = NULL;
int key;
if (key_table[key].value == key_value)
seq = key_table[key].name;
- if (seq == NULL &&
- key_value < 127 &&
- isprint(key_value)) {
- key_char[1] = (char) key_value;
+ if (seq == NULL && key_value < 0x7f) {
+ char *s = key_char + 1;
+
+ if (key_value >= 0x20) {
+ *s++ = key_value;
+ } else {
+ *s++ = '^';
+ *s++ = 0x40 | (key_value & 0x1f);
+ }
+ *s++ = '\'';
+ *s++ = '\0';
seq = key_char;
}
if (!strcmp(argv[0], "commit-encoding"))
return parse_string(opt_encoding, argv[2], sizeof(opt_encoding));
+ if (!strcmp(argv[0], "status-untracked-dirs"))
+ return parse_bool(&opt_untracked_dirs_content, argv[2]);
+
config_msg = "Unknown variable name";
return ERR;
}
* that conflict with keybindings. */
add_builtin_run_requests();
- if (!opt_diff_args && tig_diff_opts && *tig_diff_opts) {
+ if (!opt_diff_argv && tig_diff_opts && *tig_diff_opts) {
static const char *diff_opts[SIZEOF_ARG] = { NULL };
int argc = 0;
if (!string_format(buf, "%s", tig_diff_opts) ||
!argv_from_string(diff_opts, &argc, buf))
die("TIG_DIFF_OPTS contains too many arguments");
- else if (!argv_copy(&opt_diff_args, diff_opts))
+ else if (!argv_copy(&opt_diff_argv, diff_opts))
die("Failed to format TIG_DIFF_OPTS arguments");
}
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_(PAGER, "pager", &pager_ops, FALSE, ""),
VIEW_(STATUS, "status", &status_ops, TRUE, ""),
VIEW_(STAGE, "stage", &stage_ops, TRUE, ""),
};
}
waddnstr(view->win, string, len);
- }
- if (trimmed && use_tilde) {
- set_view_attr(view, LINE_DELIMITER);
- waddch(view->win, '~');
- col++;
+
+ if (trimmed && use_tilde) {
+ set_view_attr(view, LINE_DELIMITER);
+ waddch(view->win, '~');
+ col++;
+ }
}
return col;
assert(view_is_displayed(view));
switch (request) {
+ case REQ_SCROLL_FIRST_COL:
+ view->yoffset = 0;
+ redraw_view_from(view, 0);
+ report("");
+ return;
case REQ_SCROLL_LEFT:
if (view->yoffset == 0) {
report("Cannot scroll beyond the first column");
}
static bool
-format_argv(const char ***dst_argv, const char *src_argv[], bool replace)
+format_argv(const char ***dst_argv, const char *src_argv[], bool replace, bool first)
{
char buf[SIZEOF_STR];
int argc;
size_t bufpos = 0;
if (!strcmp(arg, "%(fileargs)")) {
- if (!argv_append_array(dst_argv, opt_file_args))
+ if (!argv_append_array(dst_argv, opt_file_argv))
break;
continue;
} else if (!strcmp(arg, "%(diffargs)")) {
- if (!argv_append_array(dst_argv, opt_diff_args))
+ if (!argv_append_array(dst_argv, opt_diff_argv))
break;
continue;
- } else if (!strcmp(arg, "%(revargs)")) {
- if (!argv_append_array(dst_argv, opt_rev_args))
+ } else if (!strcmp(arg, "%(revargs)") ||
+ (first && !strcmp(arg, "%(commit)"))) {
+ if (!argv_append_array(dst_argv, opt_rev_argv))
break;
continue;
}
prepare_io(struct view *view, const char *dir, const char *argv[], bool replace)
{
view->dir = dir;
- return format_argv(&view->argv, argv, replace);
+ return format_argv(&view->argv, argv, replace, !view->prev);
}
static bool
return;
}
- if (format_argv(&argv, req->argv, TRUE))
+ if (format_argv(&argv, req->argv, TRUE, FALSE))
open_external_viewer(argv, NULL);
if (argv)
argv_free(argv);
move_view(view, request);
break;
+ case REQ_SCROLL_FIRST_COL:
case REQ_SCROLL_LEFT:
case REQ_SCROLL_RIGHT:
case REQ_SCROLL_LINE_DOWN:
break;
case REQ_VIEW_PAGER:
+ if (view == NULL) {
+ if (!io_open(&VIEW(REQ_VIEW_PAGER)->io, ""))
+ die("Failed to open stdin");
+ open_view(view, request, OPEN_PREPARED);
+ break;
+ }
+
if (!VIEW(REQ_VIEW_PAGER)->pipe && !VIEW(REQ_VIEW_PAGER)->lines) {
report("No pager content, press %s to run command from prompt",
get_key(view->keymap, REQ_PROMPT));
"%(diffargs)", "%(commit)", "--", "%(fileargs)", NULL
};
+static bool
+diff_read(struct view *view, char *data)
+{
+ if (!data) {
+ /* Fall back to retry if no diff will be shown. */
+ if (view->lines == 0 && opt_file_argv) {
+ int pos = argv_size(view->argv)
+ - argv_size(opt_file_argv) - 1;
+
+ if (pos > 0 && !strcmp(view->argv[pos], "--")) {
+ for (; view->argv[pos]; pos++) {
+ free((void *) view->argv[pos]);
+ view->argv[pos] = NULL;
+ }
+
+ if (view->pipe)
+ io_done(view->pipe);
+ if (io_run(&view->io, IO_RD, view->dir, view->argv))
+ return FALSE;
+ }
+ }
+ return TRUE;
+ }
+
+ return pager_read(view, data);
+}
+
static struct view_ops diff_ops = {
"line",
diff_argv,
NULL,
- pager_read,
+ diff_read,
pager_draw,
pager_request,
pager_grep,
};
static const char *status_list_other_argv[] = {
- "git", "ls-files", "-z", "--others", "--exclude-standard", opt_prefix, NULL
+ "git", "ls-files", "-z", "--others", "--exclude-standard", opt_prefix, NULL, NULL,
};
static const char *status_list_no_head_argv[] = {
return FALSE;
}
+ if (!opt_untracked_dirs_content)
+ status_list_other_argv[ARRAY_SIZE(status_list_other_argv) - 2] = "--directory";
+
if (!status_run(view, status_diff_files_argv, 0, LINE_STAT_UNSTAGED) ||
!status_run(view, status_list_other_argv, '?', LINE_STAT_UNTRACKED))
return FALSE;
switch (request) {
case REQ_ENTER:
+ if (view_is_displayed(view) && display[0] != view)
+ maximize_view(view);
open_view(view, REQ_VIEW_DIFF, flags);
break;
case REQ_REFRESH:
keypad(status_win, TRUE);
wbkgdset(status_win, get_line_attr(LINE_STATUS));
+#if defined(NCURSES_VERSION_PATCH) && (NCURSES_VERSION_PATCH >= 20080119)
+ set_tabsize(opt_tab_size);
+#else
TABSIZE = opt_tab_size;
+#endif
term = getenv("XTERM_VERSION") ? NULL : getenv("COLORTERM");
if (term && !strcmp(term, "gnome-terminal")) {
@@ -7715,9 +7795,9 @@ filter_rev_parse(const char ***args, const char *arg1, const char *arg2, const c
static void
filter_options(const char *argv[])
{
- filter_rev_parse(&opt_file_args, "--no-revs", "--no-flags", argv);
- filter_rev_parse(&opt_diff_args, "--no-revs", "--flags", argv);
- filter_rev_parse(&opt_rev_args, "--symbolic", "--revs-only", argv);
+ filter_rev_parse(&opt_file_argv, "--no-revs", "--no-flags", argv);
+ filter_rev_parse(&opt_diff_argv, "--no-revs", "--flags", argv);
+ filter_rev_parse(&opt_rev_argv, "--symbolic", "--revs-only", argv);
}
static enum request
const char **filter_argv = NULL;
int i;
- if (!isatty(STDIN_FILENO)) {
- io_open(&VIEW(REQ_VIEW_PAGER)->io, "");
+ if (!isatty(STDIN_FILENO))
return REQ_VIEW_PAGER;
- }
if (argc <= 1)
return REQ_VIEW_MAIN;
const char *opt = argv[i];
if (seen_dashdash) {
- argv_append(&opt_file_args, opt);
+ argv_append(&opt_file_argv, opt);
continue;
} else if (!strcmp(opt, "--")) {
quit(0);
} else if (!strcmp(opt, "--all")) {
- argv_append(&opt_rev_args, opt);
+ argv_append(&opt_rev_argv, opt);
continue;
}