diff --git a/tests/actions-test-lib.sh b/tests/actions-test-lib.sh new file mode 100644 index 0000000..2928261 --- /dev/null +++ b/tests/actions-test-lib.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +make_action() +{ + unset TODO_ACTIONS_DIR + [ -d .todo.actions.d ] || mkdir .todo.actions.d + cat > ".todo.actions.d/$1" <>> todo.sh help | sed '/^ [A-Z]/!d' + Usage: todo.sh [-fhpantvV] [-d todo_config] action [task_number] [task_description] + Options: + Built-in Actions: +EOF + +test_todo_session 'verbose help output' <>> todo.sh -v help | sed '/^ [A-Z]/!d' + Usage: todo.sh [-fhpantvV] [-d todo_config] action [task_number] [task_description] + Options: + Built-in Actions: +EOF + +test_todo_session 'very verbose help output' <>> todo.sh -vv help | sed '/^ [A-Z]/!d' + Usage: todo.sh [-fhpantvV] [-d todo_config] action [task_number] [task_description] + Options: + Environment variables: + Built-in Actions: +EOF + +make_action "foo" +test_todo_session 'help output with custom action' <>> todo.sh -v help | sed '/^ [A-Z]/!d' + Usage: todo.sh [-fhpantvV] [-d todo_config] action [task_number] [task_description] + Options: + Built-in Actions: + Add-on Actions: +EOF + +test_done diff --git a/tests/t2110-help-action.sh b/tests/t2110-help-action.sh new file mode 100755 index 0000000..06d910c --- /dev/null +++ b/tests/t2110-help-action.sh @@ -0,0 +1,66 @@ +#!/bin/bash + +test_description='built-in actions help functionality + +This test checks listing the usage help of a built-in action. +' +. ./test-lib.sh + +test_todo_session 'nonexisting action help' <<'EOF' +>>> todo.sh help doesnotexist +TODO: No action "doesnotexist" exists. +=== 1 + +>>> todo.sh help hel +TODO: No action "hel" exists. +=== 1 + +>>> todo.sh help h +TODO: No action "h" exists. +=== 1 +EOF + +test_todo_session 'single action help' <<'EOF' +>>> todo.sh help shorthelp + shorthelp + List the one-line usage of all built-in and add-on actions. +\ +EOF + +test_todo_session 'multiple actions help' <<'EOF' +>>> todo.sh help shorthelp append + shorthelp + List the one-line usage of all built-in and add-on actions. +\ + append ITEM# "TEXT TO APPEND" + app ITEM# "TEXT TO APPEND" + Adds TEXT TO APPEND to the end of the task on line ITEM#. + Quotes optional. +\ +EOF + +test_todo_session 'short and long form of action help' <<'EOF' +>>> todo.sh help append + append ITEM# "TEXT TO APPEND" + app ITEM# "TEXT TO APPEND" + Adds TEXT TO APPEND to the end of the task on line ITEM#. + Quotes optional. +\ + +>>> todo.sh help app + app ITEM# "TEXT TO APPEND" + Adds TEXT TO APPEND to the end of the task on line ITEM#. + Quotes optional. +\ +EOF + +test_todo_session 'mixed existing and nonexisting action help' <<'EOF' +>>> todo.sh help shorthelp doesnotexist list + shorthelp + List the one-line usage of all built-in and add-on actions. +\ +TODO: No action "doesnotexist" exists. +=== 1 +EOF + +test_done diff --git a/tests/t6100-completion-help.sh b/tests/t6100-completion-help.sh new file mode 100755 index 0000000..079099f --- /dev/null +++ b/tests/t6100-completion-help.sh @@ -0,0 +1,20 @@ +#!/bin/bash +# + +test_description='Bash help completion functionality + +This test checks todo_completion of actions for usage help. +' +. ./actions-test-lib.sh +. ./test-lib.sh +make_action "zany" +make_action "aardvark" + +readonly ACTIONS='add a addto addm append app archive command del rm depri dp do help list ls listaddons listall lsa listcon lsc listfile lf listpri lsp listproj lsprj move mv prepend prep pri p replace report shorthelp' +readonly ADDONS='aardvark zany' + +test_todo_completion 'all actions after help' 'todo.sh help ' "$ACTIONS $ADDONS" +test_todo_completion 'all actions after command help' 'todo.sh command help ' "$ACTIONS $ADDONS" +test_todo_completion 'actions beginning with a' 'todo.sh help a' 'add a addto addm append app archive aardvark' + +test_done diff --git a/tests/t8000-actions.sh b/tests/t8000-actions.sh index 5c8b7d5..763c4e9 100755 --- a/tests/t8000-actions.sh +++ b/tests/t8000-actions.sh @@ -4,19 +4,9 @@ test_description='custom actions functionality This test covers the contract between todo.sh and custom actions. ' +. ./actions-test-lib.sh . ./test-lib.sh -unset TODO_ACTIONS_DIR -mkdir .todo.actions.d -make_action() -{ - cat > ".todo.actions.d/$1" <<- EOF - #!/bin/bash - echo "custom action $1" -EOF -chmod +x ".todo.actions.d/$1" -} - make_action "foo" test_todo_session 'executable action' <>> todo.sh foo diff --git a/tests/t8010-listaddons.sh b/tests/t8010-listaddons.sh new file mode 100755 index 0000000..ed0cb05 --- /dev/null +++ b/tests/t8010-listaddons.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +test_description='listaddons functionality + +This test checks listing of custom actions. +' +. ./actions-test-lib.sh +. ./test-lib.sh + +test_todo_session 'no custom actions' <>> todo.sh listaddons +EOF + +make_action "foo" +test_todo_session 'one custom action' <>> todo.sh listaddons +foo +EOF + +make_action "bar" +make_action "ls" +make_action "quux" +test_todo_session 'multiple custom actions' <>> todo.sh listaddons +bar +foo +ls +quux +EOF + +chmod -x .todo.actions.d/foo +# On Cygwin, clearing the executable flag may have no effect, as the Windows ACL +# may still grant execution rights. In this case, we skip the test. +if [ -x .todo.actions.d/foo ]; then + SKIP_TESTS="${SKIP_TESTS}${SKIP_TESTS+ }t8010.4" +fi +test_todo_session 'nonexecutable action' <>> todo.sh listaddons +bar +ls +quux +EOF + +test_done diff --git a/tests/t8020-actions-help.sh b/tests/t8020-actions-help.sh new file mode 100755 index 0000000..cc79bc1 --- /dev/null +++ b/tests/t8020-actions-help.sh @@ -0,0 +1,76 @@ +#!/bin/bash + +test_description='custom actions help functionality + +This test checks listing the usage help of a custom action. +' +. ./actions-test-lib.sh +. ./test-lib.sh + +test_todo_session 'custom action help with no custom action directory' <<'EOF' +>>> todo.sh help foo +TODO: No action "foo" exists. +=== 1 +EOF + +make_action "foo" +make_action "bar" +make_action "ls" +make_action "quux" + +test_todo_session 'custom action help' <<'EOF' +>>> todo.sh help foo + foo ITEM#[, ITEM#, ...] [TERM...] + This custom action does foo. +\ + +>>> todo.sh help bar + bar ITEM#[, ITEM#, ...] [TERM...] + This custom action does bar. +\ +EOF + +test_todo_session 'multiple custom actions help' <<'EOF' +>>> todo.sh help foo bar + foo ITEM#[, ITEM#, ...] [TERM...] + This custom action does foo. +\ + bar ITEM#[, ITEM#, ...] [TERM...] + This custom action does bar. +\ +EOF + +test_todo_session 'nonexisting action help' <<'EOF' +>>> todo.sh help doesnotexist +TODO: No action "doesnotexist" exists. +=== 1 + +>>> todo.sh help foo doesnotexist bar + foo ITEM#[, ITEM#, ...] [TERM...] + This custom action does foo. +\ +TODO: No action "doesnotexist" exists. +=== 1 +EOF + +test_todo_session 'mixed built-in and custom actions help' <<'EOF' +>>> todo.sh help foo shorthelp bar + foo ITEM#[, ITEM#, ...] [TERM...] + This custom action does foo. +\ + shorthelp + List the one-line usage of all built-in and add-on actions. +\ + bar ITEM#[, ITEM#, ...] [TERM...] + This custom action does bar. +\ +EOF + +test_todo_session 'custom override of built-in action help' <<'EOF' +>>> todo.sh help ls + ls ITEM#[, ITEM#, ...] [TERM...] + This custom action does ls. +\ +EOF + +test_done diff --git a/todo.sh b/todo.sh index b861178..a6c6c54 100755 --- a/todo.sh +++ b/todo.sh @@ -54,7 +54,7 @@ shorthelp() del|rm ITEM# [TERM] depri|dp ITEM#[, ITEM#, ITEM#, ...] do ITEM#[, ITEM#, ITEM#, ...] - help + help [ACTION...] list|ls [TERM...] listall|lsa [TERM...] listaddons @@ -154,6 +154,12 @@ help() EndVerboseHelp + actionsHelp + addonHelp +} + +actionsHelp() +{ cat <<-EndActionsHelp Built-in Actions: add "THING I NEED TO DO +project @context" @@ -200,8 +206,9 @@ help() do ITEM#[, ITEM#, ITEM#, ...] Marks task(s) on line ITEM# as done in todo.txt. - help - Display this help message. + help [ACTION...] + Display help about usage, options, built-in and add-on actions, + or just the usage help for the passed ACTION(s). list [TERM...] ls [TERM...] @@ -280,9 +287,6 @@ help() List the one-line usage of all built-in and add-on actions. EndActionsHelp - - addonHelp - exit 1 } addonHelp() @@ -304,6 +308,25 @@ addonHelp() fi } +actionUsage() +{ + for actionName + do + action="${TODO_ACTIONS_DIR}/${actionName}" + if [ -f "$action" -a -x "$action" ]; then + "$action" usage + else + builtinActionUsage=$(actionsHelp | sed -n -e "/^ ${actionName//\//\\/} /,/^\$/p" -e "/^ ${actionName//\//\\/}$/,/^\$/p") + if [ "$builtinActionUsage" ]; then + echo "$builtinActionUsage" + echo + else + die "TODO: No action \"${actionName}\" exists." + fi + fi + done +} + die() { echo "$*" @@ -1088,13 +1111,19 @@ case $action in ;; "help" ) - if [ -t 1 ] ; then # STDOUT is a TTY - if which "${PAGER:-less}" >/dev/null 2>&1; then - # we have a working PAGER (or less as a default) - help | "${PAGER:-less}" && exit 0 + shift ## Was help; new $1 is first help topic / action name + if [ $# -gt 0 ]; then + # Don't use PAGER here; we don't expect much usage output from one / few actions. + actionUsage "$@" + else + if [ -t 1 ] ; then # STDOUT is a TTY + if which "${PAGER:-less}" >/dev/null 2>&1; then + # we have a working PAGER (or less as a default) + help | "${PAGER:-less}" && exit 0 + fi fi + help # just in case something failed above, we go ahead and just spew to STDOUT fi - help # just in case something failed above, we go ahead and just spew to STDOUT ;; "shorthelp" ) diff --git a/todo_completion b/todo_completion index 95ee0c9..f443acb 100644 --- a/todo_completion +++ b/todo_completion @@ -29,6 +29,8 @@ _todo() case "$prev" in command) completions=$COMMANDS;; + help) + completions="$COMMANDS $(eval TODOTXT_VERBOSE=0 $_todo_sh command listaddons)";; addto|listfile|lf) completions=$(eval TODOTXT_VERBOSE=0 $_todo_sh command listfile);; -*) completions="$COMMANDS $(eval TODOTXT_VERBOSE=0 $_todo_sh command listaddons) $OPTS";;