From e600a2162bb3bb79218ded4bd66a2ea129408370 Mon Sep 17 00:00:00 2001 From: Ingo Karkat Date: Mon, 27 Feb 2012 14:19:11 +0100 Subject: [PATCH] ENH: completion can use different todo.sh locations and configurations. This was previously not supported; todo_completion always used plain todo.sh from the PATH. Now it's possible to override the used executable (and configuration used through _todo_sh, set from a completion function wrapper. Cp. http://tech.groups.yahoo.com/group/todotxt/message/4003 --- tests/t6080-completion-path.sh | 45 ++++++++++++++++++++++ tests/t6090-completion-aliases.sh | 62 +++++++++++++++++++++++++++++++ todo_completion | 36 ++++++++++++++---- 3 files changed, 136 insertions(+), 7 deletions(-) create mode 100755 tests/t6080-completion-path.sh create mode 100755 tests/t6090-completion-aliases.sh diff --git a/tests/t6080-completion-path.sh b/tests/t6080-completion-path.sh new file mode 100755 index 0000000..efbea4c --- /dev/null +++ b/tests/t6080-completion-path.sh @@ -0,0 +1,45 @@ +#!/bin/bash +# + +test_description='Bash completion with different path functionality + +This test checks that todo_completion can use a different path to todo.sh when +it is not accessible through PATH. +' +. ./test-lib.sh + +cat > todo.txt < todo.txt < todo2.txt <> todo2.cfg <<'EOF' +export TODO_FILE="$TODO_DIR/todo2.txt" +EOF + +# Note: We cannot use aliases within the test framework, but functions are +# equivalent and work fine. +todo1() +{ + todo.sh "$@" +} +todo2() +{ + todo.sh -d "$HOME/todo2.cfg" "$@" +} + +# Ensure that the test fixture works as planned. +test_todo_session 'todo 1 and 2 contexts' <>> todo1 listcon +@garden +@outdoor +@outside + +>>> todo2 listcon +@home +@oriental +EOF + + +# Define a second completion function that injects the different configuration +# file. In real use, this would be installed via +# complete -F _todo2 todo2 +_todo2() +{ + local _todo_sh='todo.sh -d "$HOME/todo2.cfg"' + _todo "$@" +} + +test_todo_completion 'all todo1 contexts' 'todo1 list @' '@garden @outdoor @outside' +test_todo_custom_completion _todo2 'all todo2 contexts' 'todo2 list @' '@home @oriental' + +test_done diff --git a/todo_completion b/todo_completion index df1fd07..4d1870e 100644 --- a/todo_completion +++ b/todo_completion @@ -19,6 +19,7 @@ _todo() # TODO: Filter for executable flag of files found in $TODO_ACTIONS_DIR. local allCommands="$COMMANDS $('ls' "${TODO_ACTIONS_DIR:-$HOME/.todo.actions.d}/" 2>/dev/null)" + local _todo_sh=${_todo_sh:-todo.sh} local completions if [ $COMP_CWORD -eq 1 ]; then completions="$allCommands $OPTS" @@ -26,26 +27,26 @@ _todo() "${COMP_WORDS[COMP_CWORD-2]}" =~ ^(move|mv)$ || \ "${COMP_WORDS[COMP_CWORD-3]}" =~ ^(move|mv)$ ) ]]; then # "move ITEM# DEST [SRC]" has file arguments on positions 2 and 3. - completions=$(TODOTXT_VERBOSE=0 todo.sh command listfile) + completions=$(eval TODOTXT_VERBOSE=0 $_todo_sh command listfile) else case "$prev" in command) completions=$COMMANDS;; addto|listfile|lf) - completions=$(TODOTXT_VERBOSE=0 todo.sh command listfile);; + completions=$(eval TODOTXT_VERBOSE=0 $_todo_sh command listfile);; -*) completions="$allCommands $OPTS";; *) case "$cur" in - +*) completions=$(TODOTXT_VERBOSE=0 todo.sh command listproj) + +*) completions=$(eval TODOTXT_VERBOSE=0 $_todo_sh command listproj) COMPREPLY=( $( compgen -W "$completions" -- $cur )) [ ${#COMPREPLY[@]} -gt 0 ] && return 0 # Fall back to projects extracted from done tasks. - completions=$(TODOTXT_VERBOSE=0 TODOTXT_SOURCEVAR=\$DONE_FILE todo.sh command listproj) + completions=$(eval 'TODOTXT_VERBOSE=0 TODOTXT_SOURCEVAR=\$DONE_FILE' $_todo_sh command listproj) ;; - @*) completions=$(TODOTXT_VERBOSE=0 todo.sh command listcon) + @*) completions=$(eval TODOTXT_VERBOSE=0 $_todo_sh command listcon) COMPREPLY=( $( compgen -W "$completions" -- $cur )) [ ${#COMPREPLY[@]} -gt 0 ] && return 0 # Fall back to contexts extracted from done tasks. - completions=$(TODOTXT_VERBOSE=0 TODOTXT_SOURCEVAR=\$DONE_FILE todo.sh command listcon) + completions=$(eval 'TODOTXT_VERBOSE=0 TODOTXT_SOURCEVAR=\$DONE_FILE' $_todo_sh command listcon) ;; *) if [[ "$cur" =~ ^[0-9]+$ ]]; then # Remove the (padded) task number; we prepend the @@ -60,7 +61,7 @@ _todo() # Finally, limit the output to a single line just as # a safety check of the ls action output. local todo=$( \ - TODOTXT_VERBOSE=0 todo.sh -@ -+ -p -x command ls "^ *${cur} " | \ + eval TODOTXT_VERBOSE=0 $_todo_sh '-@ -+ -p -x command ls "^ *${cur} "' | \ sed -e 's/^ *[0-9]\+ //' -e 's/\((.) \)[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/' \ -e 's/[[:space:]]*$//' \ @@ -84,6 +85,27 @@ _todo() return 0 } complete -F _todo todo.sh + # If you define an alias (e.g. "t") to todo.sh, you need to explicitly enable # completion for it, too: #complete -F _todo t + +# If you have renamed the todo.sh executable, or if it is not accessible through +# PATH, you need to add and use a wrapper completion function, like this: +#_todoElsewhere() +#{ +# local _todo_sh='/path/to/todo2.sh' +# _todo "$@" +#} +#complete -F _todoElsewhere /path/to/todo2.sh + +# If you use aliases to use different configuration(s), you need to add and use +# a wrapper completion function for each configuration if you want to complete +# fron the actual configured task locations: +#alias todo2='todo.sh -d "$HOME/todo2.cfg"' +#_todo2() +#{ +# local _todo_sh='todo.sh -d "$HOME/todo2.cfg"' +# _todo "$@" +#} +#complete -F _todo2 todo2