X-Git-Url: https://git.distorted.org.uk/~mdw/tig/blobdiff_plain/07c3971e15e6eb8279ca1a112ab3b2cdc3ca020c..a4927c1d12c8765f3b3718f0375e15cd0986bcac:/tig.c diff --git a/tig.c b/tig.c index b09d91b..b9c10ab 100644 --- a/tig.c +++ b/tig.c @@ -336,7 +336,8 @@ sq_quote(char buf[SIZEOF_STR], size_t bufsize, const char *src) REQ_(SHOW_VERSION, "Show version information"), \ REQ_(STOP_LOADING, "Stop all loading views"), \ REQ_(TOGGLE_LINENO, "Toggle line numbers"), \ - REQ_(TOGGLE_REV_GRAPH, "Toggle revision graph visualization") + REQ_(TOGGLE_REV_GRAPH, "Toggle revision graph visualization"), \ + REQ_(STATUS_UPDATE, "Update file status") \ /* User action requests. */ @@ -765,6 +766,7 @@ static struct keybinding default_keybindings[] = { { '.', REQ_TOGGLE_LINENO }, { 'g', REQ_TOGGLE_REV_GRAPH }, { ':', REQ_PROMPT }, + { 'u', REQ_STATUS_UPDATE }, /* Using the ncurses SIGWINCH handler. */ { KEY_RESIZE, REQ_SCREEN_RESIZE }, @@ -1289,8 +1291,8 @@ static struct view views[] = { VIEW_(LOG, "log", &pager_ops, ref_head), VIEW_(TREE, "tree", &tree_ops, ref_commit), VIEW_(BLOB, "blob", &blob_ops, ref_blob), - VIEW_(HELP, "help", &help_ops, ""), - VIEW_(PAGER, "pager", &pager_ops, ""), + VIEW_(HELP, "help", &help_ops, ""), + VIEW_(PAGER, "pager", &pager_ops, "stdin"), VIEW_(STATUS, "status", &status_ops, ""), }; @@ -1394,7 +1396,7 @@ update_view_title(struct view *view) if (minsize < view->width) refsize = view->width - minsize + 7; - string_format_from(buf, &bufpos, " %.*s", refsize, view->ref); + string_format_from(buf, &bufpos, " %.*s", (int) refsize, view->ref); } if (statelen && bufpos < view->width) { @@ -2120,6 +2122,8 @@ open_view(struct view *prev, enum request request, enum open_flags flags) * User request switch noodle */ +static void status_update(struct view *view); + static int view_driver(struct view *view, enum request request) { @@ -2152,7 +2156,7 @@ view_driver(struct view *view, enum request request) break; case REQ_VIEW_PAGER: - if (!VIEW(REQ_VIEW_PAGER)->lines) { + if (!opt_pipe && !VIEW(REQ_VIEW_PAGER)->lines) { report("No pager content, press %s to run command from prompt", get_key(REQ_PROMPT)); break; @@ -2177,10 +2181,15 @@ view_driver(struct view *view, enum request request) view->parent == VIEW(REQ_VIEW_MAIN)) || (view == VIEW(REQ_VIEW_BLOB) && view->parent == VIEW(REQ_VIEW_TREE))) { + int line; + view = view->parent; + line = view->lineno; move_view(view, request); if (view_is_displayed(view)) update_view_title(view); + if (line == view->lineno) + break; } else { move_view(view, request); break; @@ -2255,6 +2264,10 @@ view_driver(struct view *view, enum request request) redraw_display(); break; + case REQ_STATUS_UPDATE: + status_update(view); + break; + case REQ_NONE: doupdate(); return TRUE; @@ -2907,6 +2920,9 @@ 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" + /* First parse staged info using git-diff-index(1), then parse unstaged * info using git-diff-files(1), and finally untracked files using * git-ls-files(1). */ @@ -3008,6 +3024,60 @@ static bool status_enter(struct view *view, struct line *line) { struct status *status = line->data; + char path[SIZEOF_STR]; + char *info; + size_t cmdsize = 0; + + if (!status || line->type == LINE_STAT_NONE) { + report("No file has been chosen"); + return TRUE; + } + + if (sq_quote(path, 0, status->name) >= sizeof(path)) + return FALSE; + + if (opt_cdup[0] && + line->type != LINE_STAT_UNTRACKED && + !string_format_from(opt_cmd, &cmdsize, "cd %s;", opt_cdup)) + return FALSE; + + switch (line->type) { + case LINE_STAT_STAGED: + if (!string_format_from(opt_cmd, &cmdsize, STATUS_DIFF_SHOW_CMD, + "--cached", path)) + return FALSE; + info = "Staged changes to %s"; + break; + + case LINE_STAT_UNSTAGED: + if (!string_format_from(opt_cmd, &cmdsize, STATUS_DIFF_SHOW_CMD, + "", path)) + return FALSE; + info = "Unstaged changes to %s"; + break; + + case LINE_STAT_UNTRACKED: + if (opt_pipe) + return FALSE; + opt_pipe = fopen(status->name, "r"); + info = "Untracked file %s"; + break; + + default: + die("w00t"); + } + + open_view(view, REQ_VIEW_DIFF, OPEN_RELOAD | OPEN_SPLIT); + if (view_is_displayed(VIEW(REQ_VIEW_DIFF))) { + string_format(VIEW(REQ_VIEW_DIFF)->ref, info, status->name); + } + + return TRUE; +} + +static bool +status_update_file(struct view *view, struct status *status, enum line_type type) +{ char cmd[SIZEOF_STR]; char buf[SIZEOF_STR]; size_t cmdsize = 0; @@ -3015,15 +3085,12 @@ status_enter(struct view *view, struct line *line) size_t written = 0; FILE *pipe; - if (!status) - return TRUE; - if (opt_cdup[0] && - line->type != LINE_STAT_UNTRACKED && + type != LINE_STAT_UNTRACKED && !string_format_from(cmd, &cmdsize, "cd %s;", opt_cdup)) return FALSE; - switch (line->type) { + switch (type) { case LINE_STAT_STAGED: if (!string_format_from(buf, &bufsize, "%06o %s\t%s%c", status->old.mode, @@ -3064,21 +3131,40 @@ status_enter(struct view *view, struct line *line) } static void +status_update(struct view *view) +{ + if (view == VIEW(REQ_VIEW_STATUS)) { + struct line *line = view->lines + ? &view->line[view->lineno] : NULL; + + if (!line || !line->data) { + report("No file has been chosen"); + return; + } + + if (!status_update_file(view, line->data, line->type)) + report("Failed to update file status"); + } else { + report("This action is only valid for the status view"); + } +} + +static void status_select(struct view *view, struct line *line) { char *text; switch (line->type) { case LINE_STAT_STAGED: - text = "Press Enter to unstage file for commit"; + text = "Press %s to unstage file for commit"; break; case LINE_STAT_UNSTAGED: - text = "Press Enter to stage file for commit "; + text = "Press %s to stage file for commit "; break; case LINE_STAT_UNTRACKED: - text = "Press Enter to stage file for addition"; + text = "Press %s to stage file for addition"; break; case LINE_STAT_NONE: @@ -3088,7 +3174,7 @@ status_select(struct view *view, struct line *line) die("w00t"); } - string_ncopy(view->ref, text, strlen(text)); + string_format(view->ref, text, get_key(REQ_STATUS_UPDATE)); } static bool