Search code examples
gitawkseddocumentation-generationgit-config

Automatic documentation of gitconfig aliases using sed or awk


I'm currently using the below code (hacked together) to generate documentation for my git aliases using 'git alias'. This assumes there is a comment above each alias starting with ### and the aliases are formatted as 'alias_name = command'. This works as is but does anyone have a more gooder method? :)

Current code (contents of $HOME/.bin/bin/gdoc):

grep --no-group-separator -A1 '###' "$HOME"/.gitconfig | awk 'END{if((NR%2))print p}!(NR%2){print$0p}{p=$0}' | sed -re 's/( =)(.*)(###)/:*/g' | awk -F* '{printf "\033[1;31m%-30s\033[0m %s\n", $1, $2}' | sort

Example aliases:

### use difftool to view differences in file
dt = difftool

# https://stackoverflow.com/questions/3321492/git-alias-with-positional-parameters/39523506#39523506
### add and commit a file, arg1=file, arg2=commit_message
ac = "!cd -- \"${GIT_PREFIX:-.}\" && git add \"$1\" && git commit -m \"$2\" #"

### remove any files that are in gitignore from tracking
ig = "!git rm --cached `git ls-files -i --exclude-from=.gitignore` #"

### print out available aliases
alias = "!$HOME/.bin/bin/gdoc #"

### add a file to gitignore
ignore = "!([ ! -e .gitignore ] && touch .gitignore) | echo $1 >> .gitignore #"

### git rm files that have been deleted without using git
r = "!git ls-files -z --deleted | xargs -0 git rm #"

# https://stackoverflow.com/questions/38057261/git-config-alias-escaping/39616600#39616600
### Quote a sh command, converting it to a git alias string
quote-string = "!read -r l; printf \\\"!; printf %s \"$l\" | sed 's/\\([\\\"]\\)/\\\\\\1/g'; printf \" #\\\"\\n\" #"
### Unquote a git alias command command, converting it to a sh command
quote-string-undo = "!read -r l; printf %s \"$l\" | sed 's/\\\\\\([\\\"]\\)/\\1/g'; printf \"\\n\" #"

### debug git aliases - 'git debug <alias>'
debug = "!set -x; GIT_TRACE=2 GIT_CURL_VERBOSE=2 GIT_TRACE_PERFORMANCE=2 GIT_TRACE_PACK_ACCESS=2 GIT_TRACE_PACKET=2 GIT_TRACE_PACKFILE=2 GIT_TRACE_SETUP=2 GIT_TRACE_SHALLOW=2 git"

Current output:

ac:                         add and commit a file, arg1=file, arg2=commit_message
alias:                      print out available aliases
debug:                      debug git aliases - 'git debug <alias>'
dt:                         use difftool to view differences in file
ig:                         remove any files that are in gitignore from tracking
ignore:                     add a file to gitignore
quote-string-undo:          Unquote a git alias command command, converting it to a sh command
quote-string:               Quote a sh command, converting it to a git alias string
r:                          git rm files that have been deleted without using git

Solution

  • Like this:

    awk 'a{print $1""c;a=0}/###/{$1="";c=$0;a=1}' "$HOME"/.gitconfig | sort
    

    Using awk, grep and sed in the same pipe is mostly a sign that they are not used efficiently. Usually they can be replaced by a single awk command.

    For nicely indented output you may use column:

    awk 'a{print $1"%"c;a=0}/###/{$1="";c=$0;a=1}' "$HOME"/.gitconfig | sort | column -ts%
    

    Note: I'm injecting a % separator with awk which is used to indent the output with column

    Output:

    ac                  add and commit a file, arg1=file, arg2=commit_message
    alias               print out available aliases
    debug               debug git aliases - 'git debug <alias>'
    dt                  use difftool to view differences in file
    ignore              add a file to gitignore
    ig                  remove any files that are in gitignore from tracking
    quote-string        Quote a sh command, converting it to a git alias string
    quote-string-undo   Unquote a git alias command command, converting it to a sh command
    r                   git rm files that have been deleted without using git
    

    If you have gawk (GNU awk), you can also use just awk, like this:

    #!/usr/bin/gawk -f
    in_alias{
        aliases[$1]=comment
        in_alias=0
        len=length($1)
        if(len > maxlen){
            maxlen = len
        }
    }
    /###/{
        $1=""
        comment=$0
        in_alias=1
    }
    END{
        n = asorti(aliases, sorted) # <-- Requires gawk
        for(i = 1; i <= n; i ++){
            pad = maxlen - length(sorted[i]) + 1
            printf "%s%"pad"s%s\n",sorted[i]," ",aliases[sorted[i]]
        }
    }
    

    Save that to a file at, let's say, /usr/local/bin/git-aliases and make it executable:

    chmod +x /usr/local/bin/git-aliases
    git-aliases "$HOME"/.gitconfig