112 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			112 lines
		
	
	
		
			3.4 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
 | |
| 
 | |
| # TODO 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.
 | |
| 
 | |
| # TODO 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 can read from stdin but it does not.
 | |
| 
 | |
| # 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 < <(hledger accounts --flat | grep "^$wordToComplete")
 | |
| 	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
 | |
| 
 | |
| }
 | |
| 
 | |
| # Register completion function for hledger:
 | |
| complete -F _hledger_completion_function hledger
 | |
| 
 | |
| # 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/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
 | |
| ')
 |