mirror of
https://github.com/simonmichael/hledger.git
synced 2024-09-18 17:57:11 +03:00
Add files for bash completion
This commit is contained in:
parent
50175a9698
commit
dc73b55b7b
28
shell-completion/Makefile
Normal file
28
shell-completion/Makefile
Normal file
@ -0,0 +1,28 @@
|
||||
|
||||
.PHONY: commands clean
|
||||
|
||||
all: generic-options.txt commands hledger-completion.bash
|
||||
|
||||
generic-options.txt:
|
||||
hledger -h | ./output-options.sh > $@
|
||||
|
||||
commands.txt:
|
||||
hledger | ./output-commands.sh > $@
|
||||
|
||||
commands-list.txt: commands.txt
|
||||
paste -sd, $^ | tr -d '\n' > $@
|
||||
|
||||
commands: commands.txt
|
||||
#parallel 'touch {}.command' < commands.txt
|
||||
parallel 'hledger {} -h | ./output-options.sh > options-{}.txt' < commands.txt
|
||||
|
||||
# It's possible to call this rule explicitly but it's not invoked automatically.
|
||||
# Better generate *-options.txt with the 'commands' phony rule.
|
||||
%-options.txt: %.command
|
||||
hledger $* -h | ./output-options.sh > $@
|
||||
|
||||
hledger-completion.bash: hledger-completion.bash.m4 commands-list.txt
|
||||
m4 hledger-completion.bash.m4 > $@
|
||||
|
||||
clean:
|
||||
rm -f *.commands *.txt hledger-completion.bash
|
10
shell-completion/foreach2.m4
Normal file
10
shell-completion/foreach2.m4
Normal file
@ -0,0 +1,10 @@
|
||||
include(`quote.m4')dnl
|
||||
divert(`-1')
|
||||
# foreach(x, (item_1, item_2, ..., item_n), stmt)
|
||||
# parenthesized list, improved version
|
||||
define(`foreach', `pushdef(`$1')_$0(`$1',
|
||||
(dquote(dquote_elt$2)), `$3')popdef(`$1')')
|
||||
define(`_arg1', `$1')
|
||||
define(`_foreach', `ifelse(`$2', `(`')', `',
|
||||
`define(`$1', _arg1$2)$3`'$0(`$1', (dquote(shift$2)), `$3')')')
|
||||
divert`'dnl
|
94
shell-completion/hledger-completion.bash.m4
Normal file
94
shell-completion/hledger-completion.bash.m4
Normal file
@ -0,0 +1,94 @@
|
||||
#!/bin/bash
|
||||
# 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 not safe to use if the word contains regex
|
||||
# special chars. But it might be no problem because of COMP_WORDBREAKS.
|
||||
|
||||
# TODO Try to get file from -f --file arguments from COMP_WORDS and pass it to
|
||||
# the 'hledger accounts' call.
|
||||
|
||||
# Working with bash arrays is nasty compared to editing a text file. Consider
|
||||
# for example grepping an array or map a substitution on it.
|
||||
# Therefore, we create temp files in RAM for completion suggestions (see below).
|
||||
|
||||
declare -g HLEDGER_COMPLETION_TEMPDIR
|
||||
HLEDGER_COMPLETION_TEMPDIR=$(mktemp -d)
|
||||
|
||||
hledgerCompletionFunction() {
|
||||
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
|
||||
#declare -a options
|
||||
#readarray -t options <(grep "^$wordToComplete" "$HLEDGER_COMPLETION_TEMPDIR/options-$subcommand.txt")
|
||||
#COMPREPLY+=( "${options[@]}" )
|
||||
COMPREPLY+=( $(grep -h "^$wordToComplete" -- "$HLEDGER_COMPLETION_TEMPDIR/options-$subcommand.txt") )
|
||||
break
|
||||
fi
|
||||
subcommand=
|
||||
done
|
||||
|
||||
if [[ -z $subcommand ]]; then
|
||||
|
||||
declare completeFiles filenameSoFar
|
||||
case $wordToComplete in
|
||||
--file=*|--rules-file=*)
|
||||
completeFiles=1
|
||||
filenameSoFar=${wordToComplete#*=}
|
||||
;;
|
||||
esac
|
||||
case $precedingWord in
|
||||
-f|--file|--rules-file)
|
||||
completeFiles=1
|
||||
filenameSoFar=$wordToComplete
|
||||
;;
|
||||
esac
|
||||
|
||||
if [[ -n $completeFiles ]]; then
|
||||
:
|
||||
#COMP_WORDBREAKS='= '
|
||||
COMPREPLY+=( $(compgen -df | grep "^$filenameSoFar") )
|
||||
|
||||
else
|
||||
COMPREPLY+=( $(grep -h "^$wordToComplete" -- "$HLEDGER_COMPLETION_TEMPDIR/commands.txt" "$HLEDGER_COMPLETION_TEMPDIR/generic-options.txt") )
|
||||
fi
|
||||
|
||||
else
|
||||
|
||||
# Almost all subcommands accpt [QUERY] -> always add accounts to completion list
|
||||
|
||||
COMP_WORDBREAKS=' '
|
||||
COMPREPLY+=( $(hledger accounts --flat | grep "^$wordToComplete") )
|
||||
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
complete -F hledgerCompletionFunction hledger
|
||||
|
||||
# Include lists of commands and options generated by the Makefile using 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
|
||||
')
|
65
shell-completion/hledger-completion.sh
Normal file
65
shell-completion/hledger-completion.sh
Normal file
@ -0,0 +1,65 @@
|
||||
#!/bin/bash
|
||||
# Completion script for hledger.
|
||||
# Created using a Makefile and real hledger.
|
||||
|
||||
#set -eo pipefail
|
||||
|
||||
completeFunction() {
|
||||
declare cmd=$1
|
||||
declare wordToComplete=$2
|
||||
declare precedingWord=$3
|
||||
|
||||
declare subcommand
|
||||
for subcommand in "${COMP_WORDS[@]}"; do
|
||||
if grep -Fxq "$subcommand" commands.txt; then
|
||||
#declare -a options
|
||||
#readarray -t options <(grep "^$wordToComplete" "$subcommand-options.txt")
|
||||
#COMPREPLY+=( "${options[@]}" )
|
||||
COMPREPLY+=( $(cat "$subcommand-options.txt" | grep "^$wordToComplete") )
|
||||
break
|
||||
fi
|
||||
subcommand=
|
||||
done
|
||||
|
||||
if [[ -z $subcommand ]]; then
|
||||
|
||||
# echo;echo no subcommand
|
||||
|
||||
case $precedingWord in
|
||||
-f|--file|--rules-file)
|
||||
# COMPREPLY+=( $(compgen -df | grep "^$wordToComplete") )
|
||||
:
|
||||
;;
|
||||
*)
|
||||
# echo "completing sub commands and general options"
|
||||
COMPREPLY+=( $(cat commands.txt generic-options.txt | grep "^$wordToComplete") )
|
||||
;;
|
||||
esac
|
||||
|
||||
else
|
||||
:
|
||||
# echo;echo subcommand is $subcommand
|
||||
|
||||
# if grep -Eqv '\b(register|reg|r)\b' <<< "$COMP_LINE"; then
|
||||
# return
|
||||
# fi
|
||||
# case $precedingWord in
|
||||
# register|reg|r) : ;;
|
||||
# *) return 1 ;;
|
||||
# esac
|
||||
|
||||
declare journalFile
|
||||
# TODO try to get file from -f --file first
|
||||
if [[ -n $HLEDGER_FILE ]]; then
|
||||
journalFile=$HLEDGER_FILE
|
||||
else
|
||||
journalFile=~/.hledger.journal
|
||||
fi
|
||||
COMP_WORDBREAKS=' '
|
||||
COMPREPLY+=( $(sed -rn 's/^ +([-_:a-zA-Z0-9]+).*/\1/p' "$journalFile" | grep "^$wordToComplete") )
|
||||
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
complete -F completeFunction hledger
|
21
shell-completion/output-commands.sh
Executable file
21
shell-completion/output-commands.sh
Executable file
@ -0,0 +1,21 @@
|
||||
#!/bin/bash
|
||||
# Output subcommands from man/usage text
|
||||
|
||||
set -o errexit -o pipefail -o nounset
|
||||
|
||||
printCommands() {
|
||||
declare tmp=$1
|
||||
sed -rn 's/^ ([-a-z]+).*/\1/gp' "$tmp"
|
||||
sed -rn 's/^ .*\(([a-z]+)\).*/\1/gp' "$tmp"
|
||||
# TODO missing: (reg, r) (multiple aliases)
|
||||
}
|
||||
|
||||
main() {
|
||||
declare tmp
|
||||
tmp=$(mktemp)
|
||||
cat > "$tmp"
|
||||
|
||||
printCommands "$tmp" | grep -v ^hledger
|
||||
}
|
||||
|
||||
main "$@"
|
17
shell-completion/output-options.sh
Executable file
17
shell-completion/output-options.sh
Executable file
@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
# Output short and long options from man/usage text
|
||||
|
||||
set -o errexit -o pipefail -o nounset
|
||||
|
||||
main() {
|
||||
declare tmp
|
||||
tmp=$(mktemp)
|
||||
cat > "$tmp"
|
||||
sed -rn 's/.* (-[a-zA-Z0-9]).*/\1/gp' < "$tmp"
|
||||
|
||||
# Do not print '=' after long options with arg because it makes completion
|
||||
# for option arguments harder.
|
||||
sed -rn 's/.* (--[-a-zA-Z0-9]+)=?.*/\1/gp' < "$tmp"
|
||||
}
|
||||
|
||||
main "$@"
|
9
shell-completion/quote.m4
Normal file
9
shell-completion/quote.m4
Normal file
@ -0,0 +1,9 @@
|
||||
divert(`-1')
|
||||
# quote(args) - convert args to single-quoted string
|
||||
define(`quote', `ifelse(`$#', `0', `', ``$*'')')
|
||||
# dquote(args) - convert args to quoted list of quoted strings
|
||||
define(`dquote', ``$@'')
|
||||
# dquote_elt(args) - convert args to list of double-quoted strings
|
||||
define(`dquote_elt', `ifelse(`$#', `0', `', `$#', `1', ```$1''',
|
||||
```$1'',$0(shift($@))')')
|
||||
divert`'dnl
|
Loading…
Reference in New Issue
Block a user