X-Git-Url: https://git.distorted.org.uk/~mdw/tig/blobdiff_plain/f5a5e640f1fc42e3e95c51b827dff738e7dbf1ec..7672417830e55a1544b7e9d0d1afd11f0f98dbf6:/tig.c diff --git a/tig.c b/tig.c index b5e6988..dc48eed 100644 --- a/tig.c +++ b/tig.c @@ -103,6 +103,8 @@ static size_t utf8_length(const char *string, size_t max_width, int *trimmed, bo #define SCALE_SPLIT_VIEW(height) ((height) * 2 / 3) +#define NULL_ID "0000000000000000000000000000000000000000" + #ifndef GIT_CONFIG #define GIT_CONFIG "git config" #endif @@ -444,6 +446,7 @@ static char opt_path[SIZEOF_STR] = ""; static char opt_file[SIZEOF_STR] = ""; static char opt_ref[SIZEOF_REF] = ""; static char opt_head[SIZEOF_REF] = ""; +static bool opt_no_head = TRUE; static FILE *opt_pipe = NULL; static char opt_encoding[20] = "UTF-8"; static bool opt_utf8 = TRUE; @@ -521,7 +524,7 @@ parse_options(int argc, char *argv[]) return FALSE; } else if (!strcmp(opt, "-h") || !strcmp(opt, "--help")) { - printf(usage); + printf("%s\n", usage); return FALSE; } @@ -579,12 +582,12 @@ LINE(ACKED, " Acked-by", COLOR_YELLOW, COLOR_DEFAULT, 0), \ LINE(DEFAULT, "", COLOR_DEFAULT, COLOR_DEFAULT, A_NORMAL), \ LINE(CURSOR, "", COLOR_WHITE, COLOR_GREEN, A_BOLD), \ LINE(STATUS, "", COLOR_GREEN, COLOR_DEFAULT, 0), \ +LINE(DELIMITER, "", COLOR_MAGENTA, COLOR_DEFAULT, 0), \ LINE(TITLE_BLUR, "", COLOR_WHITE, COLOR_BLUE, 0), \ LINE(TITLE_FOCUS, "", COLOR_WHITE, COLOR_BLUE, A_BOLD), \ LINE(MAIN_DATE, "", COLOR_BLUE, COLOR_DEFAULT, 0), \ LINE(MAIN_AUTHOR, "", COLOR_GREEN, COLOR_DEFAULT, 0), \ LINE(MAIN_COMMIT, "", COLOR_DEFAULT, COLOR_DEFAULT, 0), \ -LINE(MAIN_DELIM, "", COLOR_MAGENTA, COLOR_DEFAULT, 0), \ LINE(MAIN_TAG, "", COLOR_MAGENTA, COLOR_DEFAULT, A_BOLD), \ LINE(MAIN_LOCAL_TAG,"", COLOR_MAGENTA, COLOR_DEFAULT, A_BOLD), \ LINE(MAIN_REMOTE, "", COLOR_YELLOW, COLOR_DEFAULT, A_BOLD), \ @@ -650,8 +653,9 @@ get_line_attr(enum line_type type) } static struct line_info * -get_line_info(char *name, int namelen) +get_line_info(char *name) { + size_t namelen = strlen(name); enum line_type type; for (type = 0; type < ARRAY_SIZE(line_info); type++) @@ -1047,10 +1051,15 @@ option_color_command(int argc, char *argv[]) return ERR; } - info = get_line_info(argv[0], strlen(argv[0])); + info = get_line_info(argv[0]); if (!info) { - config_msg = "Unknown color name"; - return ERR; + if (!string_enum_compare(argv[0], "main-delim", strlen("main-delim"))) { + info = get_line_info("delimiter"); + + } else { + config_msg = "Unknown color name"; + return ERR; + } } if (set_color(&info->fg, argv[1]) == ERR || @@ -1437,7 +1446,7 @@ static struct view views[] = { static int draw_text(struct view *view, const char *string, int max_len, - bool use_tilde, int tilde_attr) + bool use_tilde, bool selected) { int len = 0; int trimmed = FALSE; @@ -1460,8 +1469,8 @@ draw_text(struct view *view, const char *string, int max_len, waddnstr(view->win, string, len); if (trimmed && use_tilde) { - if (tilde_attr != -1) - wattrset(view->win, tilde_attr); + if (!selected) + wattrset(view->win, get_line_attr(LINE_DELIMITER)); waddch(view->win, '~'); len++; } @@ -2731,9 +2740,7 @@ pager_draw(struct view *view, struct line *line, unsigned int lineno, bool selec } } else { - int tilde_attr = get_line_attr(LINE_MAIN_DELIM); - - draw_text(view, text, view->width, TRUE, tilde_attr); + draw_text(view, text, view->width, TRUE, selected); } return TRUE; @@ -3407,9 +3414,9 @@ parse_blame_commit(struct view *view, char *text, int *blamed) blame = line->data; blame->commit = commit; + blame->header = !group; line->dirty = 1; } - blame->header = 1; return commit; } @@ -3519,7 +3526,6 @@ blame_read(struct view *view, char *line) static bool blame_draw(struct view *view, struct line *line, unsigned int lineno, bool selected) { - int tilde_attr = -1; struct blame *blame = line->data; int col = 0; @@ -3530,7 +3536,6 @@ blame_draw(struct view *view, struct line *line, unsigned int lineno, bool selec wchgat(view->win, -1, 0, LINE_CURSOR, NULL); } else { wattrset(view->win, A_NORMAL); - tilde_attr = get_line_attr(LINE_MAIN_DELIM); } if (opt_date) { @@ -3543,8 +3548,8 @@ blame_draw(struct view *view, struct line *line, unsigned int lineno, bool selec int timelen; timelen = strftime(buf, sizeof(buf), DATE_FORMAT, &blame->commit->time); - n = draw_text(view, buf, view->width - col, FALSE, tilde_attr); - draw_text(view, " ", view->width - col - n, FALSE, tilde_attr); + n = draw_text(view, buf, view->width - col, FALSE, selected); + draw_text(view, " ", view->width - col - n, FALSE, selected); } col += DATE_COLS; @@ -3559,7 +3564,7 @@ blame_draw(struct view *view, struct line *line, unsigned int lineno, bool selec if (!selected) wattrset(view->win, get_line_attr(LINE_MAIN_AUTHOR)); if (blame->commit) - draw_text(view, blame->commit->author, max, TRUE, tilde_attr); + draw_text(view, blame->commit->author, max, TRUE, selected); col += AUTHOR_COLS; if (col >= view->width) return TRUE; @@ -3601,7 +3606,7 @@ blame_draw(struct view *view, struct line *line, unsigned int lineno, bool selec max = view->width - col; if (!selected) wattrset(view->win, get_line_attr(LINE_BLAME_LINENO)); - col += draw_text(view, number, max, showtrimmed, tilde_attr); + col += draw_text(view, number, max, showtrimmed, selected); if (col >= view->width) return TRUE; } @@ -3617,7 +3622,7 @@ blame_draw(struct view *view, struct line *line, unsigned int lineno, bool selec return TRUE; waddch(view->win, ' '); col++; - col += draw_text(view, blame->text, view->width - col, TRUE, tilde_attr); + col += draw_text(view, blame->text, view->width - col, TRUE, selected); return TRUE; } @@ -3635,7 +3640,7 @@ blame_request(struct view *view, enum request request, struct line *line) break; } - if (!strcmp(blame->commit->id, "0000000000000000000000000000000000000000")) { + if (!strcmp(blame->commit->id, NULL_ID)) { char path[SIZEOF_STR]; if (sq_quote(path, 0, view->vid) >= sizeof(path)) @@ -3690,7 +3695,7 @@ blame_select(struct view *view, struct line *line) if (!commit) return; - if (!strcmp(commit->id, "0000000000000000000000000000000000000000")) + if (!strcmp(commit->id, NULL_ID)) string_ncopy(ref_commit, "HEAD", 4); else string_copy_rev(ref_commit, commit->id); @@ -3762,7 +3767,7 @@ status_get_diff(struct status *file, char *buf, size_t bufsize) } static bool -status_run(struct view *view, const char cmd[], bool diff, enum line_type type) +status_run(struct view *view, const char cmd[], char status, enum line_type type) { struct status *file = NULL; struct status *unmerged = NULL; @@ -3801,8 +3806,10 @@ status_run(struct view *view, const char cmd[], bool diff, enum line_type type) } /* Parse diff info part. */ - if (!diff) { - file->status = '?'; + if (status) { + file->status = status; + if (status == 'A') + string_copy(file->old.rev, NULL_ID); } else if (!file->status) { if (!status_get_diff(file, buf, sepsize)) @@ -3878,6 +3885,8 @@ error_out: #define STATUS_DIFF_FILES_CMD "git diff-files -z" #define STATUS_LIST_OTHER_CMD \ "git ls-files -z --others --exclude-per-directory=.gitignore" +#define STATUS_LIST_NO_HEAD_CMD \ + "git ls-files -z --cached --exclude-per-directory=.gitignore" #define STATUS_DIFF_INDEX_SHOW_CMD \ "git diff-index --root --patch-with-stat -C -M --cached HEAD -- %s %s 2>/dev/null" @@ -3885,6 +3894,9 @@ error_out: #define STATUS_DIFF_FILES_SHOW_CMD \ "git diff-files --root --patch-with-stat -C -M -- %s %s 2>/dev/null" +#define STATUS_DIFF_NO_HEAD_SHOW_CMD \ + "git diff --no-color --patch-with-stat /dev/null %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). */ @@ -3893,8 +3905,10 @@ status_open(struct view *view) { struct stat statbuf; char exclude[SIZEOF_STR]; - char cmd[SIZEOF_STR]; + char indexcmd[SIZEOF_STR] = STATUS_DIFF_INDEX_CMD; + char othercmd[SIZEOF_STR] = STATUS_LIST_OTHER_CMD; unsigned long prev_lineno = view->lineno; + char indexstatus = 0; size_t i; for (i = 0; i < view->lines; i++) @@ -3907,29 +3921,40 @@ status_open(struct view *view) return FALSE; add_line_data(view, NULL, LINE_STAT_HEAD); - if (!*opt_head) + if (opt_no_head) + string_copy(status_onbranch, "Initial commit"); + else if (!*opt_head) string_copy(status_onbranch, "Not currently on any branch"); else if (!string_format(status_onbranch, "On branch %s", opt_head)) return FALSE; + if (opt_no_head) { + string_copy(indexcmd, STATUS_LIST_NO_HEAD_CMD); + indexstatus = 'A'; + } + if (!string_format(exclude, "%s/info/exclude", opt_git_dir)) return FALSE; - string_copy(cmd, STATUS_LIST_OTHER_CMD); - if (stat(exclude, &statbuf) >= 0) { - size_t cmdsize = strlen(cmd); + size_t cmdsize = strlen(othercmd); - if (!string_format_from(cmd, &cmdsize, " %s", "--exclude-from=") || - sq_quote(cmd, cmdsize, exclude) >= sizeof(cmd)) + if (!string_format_from(othercmd, &cmdsize, " %s", "--exclude-from=") || + sq_quote(othercmd, cmdsize, exclude) >= sizeof(othercmd)) + return FALSE; + + cmdsize = strlen(indexcmd); + if (opt_no_head && + (!string_format_from(indexcmd, &cmdsize, " %s", "--exclude-from=") || + sq_quote(indexcmd, cmdsize, exclude) >= sizeof(indexcmd))) return FALSE; } system("git update-index -q --refresh"); - if (!status_run(view, STATUS_DIFF_INDEX_CMD, TRUE, LINE_STAT_STAGED) || - !status_run(view, STATUS_DIFF_FILES_CMD, TRUE, LINE_STAT_UNSTAGED) || - !status_run(view, cmd, FALSE, LINE_STAT_UNTRACKED)) + if (!status_run(view, indexcmd, indexstatus, LINE_STAT_STAGED) || + !status_run(view, STATUS_DIFF_FILES_CMD, 0, LINE_STAT_UNSTAGED) || + !status_run(view, othercmd, '?', LINE_STAT_UNTRACKED)) return FALSE; /* If all went well restore the previous line number to stay in @@ -3953,14 +3978,12 @@ static bool status_draw(struct view *view, struct line *line, unsigned int lineno, bool selected) { struct status *status = line->data; - int tilde_attr = get_line_attr(LINE_MAIN_DELIM); wmove(view->win, lineno, 0); if (selected) { wattrset(view->win, get_line_attr(LINE_CURSOR)); wchgat(view->win, -1, 0, LINE_CURSOR, NULL); - tilde_attr = -1; } else if (line->type == LINE_STAT_HEAD) { wattrset(view->win, get_line_attr(LINE_STAT_HEAD)); @@ -4002,7 +4025,7 @@ status_draw(struct view *view, struct line *line, unsigned int lineno, bool sele return FALSE; } - draw_text(view, text, view->width, TRUE, tilde_attr); + draw_text(view, text, view->width, TRUE, selected); return TRUE; } @@ -4013,7 +4036,7 @@ status_draw(struct view *view, struct line *line, unsigned int lineno, bool sele if (view->width < 5) return TRUE; - draw_text(view, status->new.name, view->width - 5, TRUE, tilde_attr); + draw_text(view, status->new.name, view->width - 5, TRUE, selected); return TRUE; } @@ -4049,9 +4072,18 @@ status_enter(struct view *view, struct line *line) switch (line->type) { case LINE_STAT_STAGED: - if (!string_format_from(opt_cmd, &cmdsize, - STATUS_DIFF_INDEX_SHOW_CMD, oldpath, newpath)) - return REQ_QUIT; + if (opt_no_head) { + if (!string_format_from(opt_cmd, &cmdsize, + STATUS_DIFF_NO_HEAD_SHOW_CMD, + newpath)) + return REQ_QUIT; + } else { + if (!string_format_from(opt_cmd, &cmdsize, + STATUS_DIFF_INDEX_SHOW_CMD, + oldpath, newpath)) + return REQ_QUIT; + } + if (status) info = "Staged changes to %s"; else @@ -4072,7 +4104,6 @@ status_enter(struct view *view, struct line *line) if (opt_pipe) return REQ_QUIT; - if (!status) { report("No file to show"); return REQ_NONE; @@ -4162,7 +4193,7 @@ status_update_file(struct view *view, struct status *status, enum line_type type return TRUE; } -static void +static bool status_update(struct view *view) { struct line *line = &view->line[view->lineno]; @@ -4177,12 +4208,14 @@ status_update(struct view *view) if (!line[-1].data) { report("Nothing to update"); - return; + return FALSE; } } else if (!status_update_file(view, line->data, line->type)) { report("Failed to update file status"); } + + return TRUE; } static enum request @@ -4192,7 +4225,8 @@ status_request(struct view *view, enum request request, struct line *line) switch (request) { case REQ_STATUS_UPDATE: - status_update(view); + if (!status_update(view)) + return REQ_NONE; break; case REQ_STATUS_MERGE: @@ -4436,7 +4470,7 @@ stage_update_chunk(struct view *view, struct line *line) static void stage_update(struct view *view, struct line *line) { - if (stage_line_type != LINE_STAT_UNTRACKED && + if (!opt_no_head && stage_line_type != LINE_STAT_UNTRACKED && (line->type == LINE_DIFF_CHUNK || !stage_status.status)) { if (!stage_update_chunk(view, line)) { report("Failed to apply chunk"); @@ -4717,7 +4751,6 @@ main_draw(struct view *view, struct line *line, unsigned int lineno, bool select enum line_type type; int col = 0; size_t timelen; - int tilde_attr; int space; if (!*commit->author) @@ -4730,19 +4763,17 @@ main_draw(struct view *view, struct line *line, unsigned int lineno, bool select type = LINE_CURSOR; wattrset(view->win, get_line_attr(type)); wchgat(view->win, -1, 0, type, NULL); - tilde_attr = -1; } else { type = LINE_MAIN_COMMIT; wattrset(view->win, get_line_attr(LINE_MAIN_DATE)); - tilde_attr = get_line_attr(LINE_MAIN_DELIM); } if (opt_date) { int n; timelen = strftime(buf, sizeof(buf), DATE_FORMAT, &commit->time); - n = draw_text(view, buf, view->width - col, FALSE, tilde_attr); - draw_text(view, " ", view->width - col - n, FALSE, tilde_attr); + n = draw_text(view, buf, view->width - col, FALSE, selected); + draw_text(view, " ", view->width - col - n, FALSE, selected); col += DATE_COLS; wmove(view->win, lineno, col); @@ -4758,7 +4789,7 @@ main_draw(struct view *view, struct line *line, unsigned int lineno, bool select max_len = view->width - col; if (max_len > AUTHOR_COLS - 1) max_len = AUTHOR_COLS - 1; - draw_text(view, commit->author, max_len, TRUE, tilde_attr); + draw_text(view, commit->author, max_len, TRUE, selected); col += AUTHOR_COLS; if (col >= view->width) return TRUE; @@ -4805,13 +4836,13 @@ main_draw(struct view *view, struct line *line, unsigned int lineno, bool select else wattrset(view->win, get_line_attr(LINE_MAIN_REF)); - col += draw_text(view, "[", view->width - col, TRUE, tilde_attr); + col += draw_text(view, "[", view->width - col, TRUE, selected); col += draw_text(view, commit->refs[i]->name, view->width - col, - TRUE, tilde_attr); - col += draw_text(view, "]", view->width - col, TRUE, tilde_attr); + TRUE, selected); + col += draw_text(view, "]", view->width - col, TRUE, selected); if (type != LINE_CURSOR) wattrset(view->win, A_NORMAL); - col += draw_text(view, " ", view->width - col, TRUE, tilde_attr); + col += draw_text(view, " ", view->width - col, TRUE, selected); if (col >= view->width) return TRUE; } while (commit->refs[i++]->next); @@ -4820,7 +4851,7 @@ main_draw(struct view *view, struct line *line, unsigned int lineno, bool select if (type != LINE_CURSOR) wattrset(view->win, get_line_attr(type)); - draw_text(view, commit->title, view->width - col, TRUE, tilde_attr); + draw_text(view, commit->title, view->width - col, TRUE, selected); return TRUE; } @@ -5435,6 +5466,7 @@ read_ref(char *id, size_t idlen, char *name, size_t namelen) head = !strncmp(opt_head, name, namelen); } else if (!strcmp(name, "HEAD")) { + opt_no_head = FALSE; return OK; }