From 77452abca082e3d7d6ec4f079928583aa1ad6f50 Mon Sep 17 00:00:00 2001 From: Jonas Fonseca Date: Thu, 7 Feb 2008 20:00:38 +0100 Subject: [PATCH] Make command line parsing more compatible with gitk Many of the command line arguments are relics from the beginning of the project and served as a method of configuring tig before support for the configuration file was introduced. Since then they have become less useful and make tig less compatible with gitk and other git repo viewers. This commit tries to fix this by deprecating all command line arguments except the very tig specific version and help arguments. The option to enter the status view (-S) is moved to a new "status" subcommand. Tig will warn about the deprecation and advise -S users to use the new subcommand. The handling of "--" is kept as it is for compatibility, but will be removed in a future version. Finally, the man page and manual was updated to reflect the new options and subcommands. So enjoy the new less cludgy `tig --all' ... I will! :) --- contrib/tig-completion.bash | 44 ++++++++---------- manual.txt | 28 ++++++------ tig.1.txt | 69 ++++++++++------------------ tig.c | 91 +++++++++++++++++++++++++------------ 4 files changed, 118 insertions(+), 114 deletions(-) diff --git a/contrib/tig-completion.bash b/contrib/tig-completion.bash index 3b6fd6d..79b414b 100755 --- a/contrib/tig-completion.bash +++ b/contrib/tig-completion.bash @@ -43,7 +43,7 @@ __tigdir () fi } -tigcomp () +_tigcomp () { local all c s=$'\n' IFS=' '$'\t'$'\n' local cur="${COMP_WORDS[COMP_CWORD]}" @@ -120,7 +120,7 @@ __tig_complete_file () -- "$cur")) ;; *) - tigcomp "$(__tig_refs)" + _tigcomp "$(__tig_refs)" ;; esac } @@ -132,39 +132,34 @@ __tig_complete_revlist () *...*) pfx="${cur%...*}..." cur="${cur#*...}" - tigcomp "$(__tig_refs)" "$pfx" "$cur" + _tigcomp "$(__tig_refs)" "$pfx" "$cur" ;; *..*) pfx="${cur%..*}.." cur="${cur#*..}" - tigcomp "$(__tig_refs)" "$pfx" "$cur" + _tigcomp "$(__tig_refs)" "$pfx" "$cur" ;; *.) - tigcomp "$cur." + _tigcomp "$cur." ;; *) - tigcomp "$(__tig_refs)" + _tigcomp "$(__tig_refs)" ;; esac } -_tig_diff () -{ - __tig_complete_file -} - -_tig_log () +_tig_options () { local cur="${COMP_WORDS[COMP_CWORD]}" case "$cur" in --pretty=*) - tigcomp " + _tigcomp " oneline short medium full fuller email raw " "" "${cur##--pretty=}" return ;; --*) - tigcomp " + _tigcomp " --max-count= --max-age= --since= --after= --min-age= --before= --until= --root --not --topo-order --date-order @@ -175,9 +170,14 @@ _tig_log () --all-match --pretty= --name-status --name-only --not --all + --help --version " return ;; + -*) + _tigcomp "-v -h" + return + ;; esac __tig_complete_revlist } @@ -187,13 +187,13 @@ _tig_show () local cur="${COMP_WORDS[COMP_CWORD]}" case "$cur" in --pretty=*) - tigcomp " + _tigcomp " oneline short medium full fuller email raw " "" "${cur##--pretty=}" return ;; --*) - tigcomp "--pretty=" + _tigcomp "--pretty=" return ;; esac @@ -217,20 +217,16 @@ _tig () if [ $c -eq $COMP_CWORD -a -z "$command" ]; then case "${COMP_WORDS[COMP_CWORD]}" in --*=*) COMPREPLY=() ;; - -*) tigcomp " - --line-number= --tab-size= --version --help - -b -d -h -l -S -v - " ;; - *) tigcomp "log diff show $(__tig_refs)" ;; + -*) _tig_options ;; + *) _tigcomp "status show $(__tig_refs)" ;; esac return fi case "$command" in - diff) _tig_diff ;; show) _tig_show ;; - log) _tig_log ;; - *) tigcomp " + status) ;; + *) _tigcomp " $(__tig_complete_file) $(__tig_refs) " ;; diff --git a/manual.txt b/manual.txt index efdb079..ca01561 100644 --- a/manual.txt +++ b/manual.txt @@ -47,11 +47,11 @@ NOTE: If you specify options for the main view, you should not use the `--pretty` option as this option will be set automatically to the format expected by the main view. -Example on how to open the log view and show both author and committer +Example on how to view a commit and show both author and committer information: ----------------------------------------------------------------------------- -$ tig log --pretty=fuller +$ tig show --pretty=fuller ----------------------------------------------------------------------------- See the <> section below for an introduction @@ -399,16 +399,16 @@ 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 README +$ tig 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: +To avoid ambiguity with tig's subcommands or repository references such as tag +name, be sure to separate file names from other git options using "\--". So if +you have a file named 'status' it will clash with the 'status' subcommand, and +thus you will have to use: ----------------------------------------------------------------------------- -$ tig log -- master +$ tig -- status ----------------------------------------------------------------------------- NOTE: For the main view, avoiding ambiguity will in some cases require you to @@ -427,7 +427,7 @@ 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" +$ tig --after="May 5th" --before="2006-05-16 15:44" ----------------------------------------------------------------------------- NOTE: If you want to avoid having to quote dates containing spaces you can use @@ -441,7 +441,7 @@ Alternatively, commits can be limited to a specific range, such as "all commits between 'tag-1.0' and 'tag-2.0'". For example: ----------------------------------------------------------------------------- -$ tig log tag-1.0..tag-2.0 +$ tig tag-1.0..tag-2.0 ----------------------------------------------------------------------------- This way of commit limiting makes it trivial to only browse the commits which @@ -449,7 +449,7 @@ haven't been pushed to a remote branch. Assuming 'origin' is your upstream remote branch, using: ----------------------------------------------------------------------------- -$ tig log origin..HEAD +$ tig origin..HEAD ----------------------------------------------------------------------------- will list what will be pushed to the remote branch. Optionally, the ending @@ -468,7 +468,7 @@ If you prefer to specify which commit to preview in this way use the following: ----------------------------------------------------------------------------- -$ tig log tag-2.0 ^tag-1.0 +$ tig tag-2.0 ^tag-1.0 ----------------------------------------------------------------------------- You can think of '^' as a negation operator. Using this alternate syntax, it @@ -483,7 +483,7 @@ say "show at most 20 commits from within the last month that changed files under the Documentation/ directory." ----------------------------------------------------------------------------- -$ tig -- --since=1.month -n20 -- Documentation/ +$ tig --since=1.month -n20 -- Documentation/ ----------------------------------------------------------------------------- [[refspec-all]] @@ -496,7 +496,7 @@ repository change a particular file within the last week". This can be accomplished using: ----------------------------------------------------------------------------- -$ tig -- --all --since=1.week -- Makefile +$ tig --all --since=1.week -- Makefile ----------------------------------------------------------------------------- include::BUGS[] diff --git a/tig.1.txt b/tig.1.txt index 7b1c779..8730c06 100644 --- a/tig.1.txt +++ b/tig.1.txt @@ -8,12 +8,10 @@ tig - text-mode interface for git SYNOPSIS -------- [verse] -tig [options] -tig [options] [--] [git options] -tig [options] log [git options] -tig [options] diff [git options] -tig [options] show [git options] -tig [options] < [git command output] +tig [options] [revisions] [--] [paths] +tig show [options] [revisions] [--] [paths] +tig status +tig < [git command output] DESCRIPTION ----------- @@ -30,22 +28,19 @@ to colorize it. OPTIONS ------- --l:: - Start up in log view using the internal log command. +Command line options recognized by tig include all valid git-log(1) and +git-diff(1) options, as well as the following subcommands and tig specific +options. The first command line parameter not starting with "-" is interpreted +as being either a revision specification or a path and will end the option +parsing. All following options will be passed untouched to the underlying git +command. --d:: - Start up in diff view using the internal diff command. +show:: + Open diff view using the given git show options. --S:: +status:: Start up in status view. --n[INTERVAL], --line-number[=INTERVAL]:: - Prefix line numbers in log and diff view. - Optionally, with interval different than each line. - --b[NSPACES], --tab-size[=NSPACES]:: - Set the number of spaces tabs should be expanded to. - -v, --version:: Show version and exit. @@ -53,32 +48,9 @@ OPTIONS Show help message and exit. \--:: - End of tig(1) options. Useful when specifying command - options for the main view. Example: -+ ----------------------------------------------------------------------------- -$ tig -- --since=1.month ------------------------------------------------------------------------------ - -log:: - Open log view using the given git log options. - -diff:: - Open diff view using the given git diff options. - -show:: - Open diff view using the given git show options. - -[git options]:: - tig(1) will stop the option parsing when the first - command line parameter not starting with "-" is - encountered. All options including this one will be - passed to git log when loading the main view. - This makes it possible to say: -+ ------------------------------------------------------------------------------ -$ tig tag-1.0..HEAD ------------------------------------------------------------------------------ + End of tig options. This ends tig option parsing, and passes any + following options untouched to the underlying git command. Kept for + compatibility and will be deprecated in a future version. EXAMPLES -------- @@ -95,7 +67,7 @@ $ tig test master Display all branches: ----------------------------------------------------------------------------- -$ tig -- --all +$ tig --all ----------------------------------------------------------------------------- Display differences between two branches: @@ -108,9 +80,14 @@ Display changes for a single file: $ tig -- README ----------------------------------------------------------------------------- +Display contents of the README file in a specific revision: +----------------------------------------------------------------------------- +$ tig show tig-0.8:README +----------------------------------------------------------------------------- + Display revisions between two dates for a specific file: ----------------------------------------------------------------------------- -$ tig -- --after "2004-01-01" --before="2006-05-16" -- README +$ tig --after="2004-01-01" --before="2006-05-16" -- README ----------------------------------------------------------------------------- ENVIRONMENT VARIABLES diff --git a/tig.c b/tig.c index c44409e..89a4c5d 100644 --- a/tig.c +++ b/tig.c @@ -51,6 +51,7 @@ #endif static void __NORETURN die(const char *err, ...); +static void warn(const char *msg, ...); static void report(const char *msg, ...); static int read_properties(FILE *pipe, const char *separators, int (*read)(char *, size_t, char *, size_t)); static void set_nonblocking_input(bool loading); @@ -408,22 +409,14 @@ get_request(const char *name) static const char usage[] = "tig " TIG_VERSION " (" __DATE__ ")\n" "\n" -"Usage: tig [options]\n" -" or: tig [options] [--] [git log options]\n" -" or: tig [options] log [git log options]\n" -" or: tig [options] diff [git diff options]\n" -" or: tig [options] show [git show options]\n" -" or: tig [options] < [git command output]\n" +"Usage: tig [options] [revs] [--] [paths]\n" +" or: tig show [options] [revs] [--] [paths]\n" +" or: tig status\n" +" or: tig < [git command output]\n" "\n" "Options:\n" -" -l Start up in log view\n" -" -d Start up in diff view\n" -" -S Start up in status view\n" -" -n[I], --line-number[=I] Show line numbers with given interval\n" -" -b[N], --tab-size[=N] Set number of spaces for tab expansion\n" -" -- Mark end of tig options\n" -" -v, --version Show version and exit\n" -" -h, --help Show help message and exit\n"; +" -v, --version Show version and exit\n" +" -h, --help Show help message and exit\n"; /* Option and state variables. */ static bool opt_line_number = FALSE; @@ -491,16 +484,32 @@ check_option(char *opt, char short_name, char *name, enum option_type type, ...) static bool parse_options(int argc, char *argv[]) { + char *altargv[1024]; + int altargc = 0; + char *subcommand = NULL; int i; for (i = 1; i < argc; i++) { char *opt = argv[i]; if (!strcmp(opt, "log") || - !strcmp(opt, "diff") || - !strcmp(opt, "show")) { + !strcmp(opt, "diff")) { + subcommand = opt; opt_request = opt[0] == 'l' ? REQ_VIEW_LOG : REQ_VIEW_DIFF; + warn("`tig %s' has been deprecated", opt); + break; + } + + if (!strcmp(opt, "show")) { + subcommand = opt; + opt_request = REQ_VIEW_DIFF; + break; + } + + if (!strcmp(opt, "status")) { + subcommand = opt; + opt_request = REQ_VIEW_STATUS; break; } @@ -523,38 +532,43 @@ parse_options(int argc, char *argv[]) } if (!strcmp(opt, "-S")) { + warn("`%s' has been deprecated; use `tig status' instead", opt); opt_request = REQ_VIEW_STATUS; continue; } if (!strcmp(opt, "-l")) { opt_request = REQ_VIEW_LOG; - continue; - } - - if (!strcmp(opt, "-d")) { + } else if (!strcmp(opt, "-d")) { opt_request = REQ_VIEW_DIFF; - continue; - } - - if (check_option(opt, 'n', "line-number", OPT_INT, &opt_num_interval)) { + } else if (check_option(opt, 'n', "line-number", OPT_INT, &opt_num_interval)) { opt_line_number = TRUE; - continue; - } - - if (check_option(opt, 'b', "tab-size", OPT_INT, &opt_tab_size)) { + } else if (check_option(opt, 'b', "tab-size", OPT_INT, &opt_tab_size)) { opt_tab_size = MIN(opt_tab_size, TABSIZE); + } else { + if (altargc >= ARRAY_SIZE(altargv)) + die("maximum number of arguments exceeded"); + altargv[altargc++] = opt; continue; } - die("unknown option '%s'\n\n%s", opt, usage); + warn("`%s' has been deprecated", opt); } + /* Check that no 'alt' arguments occured before a subcommand. */ + if (subcommand && i < argc && altargc > 0) + die("unknown arguments before `%s'", argv[i]); + if (!isatty(STDIN_FILENO)) { opt_request = REQ_VIEW_PAGER; opt_pipe = stdin; - } else if (i < argc) { + } else if (opt_request == REQ_VIEW_STATUS) { + if (argc - i > 1) + warn("ignoring arguments after `%s'", argv[i]); + + } else if (i < argc || altargc > 0) { + int alti = 0; size_t buf_size; if (opt_request == REQ_VIEW_MAIN) @@ -565,6 +579,11 @@ parse_options(int argc, char *argv[]) string_copy(opt_cmd, "git"); buf_size = strlen(opt_cmd); + while (buf_size < sizeof(opt_cmd) && alti < altargc) { + opt_cmd[buf_size++] = ' '; + buf_size = sq_quote(opt_cmd, buf_size, altargv[alti++]); + } + while (buf_size < sizeof(opt_cmd) && i < argc) { opt_cmd[buf_size++] = ' '; buf_size = sq_quote(opt_cmd, buf_size, argv[i++]); @@ -4929,6 +4948,18 @@ die(const char *err, ...) exit(1); } +static void +warn(const char *msg, ...) +{ + va_list args; + + va_start(args, msg); + fputs("tig warning: ", stderr); + vfprintf(stderr, msg, args); + fputs("\n", stderr); + va_end(args); +} + int main(int argc, char *argv[]) { -- 2.30.2