Code

Make command line parsing more compatible with gitk
authorJonas Fonseca <fonseca@diku.dk>
Thu, 7 Feb 2008 19:00:38 +0000 (20:00 +0100)
committerJonas Fonseca <fonseca@diku.dk>
Mon, 17 Mar 2008 01:22:25 +0000 (02:22 +0100)
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
manual.txt
tig.1.txt
tig.c

index 3b6fd6dd2339a5f46ea8db8734e86180bf8c9bce..79b414bab42235a82d249e49ba24de6c52ed3b7f 100755 (executable)
@@ -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)
                " ;;
index efdb0799fa800ccc27204f4b816c749856cf7ae9..ca015613e9eb3a5f6bf26ea83944ae9f7cccd5af 100644 (file)
@@ -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 <<refspec, "Specifying revisions">> 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[]
index 7b1c779ebfc2becea792ca0772d51509edd5ce98..8730c06c52abaa1b7f577c77baea4c7d4ddcd8b0 100644 (file)
--- 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 c44409e8c85bd88bcda3522ea0c618a71d5878e0..89a4c5d72996a8b026e1d012f79902b9ac2a4538 100644 (file)
--- 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[])
 {