X-Git-Url: https://git.distorted.org.uk/~mdw/tig/blobdiff_plain/9eb14b72b27aedbd14b99332b22bb48651812204..4ef1bf121de1697c9d54e10addcd34a4d19d3526:/tig.c?ds=sidebyside diff --git a/tig.c b/tig.c index 84e51b0..446453d 100644 --- a/tig.c +++ b/tig.c @@ -105,13 +105,13 @@ static size_t utf8_length(const char *string, size_t max_width, int *coloffset, "git ls-remote $(git rev-parse --git-dir) 2>/dev/null" #define TIG_DIFF_CMD \ - "git show --root --patch-with-stat --find-copies-harder -B -C %s 2>/dev/null" + "git show --no-color --root --patch-with-stat --find-copies-harder -C %s 2>/dev/null" #define TIG_LOG_CMD \ - "git log --cc --stat -n100 %s 2>/dev/null" + "git log --no-color --cc --stat -n100 %s 2>/dev/null" #define TIG_MAIN_CMD \ - "git log --topo-order --pretty=raw %s 2>/dev/null" + "git log --no-color --topo-order --pretty=raw %s 2>/dev/null" #define TIG_TREE_CMD \ "git ls-tree %s %s" @@ -352,8 +352,8 @@ sq_quote(char buf[SIZEOF_STR], size_t bufsize, const char *src) REQ_(TOGGLE_REV_GRAPH, "Toggle revision graph visualization"), \ REQ_(STATUS_UPDATE, "Update file status"), \ REQ_(STATUS_MERGE, "Merge file using external tool"), \ + REQ_(TREE_PARENT, "Switch to parent directory in tree view"), \ REQ_(EDIT, "Open in editor"), \ - REQ_(CHERRY_PICK, "Cherry-pick commit to current branch"), \ REQ_(NONE, "Do nothing") @@ -506,6 +506,26 @@ parse_options(int argc, char *argv[]) if (opt[0] && opt[0] != '-') break; + if (!strcmp(opt, "--")) { + i++; + break; + } + + if (check_option(opt, 'v', "version", OPT_NONE)) { + printf("tig version %s\n", TIG_VERSION); + return FALSE; + } + + if (check_option(opt, 'h', "help", OPT_NONE)) { + printf(usage); + return FALSE; + } + + if (!strcmp(opt, "-S")) { + opt_request = REQ_VIEW_STATUS; + continue; + } + if (!strcmp(opt, "-l")) { opt_request = REQ_VIEW_LOG; continue; @@ -516,11 +536,6 @@ parse_options(int argc, char *argv[]) continue; } - if (!strcmp(opt, "-S")) { - opt_request = REQ_VIEW_STATUS; - continue; - } - if (check_option(opt, 'n', "line-number", OPT_INT, &opt_num_interval)) { opt_line_number = TRUE; continue; @@ -531,21 +546,6 @@ parse_options(int argc, char *argv[]) continue; } - if (check_option(opt, 'v', "version", OPT_NONE)) { - printf("tig version %s\n", TIG_VERSION); - return FALSE; - } - - if (check_option(opt, 'h', "help", OPT_NONE)) { - printf(usage); - return FALSE; - } - - if (!strcmp(opt, "--")) { - i++; - break; - } - die("unknown option '%s'\n\n%s", opt, usage); } @@ -559,7 +559,7 @@ parse_options(int argc, char *argv[]) if (opt_request == REQ_VIEW_MAIN) /* XXX: This is vulnerable to the user overriding * options required for the main view parser. */ - string_copy(opt_cmd, "git log --pretty=raw"); + string_copy(opt_cmd, "git log --no-color --pretty=raw"); else string_copy(opt_cmd, "git"); buf_size = strlen(opt_cmd); @@ -627,6 +627,7 @@ LINE(MAIN_DELIM, "", COLOR_MAGENTA, COLOR_DEFAULT, 0), \ LINE(MAIN_TAG, "", COLOR_MAGENTA, COLOR_DEFAULT, A_BOLD), \ LINE(MAIN_REMOTE, "", COLOR_YELLOW, COLOR_DEFAULT, A_BOLD), \ LINE(MAIN_REF, "", COLOR_CYAN, COLOR_DEFAULT, A_BOLD), \ +LINE(MAIN_REVGRAPH,"", COLOR_MAGENTA, COLOR_DEFAULT, 0), \ LINE(TREE_DIR, "", COLOR_DEFAULT, COLOR_DEFAULT, A_NORMAL), \ LINE(TREE_FILE, "", COLOR_DEFAULT, COLOR_DEFAULT, A_NORMAL), \ LINE(STAT_SECTION, "", COLOR_CYAN, COLOR_DEFAULT, 0), \ @@ -788,8 +789,8 @@ static struct keybinding default_keybindings[] = { { ':', REQ_PROMPT }, { 'u', REQ_STATUS_UPDATE }, { 'M', REQ_STATUS_MERGE }, + { ',', REQ_TREE_PARENT }, { 'e', REQ_EDIT }, - { 'C', REQ_CHERRY_PICK }, /* Using the ncurses SIGWINCH handler. */ { KEY_RESIZE, REQ_SCREEN_RESIZE }, @@ -939,7 +940,6 @@ static char * get_key(enum request request) { static char buf[BUFSIZ]; - static char key_char[] = "'X'"; size_t pos = 0; char *sep = ""; int i; @@ -948,27 +948,12 @@ get_key(enum request request) for (i = 0; i < ARRAY_SIZE(default_keybindings); i++) { struct keybinding *keybinding = &default_keybindings[i]; - char *seq = NULL; - int key; if (keybinding->request != request) continue; - for (key = 0; key < ARRAY_SIZE(key_table); key++) - if (key_table[key].value == keybinding->alias) - seq = key_table[key].name; - - if (seq == NULL && - keybinding->alias < 127 && - isprint(keybinding->alias)) { - key_char[1] = (char) keybinding->alias; - seq = key_char; - } - - if (!seq) - seq = "'?'"; - - if (!string_format_from(buf, &pos, "%s%s", sep, seq)) + if (!string_format_from(buf, &pos, "%s%s", sep, + get_key_name(keybinding->alias))) return "Too many keybindings!"; sep = ", "; } @@ -1016,6 +1001,28 @@ get_run_request(enum request request) return &run_request[request - REQ_NONE - 1]; } +static void +add_builtin_run_requests(void) +{ + struct { + enum keymap keymap; + int key; + char *argv[1]; + } reqs[] = { + { KEYMAP_MAIN, 'C', { "git cherry-pick %(commit)" } }, + { KEYMAP_GENERIC, 'G', { "git gc" } }, + }; + int i; + + for (i = 0; i < ARRAY_SIZE(reqs); i++) { + enum request req; + + req = add_run_request(reqs[i].keymap, reqs[i].key, 1, reqs[i].argv); + if (req != REQ_NONE) + add_keybinding(reqs[i].keymap, req, reqs[i].key); + } +} + /* * User config file handling. */ @@ -1164,6 +1171,19 @@ option_bind_command(int argc, char *argv[]) } request = get_request(argv[2]); + if (request == REQ_NONE) { + const char *obsolete[] = { "cherry-pick" }; + size_t namelen = strlen(argv[2]); + int i; + + for (i = 0; i < ARRAY_SIZE(obsolete); i++) { + if (namelen == strlen(obsolete[i]) && + !string_enum_compare(obsolete[i], argv[2], namelen)) { + config_msg = "Obsolete request name"; + return ERR; + } + } + } if (request == REQ_NONE && *argv[2]++ == '!') request = add_run_request(keymap, key, argc - 2, argv + 2); if (request == REQ_NONE) { @@ -1186,9 +1206,10 @@ set_option(char *opt, char *value) /* Tokenize */ while (argc < ARRAY_SIZE(argv) && (valuelen = strcspn(value, " \t"))) { argv[argc++] = value; - value += valuelen; - if (!*value) + + /* Nothing more to tokenize or last available token. */ + if (!*value || argc >= ARRAY_SIZE(argv)) break; *value++ = 0; @@ -1259,6 +1280,8 @@ load_options(void) config_lineno = 0; config_errors = FALSE; + add_builtin_run_requests(); + if (!home || !string_format(buf, "%s/.tigrc", home)) return ERR; @@ -2486,9 +2509,6 @@ view_driver(struct view *view, enum request request) report("Nothing to edit"); break; - case REQ_CHERRY_PICK: - report("Nothing to cherry-pick"); - break; case REQ_ENTER: report("Nothing to enter"); @@ -3002,6 +3022,16 @@ tree_request(struct view *view, enum request request, struct line *line) { enum open_flags flags; + if (request == REQ_TREE_PARENT) { + if (*opt_path) { + /* fake 'cd ..' */ + request = REQ_ENTER; + line = &view->line[1]; + } else { + /* quit view if at top of tree */ + return REQ_VIEW_CLOSE; + } + } if (request != REQ_ENTER) return request; @@ -3243,8 +3273,11 @@ error_out: #define STATUS_LIST_OTHER_CMD \ "git ls-files -z --others --exclude-per-directory=.gitignore" -#define STATUS_DIFF_SHOW_CMD \ - "git diff --root --patch-with-stat --find-copies-harder -B -C %s -- %s 2>/dev/null" +#define STATUS_DIFF_INDEX_SHOW_CMD \ + "git diff-index --root --patch-with-stat --find-copies-harder -C --cached HEAD -- %s 2>/dev/null" + +#define STATUS_DIFF_FILES_SHOW_CMD \ + "git diff-files --root --patch-with-stat --find-copies-harder -C -- %s 2>/dev/null" /* First parse staged info using git-diff-index(1), then parse unstaged * info using git-diff-files(1), and finally untracked files using @@ -3375,8 +3408,8 @@ status_enter(struct view *view, struct line *line) switch (line->type) { case LINE_STAT_STAGED: - if (!string_format_from(opt_cmd, &cmdsize, STATUS_DIFF_SHOW_CMD, - "--cached", path)) + if (!string_format_from(opt_cmd, &cmdsize, + STATUS_DIFF_INDEX_SHOW_CMD, path)) return REQ_QUIT; if (status) info = "Staged changes to %s"; @@ -3385,8 +3418,8 @@ status_enter(struct view *view, struct line *line) break; case LINE_STAT_UNSTAGED: - if (!string_format_from(opt_cmd, &cmdsize, STATUS_DIFF_SHOW_CMD, - "", path)) + if (!string_format_from(opt_cmd, &cmdsize, + STATUS_DIFF_FILES_SHOW_CMD, path)) return REQ_QUIT; if (status) info = "Unstaged changes to %s"; @@ -3409,7 +3442,7 @@ status_enter(struct view *view, struct line *line) break; default: - die("w00t"); + die("line type %d not handled in switch", line->type); } open_view(view, REQ_VIEW_STAGE, OPEN_RELOAD | OPEN_SPLIT); @@ -3463,7 +3496,7 @@ status_update_file(struct view *view, struct status *status, enum line_type type break; default: - die("w00t"); + die("line type %d not handled in switch", type); } pipe = popen(cmd, "w"); @@ -3516,6 +3549,10 @@ status_request(struct view *view, enum request request, struct line *line) break; case REQ_STATUS_MERGE: + if (!status || status->status != 'U') { + report("Merging only possible for files with unmerged status ('U')."); + return REQ_NONE; + } open_mergetool(status->name); break; @@ -3578,7 +3615,7 @@ status_select(struct view *view, struct line *line) break; default: - die("w00t"); + die("line type %d not handled in switch", line->type); } if (status && status->status == 'U') { @@ -4061,12 +4098,12 @@ main_draw(struct view *view, struct line *line, unsigned int lineno, bool select } col += AUTHOR_COLS; - if (type != LINE_CURSOR) - wattrset(view->win, A_NORMAL); if (opt_rev_graph && commit->graph_size) { size_t i; + if (type != LINE_CURSOR) + wattrset(view->win, get_line_attr(LINE_MAIN_REVGRAPH)); wmove(view->win, lineno, col); /* Using waddch() instead of waddnstr() ensures that * they'll be rendered correctly for the cursor line. */ @@ -4076,6 +4113,8 @@ main_draw(struct view *view, struct line *line, unsigned int lineno, bool select waddch(view->win, ' '); col += commit->graph_size + 1; } + if (type != LINE_CURSOR) + wattrset(view->win, A_NORMAL); wmove(view->win, lineno, col); @@ -4226,20 +4265,6 @@ main_read(struct view *view, char *line) return TRUE; } -static void -cherry_pick_commit(struct commit *commit) -{ - char cmd[SIZEOF_STR]; - char *cherry_pick = getenv("TIG_CHERRY_PICK"); - - if (!cherry_pick) - cherry_pick = "git cherry-pick"; - - if (string_format(cmd, "%s %s", cherry_pick, commit->id)) { - open_external_viewer(cmd); - } -} - static enum request main_request(struct view *view, enum request request, struct line *line) { @@ -4247,8 +4272,6 @@ main_request(struct view *view, enum request request, struct line *line) if (request == REQ_ENTER) open_view(view, REQ_VIEW_DIFF, flags); - else if (request == REQ_CHERRY_PICK) - cherry_pick_commit(line->data); else return request;