X-Git-Url: https://git.distorted.org.uk/~mdw/tig/blobdiff_plain/e47afdf2f78acbcb5c08f422be5ce37e0e99a5fc..3dd65d9533e11d892ed58e334cd9b69b27751ab5:/tig.c diff --git a/tig.c b/tig.c index 0390b3a..620f14b 100644 --- a/tig.c +++ b/tig.c @@ -80,6 +80,9 @@ static size_t utf8_length(const char *string, size_t max_width, int *coloffset, #define COLOR_DEFAULT (-1) #define ICONV_NONE ((iconv_t) -1) +#ifndef ICONV_CONST +#define ICONV_CONST /* nothing */ +#endif /* The format and size of the date column in the main view. */ #define DATE_FORMAT "%Y-%m-%d %H:%M" @@ -348,7 +351,8 @@ sq_quote(char buf[SIZEOF_STR], size_t bufsize, const char *src) REQ_(TOGGLE_LINENO, "Toggle line numbers"), \ REQ_(TOGGLE_REV_GRAPH, "Toggle revision graph visualization"), \ REQ_(STATUS_UPDATE, "Update file status"), \ - REQ_(EDIT, "Open in editor") + REQ_(EDIT, "Open in editor"), \ + REQ_(CHERRY_PICK, "Cherry-pick commit to current branch") /* User action requests. */ @@ -781,6 +785,7 @@ static struct keybinding default_keybindings[] = { { ':', REQ_PROMPT }, { 'u', REQ_STATUS_UPDATE }, { 'e', REQ_EDIT }, + { 'C', REQ_CHERRY_PICK }, /* Using the ncurses SIGWINCH handler. */ { KEY_RESIZE, REQ_SCREEN_RESIZE }, @@ -2138,11 +2143,12 @@ open_view(struct view *prev, enum request request, enum open_flags flags) } static void -open_editor(struct view *view, char *file) +open_editor(bool from_root, char *file) { char cmd[SIZEOF_STR]; char file_sq[SIZEOF_STR]; char *editor; + char *prefix = from_root ? opt_cdup : ""; editor = getenv("GIT_EDITOR"); if (!editor && *opt_editor) @@ -2155,7 +2161,7 @@ open_editor(struct view *view, char *file) editor = "vi"; if (sq_quote(file_sq, 0, file) < sizeof(file_sq) && - string_format(cmd, "%s %s", editor, file_sq)) { + string_format(cmd, "%s %s%s", editor, prefix, file_sq)) { def_prog_mode(); /* save current tty modes */ endwin(); /* restore original tty modes */ system(cmd); @@ -2173,6 +2179,11 @@ view_driver(struct view *view, enum request request) { int i; + if (request == REQ_NONE) { + doupdate(); + return TRUE; + } + if (view && view->lines) { request = view->ops->request(view, request, &view->line[view->lineno]); if (request == REQ_NONE) @@ -2323,13 +2334,14 @@ 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"); break; - case REQ_NONE: - doupdate(); - return TRUE; case REQ_VIEW_CLOSE: /* XXX: Mark closed views by letting view->parent point to the @@ -3040,12 +3052,14 @@ status_open(struct view *view) struct stat statbuf; char exclude[SIZEOF_STR]; char cmd[SIZEOF_STR]; + unsigned long prev_lineno = view->lineno; size_t i; + for (i = 0; i < view->lines; i++) free(view->line[i].data); free(view->line); - view->lines = view->line_size = 0; + view->lines = view->line_size = view->lineno = 0; view->line = NULL; if (!realloc_lines(view, view->line_size + 6)) @@ -3069,6 +3083,13 @@ status_open(struct view *view) !status_run(view, cmd, FALSE, LINE_STAT_UNTRACKED)) return FALSE; + /* If all went well restore the previous line number to stay in + * the context. */ + if (prev_lineno < view->lines) + view->lineno = prev_lineno; + else + view->lineno = view->lines - 1; + return TRUE; } @@ -3298,7 +3319,7 @@ status_request(struct view *view, enum request request, struct line *line) if (!status) return request; - open_editor(view, status->name); + open_editor(status->status != '?', status->name); break; case REQ_ENTER: @@ -3532,7 +3553,7 @@ stage_request(struct view *view, enum request request, struct line *line) if (!stage_status.name[0]) return request; - open_editor(view, stage_status.name); + open_editor(stage_status.status != '?', stage_status.name); break; case REQ_ENTER: @@ -3983,6 +4004,26 @@ 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)) { + def_prog_mode(); /* save current tty modes */ + endwin(); /* restore original tty modes */ + system(cmd); + fprintf(stderr, "Press Enter to continue"); + getc(stdin); + reset_prog_mode(); + redraw_display(); + } +} + static enum request main_request(struct view *view, enum request request, struct line *line) { @@ -3990,6 +4031,8 @@ 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; @@ -4611,10 +4654,6 @@ main(int argc, char *argv[]) if (load_repo_info() == ERR) die("Failed to load repo info."); - /* Require a git repository unless when running in pager mode. */ - if (!opt_git_dir[0]) - die("Not a git repository"); - if (load_options() == ERR) die("Failed to load user config."); @@ -4626,6 +4665,10 @@ main(int argc, char *argv[]) if (!parse_options(argc, argv)) return 0; + /* Require a git repository unless when running in pager mode. */ + if (!opt_git_dir[0]) + die("Not a git repository"); + if (*opt_codeset && strcmp(opt_codeset, opt_encoding)) { opt_iconv = iconv_open(opt_codeset, opt_encoding); if (opt_iconv == ICONV_NONE)