ENH: Enable file completion for add-on actions via _todo_file{1,2,3}_actions (#270)

* Refactoring: Use regular expression match instead of case globbing for actions taking a SRC argument

Making it consistent with the test for MOVE_COMMAND_PATTERN, and allowing to extend the pattern with custom actions in the future.

* Refactoring: Move the anchoring and grouping out of MOVE_COMMAND_PATTERN

So that additional (custom) add-on actions can be configured in the future.

* ENH: Enable file completion for add-on actions via _todo_file{1,2,3}_actions

Allowing completion of todo files directly after the add-on action (1), with one (2) / two (3) arguments in between. This should handle most cases.

In order to configure the add-on completion, the corresponding configuration variable has to be defined in the user's shell (e.g. via ~/.bashrc):
_todo_file1_actions='myaction|anotheraction'
This commit is contained in:
Ingo Karkat
2020-03-31 00:44:50 +02:00
committed by GitHub
parent abdbe5371c
commit 177432ec94
2 changed files with 82 additions and 52 deletions

View File

@@ -0,0 +1,28 @@
#!/bin/bash
#
test_description='Bash add-on action file completion functionality
This test checks todo_completion of files for add-on actions that have file argument(s) configured
'
. ./test-lib.sh
readonly FILES='done.txt report.txt todo.txt'
test_todo_completion 'nothing after unconfigured bar' 'todo.sh bar ' ''
_todo_file1_actions='foo|bar'
test_todo_completion 'all files after configured bar' 'todo.sh bar ' "$FILES"
test_todo_completion 'nothing after configured bar ITEM#' 'todo.sh bar 1 ' ''
_todo_file2_actions='baz'
test_todo_completion 'nothing after configured baz' 'todo.sh baz ' ''
test_todo_completion 'all files after configured baz ITEM#' 'todo.sh baz 1 ' "$FILES"
test_todo_completion 'nothing after configured baz ITEM# MORE' 'todo.sh baz 1 more ' ''
_todo_file3_actions='biz'
test_todo_completion 'nothing after configured biz' 'todo.sh biz ' ''
test_todo_completion 'nothing after configured biz ITEM#' 'todo.sh biz 1 ' ''
test_todo_completion 'all files after configured biz ITEM# MORE' 'todo.sh biz 1 more ' "$FILES"
test_todo_completion 'nothing after configured biz ITEM# EVEN MORE' 'todo.sh biz 1 even more ' ''
test_done

View File

@@ -14,15 +14,15 @@ _todo()
rm depri dp do help list ls listaddons listall lsa listcon \ rm depri dp do help list ls listaddons listall lsa listcon \
lsc listfile lf listpri lsp listproj lsprj move \ lsc listfile lf listpri lsp listproj lsprj move \
mv prepend prep pri p replace report shorthelp" mv prepend prep pri p replace report shorthelp"
local -r MOVE_COMMAND_PATTERN='^(move|mv)$' local -r MOVE_COMMAND_PATTERN='move|mv'
local _todo_sh=${_todo_sh:-todo.sh} local _todo_sh=${_todo_sh:-todo.sh}
local completions local completions
if [ $COMP_CWORD -eq 1 ]; then if [ $COMP_CWORD -eq 1 ]; then
completions="$COMMANDS $(eval TODOTXT_VERBOSE=0 $_todo_sh command listaddons 2>/dev/null) $OPTS" completions="$COMMANDS $(eval TODOTXT_VERBOSE=0 $_todo_sh command listaddons 2>/dev/null) $OPTS"
elif [[ $COMP_CWORD -gt 2 && ( \ elif [[ $COMP_CWORD -gt 2 && ( \
"${COMP_WORDS[COMP_CWORD-2]}" =~ $MOVE_COMMAND_PATTERN || \ "${COMP_WORDS[COMP_CWORD-2]}" =~ ^($MOVE_COMMAND_PATTERN${_todo_file2_actions:+|${_todo_file2_actions}})$ || \
"${COMP_WORDS[COMP_CWORD-3]}" =~ $MOVE_COMMAND_PATTERN ) ]]; then "${COMP_WORDS[COMP_CWORD-3]}" =~ ^($MOVE_COMMAND_PATTERN${_todo_file3_actions:+|${_todo_file3_actions}})$ ) ]]; then
# "move ITEM# DEST [SRC]" has file arguments on positions 2 and 3. # "move ITEM# DEST [SRC]" has file arguments on positions 2 and 3.
completions=$(eval TODOTXT_VERBOSE=0 $_todo_sh command listfile 2>/dev/null) completions=$(eval TODOTXT_VERBOSE=0 $_todo_sh command listfile 2>/dev/null)
else else
@@ -31,56 +31,58 @@ _todo()
completions=$COMMANDS;; completions=$COMMANDS;;
help) help)
completions="$COMMANDS $(eval TODOTXT_VERBOSE=0 $_todo_sh command listaddons 2>/dev/null)";; completions="$COMMANDS $(eval TODOTXT_VERBOSE=0 $_todo_sh command listaddons 2>/dev/null)";;
addto|listfile|lf)
completions=$(eval TODOTXT_VERBOSE=0 $_todo_sh command listfile 2>/dev/null);;
-*) completions="$COMMANDS $(eval TODOTXT_VERBOSE=0 $_todo_sh command listaddons 2>/dev/null) $OPTS";; -*) completions="$COMMANDS $(eval TODOTXT_VERBOSE=0 $_todo_sh command listaddons 2>/dev/null) $OPTS";;
*) case "$cur" in *) if [[ "$prev" =~ ^(addto|listfile|lf${_todo_file1_actions:+|${_todo_file1_actions}})$ ]]; then
+*) completions=$(eval TODOTXT_VERBOSE=0 $_todo_sh command listproj 2>/dev/null) completions=$(eval TODOTXT_VERBOSE=0 $_todo_sh command listfile 2>/dev/null)
COMPREPLY=( $( compgen -W "$completions" -- $cur )) else
[ ${#COMPREPLY[@]} -gt 0 ] && return 0 case "$cur" in
# Fall back to projects extracted from done tasks. +*) completions=$(eval TODOTXT_VERBOSE=0 $_todo_sh command listproj 2>/dev/null)
completions=$(eval 'TODOTXT_VERBOSE=0 TODOTXT_SOURCEVAR=\$DONE_FILE' $_todo_sh command listproj 2>/dev/null) COMPREPLY=( $( compgen -W "$completions" -- $cur ))
;; [ ${#COMPREPLY[@]} -gt 0 ] && return 0
@*) completions=$(eval TODOTXT_VERBOSE=0 $_todo_sh command listcon 2>/dev/null) # Fall back to projects extracted from done tasks.
COMPREPLY=( $( compgen -W "$completions" -- $cur )) completions=$(eval 'TODOTXT_VERBOSE=0 TODOTXT_SOURCEVAR=\$DONE_FILE' $_todo_sh command listproj 2>/dev/null)
[ ${#COMPREPLY[@]} -gt 0 ] && return 0 ;;
# Fall back to contexts extracted from done tasks. @*) completions=$(eval TODOTXT_VERBOSE=0 $_todo_sh command listcon 2>/dev/null)
completions=$(eval 'TODOTXT_VERBOSE=0 TODOTXT_SOURCEVAR=\$DONE_FILE' $_todo_sh command listcon 2>/dev/null) COMPREPLY=( $( compgen -W "$completions" -- $cur ))
;; [ ${#COMPREPLY[@]} -gt 0 ] && return 0
*) if [[ "$cur" =~ ^[0-9]+$ ]]; then # Fall back to contexts extracted from done tasks.
declare -a sedTransformations=( completions=$(eval 'TODOTXT_VERBOSE=0 TODOTXT_SOURCEVAR=\$DONE_FILE' $_todo_sh command listcon 2>/dev/null)
# Remove the (padded) task number; we prepend the ;;
# user-provided $cur instead. *) if [[ "$cur" =~ ^[0-9]+$ ]]; then
-e 's/^ *[0-9]\{1,\} //' declare -a sedTransformations=(
# Remove the timestamp prepended by the -t option, # Remove the (padded) task number; we prepend the
# but keep any priority (as it's short and may # user-provided $cur instead.
# provide useful context). -e 's/^ *[0-9]\{1,\} //'
-e 's/^\((.) \)\{0,1\}[0-9]\{2,4\}-[0-9]\{2\}-[0-9]\{2\} /\1/' # Remove the timestamp prepended by the -t option,
# Remove the done date and (if there) the timestamp. # but keep any priority (as it's short and may
# Keep the "x" (as it's short and may provide useful # provide useful context).
# context) -e 's/^\((.) \)\{0,1\}[0-9]\{2,4\}-[0-9]\{2\}-[0-9]\{2\} /\1/'
-e 's/^\([xX] \)\([0-9]\{2,4\}-[0-9]\{2\}-[0-9]\{2\} \)\{1,2\}/\1/' # Remove the done date and (if there) the timestamp.
# Remove any trailing whitespace; the Bash # Keep the "x" (as it's short and may provide useful
# completion inserts a trailing space itself. # context)
-e 's/[[:space:]]*$//' -e 's/^\([xX] \)\([0-9]\{2,4\}-[0-9]\{2\}-[0-9]\{2\} \)\{1,2\}/\1/'
# Finally, limit the output to a single line just as # Remove any trailing whitespace; the Bash
# a safety check of the ls action output. # completion inserts a trailing space itself.
-e '1q' -e 's/[[:space:]]*$//'
) # Finally, limit the output to a single line just as
local todo=$( \ # a safety check of the ls action output.
eval TODOTXT_VERBOSE=0 $_todo_sh '-@ -+ -p -x command ls "^ *${cur} "' 2>/dev/null | \ -e '1q'
sed "${sedTransformations[@]}" \ )
) local todo=$( \
# Append task text as a shell comment. This eval TODOTXT_VERBOSE=0 $_todo_sh '-@ -+ -p -x command ls "^ *${cur} "' 2>/dev/null | \
# completion can be a safety check before a sed "${sedTransformations[@]}" \
# destructive todo.txt operation. )
[ "$todo" ] && COMPREPLY[0]="$cur # $todo" # Append task text as a shell comment. This
return 0 # completion can be a safety check before a
else # destructive todo.txt operation.
return 0 [ "$todo" ] && COMPREPLY[0]="$cur # $todo"
fi return 0
;; else
esac return 0
fi
;;
esac
fi
;; ;;
esac esac
fi fi