# (C) 2010 magicant

# Completion script for the "patch" command.
# Supports POSIX 2008, GNU patch 2.6.1, SunOS 5.10, HP-UX 11i v3.

function completion/patch {

        if "${WORDS[1]}" --version >/dev/null 2>&1; then
                typeset type=GNU
        else
                typeset type="$(uname 2>/dev/null)"
        fi
        case $type in
                (GNU) typeset long=true ;;
                (*)   typeset long= ;;
        esac

        typeset OPTIONS POSIXOPTIONS ADDOPTIONS ARGOPT PREFIX
        POSIXOPTIONS=( #>#
        "b ${long:+--backup}; back up files before patching"
        "c ${long:+--context}; assume copied context format"
        "D: ${long:+--ifdef:}; output in merged #ifdef format with the specified conditional macro name"
        "d: ${long:+--directory:}; specify a directory to work in"
        "e ${long:+--ed}; assume ed script format"
        "i: ${long:+--input:}; specify the patch file"
        "l ${long:+--ignore-whitespace}; tolerate whitespace mismatches"
        "N ${long:+--forward}; ignore patches that seem reversed or already applied"
        "n ${long:+--normal}; assume normal diff format"
        "o: ${long:+--output:}; specify the result file name"
        "p: ${long:+--strip:}; specify the number of pathname components to strip from file names"
        "R ${long:+--reverse}; patch in reverse"
        "r: ${long:+-reject-file:}; specify the reject file name"
        "u ${long:+--unified}; assume unified context format"
        ) #<#

        ADDOPTIONS=()
        case $type in (GNU|HP-UX)
                ADDOPTIONS=("$ADDOPTIONS" #>#
                "F: ${long:+--fuzz:}; specify the number of lines in context that may mismatch"
                "f ${long:+--force}; don't ask anything to the user"
                "s ${long:+--silent --quiet}; suppress informative messages"
                "v ${long:+--version}; print version info"
                ) #<#
        esac
        case $type in
        (GNU)
                ADDOPTIONS=("$ADDOPTIONS" #>#
                "--backup-if-mismatch; back up a file if the patch doesn't match the file exactly"
                "--no-backup-if-mismatch; don't back up a file even if the patch doesn't match the file exactly"
                "B: --prefix:; specify a backup file pathname prefix"
                "--binary; don't convert CR-LF into LF"
                "--dry-run; don't modify files actually but print messages as usual"
                "E --remove-empty-files; remove empty result files"
                "g: --get:; specify what to do when a file is missing or read-only"
                "--merge::; leave conflicts in the result file like diff3 and merge"
                "--posix; disable non-POSIX extensions"
                "--quoting-style:; specify the quoting style for output names"
                "--reject-format:; specify the reject file format"
                "T --set-time; set the time stamp of result files using local time"
                "t --batch; don't ask anything to the user"
                "V: --version-control:; specify how to make a backup"
                "--verbose; print extra informative messages"
                "Y: --basename-prefix:; make backups in subdirectories with the specified name"
                "Z --set-utc; set the time stamp of result files using UTC"
                "z: --suffix:; make backups in the same directory with the specified suffix"
                "--help"
                ) #<#
                ;;
        (HP-UX)
                ADDOPTIONS=("$ADDOPTIONS" #>#
                "S; ignore this patch and process the next patch"
                ) #<#
                ;;
        esac

        OPTIONS=("$POSIXOPTIONS" "$ADDOPTIONS")
        unset POSIXOPTIONS ADDOPTIONS

        case $type in (HP-UX)
                typeset i="${WORDS[#]}"
                while [ $i -gt 1 ]; do
                        if [ "${WORDS[i]}" = "+" ]; then
                                WORDS=("${WORDS[1]}" "${WORDS[i+1,-1]}")
                                break
                        fi
                        i=$((i-1))
                done
        esac

        command -f completion//parseoptions ${long:+-es}
        case $ARGOPT in
        (-)
                command -f completion//completeoptions
                ;;
        (D|--ifdef)
                if [ -r tags ]; then
                        complete -P "$PREFIX" -R "!_TAG_*" -- \
                                $(cut -f 1 tags 2>/dev/null)
                fi
                ;;
        (d|--directory)
                complete -T -P "$PREFIX" -S / -d
                ;;
        (g|--get) #>>#
                complete -P "$PREFIX" -D "check out the missing file" 1
                complete -P "$PREFIX" -D "do nothing" 0
                complete -P "$PREFIX" -D "ask whether to check out the file" -- -1
                ;; #<<#
        (--merge) #>>#
                complete -P "$PREFIX" -D "contains original lines from the patch" diff3
                complete -P "$PREFIX" -D "doesn't contain original lines from the patch" merge
                ;; #<<#
        (--quoting-style) #>>#
                complete -P "$PREFIX" -D "no quotation" literal
                complete -P "$PREFIX" -D "quotation suitable for the shell" shell
                complete -P "$PREFIX" -D "always quote in the shell style" shell-always
                complete -P "$PREFIX" -D "C string literal" c
                complete -P "$PREFIX" -D "C string literal without surrounding double-quotes" escape
                ;; #<<#
        (--reject-format) #>>#
                complete -P "$PREFIX" -D "copied context format" context
                complete -P "$PREFIX" -D "unified context format" unified
                ;; #<<#
        (V|--version-control)
                if command -vf completion//completebackup >/dev/null 2>&1 ||
                                . -AL completion/_backup; then
                        command -f completion//completebackup
                fi
                ;;
        ([Fp]|--fuzz|--strip)
                ;;
        (*)
                complete -P "$PREFIX" -f
                ;;
        esac

}


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