X-Git-Url: https://git.distorted.org.uk/~mdw/tig/blobdiff_plain/424aff35dbb21dd92c4b7b72d2e3f8257ce4856b..4d55caff4cc89335192f3e566004b4ceef572521:/tig.c diff --git a/tig.c b/tig.c index ca2c6e5..e57206c 100644 --- a/tig.c +++ b/tig.c @@ -32,7 +32,7 @@ **/ #ifndef VERSION -#define VERSION "tig-0.1" +#define VERSION "tig-0.3" #endif #ifndef DEBUG @@ -146,7 +146,7 @@ struct commit { */ static inline void -string_ncopy(char *dst, char *src, int dstlen) +string_ncopy(char *dst, const char *src, int dstlen) { strncpy(dst, src, dstlen - 1); dst[dstlen - 1] = 0; @@ -180,7 +180,7 @@ sq_quote(char buf[SIZEOF_CMD], size_t bufsize, const char *src) { char c; -#define BUFPUT(x) ( (bufsize < SIZEOF_CMD) && (buf[bufsize++] = (x)) ) +#define BUFPUT(x) do { if (bufsize < SIZEOF_CMD) buf[bufsize++] = (x); } while (0) BUFPUT('\''); while ((c = *src++)) { @@ -458,7 +458,7 @@ enum line_type { }; struct line_info { - char *line; /* The start of line to match. */ + const char *line; /* The start of line to match. */ int linelen; /* Size of string to match. */ int fg, bg, attr; /* Color and text attributes for the lines. */ }; @@ -542,7 +542,7 @@ init_colors(void) **/ #define TIG_LS_REMOTE \ - "git ls-remote ." + "git ls-remote . 2>/dev/null" /** * [[view-commands]] @@ -586,7 +586,7 @@ init_colors(void) /* ... silently ignore that the following are also exported. */ #define TIG_HELP_CMD \ - "man tig 2> /dev/null" + "man tig 2>/dev/null" #define TIG_PAGER_CMD \ "" @@ -600,7 +600,7 @@ init_colors(void) * * The main view:: * Is the default view, and it shows a one line summary of each commit - * in the chosen list of revision. The summary includes commit date, + * in the chosen list of revisions. The summary includes commit date, * author, and the first line of the log message. Additionally, any * repository references, such as tags, will be shown. * @@ -624,15 +624,15 @@ init_colors(void) struct view { const char *name; /* View name */ - char *cmd_fmt; /* Default command line format */ - char *cmd_env; /* Command line set via environment */ - char *id; /* Points to either of ref_{head,commit} */ + const char *cmd_fmt; /* Default command line format */ + const char *cmd_env; /* Command line set via environment */ + const char *id; /* Points to either of ref_{head,commit} */ size_t objsize; /* Size of objects in the line index */ struct view_ops { /* What type of content being displayed. Used in the * title bar. */ - char *type; + const char *type; /* Draw one line; @lineno must be < view->height. */ bool (*draw)(struct view *view, unsigned int lineno); /* Read one line; updates view->line. */ @@ -666,8 +666,8 @@ struct view { static struct view_ops pager_ops; static struct view_ops main_ops; -char ref_head[SIZEOF_REF] = "HEAD"; -char ref_commit[SIZEOF_REF] = "HEAD"; +static char ref_head[SIZEOF_REF] = "HEAD"; +static char ref_commit[SIZEOF_REF] = "HEAD"; #define VIEW_STR(name, cmd, env, ref, objsize, ops) \ { name, cmd, #env, ref, objsize, ops } @@ -715,6 +715,35 @@ redraw_view(struct view *view) } static void +update_view_title(struct view *view) +{ + if (view == display[current_view]) + wbkgdset(view->title, get_line_attr(LINE_TITLE_FOCUS)); + else + wbkgdset(view->title, get_line_attr(LINE_TITLE_BLUR)); + + werase(view->title); + wmove(view->title, 0, 0); + + /* [main] ref: 334b506... - commit 6 of 4383 (0%) */ + + if (*view->ref) + wprintw(view->title, "[%s] %s", view->name, view->ref); + else + wprintw(view->title, "[%s]", view->name); + + if (view->lines) { + wprintw(view->title, " - %s %d of %d (%d%%)", + view->ops->type, + view->lineno + 1, + view->lines, + (view->lineno + 1) * 100 / view->lines); + } + + wrefresh(view->title); +} + +static void resize_display(void) { int offset, i; @@ -744,9 +773,9 @@ resize_display(void) offset = 0; foreach_view (view, i) { - /* Keep the size of the all view windows one lager than is - * required. This makes current line management easier when the - * cursor will go outside the window. */ + /* Keep the height of all view->win windows one larger than is + * required so that the cursor can wrap-around on the last line + * without scrolling the window. */ if (!view->win) { view->win = newwin(view->height + 1, 0, offset, 0); if (!view->win) @@ -770,34 +799,18 @@ resize_display(void) } static void -update_view_title(struct view *view) +redraw_display(void) { - if (view == display[current_view]) - wbkgdset(view->title, get_line_attr(LINE_TITLE_FOCUS)); - else - wbkgdset(view->title, get_line_attr(LINE_TITLE_BLUR)); - - werase(view->title); - wmove(view->title, 0, 0); - - /* [main] ref: 334b506... - commit 6 of 4383 (0%) */ - - if (*view->ref) - wprintw(view->title, "[%s] %s", view->name, view->ref); - else - wprintw(view->title, "[%s]", view->name); + struct view *view; + int i; - if (view->lines) { - wprintw(view->title, " - %s %d of %d (%d%%)", - view->ops->type, - view->lineno + 1, - view->lines, - (view->lineno + 1) * 100 / view->lines); + foreach_view (view, i) { + redraw_view(view); + update_view_title(view); } - - wrefresh(view->title); } + /* * Navigation */ @@ -987,7 +1000,7 @@ move_view(struct view *view, enum request request) static bool begin_update(struct view *view) { - char *id = view->id; + const char *id = view->id; if (opt_cmd[0]) { string_copy(view->cmd, opt_cmd); @@ -996,7 +1009,7 @@ begin_update(struct view *view) * invalid so clear it. */ view->ref[0] = 0; } else { - char *format = view->cmd_env ? view->cmd_env : view->cmd_fmt; + const char *format = view->cmd_env ? view->cmd_env : view->cmd_fmt; if (snprintf(view->cmd, sizeof(view->cmd), format, id, id, id, id, id) >= sizeof(view->cmd)) @@ -1125,7 +1138,7 @@ update_view(struct view *view) time_t secs = time(NULL) - view->start_time; if (view == VIEW(REQ_VIEW_HELP)) { - char *msg = TIG_HELP; + const char *msg = TIG_HELP; if (view->lines == 0) { /* Slightly ugly, but abusing view->ref keeps @@ -1310,8 +1323,7 @@ view_driver(struct view *view, enum request request) } case REQ_TOGGLE_LINE_NUMBERS: opt_line_number = !opt_line_number; - redraw_view(view); - update_view_title(view); + redraw_display(); break; case REQ_PROMPT: @@ -1335,10 +1347,7 @@ view_driver(struct view *view, enum request request) resize_display(); /* Fall-through */ case REQ_SCREEN_REDRAW: - foreach_view (view, i) { - redraw_view(view); - update_view_title(view); - } + redraw_display(); break; case REQ_SCREEN_UPDATE: @@ -1693,7 +1702,7 @@ struct keymap { int request; }; -struct keymap keymap[] = { +static struct keymap keymap[] = { /** * View switching * ~~~~~~~~~~~~~~ @@ -1919,7 +1928,7 @@ init_display(void) */ static struct ref *refs; -size_t refs_size; +static size_t refs_size; static struct ref ** get_refs(char *id) @@ -1959,8 +1968,8 @@ get_refs(char *id) static int load_refs(void) { - char *cmd_env = getenv("TIG_LS_REMOTE"); - char *cmd = cmd_env && *cmd_env ? cmd_env : TIG_LS_REMOTE; + const char *cmd_env = getenv("TIG_LS_REMOTE"); + const char *cmd = cmd_env && *cmd_env ? cmd_env : TIG_LS_REMOTE; FILE *pipe = popen(cmd, "r"); char buffer[BUFSIZ]; char *line; @@ -2021,6 +2030,9 @@ load_refs(void) pclose(pipe); + if (refs_size == 0) + die("Not a git repository"); + return OK; } @@ -2028,7 +2040,13 @@ load_refs(void) * Main */ -static void +#if __GNUC__ >= 3 +#define __NORETURN __attribute__((__noreturn__)) +#else +#define __NORETURN +#endif + +static void __NORETURN quit(int sig) { /* XXX: Restore tty modes and let the OS cleanup the rest! */ @@ -2037,7 +2055,8 @@ quit(int sig) exit(0); } -static void die(const char *err, ...) +static void __NORETURN +die(const char *err, ...) { va_list args; @@ -2131,25 +2150,31 @@ main(int argc, char *argv[]) /** * [[refspec]] - * Specifying revisions - * -------------------- + * Revision specification + * ---------------------- * This section describes various ways to specify what revisions to display - * or otherwise limit the view to. Note, that tig(1) does not itself parse - * the described revision options. + * or otherwise limit the view to. tig(1) does not itself parse the described + * revision options so refer to the relevant git man pages for futher + * information. Relevant man pages besides git-log(1) are git-diff(1) and + * git-rev-list(1). + * + * You can tune the interaction with git by making use of the options + * explained in this section. For example, by configuring the environment + * variables described in the <> section. * - * File history - * ~~~~~~~~~~~~ + * Limit by path name + * ~~~~~~~~~~~~~~~~~~ * If you are interested only in those revisions that made changes to a * specific file (or even several files) list the files like this: * - * $ tig log Makefile + * $ tig log Makefile README * * To avoid ambiguity with repository references such as tag name, be sure * to separate file names from other git options using "\--". So if you * have a file named 'master' it will clash with the reference named * 'master', and thus you will have to use: * - * $ tag log -- master + * $ tig log -- master * * NOTE: For the main view, avoiding ambiguity will in some cases require * you to specify two "\--" options. The first will make tig(1) stop @@ -2161,12 +2186,16 @@ main(int argc, char *argv[]) * to show both for the log and main view. Either limit by date using * e.g. `--since=1.month` or limit by the number of commits using `-n400`. * - * NOTE: You can tune the interaction with git by making use of the options - * explained in this section. For example, by configuring the environment - * variables described in the <> section. + * If you are only interested in changed that happened between two dates + * you can use: + * + * $ tig -- --after="May 5th" --before="2006-05-16 15:44" * - * Ranges - * ~~~~~~ + * NOTE: If you want to avoid having to quote dates containing spaces you + * can use "." instead, e.g. `--after=May.5th`. + * + * Limiting by commit ranges + * ~~~~~~~~~~~~~~~~~~~~~~~~~ * Alternatively, commits can be limited to a specific range, such as * "all commits between 'tag-1.0' and 'tag-2.0'". For example: * @@ -2185,6 +2214,9 @@ main(int argc, char *argv[]) * ~~~~~~~~~~~~~~~~~~~~~~~~ * Git interprets the range specifier "tag-1.0..tag-2.0" as * "all commits reachable from 'tag-2.0' but not from 'tag-1.0'". + * Where reachability refers to what commits are ancestors (or part of the + * history) of the branch or tagged revision in question. + * * If you prefer to specify which commit to preview in this way use the * following: * @@ -2194,6 +2226,23 @@ main(int argc, char *argv[]) * it is possible to further prune commits by specifying multiple branch * cut offs. * + * Combining revisions specification + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * Revisions options can to some degree be combined, which makes it possible + * to say "show at most 20 commits from within the last month that changed + * files under the Documentation/ directory." + * + * $ tig -- --since=1.month -n20 -- Documentation/ + * + * Examining all repository references + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * In some cases, it can be useful to query changes across all references + * in a repository. An example is to ask "did any line of development in + * this repository change a particular file within the last week". This + * can be accomplished using: + * + * $ tig -- --all --since=1.week -- Makefile + * * BUGS * ---- * Known bugs and problems: @@ -2225,5 +2274,6 @@ main(int argc, char *argv[]) * link:http://www.kernel.org/pub/software/scm/git/docs/[git(7)], * link:http://www.kernel.org/pub/software/scm/cogito/docs/[cogito(7)] * gitk(1): git repository browser written using tcl/tk, + * qgit(1): git repository browser written using c++/Qt, * gitview(1): git repository browser written using python/gtk. **/