# (C) 2011-2025 magicant

# Completion script for the "git-diff" command.
# Supports Git 2.48.1.

function completion/git-diff {
        WORDS=(git diff "${WORDS[2,-1]}")
        command -f completion//reexecute
}

function completion/git::diff:arg {

        OPTIONS=( #>#
        "0; no diff for unmerged files"
        "1 --base; compare unmerged files with the merge base"
        "2 --ours; compare unmerged files with our version"
        "3 --theirs; compare unmerged files with their version"
        "--cached --staged; compare the index with a commit"
        "--merge-base; compare with the merge base of two commits"
        ) #<#
        command -f completion/git::diff:getopt

        command -f completion//parseoptions -n
        case $ARGOPT in
                (-)
                        command -f completion//completeoptions
                        ;;
                ('')
                        command -f completion/git::completerefpath range=true
                        ;;
                (*)
                        command -f completion/git::diff:compopt
                        ;;
        esac

}

function completion/git::diff:getopt {
        case $gitcmd in
                (diff|log|show) typeset u=u;;
                (*)             typeset u=;;
        esac
        case $gitcmd in
                (format-patch) typeset no_format_patch=;;
                (*)            typeset no_format_patch=true;;
        esac
        OPTIONS=("$OPTIONS" #>#
        "--abbrev::; abbreviate commit IDs"
        "--anchored:; generate a diff with the specified anchor"
        "--binary; print diffs for binary files"
        "B:: --break-rewrites::; treat a way different file as a new file"
        "--cc; show diffs for resolved merge conflicts only"
        "${no_format_patch:+--check}; check for whitespace errors"
        "--color::; show symbols in color"
        "--color-moved:; show moved lines in the specified color"
        "--color-moved-ws:; specify treatment of whitespace in moved lines"
        "--color-words::; like --word-diff=color --word-diff-regex=..."
        "--compact-summary; print an extended diffstat"
        "--cumulative; print a diffstat with cumulative counts"
        "--default-prefix; use the default prefix for filenames in diffs"
        "--diff-algorithm:; specify a diff algorithm"
        "${no_format_patch:+--diff-filter:}; specify categories of changes to show"
        "X: --dirstat::; print a dirstat with the specified style"
        "--dirstat-by-file::; print the number of changed files"
        "--dst-prefix:; specify a prefix for destination filenames in diffs"
        "${no_format_patch:+--exit-code}; return the exit status of 1 when there is any diffs"
        "--ext-diff; use an external diff program"
        "C:: --find-copies::; detect copies of files with the specified threshold"
        "--find-copies-harder; find files copied from unmodified existing files"
        "${no_format_patch:+--find-object}; specify an object to look for in diffs"
        "M:: --find-renames::; detect renames of files with the specified threshold"
        "--full-index; print full commit IDs in the patch format"
        "W --function-context; show whole function as context"
        "${no_format_patch:+G:}; specify a regular expression to look for in diffs"
        "--histogram; generate a diff using the histogram diff algorithm"
        "w --ignore-all-space; ignore whitespaces in comparison"
        "--ignore-blank-lines; ignore changes whose lines are all blank"
        "--ignore-cr-at-eol; ignore carriage returns at end of lines"
        "I: --ignore-matching-lines:; ignore changes that match the specified regex"
        "--ignore-space-at-eol; ignore changes in whitespace at end of lines"
        "b --ignore-space-change; ignore changes in amount of whitespaces only"
        "--ignore-submodules::; ignore changes to submodules"
        "--indent-heuristic; shift diff hunk boundaries to align"
        "--inter-hunk-context:; specify the number of lines to show between hunks"
        "D --irreversible-delete; don't print diffs for deleted files"
        "--ita-invisible-in-index; treat intent-to-add files as untracked"
        "--ita-visible-in-index; treat intent-to-add files as was empty"
        "l:; specify a threshold at which rename/copy detection is given up"
        "--line-prefix:; specify an additional prefix for lines in diffs"
        "--minimal; minimize the diff at the cost of time"
        "--name-only; just print the names of differing files"
        "--name-status; just print the names and statuses of differing files"
        "--no-color; like --color=never"
        "--no-color-moved; don't highlight moved lines"
        "--no-color-moved-ws; treat whitespace intactly in moved lines"
        "--no-ext-diff; use the internal diff program"
        "--no-indent-heuristic; disable shift of diff hunk boundaries"
        "--no-index; compare a file with another file outside the repository"
        "--no-prefix; don't prefix filenames in diffs"
        "--no-relative; show diffs for all files, relative to the repository root"
        "--no-renames; disable rename detection"
        "--no-rename-empty; don't use empty blobs as rename sources"
        "--no-textconv; don't use an external text filter to compare binary files"
        "--numstat; print a diffstat in the machine-friendly format"
        "O:; specify a file containing the order in which diffs are printed"
        "--output:; specify a file to write the diff to"
        "--output-indicator-context:; specify the indicator for context"
        "--output-indicator-new:; specify the indicator for new files"
        "--output-indicator-old:; specify the indicator for old files"
        "${no_format_patch:+p} $u --patch; print a patch"
        "${no_format_patch:+--patch-with-raw}; like --patch --raw"
        "${no_format_patch:+--patch-with-stat}; like --patch --stat"
        "--patience; generate a diff using the patience diff algorithm"
        "${no_format_patch:+--pickaxe-all}; show the whole changeset when -S/-G is specified"
        "${no_format_patch:+--pickaxe-regex}; treat the specified string as a regular expression (with -S)"
        "${no_format_patch:+--quiet}; don't print anything"
        "${no_format_patch:+R}; print reverse diffs"
        "${no_format_patch:+--raw}; print in the raw format"
        "--relative::; only show diffs in the specified directory"
        "--rename-empty; use empty blobs as rename sources"
        "--rotate-to::; specify a file to start the diff from"
        "${no_format_patch:+S:}; specify a string to look for in diffs"
        "--shortstat; print a diffstat summary"
        "--skip-to:; discard files until the specified file is found"
        "--src-prefix:; specify a prefix for source filenames in diffs"
        "--stat::; print a diffstat with the specified column widths"
        "--stat-count:; specify the max number of files shown in the diffstat"
        "--stat-name-width:; specify the width of filenames in the diffstat"
        "--stat-width:; specify the width of the diffstat"
        "--submodule::; print diffs in submodules"
        "--summary; print summary"
        "a --text; assume all files are text"
        "--textconv; use an external text filter to compare binary files"
        "U:: --unified::; output in unified context format with the specified number of context lines"
        "--word-diff::; print word-based diffs"
        "--word-diff-regex:; specify a regular expression that defines a word"
        "${no_format_patch:+--ws-error-highlight:}; specify the whitespace error highlighting style"
        "z; print a null byte after each filename"
        ) #<#
}

function completion/git::diff:compopt
        case $ARGOPT in
                ([BClMU]|--abbrev|--break-rewrites|--find-*|--inter-hunk-context|--stat|--stat-*|--unified)
                        ;;
                (--color|--ignore-submodules)
                        command -f completion/git::$ARGOPT:arg
                        ;;
                (--color-moved) #>>#
                        complete -P "$PREFIX" -D "don't highlight moved lines" no
                        complete -P "$PREFIX" default
                        complete -P "$PREFIX" -D "detect moves line-wise" plain
                        complete -P "$PREFIX" -D "detect moved blocks of 20 characters or more" blocks
                        complete -P "$PREFIX" -D "like blocks, and use alternating colors for adjacent blocks" zebra
                        complete -P "$PREFIX" -D "like zebra, but dim uninteresting parts" dimmed-zebra
                        ;; #<<#
                (--color-moved-ws)
                        typeset word="${TARGETWORD#"$PREFIX"}"
                        word=${word##*,}
                        PREFIX=${TARGETWORD%"$word"} #>>#
                        complete -P "$PREFIX" -D "treat whitespace intactly" no
                        complete -P "$PREFIX" -S , -T -D "ignore whitespace at end of lines" ignore-space-at-eol
                        complete -P "$PREFIX" -S , -T -D "ignore amount of whitespace" ignore-space-change
                        complete -P "$PREFIX" -S , -T -D "ignore all whitespace" ignore-all-space
                        complete -P "$PREFIX" -S , -T -D "group lines having the same change in whitespace" allow-indentation-change
                        ;; #<<#
                (--color-words|--word-diff-regex)
                        ;;
                (--diff-algorithm) #>>#
                        complete -P "$PREFIX" \
                                default histogram minimal myers patience
                        ;; #<<#
                (--diff-filter) #>>#
                        complete -P "$TARGETWORD" -D "added" A
                        complete -P "$TARGETWORD" -D "pair broken" B
                        complete -P "$TARGETWORD" -D "copied" C
                        complete -P "$TARGETWORD" -D "deleted" D
                        complete -P "$TARGETWORD" -D "modified" M
                        complete -P "$TARGETWORD" -D "renamed" R
                        complete -P "$TARGETWORD" -D "type modified" T
                        complete -P "$TARGETWORD" -D "unmerged" U
                        complete -P "$TARGETWORD" -D "unknown" X
                        complete -P "$TARGETWORD" -D "not added" a
                        complete -P "$TARGETWORD" -D "not pair broken" b
                        complete -P "$TARGETWORD" -D "not copied" c
                        complete -P "$TARGETWORD" -D "not deleted" d
                        complete -P "$TARGETWORD" -D "not modified" m
                        complete -P "$TARGETWORD" -D "not renamed" r
                        complete -P "$TARGETWORD" -D "not type modified" t
                        complete -P "$TARGETWORD" -D "not unmerged" u
                        complete -P "$TARGETWORD" -D "not unknown" x
                        complete -P "$TARGETWORD" -D "all, if any of other flag matches" '*'
                        ;; #<<#
                (X|--dirstat|--dirstat-by-file)
                        typeset word="${TARGETWORD#"$PREFIX"}"
                        word=${word##*,}
                        PREFIX=${TARGETWORD%"$word"} #>>#
                        complete -P "$PREFIX" -S , -T -D "count lines that are added or removed, but not moved" changes
                        complete -P "$PREFIX" -S , -T -D "include changes in subdirectories when operating on the parent" cumulative
                        complete -P "$PREFIX" -S , -T -D "count files that are changed" files
                        complete -P "$PREFIX" -S , -T -D "count lines that appear as added or removed in diffs" lines
                        complete -P "$PREFIX" -S , -T -D "exclude changes in subdirectories when operating on the parent" noncumulative
                        ;; #<<#
                ([GS])
                        ;;
                (--relative)
                        complete -P "$PREFIX" -S / -T -d
                        ;;
                (--submodule) #>>#
                        complete -P "$PREFIX" -D "print diffs" diff
                        complete -P "$PREFIX" -D "print logs for commits in submodules" log
                        complete -P "$PREFIX" -D "just print pairs of commit IDs" short
                        ;; #<<#
                (--word-diff) #>>#
                        complete -P "$PREFIX" -D "use colors" color
                        complete -P "$PREFIX" -D "use delimiters" plain
                        complete -P "$PREFIX" -D "print in the machine-friendly format" porcelain
                        complete -P "$PREFIX" -D "disable word-based diffs" none
                        ;; #<<#
                (--ws-error-highlight)
                        typeset word="${TARGETWORD#"$PREFIX"}"
                        word=${word##*,}
                        PREFIX=${TARGETWORD%"$word"} #>>#
                        complete -P "$PREFIX" -S , -T context old new
                        complete -P "$PREFIX" -S , -T -D "clear" none
                        complete -P "$PREFIX" -S , -T -D "=none,new" default
                        complete -P "$PREFIX" -S , -T -D "=old,new,context" all
                        ;; #<<#
                (O|--dst-prefix|--src-prefix)
                        complete -P "$PREFIX" -f
                        ;;
                (*)
                        return 1
                        ;;
        esac


# vim: set ft=sh ts=8 sts=8 sw=8 et:
