Fix #1404, and more...
This was supposed to be just a fix for #1404 but upon visiting the source several issues became apparent and that is why the commit grew a bit more than expected. A complete list of changes bellow: * Fix #1404 No more orphaned temporary directories. Commands, options, etc. that used to be stored in there are included at build-time as here documents in the source. * Fix artifacts in =/tmp= after build Upon fixing the above I became aware that the build itself was leaving behind a heap of artifacts in =/tmp= that were not taken care of with a ~make clean~. Fixed by using temporary files and directories in the build directory. Makefile and build scripts adjusted. * Produce command aliases Regular expressions in build scripts changed to produce all command aliases except single letter ones (see below) * Do not propose single letters completions It is simply not useful and adds a lot of noise. It makes completion slower as well because you need to hit yes on the prompt: > Display all 200 possibilities? (y or n) =output-options.sh= now excludes those. * Query filters simplified Keep only the prefix of the filter with the colon in =query-filters.txt=. This change has two reasons: - Single letter completions are not useful (see above) - It allows for completion suggestions specific to each - Bonus reason: it's a completion engine, not a user manual. * Fix completion impacts on global environment The completion script was making a couple of changes to the global environment which had an impact for the rest of the shell session. ~set -o pipefail~: the change is hidden from the user and could lead to subtle errors throughout the shell session COMP_WORDBREAKS=" ": this affects subsequent completions for us and other programs too. I exclude the colon =:= from its value and use ~compopt -o filenames~ to handle escaping of special characters for us. I would like to find a solution without messing with COMP_WORDBREAKS but it is not straight forward. * Fix hiding of legit subcommands Completion was hiding all possibilities if a subcommand happens to be the prefix of another. On typing ~balance~, one should be proposed ~balancesheet~ and ~balancesheetequity~ as well. * Return early Try to complete depending on the current context and return immediately if successful. Keep completion list relevant and as short as possible. * Context aware completion - Add handlers for option parameter completion, see _hledger_compreply_optarg() - Add handlers for query filters:, see _hledger_compreply_query() - Use --file and --rules-file arguments when proposing completions for the above, see _hledger() - Propose only top level accounts at first. Again, keep it short and focused. * Custom ~compgen~ wrapper ~compgen~ is fairly complicated. There is no way to feed it a word list with literals. It will mangle your input in so many ways that we cannot trust it. To work around this several wrappers are used: _hledger_compgen() works with _hledger_quote_by_ref() to process and escape newline separated input which is then fed to ~compgen~ and finally in ~COMPREPLY~ through _hledger_compreply() and _hledger_compreply_append(). It sounds messy and I guess it is, I would like to find a more straight forward way to do it. I think it is still a way better and safer interface with ~readline~ than trying to ~grep~ our way through. * Replace ~declare~ with ~local~ Again, this script is sourced by the shell -- keep variable scopes as narrow as possible. * Use ~compopt -o nosort~ Often I resort to using it to keep different groups of completions together. Whether this is more ergonomic or not is subjective. But our input lists are already sorted at build-time so why not. Sort manually =query-filters.txt= when changing it. * Remove irrelevant comments And add some new ones :) I think that is all. Give it a spin, try to abuse it, in and outside of quotes, with some funky accounts, payees, tags, whatever, and tell me where it breaks or behaves unexpectedly.
This commit is contained in:
		
							parent
							
								
									4c9b72ea15
								
							
						
					
					
						commit
						72b737a42f
					
				| @ -10,7 +10,7 @@ generic-options.txt: | ||||
| 	hledger -h | ./output-options.sh | sort -u > $@ | ||||
| 
 | ||||
| commands.txt: | ||||
| 	hledger | ./output-commands.sh | grep -v ^hledger > $@ | ||||
| 	hledger | ./output-commands.sh | grep -v ^hledger | sort -u > $@ | ||||
| 	echo ui  >> $@ | ||||
| 	echo web >> $@ | ||||
| 	echo api >> $@ | ||||
| @ -23,8 +23,9 @@ commands-list.txt: commands.txt | ||||
| 	# hledger help --cat hledger | sed -n '/^QUERIES/,/^[A-Z]/p' | ||||
| 
 | ||||
| command-options: commands.txt | ||||
| 	parallel -j8 'hledger {} -h | ./output-options.sh | sort -u > options-{}.txt' < commands.txt | ||||
| 	parallel -j8 'hledger {} -h | ./output-options.sh {} | sort -u > options-{}.txt' < commands.txt | ||||
| 
 | ||||
| clean: | ||||
| 	rm -f commands*.txt generic-options.txt options-*.txt | ||||
| 	rm -f hledger-completion.bash | ||||
| 	rm -rf _{commands,options}.tmp | ||||
|  | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -1,102 +1,99 @@ | ||||
| 
 | ||||
| # 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) | ||||
| # This script is sourced by an interactive shell, so do NOT do things like | ||||
| # 'set -o pipefail' or mangle the global environment in any other way! | ||||
| # That said, we *do* remove colon (:) from COMP_WORDBREAKS which impacts | ||||
| # the rest of the session and completion for other programs. | ||||
| 
 | ||||
| _hledger_completion_function() { | ||||
|     #declare cmd=$1 | ||||
|     declare wordToComplete=$2 | ||||
|     declare precedingWord=$3 | ||||
|     # Current treatment for special characters: | ||||
|     # - exclude colon (:) from COMP_WORDBREAKS | ||||
|     # - use comptop -o filenames to escape the rest | ||||
|     COMP_WORDBREAKS=${COMP_WORDBREAKS//:} | ||||
|     compopt -o filenames | ||||
| 
 | ||||
|     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 | ||||
|     local wordToComplete=$2 | ||||
|     local subcommand | ||||
|     local subcommandOptions | ||||
|     local i | ||||
| 
 | ||||
|     for (( i=1; i<${#COMP_WORDS[@]}; i++ )); do | ||||
|         subcommand=${COMP_WORDS[i]} | ||||
|         if ! grep -Fxqe "$subcommand" <<< "$_hledger_complist_commands"; then | ||||
|             subcommand= | ||||
|             continue | ||||
|         fi | ||||
|         # There could be other commands begining with $subcommand, e.g.: | ||||
|         # $subcommand == reg --> register, register-match, | ||||
|         # $subcommand == bal --> balance, balancesheet, balancesheetequity, etc. | ||||
|         # Do not ignore them! | ||||
|         if [[ $subcommand == "$wordToComplete" ]] && ((i == COMP_CWORD)); then | ||||
|             local subcommandMatches | ||||
|             subcommandMatches=$(grep -c "^$wordToComplete" <<< "$_hledger_complist_commands") | ||||
|             if ((subcommandMatches > 1)); then | ||||
|                 subcommand= | ||||
|                 break | ||||
|             else | ||||
|                 _hledger_compreply "$subcommand" | ||||
|                 return 0 | ||||
|             fi | ||||
|         fi | ||||
|         # Replace dashes with underscores and use indirect expansion | ||||
|         subcommandOptions=_hledger_complist_options_${subcommand//-/_} | ||||
|         _hledger_compreply "$(_hledger_compgen "${!subcommandOptions}")" | ||||
|         break | ||||
|     done | ||||
| 
 | ||||
|     if [[ -z $subcommand ]]; then | ||||
|         _hledger_compreply_optarg && return | ||||
| 
 | ||||
| 	declare completeFiles filenameSoFar | ||||
| 	case $precedingWord in | ||||
| 	    -f|--file|--rules-file) | ||||
| 		completeFiles=1 | ||||
| 		filenameSoFar=$wordToComplete | ||||
| 		;; | ||||
| 	    =) | ||||
| 		completeFiles=1 | ||||
| 		filenameSoFar=$wordToComplete | ||||
| 		;; | ||||
| 	esac | ||||
|         # Completion lists are already sorted at build-time | ||||
|         # This keeps commands and options grouped separately | ||||
|         compopt -o nosort | ||||
|         _hledger_compreply "$(_hledger_compgen "$_hledger_complist_commands")" | ||||
|         _hledger_compreply_append "$(_hledger_compgen "$_hledger_complist_generic_options")" | ||||
| 
 | ||||
| 	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") ) | ||||
|         return 0 | ||||
|     fi | ||||
| 
 | ||||
|     else | ||||
|     # Option argument completion after subcommand too | ||||
|     _hledger_compreply_optarg && return | ||||
| 
 | ||||
|     # Avoid setting compopt bellow if completing an option | ||||
|     [[ $wordToComplete == -* ]] && return | ||||
| 
 | ||||
|     # Almost all subcommands accept [QUERY] | ||||
|     # -> always add accounts to completion list | ||||
|     # Except for those few that will complain | ||||
|     local noQuery=(files help test) | ||||
|     [[ " ${noQuery[*]} " =~ " $subcommand " ]] && return | ||||
|     # Add any other subcommand special treatment here, or if it becomes unwieldy | ||||
|     # move it out in say _hledger_compreply_subcommand() and return on success. | ||||
| 
 | ||||
| 	# 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=' ' | ||||
|     # Query specific completions | ||||
|     _hledger_compreply_query && return | ||||
| 
 | ||||
|     # Do not sort, keep accounts and query filters grouped separately | ||||
|     compopt -o nosort -o nospace | ||||
|     _hledger_compreply_append "$(_hledger_compgen "$_hledger_complist_query_filters")" | ||||
|     if [[ -z $wordToComplete ]]; then | ||||
|         _hledger_compreply_append "$(_hledger_compgen "$(_hledger accounts --flat --depth 1)")" | ||||
|     else | ||||
|         _hledger_compreply_append "$(_hledger_compgen "$(_hledger accounts --flat)")" | ||||
|     fi | ||||
| 
 | ||||
|     return 0 | ||||
| } | ||||
| 
 | ||||
| _hledger_extension_completion_function() { | ||||
|     declare cmd=$1 | ||||
|     local cmd=$1 | ||||
|     shift | ||||
| 
 | ||||
|     # 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 | ||||
|     local extensionName=${cmd#*-} | ||||
|     COMP_WORDS=( "hledger" "$extensionName" "${COMP_WORDS[@]:1}" ) | ||||
|     _hledger_completion_function "hledger" "$@" | ||||
| } | ||||
| 
 | ||||
| @ -107,26 +104,223 @@ complete -F _hledger_completion_function hledger | ||||
| complete -F _hledger_extension_completion_function hledger-ui | ||||
| complete -F _hledger_extension_completion_function hledger-web | ||||
| 
 | ||||
| # Helpers | ||||
| 
 | ||||
| # Comment out when done | ||||
| _hledger_debug() { | ||||
|     ((HLEDGER_DEBUG)) || return 0 | ||||
|     local var=${1:-COMP_WORDS} | ||||
|     printf '\ndebug: %s\n' "$(declare -p "$var")" >&2 | ||||
| } | ||||
| 
 | ||||
| # Stolen from bash-completion | ||||
| # This function quotes the argument in a way so that readline dequoting | ||||
| # results in the original argument.  This is necessary for at least | ||||
| # `compgen' which requires its arguments quoted/escaped: | ||||
| _hledger_quote_by_ref() | ||||
| { | ||||
|     printf -v $2 %q "$1" | ||||
| 
 | ||||
|     # If result becomes quoted like this: $'string', re-evaluate in order to | ||||
|     # drop the additional quoting.  See also: http://www.mail-archive.com/ | ||||
|     # bash-completion-devel@lists.alioth.debian.org/msg01942.html | ||||
|     [[ ${!2} == \$* ]] && eval $2=${!2} | ||||
| } | ||||
| 
 | ||||
| _hledger_quote() | ||||
| { | ||||
|     local quoted | ||||
|     _hledger_quote_by_ref "$1" quoted | ||||
|     printf %s "$quoted" | ||||
| } | ||||
| 
 | ||||
| # Set the value of COMPREPLY from newline delimited completion candidates | ||||
| _hledger_compreply() { | ||||
|     local IFS=$'\n' | ||||
|     COMPREPLY=($1) | ||||
| } | ||||
| 
 | ||||
| # Append the value of COMPREPLY from newline delimited completion candidates | ||||
| _hledger_compreply_append() { | ||||
|     local IFS=$'\n' | ||||
|     COMPREPLY+=($1) | ||||
| } | ||||
| 
 | ||||
| # Generate input suitable for _hledger_compreply() from newline delimited | ||||
| # completion candidates. It doesn't seem there is a way to feed a literal | ||||
| # wordlist to compgen -- it will eat your quotes, drink your booze and... | ||||
| # Completion candidates are quoted accordingly first and then we leave it to | ||||
| # compgen to deal with readline. | ||||
| _hledger_compgen() { | ||||
|     local wordlist=$1 | ||||
|     local quoted=() | ||||
|     local word | ||||
|     local i=0 | ||||
| 
 | ||||
|     while IFS= read -r word; do | ||||
|         _hledger_quote_by_ref "$word" word | ||||
|         quoted[i++]=$word | ||||
|     done <<< "$wordlist" | ||||
| 
 | ||||
|     local IFS=$'\n' | ||||
|     compgen -W "${quoted[*]}" -- "$wordToComplete" | ||||
| } | ||||
| 
 | ||||
| # Try required option argument completion. Set COMPREPLY and return 0 on | ||||
| # success, 1 if option doesn't require an argument or out of context | ||||
| _hledger_compreply_optarg() { | ||||
|     local optionIndex=${1:-$((COMP_CWORD - 1))} | ||||
|     local recursionLevel=${2:-0} | ||||
|     local wordlist | ||||
|     local error=0 | ||||
| 
 | ||||
|     case ${COMP_WORDS[optionIndex]} in | ||||
|         --alias) | ||||
|             compopt -o nospace | ||||
|             _hledger_compreply "$(_hledger_compgen "$(_hledger accounts --flat)")" | ||||
|             ;; | ||||
|         -f|--file|--rules-file|-o|--output-file) | ||||
|             _hledger_compreply "$(compgen -f -- "$wordToComplete")" | ||||
|             ;; | ||||
|         --pivot) | ||||
|             compopt -o nosort | ||||
|             wordlist="code description note payee" | ||||
|             _hledger_compreply "$(compgen -W "$wordlist" -- "$wordToComplete")" | ||||
|             _hledger_compreply_append "$(_hledger_compgen "$(_hledger tags)")" | ||||
|             ;; | ||||
|         --value) | ||||
|             wordlist="cost then end now" | ||||
|             _hledger_compreply "$(compgen -W "$wordlist" -- "$wordToComplete")" | ||||
|             ;; | ||||
|         -X|--exchange) | ||||
|             _hledger_compreply "$(_hledger_compgen "$(_hledger commodities)")" | ||||
|             ;; | ||||
|         --color|--colour) | ||||
|             compopt -o nosort | ||||
|             wordlist="auto always yes never no" | ||||
|             _hledger_compreply "$(compgen -W "$wordlist" -- "$wordToComplete")" | ||||
|             ;; | ||||
|         # Argument required, but no handler (yet) | ||||
|         -b|--begin|-e|--end|-p|--period|--depth) | ||||
|             _hledger_compreply "" | ||||
|             ;; | ||||
|         =) | ||||
|             # Recurse only once! | ||||
|             ((recursionLevel > 1)) && return 1 | ||||
|             if [[ ${COMP_WORDS[optionIndex - 1]} == -* ]]; then | ||||
|                 _hledger_compreply_optarg $((optionIndex - 1)) $((recursionLevel + 1)) | ||||
|                 error=$? | ||||
|             fi | ||||
|             ;; | ||||
|         *) | ||||
|             error=1 | ||||
|             ;; | ||||
|     esac | ||||
| 
 | ||||
|     return $error | ||||
| } | ||||
| 
 | ||||
| # Query filter completion through introspection | ||||
| _hledger_compreply_query() { | ||||
|     [[ $wordToComplete =~ .: ]] || return | ||||
|     local query=${wordToComplete%%:*}: | ||||
|     grep -Fxqe "$query" <<< "$_hledger_complist_query_filters" || return | ||||
| 
 | ||||
|     local hledgerArgs=() | ||||
|     case $query in | ||||
|         acct:) | ||||
|             hledgerArgs=(accounts --flat) | ||||
|             ;; | ||||
|         code:) | ||||
|             hledgerArgs=(codes) | ||||
|             ;; | ||||
|         cur:) | ||||
|             hledgerArgs=(commodities) | ||||
|             ;; | ||||
|         desc:) | ||||
|             hledgerArgs=(descriptions) | ||||
|             ;; | ||||
|         note:) | ||||
|             hledgerArgs=(notes) | ||||
|             ;; | ||||
|         payee:) | ||||
|             hledgerArgs=(payees) | ||||
|             ;; | ||||
|         tag:) | ||||
|             hledgerArgs=(tags) | ||||
|             ;; | ||||
|         *) | ||||
|             return 1 | ||||
|             ;; | ||||
|     esac | ||||
| 
 | ||||
|     _hledger_compreply "$( | ||||
|         _hledger_compgen "$( | ||||
|             _hledger "${hledgerArgs[@]}" | sed "s/^/$query/g" | ||||
|         )" | ||||
|     )" | ||||
| 
 | ||||
|     return 0 | ||||
| } | ||||
| 
 | ||||
| # Get ledger file from -f --file arguments from COMP_WORDS and pass it to the | ||||
| # 'hledger' call. Note that --rules-file - if present - must also be passed! | ||||
| _hledger() { | ||||
|     local hledgerArgs=("$@") | ||||
|     local hledgerFile | ||||
|     local hledgerRulesFile | ||||
|     local i | ||||
| 
 | ||||
|     # hledger balance --file ~/ledger _ | ||||
|     # 0       1       2      3        4 | ||||
|     for (( i=1; i < ${#COMP_WORDS[@]} - 2; i++ )); do | ||||
|         case ${COMP_WORDS[i]} in | ||||
|             -f|--file) | ||||
|                 if [[ ${COMP_WORDS[i+1]} == '=' ]]; then | ||||
|                     hledgerFile=${COMP_WORDS[i+2]} | ||||
|                 else | ||||
|                     hledgerFile=${COMP_WORDS[i+1]} | ||||
|                 fi | ||||
|                 ;; | ||||
|             --rules-file) | ||||
|                 if [[ ${COMP_WORDS[i+1]} == '=' ]]; then | ||||
|                     hledgerRulesFile=${COMP_WORDS[i+2]} | ||||
|                 else | ||||
|                     hledgerRulesFile=${COMP_WORDS[i+1]} | ||||
|                 fi | ||||
|                 ;; | ||||
|         esac | ||||
|     done | ||||
| 
 | ||||
|     [[ -f $hledgerFile ]] && hledgerArgs+=(--file "$hledgerFile") | ||||
|     [[ -f $hledgerRulesFile ]] && hledgerArgs+=(--rules-file "$hledgerRulesFile") | ||||
| 
 | ||||
|     # Discard errors. Is there a way to validate files before using them? | ||||
|     hledger "${hledgerArgs[@]}" 2>/dev/null | ||||
| } | ||||
| 
 | ||||
| # 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" | ||||
| read -r -d "" _hledger_complist_commands <<TEXT | ||||
| include(`commands.txt')dnl | ||||
| TEXT | ||||
| 
 | ||||
| cat <<TEXT > "$_HLEDGER_COMPLETION_TEMPDIR/query-filters.txt" | ||||
| read -r -d "" _hledger_complist_query_filters <<TEXT | ||||
| include(`query-filters.txt')dnl | ||||
| TEXT | ||||
| 
 | ||||
| cat <<TEXT > "$_HLEDGER_COMPLETION_TEMPDIR/generic-options.txt" | ||||
| read -r -d "" _hledger_complist_generic_options <<TEXT | ||||
| include(`generic-options.txt')dnl | ||||
| TEXT | ||||
| 
 | ||||
| include(`foreach2.m4') | ||||
| 
 | ||||
| # Dashes are replaced by m4 with underscores to form valid identifiers | ||||
| # Referenced by indirect expansion of $subcommandOptions | ||||
| dnl | ||||
| include(`foreach2.m4')dnl | ||||
| foreach(`cmd', (include(`commands-list.txt')), ` | ||||
| cat <<TEXT > "$_HLEDGER_COMPLETION_TEMPDIR/options-cmd.txt" | ||||
| read -r -d "" _hledger_complist_options_`'translit(cmd, -, _) <<TEXT | ||||
| include(options-cmd.txt)dnl | ||||
| TEXT | ||||
| ') | ||||
| ')dnl | ||||
|  | ||||
| @ -4,20 +4,16 @@ | ||||
| set -o errexit -o pipefail -o nounset | ||||
| 
 | ||||
| main() { | ||||
|     declare tmp | ||||
|     tmp=$(mktemp) | ||||
|     declare tmp="_commands.tmp" | ||||
|     cat > "$tmp" | ||||
| 
 | ||||
|     # Do not output mistaken commands that start with a dash (e.g. -h) | ||||
|     sed -rn 's/^ ([-a-z]+).*/\1/gp' "$tmp" \ | ||||
| 	| grep -v ^- | ||||
|     sed -rn 's/^\s+([a-z][-a-z]+)\s+.*/\1/p' "$tmp" | ||||
| 
 | ||||
|     # Output single command aliases in parenthesis: | ||||
|     # Output command aliases in parenthesis: | ||||
|     # Do not output single letter command aliases, it's not useful. | ||||
|     sed -rn 's/^ .*\(([a-z]+)\).*/\1/gp' "$tmp" \ | ||||
| 	| grep -v ^.$ | ||||
| 
 | ||||
|     # TODO missing: (reg, r)  (multiple aliases) | ||||
|     sed -rn 's/^\s+[a-z][-a-z]+\s+\(([a-z][ ,a-z]+)\).*/\1/p' "$tmp" | | ||||
|         sed 's/\s*,\s*/\n/g' | | ||||
|         sed '/^.$/d' | ||||
| } | ||||
| 
 | ||||
| main "$@" | ||||
|  | ||||
| @ -4,10 +4,16 @@ | ||||
| set -o errexit -o pipefail -o nounset | ||||
| 
 | ||||
| main() { | ||||
|     declare tmp | ||||
|     tmp=$(mktemp) | ||||
|     declare tmpdir="_options.tmp" | ||||
|     declare tmp="${tmpdir}/${1:-generic}" | ||||
| 
 | ||||
|     mkdir -p "$tmpdir" | ||||
|     cat > "$tmp" | ||||
|     sed -rn 's/.* (-[a-zA-Z0-9]).*/\1/gp' < "$tmp" | ||||
| 
 | ||||
|     # Do not propose single letter completions. It's not useful, it's noisy | ||||
|     # and it makes completion slower: | ||||
|     # Display all 200 possibilities? (y or n) | ||||
|     # 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. | ||||
|  | ||||
| @ -1,22 +1,15 @@ | ||||
| not: | ||||
| acct: | ||||
| amt: | ||||
| amt:< | ||||
| amt:<= | ||||
| amt:> | ||||
| amt:>= | ||||
| code: | ||||
| cur: | ||||
| desc: | ||||
| date: | ||||
| date2: | ||||
| depth: | ||||
| desc: | ||||
| inacct: | ||||
| not: | ||||
| note: | ||||
| payee: | ||||
| real: | ||||
| real:0 | ||||
| status: | ||||
| status:! | ||||
| status:* | ||||
| tag: | ||||
| inacct: | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user