133 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			133 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
 | 
						|
# Completion script for hledger.
 | 
						|
# Created using a Makefile and real hledger.
 | 
						|
 | 
						|
# No set -e because this file is sourced and is not supposed to quit the current shell.
 | 
						|
set -o pipefail
 | 
						|
 | 
						|
# Note: grep "^$wordToComplete" is (functional) not safe to use if the word
 | 
						|
# contains regex special chars. But it might be no problem because of
 | 
						|
# COMP_WORDBREAKS.
 | 
						|
 | 
						|
# Note: compgen and compopt is pretty complicated. Piping to
 | 
						|
# grep "^$wordToComplete"
 | 
						|
# seems like a hack - I'd rather use
 | 
						|
# compgen ... -- "$wordToComplete"
 | 
						|
# But what options to use? I don't want to use -W because it may exceed the
 | 
						|
# maximum command line length. -C "cat file" is not working either. It would be
 | 
						|
# best if compgen could read from stdin but it does not.
 | 
						|
 | 
						|
# Note: Working with bash arrays is nasty compared to editing a text file.
 | 
						|
# Consider for example grepping an array or mapping a substitution on it.
 | 
						|
# Therefore, we create temp files in RAM for completion suggestions (see below).
 | 
						|
 | 
						|
readonly _HLEDGER_COMPLETION_TEMPDIR=$(mktemp -d)
 | 
						|
 | 
						|
_hledger_completion_function() {
 | 
						|
    #declare cmd=$1
 | 
						|
    declare wordToComplete=$2
 | 
						|
    declare precedingWord=$3
 | 
						|
 | 
						|
    declare subcommand
 | 
						|
    for subcommand in "${COMP_WORDS[@]}"; do
 | 
						|
	if grep -Fxqe "$subcommand" "$_HLEDGER_COMPLETION_TEMPDIR/commands.txt"; then
 | 
						|
	    COMPREPLY+=( $(grep -h "^$wordToComplete" -- "$_HLEDGER_COMPLETION_TEMPDIR/options-$subcommand.txt") )
 | 
						|
	    break
 | 
						|
	fi
 | 
						|
	subcommand=
 | 
						|
    done
 | 
						|
 | 
						|
    if [[ -z $subcommand ]]; then
 | 
						|
 | 
						|
	declare completeFiles filenameSoFar
 | 
						|
	case $precedingWord in
 | 
						|
	    -f|--file|--rules-file)
 | 
						|
		completeFiles=1
 | 
						|
		filenameSoFar=$wordToComplete
 | 
						|
		;;
 | 
						|
	    =)
 | 
						|
		completeFiles=1
 | 
						|
		filenameSoFar=$wordToComplete
 | 
						|
		;;
 | 
						|
	esac
 | 
						|
 | 
						|
	if [[ -n $completeFiles ]]; then
 | 
						|
	    #COMP_WORDBREAKS='= '
 | 
						|
	    declare -a files
 | 
						|
	    # This does not work because assignment to 'files' in the "pipe
 | 
						|
	    # subshell" has no effect!
 | 
						|
	    #compgen -df | grep "^$filenameSoFar" | readarray -t files
 | 
						|
 | 
						|
	    compopt -o filenames -o dirnames
 | 
						|
	    readarray -t files < <(compgen -f -- "$filenameSoFar")
 | 
						|
	    COMPREPLY=( "${files[@]}" )
 | 
						|
 | 
						|
	else
 | 
						|
	    COMPREPLY+=( $(grep -h "^$wordToComplete" -- "$_HLEDGER_COMPLETION_TEMPDIR/commands.txt" "$_HLEDGER_COMPLETION_TEMPDIR/generic-options.txt") )
 | 
						|
	fi
 | 
						|
 | 
						|
    else
 | 
						|
 | 
						|
	# Almost all subcommands accept [QUERY]
 | 
						|
	# -> always add accounts to completion list
 | 
						|
 | 
						|
	# TODO Get ledger file from -f --file arguments from COMP_WORDS and pass it to
 | 
						|
	# the 'hledger accounts' call. Note that --rules-file - if present - must also
 | 
						|
	# be passed!
 | 
						|
 | 
						|
	declare -a accounts
 | 
						|
	readarray -t accounts < <({ cat "$_HLEDGER_COMPLETION_TEMPDIR/query-filters.txt"; hledger accounts --flat; } | grep "^$wordToComplete")
 | 
						|
	compopt -o nospace
 | 
						|
	COMPREPLY+=( "${accounts[@]}" )
 | 
						|
	# Special characters (e.g. '-', ':') are allowed in account names.
 | 
						|
	# Account names with spaces must be still be quoted (e.g. '"Expens')
 | 
						|
	# for completion. Setting COMP_WORDBREAKS='' would not help here!
 | 
						|
	COMP_WORDBREAKS=' '
 | 
						|
 | 
						|
    fi
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
_hledger_extension_completion_function() {
 | 
						|
    declare cmd=$1
 | 
						|
 | 
						|
    # Change parameters and arguments and call the
 | 
						|
    # normal hledger completion function.
 | 
						|
    declare extensionName=${cmd#*-}
 | 
						|
    export -a COMP_WORDS=( "hledger" "$extensionName" "${COMP_WORDS[@]:1}" )
 | 
						|
    #echo; echo "debug: ${COMP_WORDS[@]}"
 | 
						|
    shift
 | 
						|
    _hledger_completion_function "hledger" "$@"
 | 
						|
}
 | 
						|
 | 
						|
# Register completion function for hledger:
 | 
						|
complete -F _hledger_completion_function hledger
 | 
						|
 | 
						|
# Register completion functions for hledger extensions:
 | 
						|
complete -F _hledger_extension_completion_function hledger-ui
 | 
						|
complete -F _hledger_extension_completion_function hledger-web
 | 
						|
 | 
						|
# Include lists of commands and options generated by the Makefile using the
 | 
						|
# m4 macro processor.
 | 
						|
# Included files must have exactly one newline at EOF to prevent weired errors.
 | 
						|
 | 
						|
cat <<TEXT > "$_HLEDGER_COMPLETION_TEMPDIR/commands.txt"
 | 
						|
include(`commands.txt')dnl
 | 
						|
TEXT
 | 
						|
 | 
						|
cat <<TEXT > "$_HLEDGER_COMPLETION_TEMPDIR/query-filters.txt"
 | 
						|
include(`query-filters.txt')dnl
 | 
						|
TEXT
 | 
						|
 | 
						|
cat <<TEXT > "$_HLEDGER_COMPLETION_TEMPDIR/generic-options.txt"
 | 
						|
include(`generic-options.txt')dnl
 | 
						|
TEXT
 | 
						|
 | 
						|
include(`foreach2.m4')
 | 
						|
 | 
						|
foreach(`cmd', (include(`commands-list.txt')), `
 | 
						|
cat <<TEXT > "$_HLEDGER_COMPLETION_TEMPDIR/options-cmd.txt"
 | 
						|
include(options-cmd.txt)dnl
 | 
						|
TEXT
 | 
						|
')
 |