1

I sometimes use git diff with a --color-words='\w+|.' option to get the changes displayed inline and for whole words only.

Since I noticed that I'm using it a bit, I've made a git alias for diff --color-words='\w+|.'.

But now I notice, there are many other places where I'd like to use the same option, like git show, git stash show -p, git log -p and more probably. So it's impossible to predict where I might need that option in the future.

I've tried this:

$ git config --global alias.words "--color-words='\w+|.'"
$ git diff words
fatal: ambiguous argument 'words': unknown revision or path not in the working tree
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'

And this:

$ git config --global alias.--words "--color-words='\w+|.'"
error: invalid key: alias.--words

Is there any way to create an alias to an arduous option, so I can use it with various commands and save on typing and thinking?

arekolek
  • 9,128
  • 3
  • 58
  • 79

3 Answers3

1

Is there any way to create an alias to an arduous option?

Not with alias, no.

You still can use aliases to define your own diff/show/log command with that option. (diffw, showw, logw for instance)

Or you can consider writing a shell script (in bash, even on Windows since it is interpreted by the Git for Windows msys2), like git-diffw (without extension, set anywhere in your PATH) Any script called git-xxx alllows to use xxx as a Git command: git xxx.

That means you are in the script worls, where you can take advantage of common options (set for instance in a file, or in an environment variable)

Community
  • 1
  • 1
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • Regarding making an alias to every command, I don't think that's viable, since I can't predict with which commands I might want to use it in the future. Adding a new alias every time I need a new one would be more tedious than just typing the option. Regarding the script, how would a script help me abbreviate an option for use with any command? – arekolek Aug 06 '16 at 22:18
1

Could use a function:

git() {
    ISWORDS=false
    # "${@}" is an array of the parameters sent to the method
    for i in "${@}"; do
       # If the parameter equals "words"
       if [[ "$i" = "words" ]]; then
           ISWORDS=true
           break
       fi
    done

    # If "words" was a parameter (see above)
    if [[ "$ISWORDS" ]]; then
        # "${@}" is an array of the parameters sent to the method
        for i in "${@}"; do
            declare -a OTHERPARAMS=()

            # Add every parameter to OTHERPARAMS, apart from "words"
            if [[ ! "$i" = "words" ]]; then
                OTHERPARAMS+=("$i")
            fi
         done

         # Call /usr/bin/git with every parameter except "words", and 
         # add the extra parameter --color-words too 
         /usr/bin/git "${OTHERPARAMS[@]}" --color-words='\w+|.'
    else
         # Else, just call /usr/bin/git with all parameters normally
         /usr/bin/git "${@}"
    done
}

That overrides the git command, calling it regularly with a function from the path if the parameter "words" isn't found. If it is, it removes that from the parameters, calls the command with the other parameters and an extra parameter for the --colour-words, in place of "words"

Nick Bull
  • 9,518
  • 6
  • 36
  • 58
  • This seems promising. Can you add some reference about the`"{@}"` expression? It's hard to find anything on the topic if one doesn't know what it's called. I usually use `"$@"` for similar purposes. On a different note, wouldn't exact comparison to something like `"--words"` make more sense than regexp? Is it a regexp? [Some say](http://stackoverflow.com/a/21112809/1916449) `=~` matches regexps, but you use `~=`. – arekolek Aug 06 '16 at 22:32
  • It is, sorry I forget how confusing bashes syntax can be. Will ipdate – Nick Bull Aug 06 '16 at 22:33
  • @arekolek Updated! – Nick Bull Aug 06 '16 at 22:50
  • Thank you for making the effort to comment the code, although for me personally, the comments as they are, are redundant, I understood the code perfectly without them. The only thing I wanted was a link to a reference that defines what `"{@}"` is. For example, [here's documentation of `"$@"`](https://www.gnu.org/software/bash/manual/html_node/Special-Parameters.html#index-_0040). – arekolek Aug 06 '16 at 23:10
  • @arekolek The first comment should help you out - `# "{@}" is an array of the parameters sent to the method`. E.g., for `a() { echo "${@}"; }`, calling `a "Hi"` gives `Hi` on the console. – Nick Bull Aug 06 '16 at 23:12
  • @arekolek I must apologise... It's 12am where I am. I was reading `{@}` as `${@}`. Edited the answer, I'm very sorry! – Nick Bull Aug 06 '16 at 23:15
  • Is there any reason to use `"${@}"` rather than `"$@"`? – arekolek Aug 06 '16 at 23:23
  • @arekolek Simply force of habit. Not that I know of. Has this worked for you btw? – Nick Bull Aug 06 '16 at 23:25
  • In principle it works, I've rolled my own solution inspired by this idea (see other answer), so I'm very grateful. Specifically, there are some errors, like using `-eq` to compare strings. – arekolek Aug 07 '16 at 01:50
  • @arekolec Apologies, I'm using a phone a train so it's hard to test what I write! I'll update thoroughly – Nick Bull Aug 07 '16 at 01:57
1

Inspired by Nick Bull's answer, I've added this function to my .zshrc:

GIT=`which git`
git() {
  $GIT ${@/--words/'--color-words=\w+|.'}
}

It executes any git command with --words option replaced by '--color-words=\w+|.'.

See the Pattern replacement section of A User's Guide to the Z-Shell for more details.

Note that in bash you need additional quotes: "${@/--words/'--color-words=\w+|.'}".

The only thing missing now, is so that --words is a possible tab completion for --wor<TAB>, so that it doesn't get replaced with --word-diff instead (causing the need to backspace and rewrite).


For completness, I've initially rewritten Nick Bull's answer as:

git() {
  arguments=()
  for i in "$@"; do
    if [[ $i == --words ]]; then
      arguments+=('--color-words=\w+|.')
    else
      arguments+=($i)
    fi
  done
  /usr/bin/git $arguments
}

But pattern replacement accomplishes the same, with less code.

arekolek
  • 9,128
  • 3
  • 58
  • 79