├── tests ├── Makefile ├── testshell.sh ├── t0100-code-nobacktick.sh ├── t1900-archive.sh ├── t6100-completion-help.sh ├── t1040-add-priority.sh ├── t6040-completion-files.sh ├── t6010-completion-contexts.sh ├── t6020-completion-projects.sh ├── t6000-completion.sh ├── t6060-completion-addon-files.sh ├── t6030-completion-tasks.sh ├── t2100-help.sh ├── t6080-completion-path.sh ├── actions-test-lib.sh ├── t1380-ls-date-number-metadata-highlighting.sh ├── t2200-no-done-report-files.sh ├── t1340-listescapes.sh ├── t2110-help-action.sh ├── t1030-addto-date.sh ├── t1500-do.sh ├── t8020-actions-help.sh ├── t6090-completion-aliases.sh ├── t8010-listaddons.sh ├── aggregate-results.sh ├── t1910-deduplicate.sh ├── t1700-depri.sh ├── t1020-addtolistfile.sh ├── t1950-report.sh ├── t0002-actions.sh ├── t1010-add-date.sh ├── t0001-null.sh ├── t0000-config.sh ├── t1000-addlist.sh ├── t1600-append.sh ├── t8000-actions.sh ├── t6050-completion-addons.sh ├── t1850-move.sh ├── t1400-prepend.sh ├── t2120-shorthelp.sh ├── t2000-multiline.sh ├── t1360-ls-project-context-highlighting.sh ├── t1310-listcon.sh ├── t1200-pri.sh ├── t1250-listpri.sh ├── t1350-listall.sh ├── t9999-testsuite_example.sh ├── t1320-listproj.sh ├── t1800-del.sh ├── t1100-replace.sh ├── t1330-ls-highlighting.sh ├── README └── test-lib.sh ├── .github ├── example.gif ├── dependabot.yml ├── ISSUE_TEMPLATE.md ├── workflows │ └── tests.yml ├── PULL_REQUEST_TEMPLATE.md ├── CODE_OF_CONDUCT.md └── CONTRIBUTING.md ├── .gitignore ├── GEN-VERSION-FILE ├── todo.cfg ├── Makefile ├── README.md ├── todo_completion ├── USAGE.md └── CHANGELOG.md /tests/Makefile: -------------------------------------------------------------------------------- 1 | test: 2 | $(MAKE) -C .. test 3 | -------------------------------------------------------------------------------- /.github/example.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/todotxt/todo.txt-cli/HEAD/.github/example.gif -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | VERSION-FILE 2 | tests/test-results 3 | tests/trash\ directory.* 4 | done.txt 5 | report.txt 6 | todo.txt 7 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: github-actions 4 | directory: / 5 | schedule: 6 | interval: weekly 7 | -------------------------------------------------------------------------------- /tests/testshell.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test_description='Providing an interactive shell in the proper environment' 4 | . ./test-lib.sh 5 | 6 | test_shell 7 | -------------------------------------------------------------------------------- /GEN-VERSION-FILE: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Based on git's GIT-VERSION-GEN. 3 | 4 | VF=VERSION-FILE 5 | DEF_VER=v0.0 6 | 7 | if test -d .git -o -f .git && 8 | VN=$(git describe --dirty --tags 2>/dev/null) 9 | then 10 | VN=${VN//-/.} 11 | else 12 | VN="$DEF_VER" 13 | fi 14 | 15 | VN=$(expr "$VN" : v*'\(.*\)') 16 | 17 | if test -r "$VF" 18 | then 19 | VC=$(sed -e 's/^VERSION=//' <"$VF") 20 | else 21 | VC=unset 22 | fi 23 | test "$VN" = "$VC" || { 24 | echo >&2 "VERSION=$VN" 25 | echo "VERSION=$VN" >"$VF" 26 | } 27 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | **Do you want to request a *feature* or report a *bug*?** 2 | 3 | 4 | **What is the current behavior?** 5 | 6 | 7 | **If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem.** 8 | 9 | 10 | **What is the expected behavior?** 11 | 12 | 13 | **Which version of todo.sh are you using?** 14 | > Run `todo.sh -V` 15 | 16 | 17 | **Which Operating System are you using?** 18 | 19 | 20 | **Which version of bash are you using?** 21 | > Run `bash --version` 22 | -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | workflow_dispatch: # Allows you to run this workflow manually from the Actions tab 9 | 10 | jobs: 11 | test: 12 | strategy: 13 | matrix: 14 | platform: [ubuntu-24.04, macos-14] 15 | runs-on: ${{ matrix.platform }} 16 | steps: 17 | - uses: actions/checkout@v4 18 | - run: make 19 | - run: make dist 20 | - run: make test 21 | - run: sudo make install 22 | - run: sudo make uninstall 23 | - run: sudo make clean 24 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | **Before submitting a pull request,** please make sure the following is done: 2 | 3 | - [ ] Fork [the repository](https://github.com/todotxt/todo.txt-cli) and create your branch from `master`. 4 | - [ ] If you've added code that should be tested, add tests! 5 | - [ ] Ensure the test suite passes. 6 | - [ ] Lint your code with [ShellCheck](https://www.shellcheck.net/). 7 | - [ ] Include a human-readable description of what the pull request is trying to accomplish. 8 | - [ ] Steps for the reviewer(s) on how they can manually QA the changes. 9 | - [ ] Have a `fixes #XX` reference to the issue that this pull request fixes. 10 | -------------------------------------------------------------------------------- /tests/t0100-code-nobacktick.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test_description='no old-style backtick command substitution 4 | 5 | This test checks the todo.sh script itself for occurrences 6 | of old-style backtick command substitution, which should be 7 | replaced with $(...). 8 | On failure, it will print each offending line number and line. 9 | ' 10 | . ./test-lib.sh 11 | 12 | backtick_check() 13 | { 14 | sed -n -e 's/\(^\|[ \t]\)#.*//' -e '/`/{' -e '=;p' -e '}' "$@" 15 | } 16 | 17 | test_todo_session 'no old-style backtick command substitution' <>> backtick_check bin/todo.sh 19 | 20 | >>> backtick_check ../../todo.cfg 21 | EOF 22 | 23 | test_done 24 | -------------------------------------------------------------------------------- /tests/t1900-archive.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test_description='archive functionality 4 | 5 | Ensure we can archive items successfully. 6 | ' 7 | . ./test-lib.sh 8 | 9 | cat > todo.txt <>> todo.sh archive 20 | x done 21 | TODO: $HOME/todo.txt archived. 22 | EOF 23 | 24 | test_todo_session 'list after archive' <>> todo.sh ls 26 | 5 four 27 | 1 one 28 | 4 one 29 | 3 three 30 | 2 two 31 | -- 32 | TODO: 5 of 5 tasks shown 33 | EOF 34 | 35 | test_todo_session 'archive warning message' <>> todo.sh archive 37 | TODO: $HOME/todo.txt does not contain any done tasks. 38 | EOF 39 | 40 | test_done 41 | -------------------------------------------------------------------------------- /tests/t6100-completion-help.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test_description='Bash help completion functionality 4 | 5 | This test checks todo_completion of actions for usage help. 6 | ' 7 | . ./actions-test-lib.sh 8 | . ./test-lib.sh 9 | make_action "zany" 10 | make_action "aardvark" 11 | 12 | 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' 13 | readonly ADDONS='aardvark zany' 14 | 15 | test_todo_completion 'all actions after help' 'todo.sh help ' "$ACTIONS $ADDONS" 16 | test_todo_completion 'all actions after command help' 'todo.sh command help ' "$ACTIONS $ADDONS" 17 | test_todo_completion 'actions beginning with a' 'todo.sh help a' 'add a addto addm append app archive aardvark' 18 | 19 | test_done 20 | -------------------------------------------------------------------------------- /tests/t1040-add-priority.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test_description='test the priority on add feature' 4 | . ./test-lib.sh 5 | 6 | ## Normal use case 7 | echo "export TODOTXT_PRIORITY_ON_ADD=A" >> todo.cfg 8 | 9 | test_todo_session 'config file priority' <>> todo.sh add take out the trash 11 | 1 (A) take out the trash 12 | TODO: 1 added. 13 | 14 | >>> todo.sh -p list 15 | 1 (A) take out the trash 16 | -- 17 | TODO: 1 of 1 tasks shown 18 | EOF 19 | 20 | ## Wrong value in config var 21 | echo "export TODOTXT_PRIORITY_ON_ADD=1" >> todo.cfg 22 | 23 | test_todo_session 'config file wrong priority' <>> todo.sh add fail to take out the trash 25 | === 1 26 | TODOTXT_PRIORITY_ON_ADD should be a capital letter from A to Z (it is now "1"). 27 | 28 | >>> todo.sh -p list 29 | === 1 30 | TODOTXT_PRIORITY_ON_ADD should be a capital letter from A to Z (it is now "1"). 31 | EOF 32 | 33 | test_done 34 | -------------------------------------------------------------------------------- /tests/t6040-completion-files.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test_description='Bash todo file completion functionality 4 | 5 | This test checks todo_completion of files in TODO_DIR. 6 | ' 7 | . ./test-lib.sh 8 | 9 | > dummy.txt 10 | readonly FILES='done.txt dummy.txt report.txt todo.txt' 11 | test_todo_completion 'all files after addto' 'todo.sh addto ' "$FILES" 12 | test_todo_completion 'files beginning with d after addto' 'todo.sh addto d' 'done.txt dummy.txt' 13 | test_todo_completion 'all files after listfile' 'todo.sh listfile ' "$FILES" 14 | test_todo_completion 'all files after lf' 'todo.sh -v lf ' "$FILES" 15 | test_todo_completion 'nothing after move' 'todo.sh move ' '' 16 | test_todo_completion 'all files after move NR' 'todo.sh move 1 ' "$FILES" 17 | test_todo_completion 'all files after mv NR' 'todo.sh mv 1 ' "$FILES" 18 | test_todo_completion 'all files after move NR DEST' 'todo.sh move 1 todo.sh ' "$FILES" 19 | 20 | test_done 21 | -------------------------------------------------------------------------------- /tests/t6010-completion-contexts.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test_description='Bash context completion functionality 4 | 5 | This test checks todo_completion of contexts 6 | ' 7 | . ./test-lib.sh 8 | 9 | cat > todo.txt < done.txt < todo.txt < done.txt < todo.txt <>> todo.sh help | sed '/^ [A-Z]/!d' 14 | Usage: todo.sh [-fhpantvV] [-d todo_config] action [task_number] [task_description] 15 | Options: 16 | Built-in Actions: 17 | EOF 18 | 19 | test_todo_session 'verbose help output' <>> todo.sh -v help | sed '/^ [A-Z]/!d' 21 | Usage: todo.sh [-fhpantvV] [-d todo_config] action [task_number] [task_description] 22 | Options: 23 | Built-in Actions: 24 | EOF 25 | 26 | test_todo_session 'very verbose help output' <>> todo.sh -vv help | sed '/^ [A-Z]/!d' 28 | Usage: todo.sh [-fhpantvV] [-d todo_config] action [task_number] [task_description] 29 | Options: 30 | Environment variables: 31 | Built-in Actions: 32 | EOF 33 | 34 | make_action "foo" 35 | test_todo_session 'help output with custom action' <>> todo.sh -v help | sed '/^ [A-Z]/!d' 37 | Usage: todo.sh [-fhpantvV] [-d todo_config] action [task_number] [task_description] 38 | Options: 39 | Built-in Actions: 40 | Add-on Actions: 41 | EOF 42 | 43 | test_done 44 | -------------------------------------------------------------------------------- /tests/t6080-completion-path.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test_description='Bash completion with different path functionality 4 | 5 | This test checks that todo_completion can use a different path to todo.sh when 6 | it is not accessible through PATH. 7 | ' 8 | . ./test-lib.sh 9 | 10 | cat > todo.txt < "$1" < todo.txt < "$TEST_TODO_LABEL_COLORS" 20 | 21 | echo "export COLOR_DATE='\\\\033[0;31m'" >>"$TEST_TODO_LABEL_COLORS" 22 | echo "export COLOR_META='\\\\033[0;32m'" >>"$TEST_TODO_LABEL_COLORS" 23 | echo "export COLOR_NUMBER='\\\\033[0;34m'" >>"$TEST_TODO_LABEL_COLORS" 24 | 25 | test_todo_session 'highlighting for date, item numbers and metadata' <<'EOF' 26 | >>> todo.sh -d "$TEST_TODO_LABEL_COLORS" ls 27 | 1 2018-11-11 task with date 28 | 2 task with metadata due:2018-12-31 29 | 3 task without date and without metadata 30 | -- 31 | TODO: 3 of 3 tasks shown 32 | EOF 33 | 34 | test_todo_session 'suppressing highlighting for date, item numbers and metadata' <<'EOF' 35 | >>> todo.sh -p -d "$TEST_TODO_LABEL_COLORS" ls 36 | 1 2018-11-11 task with date 37 | 2 task with metadata due:2018-12-31 38 | 3 task without date and without metadata 39 | -- 40 | TODO: 3 of 3 tasks shown 41 | EOF 42 | 43 | test_done 44 | -------------------------------------------------------------------------------- /tests/t2200-no-done-report-files.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test_description='todo.sh configuration with a sole todo.txt data file. 4 | 5 | This test covers turning off done.txt and report.txt, and 6 | checks that no such empty files are created. 7 | ' 8 | . ./test-lib.sh 9 | 10 | cat > test.cfg <>> todo.sh -d test.cfg add notice the daisies 21 | 1 notice the daisies 22 | TODO: 1 added. 23 | EOF 24 | 25 | test_expect_success 'the todo file has been created' '[ -e todo.txt ]' 26 | test_expect_success 'no done file has been created' '[ ! -e done.txt ]' 27 | test_expect_success 'no report file has been created' '[ ! -e report.txt ]' 28 | 29 | test_todo_session 'perform archive' <>> todo.sh -A -d test.cfg do 1 31 | 1 x 2009-02-13 notice the daisies 32 | TODO: 1 marked as done. 33 | x 2009-02-13 notice the daisies 34 | TODO: ./todo.txt archived. 35 | EOF 36 | 37 | test_expect_success 'no done file has been created by the archiving' '[ ! -e done.txt ]' 38 | 39 | test_todo_session 'perform report' <>> todo.sh -d test.cfg report 41 | TODO: ./todo.txt does not contain any done tasks. 42 | 2009-02-13T04:40:00 0 0 43 | TODO: Report file updated. 44 | EOF 45 | 46 | test_expect_success 'no report file has been created by the reporting' '[ ! -e report.txt ]' 47 | 48 | test_done 49 | -------------------------------------------------------------------------------- /tests/t1340-listescapes.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test_description='list with escape sequences 4 | 5 | This test checks listing of tasks that have embedded escape sequences in them. 6 | ' 7 | . ./test-lib.sh 8 | 9 | # 10 | # check aborted list output on \c escape sequence 11 | # 12 | cat > todo.txt <<'EOF' 13 | first todo 14 | second todo run C:\WINDOWS\sysnative\cscript.exe 15 | third todo 16 | EOF 17 | 18 | test_todo_session 'aborted list output on backslash-c' <<'EOF' 19 | >>> todo.sh ls 20 | 1 first todo 21 | 2 second todo run C:\WINDOWS\sysnative\cscript.exe 22 | 3 third todo 23 | -- 24 | TODO: 3 of 3 tasks shown 25 | 26 | >>> todo.sh ls 2 27 | 2 second todo run C:\WINDOWS\sysnative\cscript.exe 28 | -- 29 | TODO: 1 of 3 tasks shown 30 | EOF 31 | 32 | # 33 | # check various escape sequences 34 | # 35 | cat > todo.txt <<'EOF' 36 | first todo with \\, \a and \t 37 | second todo with \r\n line break 38 | third todo with \x42\x55\x47 and \033[0;31m color codes \033[0;30m 39 | EOF 40 | 41 | test_todo_session 'various escape sequences' <<'EOF' 42 | >>> todo.sh ls 43 | 1 first todo with \\, \a and \t 44 | 2 second todo with \r\n line break 45 | 3 third todo with \x42\x55\x47 and \033[0;31m color codes \033[0;30m 46 | -- 47 | TODO: 3 of 3 tasks shown 48 | EOF 49 | 50 | # 51 | # check embedding of actual color sequence 52 | # 53 | cat > todo.txt <<'EOF' 54 | A task with  actual color  55 | EOF 56 | 57 | test_todo_session 'embedding of actual color sequence' <<'EOF' 58 | >>> todo.sh ls 59 | 1 A task with  actual color  60 | -- 61 | TODO: 1 of 1 tasks shown 62 | EOF 63 | 64 | test_done 65 | -------------------------------------------------------------------------------- /tests/t2110-help-action.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test_description='built-in actions help functionality 4 | 5 | This test checks listing the usage help of a built-in action. 6 | ' 7 | . ./test-lib.sh 8 | 9 | test_todo_session 'nonexisting action help' <<'EOF' 10 | >>> todo.sh help doesnotexist 11 | TODO: No action "doesnotexist" exists. 12 | === 1 13 | 14 | >>> todo.sh help hel 15 | TODO: No action "hel" exists. 16 | === 1 17 | 18 | >>> todo.sh help h 19 | TODO: No action "h" exists. 20 | === 1 21 | EOF 22 | 23 | test_todo_session 'single action help' <<'EOF' 24 | >>> todo.sh help shorthelp 25 | shorthelp 26 | List the one-line usage of all built-in and add-on actions. 27 | \ 28 | EOF 29 | 30 | test_todo_session 'multiple actions help' <<'EOF' 31 | >>> todo.sh help shorthelp append 32 | shorthelp 33 | List the one-line usage of all built-in and add-on actions. 34 | \ 35 | append NR "TEXT TO APPEND" 36 | app NR "TEXT TO APPEND" 37 | Adds TEXT TO APPEND to the end of the task on line NR. 38 | Quotes optional. 39 | \ 40 | EOF 41 | 42 | test_todo_session 'short and long form of action help' <<'EOF' 43 | >>> todo.sh help append 44 | append NR "TEXT TO APPEND" 45 | app NR "TEXT TO APPEND" 46 | Adds TEXT TO APPEND to the end of the task on line NR. 47 | Quotes optional. 48 | \ 49 | 50 | >>> todo.sh help app 51 | app NR "TEXT TO APPEND" 52 | Adds TEXT TO APPEND to the end of the task on line NR. 53 | Quotes optional. 54 | \ 55 | EOF 56 | 57 | test_todo_session 'mixed existing and nonexisting action help' <<'EOF' 58 | >>> todo.sh help shorthelp doesnotexist list 59 | shorthelp 60 | List the one-line usage of all built-in and add-on actions. 61 | \ 62 | TODO: No action "doesnotexist" exists. 63 | === 1 64 | EOF 65 | 66 | test_done 67 | -------------------------------------------------------------------------------- /tests/t1030-addto-date.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test_description='test the date on addto feature 4 | 5 | Tests paths by which we might automatically add 6 | a date to each item. 7 | ' 8 | . ./test-lib.sh 9 | 10 | touch "$HOME/garden.txt" 11 | 12 | # 13 | # Add and list 14 | # 15 | test_todo_session 'cmd line first day' <>> todo.sh -t addto garden.txt notice the daisies 17 | 1 2009-02-13 notice the daisies 18 | GARDEN: 1 added. 19 | 20 | >>> todo.sh listfile garden.txt 21 | 1 2009-02-13 notice the daisies 22 | -- 23 | GARDEN: 1 of 1 tasks shown 24 | EOF 25 | 26 | test_tick 27 | 28 | test_todo_session 'cmd line second day' <>> todo.sh -t addto garden.txt smell the roses 30 | 2 2009-02-14 smell the roses 31 | GARDEN: 2 added. 32 | 33 | >>> todo.sh listfile garden.txt 34 | 1 2009-02-13 notice the daisies 35 | 2 2009-02-14 smell the roses 36 | -- 37 | GARDEN: 2 of 2 tasks shown 38 | EOF 39 | 40 | test_tick 41 | 42 | test_todo_session 'cmd line third day' <>> todo.sh -t addto garden.txt mow the lawn 44 | 3 2009-02-15 mow the lawn 45 | GARDEN: 3 added. 46 | 47 | >>> todo.sh listfile garden.txt 48 | 1 2009-02-13 notice the daisies 49 | 2 2009-02-14 smell the roses 50 | 3 2009-02-15 mow the lawn 51 | -- 52 | GARDEN: 3 of 3 tasks shown 53 | EOF 54 | 55 | # Switch to config file 56 | echo "export TODOTXT_DATE_ON_ADD=1" >> todo.cfg 57 | 58 | # Bump the clock, for good measure. 59 | test_tick 3600 60 | 61 | test_todo_session 'config file third day' <>> todo.sh addto garden.txt take out the trash 63 | 4 2009-02-15 take out the trash 64 | GARDEN: 4 added. 65 | 66 | >>> todo.sh listfile garden.txt 67 | 1 2009-02-13 notice the daisies 68 | 2 2009-02-14 smell the roses 69 | 3 2009-02-15 mow the lawn 70 | 4 2009-02-15 take out the trash 71 | -- 72 | GARDEN: 4 of 4 tasks shown 73 | EOF 74 | 75 | test_done 76 | -------------------------------------------------------------------------------- /tests/t1500-do.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test_description='do functionality 4 | ' 5 | . ./test-lib.sh 6 | 7 | #DATE=`date '+%Y-%m-%d'` 8 | 9 | test_todo_session 'do usage' <>> todo.sh do B B 11 | usage: todo.sh do NR [NR ...] 12 | === 1 13 | EOF 14 | 15 | test_todo_session 'do missing NR' <>> todo.sh do 17 | usage: todo.sh do NR [NR ...] 18 | === 1 19 | EOF 20 | 21 | cat > todo.txt <>> todo.sh list 33 | 2 notice the sunflowers 34 | 4 remove1 35 | 5 remove2 36 | 6 remove3 37 | 7 remove4 38 | 1 smell the uppercase Roses +flowers @outside 39 | 3 stop 40 | -- 41 | TODO: 7 of 7 tasks shown 42 | 43 | >>> todo.sh do 7,6 44 | 7 x 2009-02-13 remove4 45 | TODO: 7 marked as done. 46 | 6 x 2009-02-13 remove3 47 | TODO: 6 marked as done. 48 | x 2009-02-13 remove3 49 | x 2009-02-13 remove4 50 | TODO: $HOME/todo.txt archived. 51 | 52 | >>> todo.sh -p list 53 | 2 notice the sunflowers 54 | 4 remove1 55 | 5 remove2 56 | 1 smell the uppercase Roses +flowers @outside 57 | 3 stop 58 | -- 59 | TODO: 5 of 5 tasks shown 60 | 61 | >>> todo.sh do 5 4 62 | 5 x 2009-02-13 remove2 63 | TODO: 5 marked as done. 64 | 4 x 2009-02-13 remove1 65 | TODO: 4 marked as done. 66 | x 2009-02-13 remove1 67 | x 2009-02-13 remove2 68 | TODO: $HOME/todo.txt archived. 69 | 70 | >>> todo.sh -p list 71 | 2 notice the sunflowers 72 | 1 smell the uppercase Roses +flowers @outside 73 | 3 stop 74 | -- 75 | TODO: 3 of 3 tasks shown 76 | EOF 77 | 78 | test_todo_session 'fail multiple do attempts' <>> todo.sh -a do 3 80 | 3 x 2009-02-13 stop 81 | TODO: 3 marked as done. 82 | 83 | >>> todo.sh -a do 3 84 | === 1 85 | TODO: 3 is already marked done. 86 | EOF 87 | 88 | test_done 89 | -------------------------------------------------------------------------------- /tests/t8020-actions-help.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test_description='custom actions help functionality 4 | 5 | This test checks listing the usage help of a custom action. 6 | ' 7 | . ./actions-test-lib.sh 8 | . ./test-lib.sh 9 | 10 | test_todo_session 'custom action help with no custom action directory' <<'EOF' 11 | >>> todo.sh help foo 12 | TODO: No action "foo" exists. 13 | === 1 14 | EOF 15 | 16 | make_action "foo" 17 | make_action "bar" 18 | make_action "ls" 19 | make_action "quux" 20 | 21 | test_todo_session 'custom action help' <<'EOF' 22 | >>> todo.sh help foo 23 | foo NR [NR ...] [TERM...] 24 | This custom action does foo. 25 | \ 26 | 27 | >>> todo.sh help bar 28 | bar NR [NR ...] [TERM...] 29 | This custom action does bar. 30 | \ 31 | EOF 32 | 33 | test_todo_session 'multiple custom actions help' <<'EOF' 34 | >>> todo.sh help foo bar 35 | foo NR [NR ...] [TERM...] 36 | This custom action does foo. 37 | \ 38 | bar NR [NR ...] [TERM...] 39 | This custom action does bar. 40 | \ 41 | EOF 42 | 43 | test_todo_session 'nonexisting action help' <<'EOF' 44 | >>> todo.sh help doesnotexist 45 | TODO: No action "doesnotexist" exists. 46 | === 1 47 | 48 | >>> todo.sh help foo doesnotexist bar 49 | foo NR [NR ...] [TERM...] 50 | This custom action does foo. 51 | \ 52 | TODO: No action "doesnotexist" exists. 53 | === 1 54 | EOF 55 | 56 | test_todo_session 'mixed built-in and custom actions help' <<'EOF' 57 | >>> todo.sh help foo shorthelp bar 58 | foo NR [NR ...] [TERM...] 59 | This custom action does foo. 60 | \ 61 | shorthelp 62 | List the one-line usage of all built-in and add-on actions. 63 | \ 64 | bar NR [NR ...] [TERM...] 65 | This custom action does bar. 66 | \ 67 | EOF 68 | 69 | test_todo_session 'custom override of built-in action help' <<'EOF' 70 | >>> todo.sh help ls 71 | ls NR [NR ...] [TERM...] 72 | This custom action does ls. 73 | \ 74 | EOF 75 | 76 | test_done 77 | -------------------------------------------------------------------------------- /tests/t6090-completion-aliases.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test_description='Bash completion with different aliases functionality 4 | 5 | This test checks that todo_completion can use a different configuration 6 | when another todo.sh alias is defined that uses that configuration. 7 | ' 8 | . ./test-lib.sh 9 | 10 | cat > todo.txt < todo2.txt <> todo2.cfg <<'EOF' 22 | export TODO_FILE="$TODO_DIR/todo2.txt" 23 | EOF 24 | 25 | # Note: We cannot use aliases within the test framework, but functions are 26 | # equivalent and work fine. 27 | todo1() 28 | { 29 | todo.sh "$@" 30 | } 31 | todo2() 32 | { 33 | todo.sh -d "$HOME/todo2.cfg" "$@" 34 | } 35 | 36 | # Ensure that the test fixture works as planned. 37 | test_todo_session 'todo 1 and 2 contexts' <>> todo1 listcon 39 | @garden 40 | @outdoor 41 | @outside 42 | 43 | >>> todo2 listcon 44 | @home 45 | @oriental 46 | EOF 47 | 48 | # Define a second completion function that injects the different configuration 49 | # file and uppercases all output. (This is a silly behavior change that still 50 | # requires a completion function override.) 51 | # In real use, this would be installed via 52 | # complete -F _todo2 todo2 53 | _uppercase_todo() 54 | { 55 | todo.sh "$@" | tr '[:lower:]' '[:upper:]' 56 | } 57 | _todo2() 58 | { 59 | local _todo_sh='_uppercase_todo -d "$HOME/todo2.cfg"' 60 | _todo "$@" 61 | } 62 | 63 | test_todo_completion 'all todo1 contexts' 'todo1 list @' '@garden @outdoor @outside' 64 | test_todo_completion 'all todo2 contexts' 'todo2 list @' '@home @oriental' 65 | test_todo_custom_completion _todo2 'all uppercased todo2 contexts' 'doesNotMatter list @' '@HOME @ORIENTAL' 66 | 67 | test_done 68 | -------------------------------------------------------------------------------- /tests/t8010-listaddons.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test_description='listaddons functionality 4 | 5 | This test checks listing of custom actions. 6 | ' 7 | . ./actions-test-lib.sh 8 | . ./test-lib.sh 9 | 10 | test_todo_session 'no custom actions' <>> todo.sh listaddons 12 | TODO: '$TODO_ACTIONS_DIR' does not exist. 13 | === 1 14 | EOF 15 | 16 | make_action "foo" 17 | test_todo_session 'one custom action' <>> todo.sh listaddons 19 | foo 20 | -- 21 | TODO: 1 valid addon actions found. 22 | EOF 23 | 24 | make_action "bar" 25 | make_action "ls" 26 | make_action "quux" 27 | test_todo_session 'multiple custom actions' <>> todo.sh listaddons 29 | bar 30 | foo 31 | ls 32 | quux 33 | -- 34 | TODO: 4 valid addon actions found. 35 | EOF 36 | 37 | invalidate_action .todo.actions.d/foo t8010.4 38 | test_todo_session 'nonexecutable action' <>> todo.sh listaddons 40 | bar 41 | ls 42 | quux 43 | -- 44 | TODO: 3 valid addon actions found. 45 | EOF 46 | 47 | make_action_in_folder "chuck" 48 | # Add a bit of cruft in the action folders in order to ensure that we only 49 | # care about the executables with the same name as the folder in which they 50 | # reside. 51 | touch .todo.actions.d/chuck/mc_hammer # can't touch this 52 | chmod u+x .todo.actions.d/chuck/mc_hammer # better run, better run run 53 | touch .todo.actions.d/chuck/README 54 | 55 | make_action_in_folder "norris" 56 | 57 | test_todo_session 'custom actions in subfolders' <>> test -f .todo.actions.d/chuck/README 59 | === 0 60 | 61 | >>> test -x .todo.actions.d/chuck/mc_hammer 62 | === 0 63 | 64 | >>> todo.sh listaddons 65 | bar 66 | chuck 67 | ls 68 | norris 69 | quux 70 | -- 71 | TODO: 5 valid addon actions found. 72 | EOF 73 | 74 | invalidate_action .todo.actions.d/norris/norris t8010.8 75 | test_todo_session 'nonexecutable action in subfolder' <>> todo.sh listaddons 77 | bar 78 | chuck 79 | ls 80 | quux 81 | -- 82 | TODO: 4 valid addon actions found. 83 | EOF 84 | 85 | test_done 86 | -------------------------------------------------------------------------------- /tests/aggregate-results.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | [ "x$TERM" != "xdumb" ] && ( 4 | export TERM && 5 | [ -t 1 ] && 6 | tput bold >/dev/null 2>&1 && 7 | tput setaf 1 >/dev/null 2>&1 && 8 | tput sgr0 >/dev/null 2>&1 9 | ) && 10 | color=t 11 | 12 | case "$1" in 13 | --no-color) 14 | color=; shift ;; 15 | esac 16 | 17 | if test -n "$color"; then 18 | say_color() { 19 | ( 20 | export TERM 21 | case "${1:?}" in 22 | error) tput bold; tput setaf 1;; # bold red 23 | skip) tput bold; tput setaf 2;; # bold green 24 | pass) tput setaf 2;; # green 25 | info) tput setaf 3;; # brown 26 | esac 27 | shift 28 | printf "* %s" "$*" 29 | tput sgr0 30 | echo 31 | ) 32 | } 33 | else 34 | say_color() { 35 | shift 36 | echo "* $*" 37 | } 38 | fi 39 | 40 | get_color() 41 | { 42 | # Only use the supplied color if there are actually instances of that 43 | # type, so that a clean test run does not distract the user by the 44 | # appearance of the error highlighting. 45 | if [ "${1:?}" -eq 0 ] 46 | then 47 | echo 'info' 48 | else 49 | echo "${2:-info}" 50 | fi 51 | } 52 | 53 | 54 | fixed=0 55 | success=0 56 | failed=0 57 | broken=0 58 | total=0 59 | 60 | for file 61 | do 62 | while read -r type value 63 | do 64 | case $type in 65 | '') 66 | continue ;; 67 | fixed) 68 | fixed=$((fixed + value)) ;; 69 | success) 70 | success=$((success + value)) ;; 71 | failed) 72 | failed=$((failed + value)) ;; 73 | broken) 74 | broken=$((broken + value)) ;; 75 | total) 76 | total=$((total + value)) ;; 77 | esac 78 | done <"$file" 79 | done 80 | 81 | say_color 'info' "$(printf "%-8s%d\n" fixed $fixed)" 82 | say_color "$(get_color "$success" 'pass')" "$(printf "%-8s%d\n" success $success)" 83 | say_color "$(get_color "$failed" 'error')" "$(printf "%-8s%d\n" failed $failed)" 84 | say_color "$(get_color "$broken" 'error')" "$(printf "%-8s%d\n" broken $broken)" 85 | say_color 'info' "$(printf "%-8s%d\n" total $total)" 86 | 87 | [ $broken -eq 0 ] && [ $failed -eq 0 ] 88 | -------------------------------------------------------------------------------- /tests/t1910-deduplicate.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test_description='deduplicate functionality 4 | 5 | Ensure we can deduplicate items successfully. 6 | ' 7 | . ./test-lib.sh 8 | 9 | cat > todo.txt <>> todo.sh deduplicate 21 | TODO: 2 duplicate task(s) removed 22 | 23 | >>> todo.sh -p ls 24 | 5 double task 25 | 1 duplicated 26 | 7 three 27 | 2 two 28 | 3 x done 29 | -- 30 | TODO: 5 of 5 tasks shown 31 | EOF 32 | 33 | test_todo_session 'deduplicate without duplicates' <>> todo.sh deduplicate 35 | === 1 36 | TODO: No duplicate tasks found 37 | EOF 38 | 39 | cat > todo.txt <>> todo.sh -n deduplicate 50 | TODO: 2 duplicate task(s) removed 51 | 52 | >>> todo.sh -p ls 53 | 4 double task 54 | 1 duplicated 55 | 5 three 56 | 2 two 57 | 3 x done 58 | -- 59 | TODO: 5 of 5 tasks shown 60 | EOF 61 | 62 | cat > todo.txt <>> todo.sh deduplicate 73 | TODO: 3 duplicate task(s) removed 74 | 75 | >>> todo.sh -p ls 76 | 2 duplicated 77 | 1 one 78 | 6 six 79 | 3 three 80 | -- 81 | TODO: 4 of 4 tasks shown 82 | EOF 83 | 84 | cat > todo.txt <>> todo.sh deduplicate 93 | TODO: 1 duplicate task(s) removed 94 | 95 | >>> todo.sh -p ls 96 | 2 a bold task 97 | 1 normal task 98 | 3 something else 99 | 5 something more 100 | -- 101 | TODO: 4 of 4 tasks shown 102 | EOF 103 | 104 | test_done 105 | -------------------------------------------------------------------------------- /tests/t1700-depri.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test_description='basic depriority functionality 4 | ' 5 | . ./test-lib.sh 6 | 7 | test_todo_session 'depriority usage' <>> todo.sh depri B B 9 | usage: todo.sh depri NR [NR ...] 10 | === 1 11 | EOF 12 | 13 | test_todo_session 'depriority nonexistant item' <>> todo.sh depri 42 15 | TODO: No task 42. 16 | === 1 17 | EOF 18 | 19 | cat > todo.txt <>> todo.sh -p list 26 | 2 (A) notice the sunflowers 27 | 1 (B) smell the uppercase Roses +flowers @outside 28 | 3 stop 29 | -- 30 | TODO: 3 of 3 tasks shown 31 | 32 | >>> todo.sh depri 1 33 | 1 smell the uppercase Roses +flowers @outside 34 | TODO: 1 deprioritized. 35 | 36 | >>> todo.sh -p list 37 | 2 (A) notice the sunflowers 38 | 1 smell the uppercase Roses +flowers @outside 39 | 3 stop 40 | -- 41 | TODO: 3 of 3 tasks shown 42 | EOF 43 | 44 | cat > todo.txt <>> todo.sh -p list 51 | 2 (A) notice the sunflowers 52 | 1 (B) smell the uppercase Roses +flowers @outside 53 | 3 (C) stop 54 | -- 55 | TODO: 3 of 3 tasks shown 56 | 57 | >>> todo.sh depri 3 2 58 | 3 stop 59 | TODO: 3 deprioritized. 60 | 2 notice the sunflowers 61 | TODO: 2 deprioritized. 62 | 63 | >>> todo.sh -p list 64 | 1 (B) smell the uppercase Roses +flowers @outside 65 | 2 notice the sunflowers 66 | 3 stop 67 | -- 68 | TODO: 3 of 3 tasks shown 69 | EOF 70 | 71 | cat > todo.txt <>> todo.sh -p list 78 | 2 (A) notice the sunflowers 79 | 1 (B) smell the uppercase Roses +flowers @outside 80 | 3 stop 81 | -- 82 | TODO: 3 of 3 tasks shown 83 | 84 | >>> todo.sh depri 3 2 85 | === 1 86 | TODO: 3 is not prioritized. 87 | 2 notice the sunflowers 88 | TODO: 2 deprioritized. 89 | 90 | >>> todo.sh -p list 91 | 1 (B) smell the uppercase Roses +flowers @outside 92 | 2 notice the sunflowers 93 | 3 stop 94 | -- 95 | TODO: 3 of 3 tasks shown 96 | EOF 97 | 98 | test_done 99 | -------------------------------------------------------------------------------- /tests/t1020-addtolistfile.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test_description='basic addto and list functionality 4 | 5 | This test just makes sure the basic addto and listfile 6 | commands work, including support for filtering. 7 | ' 8 | . ./test-lib.sh 9 | 10 | # 11 | # Addto and listfile 12 | # 13 | test_todo_session 'nonexistant file' <>> todo.sh addto garden.txt notice the daisies 15 | TODO: Destination file $HOME/garden.txt does not exist. 16 | === 1 17 | EOF 18 | 19 | touch "$HOME/garden.txt" 20 | 21 | test_todo_session 'basic addto/listfile' <>> todo.sh addto garden.txt notice the daisies 23 | 1 notice the daisies 24 | GARDEN: 1 added. 25 | 26 | >>> todo.sh listfile garden.txt 27 | 1 notice the daisies 28 | -- 29 | GARDEN: 1 of 1 tasks shown 30 | 31 | >>> todo.sh addto garden.txt smell the roses 32 | 2 smell the roses 33 | GARDEN: 2 added. 34 | 35 | >>> todo.sh listfile garden.txt 36 | 1 notice the daisies 37 | 2 smell the roses 38 | -- 39 | GARDEN: 2 of 2 tasks shown 40 | EOF 41 | 42 | # 43 | # List available files 44 | # 45 | test_todo_session 'list available files' <>> todo.sh listfile 47 | Files in the todo.txt directory: 48 | done.txt 49 | garden.txt 50 | report.txt 51 | todo.txt 52 | 53 | >>> TODOTXT_VERBOSE=0 todo.sh listfile 54 | done.txt 55 | garden.txt 56 | report.txt 57 | todo.txt 58 | EOF 59 | 60 | # 61 | # Filter 62 | # 63 | test_todo_session 'basic listfile filtering' <>> todo.sh listfile garden.txt daisies 65 | 1 notice the daisies 66 | -- 67 | GARDEN: 1 of 2 tasks shown 68 | 69 | >>> todo.sh listfile garden.txt smell 70 | 2 smell the roses 71 | -- 72 | GARDEN: 1 of 2 tasks shown 73 | EOF 74 | 75 | test_todo_session 'case-insensitive filtering' <>> todo.sh addto garden.txt smell the uppercase Roses 77 | 3 smell the uppercase Roses 78 | GARDEN: 3 added. 79 | 80 | >>> todo.sh listfile garden.txt roses 81 | 2 smell the roses 82 | 3 smell the uppercase Roses 83 | -- 84 | GARDEN: 2 of 3 tasks shown 85 | EOF 86 | 87 | test_todo_session 'addto with &' <>> todo.sh addto garden.txt "dig the garden & water the flowers" 89 | 4 dig the garden & water the flowers 90 | GARDEN: 4 added. 91 | 92 | >>> todo.sh listfile garden.txt 93 | 4 dig the garden & water the flowers 94 | 1 notice the daisies 95 | 2 smell the roses 96 | 3 smell the uppercase Roses 97 | -- 98 | GARDEN: 4 of 4 tasks shown 99 | EOF 100 | 101 | test_done 102 | -------------------------------------------------------------------------------- /tests/t1950-report.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test_description='report functionality 4 | 5 | This test checks the reporting and the format of the report file. 6 | ' 7 | . ./test-lib.sh 8 | 9 | cat > todo.txt <>> todo.sh report 19 | TODO: $HOME/todo.txt does not contain any done tasks. 20 | 2009-02-13T04:40:00 5 0 21 | TODO: Report file updated. 22 | 23 | >>> todo.sh -p list 24 | 1 (B) smell the uppercase Roses +flowers @outside 25 | 4 make the coffee +wakeup 26 | 3 smell the coffee +wakeup 27 | 2 stop and think 28 | 5 visit http://example.com 29 | -- 30 | TODO: 5 of 5 tasks shown 31 | EOF 32 | 33 | test_todo_session 'report of done tasks' <>> todo.sh -A do 3 35 | 3 x 2009-02-13 smell the coffee +wakeup 36 | TODO: 3 marked as done. 37 | x 2009-02-13 smell the coffee +wakeup 38 | TODO: $HOME/todo.txt archived. 39 | 40 | >>> todo.sh report 41 | TODO: $HOME/todo.txt does not contain any done tasks. 42 | 2009-02-13T04:40:00 4 1 43 | TODO: Report file updated. 44 | 45 | >>> todo.sh -p list 46 | 1 (B) smell the uppercase Roses +flowers @outside 47 | 3 make the coffee +wakeup 48 | 2 stop and think 49 | 4 visit http://example.com 50 | -- 51 | TODO: 4 of 4 tasks shown 52 | EOF 53 | 54 | test_todo_session 'report performs archiving' <>> todo.sh -a do 3 56 | 3 x 2009-02-13 make the coffee +wakeup 57 | TODO: 3 marked as done. 58 | 59 | >>> todo.sh report 60 | x 2009-02-13 make the coffee +wakeup 61 | TODO: $HOME/todo.txt archived. 62 | 2009-02-13T04:40:00 3 2 63 | TODO: Report file updated. 64 | 65 | >>> todo.sh -p list 66 | 1 (B) smell the uppercase Roses +flowers @outside 67 | 2 stop and think 68 | 3 visit http://example.com 69 | -- 70 | TODO: 3 of 3 tasks shown 71 | 72 | >>> todo.sh -p listfile done.txt 73 | 2 x 2009-02-13 make the coffee +wakeup 74 | 1 x 2009-02-13 smell the coffee +wakeup 75 | -- 76 | DONE: 2 of 2 tasks shown 77 | EOF 78 | 79 | test_todo_session 'report is unchanged when no changes' <>> cat report.txt 81 | 2009-02-13T04:40:00 5 0 82 | 2009-02-13T04:40:00 4 1 83 | 2009-02-13T04:40:00 3 2 84 | 85 | >>> todo.sh report 86 | TODO: $HOME/todo.txt does not contain any done tasks. 87 | 2009-02-13T04:40:00 3 2 88 | TODO: Report file is up-to-date. 89 | 90 | >>> cat report.txt 91 | 2009-02-13T04:40:00 5 0 92 | 2009-02-13T04:40:00 4 1 93 | 2009-02-13T04:40:00 3 2 94 | EOF 95 | 96 | test_done 97 | -------------------------------------------------------------------------------- /tests/t0002-actions.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test_description='todo.sh actions.d 4 | 5 | This test just makes sure that todo.sh can locate custom actions. 6 | ' 7 | . ./test-lib.sh 8 | 9 | # All the below tests will output the custom action message 10 | cat > expect < foo < foo2 << 'EOF' 20 | shift 21 | IFS=- # Print arguments separated with dashes to recognize the individual arguments. 22 | printf 'TODO: %s\n' "$*" 23 | EOF 24 | chmod +x foo2 25 | 26 | test_expect_success 'custom action (default location 1)' ' 27 | mkdir -p .todo.actions.d && cp foo .todo.actions.d/ 28 | todo.sh foo > output; 29 | test_cmp expect output && rm -rf .todo.actions.d 30 | ' 31 | 32 | test_expect_success 'custom action (default location 2)' ' 33 | mkdir -p .todo/actions && cp foo .todo/actions/ 34 | todo.sh foo > output; 35 | test_cmp expect output && rm -rf .todo/actions 36 | ' 37 | 38 | test_expect_success 'custom action (env variable)' ' 39 | mkdir -p myactions && cp foo myactions/ 40 | TODO_ACTIONS_DIR=myactions todo.sh foo > output; 41 | test_cmp expect output && rm -rf myactions 42 | ' 43 | 44 | test_expect_success 'custom action (default action)' ' 45 | mkdir -p .todo.actions.d && cp foo2 .todo.actions.d/ 46 | TODOTXT_DEFAULT_ACTION="foo2 foo" todo.sh > output; 47 | test_cmp expect output && rm -rf .todo.actions.d 48 | ' 49 | 50 | test_todo_session 'default built-in action with multiple arguments' <>> TODOTXT_DEFAULT_ACTION='add +foo @bar baz' todo.sh 52 | 1 +foo @bar baz 53 | TODO: 1 added. 54 | EOF 55 | 56 | test_todo_session 'default custom action with multiple arguments' <>> mkdir -p .todo.actions.d && cp foo2 .todo.actions.d/ 58 | 59 | >>> TODOTXT_DEFAULT_ACTION='foo2 foo bar baz' todo.sh 60 | TODO: foo-bar-baz 61 | EOF 62 | 63 | : > todo.txt 64 | export TODOTXT_DEFAULT_ACTION="add foo\\ bar \\\$HOSTNAME O\\'Really\\? \\\"quoted\\\"" 65 | test_todo_session 'default built-in action with arguments that have special characters' <>> todo.sh 67 | 1 foo bar \$HOSTNAME O'Really? "quoted" 68 | TODO: 1 added. 69 | EOF 70 | 71 | : > todo.txt 72 | export TODOTXT_DEFAULT_ACTION="foo2 foo\\ bar \\\$HOSTNAME O\\'Really\\? \\\"quoted\\\"" 73 | test_todo_session 'default custom action with arguments that have special characters' <>> mkdir -p .todo.actions.d && cp foo2 .todo.actions.d/ 75 | 76 | >>> todo.sh 77 | TODO: foo bar-\$HOSTNAME-O'Really?-"quoted" 78 | EOF 79 | 80 | test_done 81 | -------------------------------------------------------------------------------- /tests/t1010-add-date.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test_description='test the date on add feature 4 | 5 | Tests paths by which we might automatically add 6 | a date to each item. 7 | ' 8 | . ./test-lib.sh 9 | 10 | # 11 | # Add and list 12 | # 13 | test_todo_session 'cmd line first day' <>> todo.sh -t add notice the daisies 15 | 1 2009-02-13 notice the daisies 16 | TODO: 1 added. 17 | 18 | >>> todo.sh list 19 | 1 2009-02-13 notice the daisies 20 | -- 21 | TODO: 1 of 1 tasks shown 22 | EOF 23 | 24 | test_todo_session 'cmd line first day with priority' <>> todo.sh -pt add '(A) notice the daisies' 26 | 2 (A) 2009-02-13 notice the daisies 27 | TODO: 2 added. 28 | 29 | >>> todo.sh -p list 30 | 2 (A) 2009-02-13 notice the daisies 31 | 1 2009-02-13 notice the daisies 32 | -- 33 | TODO: 2 of 2 tasks shown 34 | 35 | >>> todo.sh -npf del 2 36 | 2 (A) 2009-02-13 notice the daisies 37 | TODO: 2 deleted. 38 | EOF 39 | 40 | test_todo_session 'cmd line first day with lowercase priority' <>> todo.sh -pt add '(b) notice the daisies' 42 | 2 (B) 2009-02-13 notice the daisies 43 | TODO: 2 added. 44 | 45 | >>> todo.sh -p list 46 | 2 (B) 2009-02-13 notice the daisies 47 | 1 2009-02-13 notice the daisies 48 | -- 49 | TODO: 2 of 2 tasks shown 50 | 51 | >>> todo.sh -npf del 2 52 | 2 (B) 2009-02-13 notice the daisies 53 | TODO: 2 deleted. 54 | EOF 55 | 56 | test_tick 57 | 58 | test_todo_session 'cmd line second day' <>> todo.sh -t add smell the roses 60 | 2 2009-02-14 smell the roses 61 | TODO: 2 added. 62 | 63 | >>> todo.sh list 64 | 1 2009-02-13 notice the daisies 65 | 2 2009-02-14 smell the roses 66 | -- 67 | TODO: 2 of 2 tasks shown 68 | EOF 69 | 70 | test_tick 71 | 72 | test_todo_session 'cmd line third day' <>> todo.sh -t add mow the lawn 74 | 3 2009-02-15 mow the lawn 75 | TODO: 3 added. 76 | 77 | >>> todo.sh list 78 | 1 2009-02-13 notice the daisies 79 | 2 2009-02-14 smell the roses 80 | 3 2009-02-15 mow the lawn 81 | -- 82 | TODO: 3 of 3 tasks shown 83 | EOF 84 | 85 | # Switch to config file 86 | echo "export TODOTXT_DATE_ON_ADD=1" >> todo.cfg 87 | 88 | # Bump the clock, for good measure. 89 | test_tick 3600 90 | 91 | test_todo_session 'config file third day' <>> todo.sh add take out the trash 93 | 4 2009-02-15 take out the trash 94 | TODO: 4 added. 95 | 96 | >>> todo.sh list 97 | 1 2009-02-13 notice the daisies 98 | 2 2009-02-14 smell the roses 99 | 3 2009-02-15 mow the lawn 100 | 4 2009-02-15 take out the trash 101 | -- 102 | TODO: 4 of 4 tasks shown 103 | EOF 104 | 105 | test_done 106 | -------------------------------------------------------------------------------- /tests/t0001-null.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test_description='todo.sh basic null functionality test. 4 | 5 | This test just makes sure the basic commands work, 6 | when there are no todos. 7 | ' 8 | . ./test-lib.sh 9 | 10 | # 11 | # ls|list 12 | # 13 | cat > expect < output && test_cmp expect output 20 | ' 21 | test_expect_success 'null list' ' 22 | todo.sh list > output && test_cmp expect output 23 | ' 24 | test_expect_success 'null list filter' ' 25 | todo.sh list filter > output && test_cmp expect output 26 | ' 27 | 28 | # 29 | # lsp|listpri 30 | # 31 | # Re-use expect from ls. 32 | test_expect_success 'null lsp' ' 33 | todo.sh lsp > output && test_cmp expect output 34 | ' 35 | test_expect_success 'null listpri' ' 36 | todo.sh listpri > output && test_cmp expect output 37 | ' 38 | test_expect_success 'null listpri a' ' 39 | todo.sh listpri a > output && test_cmp expect output 40 | ' 41 | 42 | # 43 | # lsa|listall 44 | # 45 | cat > expect < output && test_cmp expect output 54 | ' 55 | test_expect_success 'null list' ' 56 | todo.sh listall > output && test_cmp expect output 57 | ' 58 | test_expect_success 'null list filter' ' 59 | todo.sh listall filter > output && test_cmp expect output 60 | ' 61 | 62 | # 63 | # lsc|listcon 64 | # 65 | test_expect_success 'null lsc' ' 66 | todo.sh lsc > output && ! test -s output 67 | ' 68 | test_expect_success 'null listcon' ' 69 | todo.sh listcon > output && ! test -s output 70 | ' 71 | 72 | # 73 | # lsprj|listproj 74 | # 75 | test_expect_success 'null lsprj' ' 76 | todo.sh lsprj > output && ! test -s output 77 | ' 78 | test_expect_success 'null listproj' ' 79 | todo.sh listproj > output && ! test -s output 80 | ' 81 | 82 | # 83 | # lf|listfile 84 | # 85 | cat > expect < output || test_cmp expect output 91 | ' 92 | test_expect_success 'null listfile' ' 93 | todo.sh listfile > output || test_cmp expect output 94 | ' 95 | cat > expect < output || test_cmp expect output 100 | ' 101 | 102 | test_done 103 | -------------------------------------------------------------------------------- /tests/t0000-config.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test_description='todo.sh configuration file location 4 | 5 | This test just makes sure that todo.sh can find its 6 | config files in the default locations and take arguments 7 | to find it somewhere else. 8 | ' 9 | . ./test-lib.sh 10 | 11 | 12 | # Override default global config file 13 | export TODOTXT_GLOBAL_CFG_FILE=global.cfg 14 | 15 | # Remove the pre-created todo.cfg to test behavior in its absence 16 | rm -f todo.cfg 17 | echo "Fatal Error: Cannot read configuration file $HOME/.todo/config" > expect 18 | test_expect_success 'no config file' ' 19 | todo.sh > output 2>&1 || test_cmp expect output 20 | ' 21 | 22 | # All the below tests will output the usage message. 23 | cat > expect < test.cfg < output; 42 | test_cmp expect output && test -f used_config && 43 | rm -rf .todo 44 | ' 45 | 46 | rm -f used_config 47 | test_expect_success 'config file (default location 2)' ' 48 | cp test.cfg todo.cfg 49 | todo.sh > output; 50 | test_cmp expect output && test -f used_config && 51 | rm -f todo.cfg 52 | ' 53 | 54 | rm -f used_config 55 | test_expect_success 'config file (default location 3)' ' 56 | cp test.cfg .todo.cfg 57 | todo.sh > output; 58 | test_cmp expect output && test -f used_config && 59 | rm -f .todo.cfg 60 | ' 61 | 62 | rm -f used_config 63 | test_expect_success 'config file (global config file)' ' 64 | cp test.cfg "$TODOTXT_GLOBAL_CFG_FILE" 65 | todo.sh > output; 66 | test_cmp expect output && test -f used_config && 67 | rm -f "$TODOTXT_GLOBAL_CFG_FILE" 68 | ' 69 | 70 | rm -f used_config 71 | test_expect_success 'config file (command line)' ' 72 | todo.sh -d test.cfg > output; 73 | test_cmp expect output && test -f used_config 74 | ' 75 | 76 | rm -f used_config 77 | test_expect_success 'config file (env variable)' ' 78 | TODOTXT_CFG_FILE=test.cfg todo.sh > output; 79 | test_cmp expect output && test -f used_config 80 | ' 81 | 82 | cat > minimal.cfg < output; 92 | test_cmp expect output && test -f used_config && 93 | rm -rf .todo 94 | ' 95 | 96 | test_done 97 | -------------------------------------------------------------------------------- /tests/t1000-addlist.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test_description='basic add and list functionality 4 | 5 | This test just makes sure the basic add and list 6 | command work, including support for filtering. 7 | ' 8 | . ./test-lib.sh 9 | 10 | # 11 | # Add and list 12 | # 13 | test_todo_session 'basic add/list' <>> todo.sh add notice the daisies 15 | 1 notice the daisies 16 | TODO: 1 added. 17 | 18 | >>> todo.sh list 19 | 1 notice the daisies 20 | -- 21 | TODO: 1 of 1 tasks shown 22 | 23 | >>> todo.sh add smell the roses 24 | 2 smell the roses 25 | TODO: 2 added. 26 | 27 | >>> todo.sh list 28 | 1 notice the daisies 29 | 2 smell the roses 30 | -- 31 | TODO: 2 of 2 tasks shown 32 | EOF 33 | 34 | # 35 | # Filter 36 | # 37 | test_todo_session 'basic list filtering' <>> todo.sh list daisies 39 | 1 notice the daisies 40 | -- 41 | TODO: 1 of 2 tasks shown 42 | 43 | >>> todo.sh list smell 44 | 2 smell the roses 45 | -- 46 | TODO: 1 of 2 tasks shown 47 | EOF 48 | 49 | test_todo_session 'case-insensitive filtering' <>> todo.sh add smell the uppercase Roses 51 | 3 smell the uppercase Roses 52 | TODO: 3 added. 53 | 54 | >>> todo.sh list roses 55 | 2 smell the roses 56 | 3 smell the uppercase Roses 57 | -- 58 | TODO: 2 of 3 tasks shown 59 | EOF 60 | 61 | test_todo_session 'add with symbols' <>> todo.sh add "~@#$%^&*()-_=+[{]}|;:',<.>/?" 63 | 4 ~@#$%^&*()-_=+[{]}|;:',<.>/? 64 | TODO: 4 added. 65 | 66 | >>> todo.sh add '\`!\\"' 67 | 5 \`!\\" 68 | TODO: 5 added. 69 | 70 | >>> todo.sh list 71 | 1 notice the daisies 72 | 2 smell the roses 73 | 3 smell the uppercase Roses 74 | 5 \`!\\" 75 | 4 ~@#$%^&*()-_=+[{]}|;:',<.>/? 76 | -- 77 | TODO: 5 of 5 tasks shown 78 | EOF 79 | 80 | # 81 | # Advanced add 82 | # 83 | 84 | cat /dev/null > todo.txt 85 | test_todo_session 'add with spaces' <>> todo.sh add "notice the three spaces" 87 | 1 notice the three spaces 88 | TODO: 1 added. 89 | 90 | >>> todo.sh add notice how the spaces get lost 91 | 2 notice how the spaces get lost 92 | TODO: 2 added. 93 | 94 | >>> todo.sh list 95 | 2 notice how the spaces get lost 96 | 1 notice the three spaces 97 | -- 98 | TODO: 2 of 2 tasks shown 99 | EOF 100 | 101 | cat /dev/null > todo.txt 102 | test_todo_session 'add with CR' <>> todo.sh add "smell the Carriage Return" 104 | 1 smell the Carriage Return 105 | TODO: 1 added. 106 | 107 | >>> todo.sh list 108 | 1 smell the Carriage Return 109 | -- 110 | TODO: 1 of 1 tasks shown 111 | EOF 112 | 113 | echo -n 'this is a first task without newline' > todo.txt 114 | test_todo_session 'add to file without EOL' <>> todo.sh add "a second task" 116 | 2 a second task 117 | TODO: 2 added. 118 | 119 | >>> todo.sh list 120 | 2 a second task 121 | 1 this is a first task without newline 122 | -- 123 | TODO: 2 of 2 tasks shown 124 | EOF 125 | 126 | test_done 127 | -------------------------------------------------------------------------------- /tests/t1600-append.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test_description='basic append functionality 4 | 5 | Ensure we can append items successfully. 6 | ' 7 | . ./test-lib.sh 8 | 9 | # 10 | # Set up the basic todo.txt 11 | # 12 | todo.sh add notice the daisies > /dev/null 13 | 14 | test_todo_session 'append usage' <>> todo.sh append adf asdfa 16 | === 1 17 | usage: todo.sh append NR "TEXT TO APPEND" 18 | EOF 19 | 20 | test_todo_session 'append error' <>> todo.sh append 10 "hej!" 22 | === 1 23 | TODO: No task 10. 24 | EOF 25 | 26 | test_todo_session 'basic append' <>> todo.sh append 1 "smell the roses" 28 | 1 notice the daisies smell the roses 29 | 30 | >>> todo.sh list 31 | 1 notice the daisies smell the roses 32 | -- 33 | TODO: 1 of 1 tasks shown 34 | EOF 35 | 36 | test_todo_session 'basic append with &' <>> todo.sh append 1 "see the wasps & bees" 38 | 1 notice the daisies smell the roses see the wasps & bees 39 | 40 | >>> todo.sh list 41 | 1 notice the daisies smell the roses see the wasps & bees 42 | -- 43 | TODO: 1 of 1 tasks shown 44 | EOF 45 | 46 | echo 'jump on hay' > todo.txt 47 | test_todo_session 'append with spaces' <>> todo.sh append 1 "and notice the three spaces" 49 | 1 jump on hay and notice the three spaces 50 | EOF 51 | 52 | cat > todo.txt <>> todo.sh append 1 "~@#$%^&*()-_=+[{]}|;:',<.>/?" 60 | 1 smell the cows ~@#$%^&*()-_=+[{]}|;:',<.>/? 61 | 62 | >>> todo.sh append 2 '\`!\\"' 63 | 2 grow some corn \`!\\" 64 | 65 | >>> todo.sh list 66 | 4 chase the chickens 67 | 2 grow some corn \`!\\" 68 | 1 smell the cows ~@#$%^&*()-_=+[{]}|;:',<.>/? 69 | 3 thrash some hay 70 | -- 71 | TODO: 4 of 4 tasks shown 72 | EOF 73 | 74 | cat > todo.txt <>> todo.sh append 1 ", lilies and roses" 79 | 1 notice the daisies, lilies and roses 80 | 81 | >>> todo.sh append 1 "; see the wasps" 82 | 1 notice the daisies, lilies and roses; see the wasps 83 | 84 | >>> todo.sh append 1 "& bees" 85 | 1 notice the daisies, lilies and roses; see the wasps & bees 86 | EOF 87 | 88 | cp todo.cfg special-delimiters.cfg 89 | cat >> special-delimiters.cfg <>> todo.sh -d special-delimiters.cfg append 1 "&beans" 94 | 1 notice the daisies, lilies and roses; see the wasps & bees&beans 95 | 96 | >>> todo.sh -d special-delimiters.cfg append 1 "%foo" 97 | 1 notice the daisies, lilies and roses; see the wasps & bees&beans %foo 98 | 99 | >>> todo.sh -d special-delimiters.cfg append 1 "*2" 100 | 1 notice the daisies, lilies and roses; see the wasps & bees&beans %foo*2 101 | EOF 102 | 103 | test_done 104 | -------------------------------------------------------------------------------- /tests/t8000-actions.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test_description='custom actions functionality 4 | 5 | This test covers the contract between todo.sh and custom actions. 6 | ' 7 | . ./actions-test-lib.sh 8 | . ./test-lib.sh 9 | 10 | make_action "foo" 11 | test_todo_session 'executable action' <>> todo.sh foo 13 | custom action foo 14 | EOF 15 | 16 | chmod -x .todo.actions.d/foo 17 | # On Cygwin, clearing the executable flag may have no effect, as the Windows ACL 18 | # may still grant execution rights. In this case, we skip the test. 19 | if [ -x .todo.actions.d/foo ]; then 20 | SKIP_TESTS="${SKIP_TESTS}${SKIP_TESTS+ }t8000.2" 21 | fi 22 | test_todo_session 'nonexecutable action' <>> todo.sh foo 24 | Usage: todo.sh [-fhpantvV] [-d todo_config] action [task_number] [task_description] 25 | Try 'todo.sh -h' for more information. 26 | === 1 27 | EOF 28 | 29 | make_action "ls" 30 | test_todo_session 'overriding built-in action' <>> todo.sh ls 32 | custom action ls 33 | 34 | >>> todo.sh command ls 35 | -- 36 | TODO: 0 of 0 tasks shown 37 | EOF 38 | 39 | make_action "bad" 40 | echo "exit 42" >> .todo.actions.d/bad 41 | test_todo_session 'failing action' <>> todo.sh bad 43 | custom action bad 44 | === 42 45 | EOF 46 | 47 | make_action 48 | ln -s /actionsdir/doesnotexist/badlink .todo.actions.d/badlink 49 | # On Cygwin, the Windows ACL may still grant execution rights. In this case, we 50 | # skip the test. 51 | if [ -x .todo.actions.d/badlink ]; then 52 | SKIP_TESTS="${SKIP_TESTS}${SKIP_TESTS+ }t8000.6 t8000.7" 53 | fi 54 | test_todo_session 'broken symlink' <>> todo.sh badlink 2>&1 | sed "s#'[^']*\(\\.todo\\.actions\\.d/[^']\{1,\}\)'#'\1'#g" 56 | Fatal Error: Broken link to custom action: '.todo.actions.d/badlink' 57 | 58 | >>> todo.sh do 2>/dev/null 59 | === 1 60 | EOF 61 | 62 | make_action 63 | mkdir .todo.actions.d/badfolderlink 64 | ln -s /actionsdir/doesnotexist/badfolderlink .todo.actions.d/badfolderlink/badfolderlink 65 | # On Cygwin, the Windows ACL may still grant execution rights. In this case, we 66 | # skip the test. 67 | if [ -x .todo.actions.d/badfolderlink/badfolderlink ]; then 68 | SKIP_TESTS="${SKIP_TESTS}${SKIP_TESTS+ }t8000.8 t8000.9" 69 | fi 70 | test_todo_session 'broken symlink in folder' <>> todo.sh badfolderlink 2>&1 | sed "s#'[^']*\(\\.todo\\.actions\\.d/[^']\{1,\}\)'#'\1'#g" 72 | Fatal Error: Broken link to custom action: '.todo.actions.d/badfolderlink/badfolderlink' 73 | 74 | >>> todo.sh do 2>/dev/null 75 | === 1 76 | EOF 77 | 78 | make_action 79 | ln -s /actionsdir/doesnotexist/do .todo.actions.d/do 80 | # On Cygwin, the Windows ACL may still grant execution rights. In this case, we 81 | # skip the test. 82 | if [ -x .todo.actions.d/do ]; then 83 | SKIP_TESTS="${SKIP_TESTS}${SKIP_TESTS+ }t8000.10 t8000.11" 84 | fi 85 | test_todo_session 'broken symlink overrides built-in action' <>> todo.sh do 2>&1 | sed "s#'[^']*\(\\.todo\\.actions\\.d/[^']\{1,\}\)'#'\1'#g" 87 | Fatal Error: Broken link to custom action: '.todo.actions.d/do' 88 | 89 | >>> todo.sh do 2>/dev/null 90 | === 1 91 | EOF 92 | 93 | test_done 94 | -------------------------------------------------------------------------------- /tests/t6050-completion-addons.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test_description='Bash add-on action completion functionality 4 | 5 | This test checks todo_completion of custom actions in .todo.actions.d 6 | ' 7 | . ./test-lib.sh 8 | 9 | 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' 10 | readonly OPTIONS='-@ -@@ -+ -++ -d -f -h -p -P -PP -a -n -t -v -vv -V -x' 11 | 12 | readonly ADDONS='bar baz foobar' 13 | 14 | readonly CONTAINED='xeno zoolander' 15 | makeCustomActions() 16 | { 17 | set -e 18 | mkdir "${1:?}" 19 | for addon in $ADDONS 20 | do 21 | addonFile="${1}/$addon" 22 | > "$addonFile" 23 | chmod +x "$addonFile" 24 | done 25 | 26 | # Also create a subdirectory, to test that it is skipped. 27 | mkdir "${1}/subdir" 28 | 29 | # Also create a non-executable file, to test that it is skipped. 30 | datafile="${1:?}/datafile" 31 | > "$datafile" 32 | chmod -x "$datafile" 33 | [ -x "$datafile" ] && rm "$datafile" # Some file systems may always make files executable; then, skip this check. 34 | 35 | # Add an executable file in a folder with the same name as the file, 36 | # in order to ensure completion 37 | for contained in $CONTAINED 38 | do 39 | mkdir "${1}/$contained" 40 | > "${1}/$contained/$contained" 41 | chmod u+x "${1}/$contained/$contained" 42 | done 43 | 44 | set +e 45 | } 46 | removeCustomActions() 47 | { 48 | set -e 49 | rmdir "${1}/subdir" 50 | 51 | for contained in $CONTAINED 52 | do 53 | rm "${1}/$contained/$contained" 54 | rmdir "${1}/$contained" 55 | done 56 | 57 | rm "${1:?}/"* 58 | rmdir "$1" 59 | set +e 60 | } 61 | 62 | # 63 | # Test resolution of the default TODO_ACTIONS_DIR. 64 | # 65 | makeCustomActions "$HOME/.todo.actions.d" 66 | test_todo_completion 'all arguments' 'todo.sh ' "$ACTIONS $ADDONS $CONTAINED $OPTIONS" 67 | test_todo_completion 'all arguments after option' 'todo.sh -a ' "$ACTIONS $ADDONS $CONTAINED $OPTIONS" 68 | test_todo_completion 'all arguments beginning with b' 'todo.sh b' 'bar baz' 69 | test_todo_completion 'all arguments beginning with f after options' 'todo.sh -a -v f' 'foobar' 70 | test_todo_completion 'nothing after addon action' 'todo.sh foobar ' '' 71 | removeCustomActions "$HOME/.todo.actions.d" 72 | 73 | # 74 | # Test resolution of an alternative TODO_ACTIONS_DIR. 75 | # 76 | mkdir "$HOME/.todo" 77 | makeCustomActions "$HOME/.todo/actions" 78 | test_todo_completion 'all arguments with actions from .todo/actions/' 'todo.sh ' "$ACTIONS $ADDONS $CONTAINED $OPTIONS" 79 | removeCustomActions "$HOME/.todo/actions" 80 | 81 | # 82 | # Test resolution of a configured TODO_ACTIONS_DIR. 83 | # 84 | makeCustomActions "$HOME/addons" 85 | cat >> todo.cfg <<'EOF' 86 | export TODO_ACTIONS_DIR="$HOME/addons" 87 | EOF 88 | test_todo_completion 'all arguments with actions from addons/' 'todo.sh ' "$ACTIONS $ADDONS $CONTAINED $OPTIONS" 89 | removeCustomActions "$HOME/addons" 90 | 91 | test_done 92 | -------------------------------------------------------------------------------- /tests/t1850-move.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test_description='basic move functionality 4 | ' 5 | . ./test-lib.sh 6 | 7 | cat > todo.txt < done.txt <>> todo.sh -f move 1 done.txt | sed "s#'[^']\{1,\}/\([^/']\{1,\}\)'#'\1'#g" 17 | 1 (B) smell the uppercase Roses +flowers @outside 18 | TODO: 1 moved from 'todo.txt' to 'done.txt'. 19 | 20 | >>> todo.sh -p ls 21 | 2 (A) notice the sunflowers 22 | -- 23 | TODO: 1 of 1 tasks shown 24 | 25 | >>> todo.sh -p listfile done.txt 26 | 3 (B) smell the uppercase Roses +flowers @outside 27 | 1 x 2009-02-13 make the coffee +wakeup 28 | 2 x 2009-02-13 smell the coffee +wakeup 29 | -- 30 | DONE: 3 of 3 tasks shown 31 | EOF 32 | 33 | cat > todo.txt < done.txt <>> printf y | todo.sh move 1 done.txt 2>&1 | sed -e "s#'[^']\{1,\}/\([^/']\{1,\}\)'#'\1'#g" -e 's#from .\{1,\}/\([^/]\{1,\}\) to .\{1,\}/\([^/]\{1,\}\)?#from \1 to \2?#g' 43 | \\ 44 | 1 (B) smell the uppercase Roses +flowers @outside 45 | TODO: 1 moved from 'todo.txt' to 'done.txt'. 46 | 47 | >>> todo.sh -p ls 48 | 2 (A) notice the sunflowers 49 | -- 50 | TODO: 1 of 1 tasks shown 51 | 52 | >>> todo.sh -p listfile done.txt 53 | 3 (B) smell the uppercase Roses +flowers @outside 54 | 1 x 2009-02-13 make the coffee +wakeup 55 | 2 x 2009-02-13 smell the coffee +wakeup 56 | -- 57 | DONE: 3 of 3 tasks shown 58 | EOF 59 | 60 | test_todo_session 'basic move with passed source' <>> todo.sh -f move 2 todo.txt done.txt | sed "s#'[^']\{1,\}/\([^/']\{1,\}\)'#'\1'#g" 62 | 2 x 2009-02-13 smell the coffee +wakeup 63 | TODO: 2 moved from 'done.txt' to 'todo.txt'. 64 | 65 | >>> todo.sh -p ls 66 | 2 (A) notice the sunflowers 67 | 3 x 2009-02-13 smell the coffee +wakeup 68 | -- 69 | TODO: 2 of 2 tasks shown 70 | 71 | >>> todo.sh -p listfile done.txt 72 | 3 (B) smell the uppercase Roses +flowers @outside 73 | 1 x 2009-02-13 make the coffee +wakeup 74 | -- 75 | DONE: 2 of 2 tasks shown 76 | EOF 77 | 78 | echo -n 'this is a first task without newline' > todo.txt 79 | cat > done.txt <>> todo.sh -f move 2 todo.txt done.txt | sed "s#'[^']\{1,\}/\([^/']\{1,\}\)'#'\1'#g" 85 | 2 x 2009-02-13 smell the coffee +wakeup 86 | TODO: 2 moved from 'done.txt' to 'todo.txt'. 87 | 88 | >>> todo.sh -p ls 89 | 1 this is a first task without newline 90 | 2 x 2009-02-13 smell the coffee +wakeup 91 | -- 92 | TODO: 2 of 2 tasks shown 93 | 94 | >>> todo.sh -p listfile done.txt 95 | 1 x 2009-02-13 make the coffee +wakeup 96 | -- 97 | DONE: 1 of 1 tasks shown 98 | EOF 99 | 100 | test_done 101 | -------------------------------------------------------------------------------- /tests/t1400-prepend.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test_description='basic prepend functionality 4 | ' 5 | . ./test-lib.sh 6 | 7 | test_todo_session 'prepend usage' <>> todo.sh prepend B B 9 | usage: todo.sh prepend NR "TEXT TO PREPEND" 10 | === 1 11 | EOF 12 | 13 | cat > todo.txt <>> todo.sh list 20 | 1 (B) smell the uppercase Roses +flowers @outside 21 | 2 notice the sunflowers 22 | 3 stop 23 | -- 24 | TODO: 3 of 3 tasks shown 25 | 26 | >>> todo.sh -p list 27 | 1 (B) smell the uppercase Roses +flowers @outside 28 | 2 notice the sunflowers 29 | 3 stop 30 | -- 31 | TODO: 3 of 3 tasks shown 32 | 33 | >>> todo.sh prepend 2 test 34 | 2 test notice the sunflowers 35 | 36 | >>> todo.sh -p list 37 | 1 (B) smell the uppercase Roses +flowers @outside 38 | 3 stop 39 | 2 test notice the sunflowers 40 | -- 41 | TODO: 3 of 3 tasks shown 42 | 43 | >>> todo.sh prepend 1 test 44 | 1 (B) test smell the uppercase Roses +flowers @outside 45 | 46 | >>> todo.sh -p list 47 | 1 (B) test smell the uppercase Roses +flowers @outside 48 | 3 stop 49 | 2 test notice the sunflowers 50 | -- 51 | TODO: 3 of 3 tasks shown 52 | 53 | EOF 54 | 55 | test_todo_session 'prepend with &' <>> todo.sh prepend 3 "no running & jumping now" 57 | 3 no running & jumping now stop 58 | EOF 59 | 60 | echo 'jump on hay' > todo.txt 61 | test_todo_session 'prepend with spaces' <>> todo.sh prepend 1 "notice the three spaces and" 63 | 1 notice the three spaces and jump on hay 64 | EOF 65 | 66 | cat > todo.txt <>> todo.sh prepend 1 "~@#$%^&*()-_=+[{]}|;:',<.>/?" 74 | 1 ~@#$%^&*()-_=+[{]}|;:',<.>/? smell the cows 75 | 76 | >>> todo.sh prepend 2 '\`!\\"' 77 | 2 \`!\\" grow some corn 78 | 79 | >>> todo.sh list 80 | 4 chase the chickens 81 | 3 thrash some hay 82 | 2 \`!\\" grow some corn 83 | 1 ~@#$%^&*()-_=+[{]}|;:',<.>/? smell the cows 84 | -- 85 | TODO: 4 of 4 tasks shown 86 | EOF 87 | 88 | cat /dev/null > todo.txt 89 | test_todo_session 'prepend handling prepended date on add' <>> todo.sh -t add "new task" 91 | 1 2009-02-13 new task 92 | TODO: 1 added. 93 | 94 | >>> todo.sh prepend 1 "this is just a" 95 | 1 2009-02-13 this is just a new task 96 | EOF 97 | 98 | cat /dev/null > todo.txt 99 | test_todo_session 'prepend handling priority and prepended date on add' <>> todo.sh -t add "new task" 101 | 1 2009-02-13 new task 102 | TODO: 1 added. 103 | 104 | >>> todo.sh pri 1 A 105 | 1 (A) 2009-02-13 new task 106 | TODO: 1 prioritized (A). 107 | 108 | >>> todo.sh prepend 1 "this is just a" 109 | 1 (A) 2009-02-13 this is just a new task 110 | EOF 111 | 112 | cat /dev/null > todo.txt 113 | test_todo_session 'prepend with prepended date keeps both' <>> todo.sh -t add "new task" 115 | 1 2009-02-13 new task 116 | TODO: 1 added. 117 | 118 | >>> todo.sh prepend 1 "2010-07-04 this is just a" 119 | 1 2009-02-13 2010-07-04 this is just a new task 120 | EOF 121 | 122 | test_done 123 | -------------------------------------------------------------------------------- /tests/t2120-shorthelp.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test_description='shorthelp functionality 4 | 5 | This test covers the output of the -h option and the shorthelp action. 6 | ' 7 | . ./actions-test-lib.sh 8 | . ./test-lib.sh 9 | 10 | # Note: To avoid having to adapt the test whenever the actions change, only 11 | # check for the section headers. 12 | test_todo_session '-h output' <>> todo.sh -h | sed '/^ [A-Z]/!d' 14 | Usage: todo.sh [-fhpantvV] [-d todo_config] action [task_number] [task_description] 15 | Actions: 16 | Actions can be added and overridden using scripts in the actions 17 | See "help" for more details. 18 | EOF 19 | 20 | test_todo_session 'shorthelp output' <>> todo.sh shorthelp | sed '/^ [A-Z]/!d' 22 | Usage: todo.sh [-fhpantvV] [-d todo_config] action [task_number] [task_description] 23 | Actions: 24 | Actions can be added and overridden using scripts in the actions 25 | See "help" for more details. 26 | EOF 27 | 28 | make_action "foo" 29 | test_todo_session 'shorthelp output with custom action' <>> todo.sh -v shorthelp | sed '/^ [A-Z]/!d' 31 | Usage: todo.sh [-fhpantvV] [-d todo_config] action [task_number] [task_description] 32 | Actions: 33 | Actions can be added and overridden using scripts in the actions 34 | Add-on Actions: 35 | See "help" for more details. 36 | EOF 37 | 38 | # Verify that custom configuration is actually processed (when the -d option 39 | # precedes the -h option) by specifying a different actions directory and moving 40 | # our custom action there. The help output should mention the "Add-On Actions". 41 | set -o pipefail # So that the sed filter doesn't swallow todo.sh's exit code. 42 | mv todo.cfg custom.cfg 43 | mv .todo.actions.d custom.actions 44 | echo 'export TODO_ACTIONS_DIR=$HOME/custom.actions' >> custom.cfg 45 | 46 | # Avoid the use of global config file, if it exists 47 | export TODOTXT_GLOBAL_CFG_FILE=global.cfg 48 | 49 | test_todo_session '-h and fatal error without config' <>> todo.sh -h 2>&1 | sed '/^ \\{0,2\\}[A-Z]/!d' 51 | Usage: todo.sh [-fhpantvV] [-d todo_config] action [task_number] [task_description] 52 | Actions: 53 | Actions can be added and overridden using scripts in the actions 54 | See "help" for more details. 55 | Fatal Error: Cannot read configuration file $HOME/.todo/config 56 | === 1 57 | EOF 58 | 59 | # Config option comes too late; "Add-on Actions" is *not* mentioned here. 60 | test_todo_session '-h and fatal error with trailing custom config' <>> todo.sh -h -d custom.cfg 2>&1 | sed '/^ \\{0,2\\}[A-Z]/!d' 62 | Usage: todo.sh [-fhpantvV] [-d todo_config] action [task_number] [task_description] 63 | Actions: 64 | Actions can be added and overridden using scripts in the actions 65 | See "help" for more details. 66 | Fatal Error: Cannot read configuration file $HOME/.todo/config 67 | === 1 68 | EOF 69 | 70 | # Config option processed; "Add-on Actions" is mentioned here. 71 | test_todo_session '-h output with preceding custom config' <>> todo.sh -d custom.cfg -h 2>&1 | sed '/^ \\{0,2\\}[A-Z]/!d' 73 | Usage: todo.sh [-fhpantvV] [-d todo_config] action [task_number] [task_description] 74 | Actions: 75 | Actions can be added and overridden using scripts in the actions 76 | Add-on Actions: 77 | See "help" for more details. 78 | EOF 79 | 80 | test_done 81 | -------------------------------------------------------------------------------- /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at TBD@TBD.tld. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /tests/t2000-multiline.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test_description='Multi-line functionality' 4 | 5 | . ./test-lib.sh 6 | 7 | ## Replace test 8 | # Create the expected file 9 | echo "1 smell the cheese 10 | TODO: Replaced task with: 11 | 1 eat apples eat oranges drink milk">"$HOME/expect.multi" 12 | 13 | test_expect_success 'multiline squash item replace' ' 14 | ( 15 | # Prepare single line todo file 16 | cat /dev/null > "$HOME/todo.txt" 17 | "$HOME/bin/todo.sh" add smell the cheese 18 | 19 | # Run replace 20 | "$HOME/bin/todo.sh" replace 1 "eat apples 21 | eat oranges 22 | drink milk" > "$HOME/output.multi" 23 | 24 | # Test output against expected 25 | diff "$HOME/output.multi" "$HOME/expect.multi" 26 | if [ $? -ne 0 ]; then 27 | exit 1 28 | else 29 | exit 0 30 | fi 31 | ) 32 | ' 33 | 34 | ## Add test 35 | # Create the expected file 36 | echo "2 eat apples eat oranges drink milk 37 | TODO: 2 added.">"$HOME/expect.multi" 38 | 39 | test_expect_success 'multiline squash item add' ' 40 | ( 41 | # Prepare single line todo file 42 | cat /dev/null > "$HOME/todo.txt" 43 | "$HOME/bin/todo.sh" add smell the cheese 44 | 45 | # Run add 46 | "$HOME/bin/todo.sh" add "eat apples 47 | eat oranges 48 | drink milk" > "$HOME/output.multi" 49 | 50 | # Test output against expected 51 | diff "$HOME/output.multi" "$HOME/expect.multi" 52 | if [ $? -ne 0 ]; then 53 | exit 1 54 | else 55 | exit 0 56 | fi 57 | ) 58 | ' 59 | 60 | ## Append test 61 | # Create the expected file 62 | echo "1 smell the cheese eat apples eat oranges drink milk">"$HOME/expect.multi" 63 | 64 | test_expect_success 'multiline squash item append' ' 65 | ( 66 | # Prepare single line todo file 67 | cat /dev/null > "$HOME/todo.txt" 68 | "$HOME/bin/todo.sh" add smell the cheese 69 | 70 | # Run append 71 | "$HOME/bin/todo.sh" append 1 "eat apples 72 | eat oranges 73 | drink milk" > "$HOME/output.multi" 74 | 75 | # Test output against expected 76 | diff "$HOME/output.multi" "$HOME/expect.multi" 77 | if [ $? -ne 0 ]; then 78 | exit 1 79 | else 80 | exit 0 81 | fi 82 | ) 83 | ' 84 | 85 | ## Prepend test 86 | # Create the expected file 87 | echo "1 eat apples eat oranges drink milk smell the cheese">"$HOME/expect.multi" 88 | 89 | test_expect_success 'multiline squash item prepend' ' 90 | ( 91 | # Prepare single line todo file 92 | cat /dev/null > "$HOME/todo.txt" 93 | "$HOME/bin/todo.sh" add smell the cheese 94 | 95 | # Run prepend 96 | "$HOME/bin/todo.sh" prepend 1 "eat apples 97 | eat oranges 98 | drink milk" > "$HOME/output.multi" 99 | 100 | # Test output against expected 101 | diff "$HOME/output.multi" "$HOME/expect.multi" 102 | if [ $? -ne 0 ]; then 103 | exit 1 104 | else 105 | exit 0 106 | fi 107 | ) 108 | ' 109 | 110 | ## Multiple line addition 111 | # Create the expected file 112 | echo "2 eat apples 113 | TODO: 2 added." > "$HOME/expect.multi" 114 | echo "3 eat oranges 115 | TODO: 3 added." >>"$HOME/expect.multi" 116 | echo "4 drink milk 117 | TODO: 4 added." >>"$HOME/expect.multi" 118 | 119 | test_expect_success 'actual multiline add' ' 120 | ( 121 | # Run addm 122 | "$HOME/bin/todo.sh" addm "eat apples 123 | eat oranges 124 | drink milk" > "$HOME/output.multi" 125 | 126 | # Test output against expected 127 | diff "$HOME/output.multi" "$HOME/expect.multi" 128 | if [ $? -ne 0 ]; then 129 | exit 1 130 | else 131 | exit 0 132 | fi 133 | ) 134 | ' 135 | 136 | test_done 137 | -------------------------------------------------------------------------------- /tests/t1360-ls-project-context-highlighting.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test_description='highlighting projects and contexts 4 | 5 | This test checks the highlighting (with colors) of projects and contexts. 6 | ' 7 | . ./test-lib.sh 8 | 9 | # Prioritized tasks with projects and contexts 10 | cat > todo.txt < "$TEST_TODO_LABEL_COLORS" 26 | 27 | echo "export COLOR_CONTEXT='\\\\033[1m'" >>"$TEST_TODO_LABEL_COLORS" 28 | echo "export COLOR_PROJECT='\\\\033[2m'" >>"$TEST_TODO_LABEL_COLORS" 29 | 30 | test_todo_session 'highlighting for contexts and projects' <<'EOF' 31 | >>> todo.sh -d "$TEST_TODO_LABEL_COLORS" ls 32 | 1 (A) prioritized @con01 context 33 | 2 (B) prioritized +prj02 project 34 | 3 (C) prioritized context at EOL @con03 35 | 4 (D) prioritized project at EOL +prj04 36 | 5 +prj05 non-prioritized project at BOL 37 | 6 @con06 non-prioritized context at BOL 38 | 7 multiple @con_ @texts and +pro_ +jects 39 | 8 non-contexts: seti@home @ @* @(foo) 40 | 9 non-projects: lost+found + +! +(bar) 41 | -- 42 | TODO: 9 of 9 tasks shown 43 | EOF 44 | 45 | test_todo_session 'suppressing highlighting for contexts and projects' <<'EOF' 46 | >>> todo.sh -p -d "$TEST_TODO_LABEL_COLORS" ls 47 | 1 (A) prioritized @con01 context 48 | 2 (B) prioritized +prj02 project 49 | 3 (C) prioritized context at EOL @con03 50 | 4 (D) prioritized project at EOL +prj04 51 | 5 +prj05 non-prioritized project at BOL 52 | 6 @con06 non-prioritized context at BOL 53 | 7 multiple @con_ @texts and +pro_ +jects 54 | 8 non-contexts: seti@home @ @* @(foo) 55 | 9 non-projects: lost+found + +! +(bar) 56 | -- 57 | TODO: 9 of 9 tasks shown 58 | EOF 59 | 60 | test_todo_session 'suppressing display of contexts' <<'EOF' 61 | >>> todo.sh -@ -d "$TEST_TODO_LABEL_COLORS" ls 62 | 1 (A) prioritized context 63 | 2 (B) prioritized +prj02 project 64 | 3 (C) prioritized context at EOL 65 | 4 (D) prioritized project at EOL +prj04 66 | 5 +prj05 non-prioritized project at BOL 67 | 6 non-prioritized context at BOL 68 | 7 multiple and +pro_ +jects 69 | 8 non-contexts: seti@home @ 70 | 9 non-projects: lost+found + +! +(bar) 71 | -- 72 | TODO: 9 of 9 tasks shown 73 | EOF 74 | 75 | test_todo_session 'suppressing display of projects' <<'EOF' 76 | >>> todo.sh -+ -d "$TEST_TODO_LABEL_COLORS" ls 77 | 1 (A) prioritized @con01 context 78 | 2 (B) prioritized project 79 | 3 (C) prioritized context at EOL @con03 80 | 4 (D) prioritized project at EOL 81 | 5 non-prioritized project at BOL 82 | 6 @con06 non-prioritized context at BOL 83 | 7 multiple @con_ @texts and 84 | 8 non-contexts: seti@home @ @* @(foo) 85 | 9 non-projects: lost+found + 86 | -- 87 | TODO: 9 of 9 tasks shown 88 | EOF 89 | 90 | test_done 91 | -------------------------------------------------------------------------------- /tests/t1310-listcon.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test_description='listcon functionality 4 | 5 | This test checks basic context listing functionality 6 | ' 7 | . ./test-lib.sh 8 | 9 | cat > todo.txt < output && ! test -s output 16 | ' 17 | 18 | cat > todo.txt <>> todo.sh listcon 27 | @1 28 | @c2 29 | @con03 30 | @con04 31 | @con05@con06 32 | EOF 33 | 34 | cat > todo.txt <>> todo.sh listcon 41 | @con01 42 | @con02 43 | @con03 44 | EOF 45 | 46 | cat > todo.txt <>> todo.sh listcon 53 | @con01 54 | @con02 55 | EOF 56 | 57 | cat > todo.txt <>> todo.sh listcon +landscape 64 | @garden 65 | EOF 66 | 67 | cat > todo.txt <>> todo.sh listcon 74 | @GinaTrapani 75 | @home) 76 | @x 77 | @y 78 | EOF 79 | test_todo_session 'listcon limiting to multi-character sequences' <>> TODOTXT_SIGIL_VALID_PATTERN='.\{2,\}' todo.sh listcon 81 | @GinaTrapani 82 | @home) 83 | EOF 84 | test_todo_session 'listcon allowing w: marker before contexts' <>> TODOTXT_SIGIL_BEFORE_PATTERN='\(w:\)\{0,1\}' todo.sh listcon 86 | @GinaTrapani 87 | @OtherContributors 88 | @home) 89 | @x 90 | @y 91 | EOF 92 | test_todo_session 'listcon allowing parentheses around contexts' <>> TODOTXT_SIGIL_BEFORE_PATTERN='(\{0,1\}' TODOTXT_SIGIL_AFTER_PATTERN=')\{0,1\}' todo.sh listcon 94 | @GinaTrapani 95 | @home 96 | @school 97 | @x 98 | @y 99 | EOF 100 | test_todo_session 'listcon with all customizations combined' <>> TODOTXT_SIGIL_VALID_PATTERN='.\{2,\}' TODOTXT_SIGIL_BEFORE_PATTERN='\(w:\)\{0,1\}\((\)\{0,1\}' TODOTXT_SIGIL_AFTER_PATTERN=')\{0,1\}' todo.sh listcon 102 | @GinaTrapani 103 | @OtherContributors 104 | @home 105 | @school 106 | EOF 107 | 108 | cat > todo.txt < done.txt <>> TODOTXT_SOURCEVAR=\$DONE_FILE todo.sh listcon 117 | @done01 118 | @done02 119 | EOF 120 | test_todo_session 'listcon from combined open + done tasks' <<'EOF' 121 | >>> TODOTXT_SOURCEVAR='("$TODO_FILE" "$DONE_FILE")' todo.sh listcon 122 | @con01 123 | @done01 124 | @done02 125 | EOF 126 | 127 | test_done 128 | -------------------------------------------------------------------------------- /tests/t1200-pri.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test_description='basic priority functionality 4 | ' 5 | . ./test-lib.sh 6 | 7 | test_todo_session 'priority usage' <>> todo.sh pri B B 9 | usage: todo.sh pri NR PRIORITY [NR PRIORITY ...] 10 | note: PRIORITY must be anywhere from A to Z. 11 | === 1 12 | EOF 13 | 14 | cat > todo.txt <>> todo.sh list 21 | 2 notice the sunflowers 22 | 1 smell the uppercase Roses +flowers @outside 23 | 3 stop 24 | -- 25 | TODO: 3 of 3 tasks shown 26 | 27 | >>> todo.sh pri 1 B 28 | 1 (B) smell the uppercase Roses +flowers @outside 29 | TODO: 1 prioritized (B). 30 | 31 | >>> todo.sh list 32 | 1 (B) smell the uppercase Roses +flowers @outside 33 | 2 notice the sunflowers 34 | 3 stop 35 | -- 36 | TODO: 3 of 3 tasks shown 37 | 38 | >>> todo.sh -p list 39 | 1 (B) smell the uppercase Roses +flowers @outside 40 | 2 notice the sunflowers 41 | 3 stop 42 | -- 43 | TODO: 3 of 3 tasks shown 44 | 45 | >>> todo.sh pri 2 C 46 | 2 (C) notice the sunflowers 47 | TODO: 2 prioritized (C). 48 | 49 | >>> todo.sh -p list 50 | 1 (B) smell the uppercase Roses +flowers @outside 51 | 2 (C) notice the sunflowers 52 | 3 stop 53 | -- 54 | TODO: 3 of 3 tasks shown 55 | 56 | >>> todo.sh add "smell the coffee +wakeup" 57 | 4 smell the coffee +wakeup 58 | TODO: 4 added. 59 | 60 | >>> todo.sh -p list 61 | 1 (B) smell the uppercase Roses +flowers @outside 62 | 2 (C) notice the sunflowers 63 | 4 smell the coffee +wakeup 64 | 3 stop 65 | -- 66 | TODO: 4 of 4 tasks shown 67 | EOF 68 | 69 | test_todo_session 'priority error' <>> todo.sh pri 10 B 71 | === 1 72 | TODO: No task 10. 73 | EOF 74 | 75 | cat > todo.txt <>> todo.sh pri 2 A 82 | 2 (A) notice the sunflowers 83 | TODO: 2 re-prioritized from (C) to (A). 84 | 85 | >>> todo.sh -p list 86 | 2 (A) notice the sunflowers 87 | 1 (B) smell the uppercase Roses +flowers @outside 88 | 3 stop 89 | -- 90 | TODO: 3 of 3 tasks shown 91 | 92 | >>> todo.sh pri 2 a 93 | === 1 94 | 2 (A) notice the sunflowers 95 | TODO: 2 already prioritized (A). 96 | 97 | >>> todo.sh -p list 98 | 2 (A) notice the sunflowers 99 | 1 (B) smell the uppercase Roses +flowers @outside 100 | 3 stop 101 | -- 102 | TODO: 3 of 3 tasks shown 103 | EOF 104 | 105 | cat > todo.txt <>> todo.sh pri 1 A 2 B 112 | 1 (A) smell the uppercase Roses +flowers @outside 113 | TODO: 1 prioritized (A). 114 | 2 (B) notice the sunflowers 115 | TODO: 2 prioritized (B). 116 | EOF 117 | 118 | test_todo_session 'multiple reprioritize' <>> todo.sh pri 1 Z 2 X 120 | 1 (Z) smell the uppercase Roses +flowers @outside 121 | TODO: 1 re-prioritized from (A) to (Z). 122 | 2 (X) notice the sunflowers 123 | TODO: 2 re-prioritized from (B) to (X). 124 | EOF 125 | 126 | test_todo_session 'multiple prioritize error' <>> todo.sh pri 1 B 4 B 128 | === 1 129 | 1 (B) smell the uppercase Roses +flowers @outside 130 | TODO: 1 re-prioritized from (Z) to (B). 131 | TODO: No task 4. 132 | 133 | >>> todo.sh pri 1 C 4 B 3 A 134 | === 1 135 | 1 (C) smell the uppercase Roses +flowers @outside 136 | TODO: 1 re-prioritized from (B) to (C). 137 | TODO: No task 4. 138 | EOF 139 | test_done 140 | -------------------------------------------------------------------------------- /todo.cfg: -------------------------------------------------------------------------------- 1 | # === EDIT FILE LOCATIONS BELOW === 2 | 3 | # Your todo.txt directory (this should be an absolute path) 4 | #export TODO_DIR="/Users/gina/Documents/todo" 5 | export TODO_DIR=${HOME:-$USERPROFILE} 6 | 7 | # Your todo/done/report.txt locations 8 | export TODO_FILE="$TODO_DIR/todo.txt" 9 | export DONE_FILE="$TODO_DIR/done.txt" 10 | export REPORT_FILE="$TODO_DIR/report.txt" 11 | 12 | # You can customize your actions directory location 13 | #export TODO_ACTIONS_DIR="$HOME/.todo.actions.d" 14 | 15 | # == EDIT FILE LOCATIONS ABOVE === 16 | 17 | # === COLOR MAP === 18 | 19 | ## Text coloring and formatting is done by inserting ANSI escape codes. 20 | ## If you have re-mapped your color codes, or use the todo.txt 21 | ## output in another output system (like Conky), you may need to 22 | ## over-ride by uncommenting and editing these defaults. 23 | ## If you change any of these here, you also need to uncomment 24 | ## the defaults in the COLORS section below. Otherwise, todo.txt 25 | ## will still use the defaults! 26 | 27 | # export BLACK='\\033[0;30m' 28 | # export RED='\\033[0;31m' 29 | # export GREEN='\\033[0;32m' 30 | # export BROWN='\\033[0;33m' 31 | # export BLUE='\\033[0;34m' 32 | # export PURPLE='\\033[0;35m' 33 | # export CYAN='\\033[0;36m' 34 | # export LIGHT_GREY='\\033[0;37m' 35 | # export DARK_GREY='\\033[1;30m' 36 | # export LIGHT_RED='\\033[1;31m' 37 | # export LIGHT_GREEN='\\033[1;32m' 38 | # export YELLOW='\\033[1;33m' 39 | # export LIGHT_BLUE='\\033[1;34m' 40 | # export LIGHT_PURPLE='\\033[1;35m' 41 | # export LIGHT_CYAN='\\033[1;36m' 42 | # export WHITE='\\033[1;37m' 43 | # export DEFAULT='\\033[0m' 44 | 45 | # === COLORS === 46 | 47 | ## Uncomment and edit to override these defaults. 48 | ## Reference the constants from the color map above, 49 | ## or use $NONE to disable highlighting. 50 | # 51 | # Priorities can be any upper-case letter. 52 | # A,B,C are highlighted; you can add coloring for more. 53 | # 54 | # export PRI_A=$YELLOW # color for A priority 55 | # export PRI_B=$GREEN # color for B priority 56 | # export PRI_C=$LIGHT_BLUE # color for C priority 57 | # export PRI_D=... # define your own 58 | # export PRI_X=$WHITE # color unless explicitly defined 59 | 60 | # There is highlighting for tasks that have been done, 61 | # but haven't been archived yet. 62 | # 63 | # export COLOR_DONE=$LIGHT_GREY 64 | 65 | # There is highlighting for projects, contexts, dates, and item numbers. 66 | # 67 | # export COLOR_PROJECT=$RED 68 | # export COLOR_CONTEXT=$RED 69 | # export COLOR_DATE=$BLUE 70 | # export COLOR_NUMBER=$LIGHT_GREY 71 | 72 | # There is highlighting for metadata key:value pairs e.g. 73 | # DUE:2006-08-01 or note:MYNOTE 74 | # 75 | # export COLOR_META=$CYAN 76 | 77 | # === BEHAVIOR === 78 | 79 | ## verbosity 80 | # 81 | # By default, additional information and confirmation of actions (like 82 | # "TODO: 1 added") are printed. You can suppress this via 0 or add extra 83 | # verbosity via 2. 84 | # export TODOTXT_VERBOSE=1 85 | 86 | ## customize list output 87 | # 88 | # TODOTXT_SORT_COMMAND will filter after line numbers are 89 | # inserted, but before colorization, and before hiding of 90 | # priority, context, and project. 91 | # 92 | # export TODOTXT_SORT_COMMAND='env LC_COLLATE=C sort -f -k2' 93 | 94 | # TODOTXT_FINAL_FILTER will filter list output after colorization, 95 | # priority hiding, context hiding, and project hiding. That is, 96 | # just before the list output is displayed. 97 | # 98 | # export TODOTXT_FINAL_FILTER='cat' 99 | 100 | ## default actions 101 | # Set a default action for calling todo.sh without arguments. 102 | # Also allows for parameters for the action. 103 | # export TODOTXT_DEFAULT_ACTION='' 104 | -------------------------------------------------------------------------------- /tests/t1250-listpri.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test_description='list priority functionality 4 | ' 5 | . ./test-lib.sh 6 | 7 | cat > todo.txt <>> todo.sh listpri A 14 | -- 15 | TODO: 0 of 3 tasks shown 16 | 17 | >>> todo.sh -p listpri c 18 | 2 (C) notice the sunflowers 19 | -- 20 | TODO: 1 of 3 tasks shown 21 | EOF 22 | 23 | test_todo_session 'listpri highlighting' <>> todo.sh listpri 25 | 1 (B) smell the uppercase Roses +flowers @outside 26 | 2 (C) notice the sunflowers 27 | -- 28 | TODO: 2 of 3 tasks shown 29 | EOF 30 | 31 | cat > todo.txt <>> todo.sh -p listpri 40 | 1 (B) smell the uppercase Roses +flowers @outside 41 | 2 (C) notice the sunflowers 42 | -- 43 | TODO: 2 of 5 tasks shown 44 | 45 | >>> todo.sh -p listpri b 46 | 1 (B) smell the uppercase Roses +flowers @outside 47 | -- 48 | TODO: 1 of 5 tasks shown 49 | 50 | >>> todo.sh -p listpri c 51 | 2 (C) notice the sunflowers 52 | -- 53 | TODO: 1 of 5 tasks shown 54 | 55 | >>> todo.sh -p listpri m 56 | -- 57 | TODO: 0 of 5 tasks shown 58 | 59 | >>> todo.sh -p listpri n 60 | -- 61 | TODO: 0 of 5 tasks shown 62 | EOF 63 | 64 | cat > todo.txt <>> todo.sh -p listpri a-c 73 | 1 (B) smell the uppercase Roses +flowers @outside 74 | 3 (C) notice the sunflowers 75 | -- 76 | TODO: 2 of 5 tasks shown 77 | 78 | >>> todo.sh -p listpri c-Z 79 | 3 (C) notice the sunflowers 80 | 2 (X) clean the house from A-Z 81 | 4 (X) listen to music 82 | -- 83 | TODO: 3 of 5 tasks shown 84 | 85 | >>> todo.sh -p listpri A- 86 | 2 (X) clean the house from A-Z 87 | -- 88 | TODO: 1 of 5 tasks shown 89 | 90 | >>> todo.sh -p listpri A-C A-Z 91 | -- 92 | TODO: 0 of 5 tasks shown 93 | 94 | >>> todo.sh -p listpri X A-Z 95 | 2 (X) clean the house from A-Z 96 | -- 97 | TODO: 1 of 5 tasks shown 98 | EOF 99 | test_todo_session 'listpri filtering concatenation of priorities and -ranges' <>> todo.sh -p listpri CX 101 | 3 (C) notice the sunflowers 102 | 2 (X) clean the house from A-Z 103 | 4 (X) listen to music 104 | -- 105 | TODO: 3 of 5 tasks shown 106 | 107 | >>> todo.sh -p listpri ABR-Y 108 | 1 (B) smell the uppercase Roses +flowers @outside 109 | 2 (X) clean the house from A-Z 110 | 4 (X) listen to music 111 | -- 112 | TODO: 3 of 5 tasks shown 113 | 114 | >>> todo.sh -p listpri A- 115 | 2 (X) clean the house from A-Z 116 | -- 117 | TODO: 1 of 5 tasks shown 118 | EOF 119 | 120 | cat > todo.txt <>> todo.sh -p listpri "should be" 130 | 3 (A) aaa zzz this line should be first. 131 | 5 (B) bbb yyy this line should be second. 132 | 1 (B) ccc xxx this line should be third. 133 | -- 134 | TODO: 3 of 6 tasks shown 135 | 136 | >>> todo.sh -p listpri a "should be" 137 | 3 (A) aaa zzz this line should be first. 138 | -- 139 | TODO: 1 of 6 tasks shown 140 | 141 | >>> todo.sh -p listpri b second 142 | 5 (B) bbb yyy this line should be second. 143 | -- 144 | TODO: 1 of 6 tasks shown 145 | 146 | >>> todo.sh -p listpri x "should be" 147 | -- 148 | TODO: 0 of 6 tasks shown 149 | EOF 150 | 151 | test_done 152 | -------------------------------------------------------------------------------- /tests/t1350-listall.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test_description='listall functionality 4 | ' 5 | . ./test-lib.sh 6 | 7 | cat > todo.txt < done.txt <>> todo.sh -p listall 21 | 5 (A) stop 22 | 3 notice the sunflowers 23 | 1 smell the uppercase Roses +flowers @outside 24 | 2 x 2011-08-08 tend the garden @outside 25 | 0 x 2011-12-01 eat breakfast 26 | 0 x 2011-12-05 smell the coffee +wakeup 27 | 4 x 2011-12-26 go outside +wakeup 28 | -- 29 | TODO: 5 of 5 tasks shown 30 | DONE: 2 of 2 tasks shown 31 | total 7 of 7 tasks shown 32 | EOF 33 | 34 | test_todo_session 'listall highlighting' <>> todo.sh listall 36 | 5 (A) stop 37 | 3 notice the sunflowers 38 | 1 smell the uppercase Roses +flowers @outside 39 | 2 x 2011-08-08 tend the garden @outside 40 | 0 x 2011-12-01 eat breakfast 41 | 0 x 2011-12-05 smell the coffee +wakeup 42 | 4 x 2011-12-26 go outside +wakeup 43 | -- 44 | TODO: 5 of 5 tasks shown 45 | DONE: 2 of 2 tasks shown 46 | total 7 of 7 tasks shown 47 | EOF 48 | 49 | test_todo_session 'listall nonverbose' <>> TODOTXT_VERBOSE=0 todo.sh -p listall 51 | 5 (A) stop 52 | 3 notice the sunflowers 53 | 1 smell the uppercase Roses +flowers @outside 54 | 2 x 2011-08-08 tend the garden @outside 55 | 0 x 2011-12-01 eat breakfast 56 | 0 x 2011-12-05 smell the coffee +wakeup 57 | 4 x 2011-12-26 go outside +wakeup 58 | EOF 59 | 60 | test_todo_session 'listall filtering' <>> todo.sh -p listall @outside 62 | 1 smell the uppercase Roses +flowers @outside 63 | 2 x 2011-08-08 tend the garden @outside 64 | -- 65 | TODO: 2 of 5 tasks shown 66 | DONE: 0 of 2 tasks shown 67 | total 2 of 7 tasks shown 68 | 69 | >>> todo.sh -p listall the 70 | 3 notice the sunflowers 71 | 1 smell the uppercase Roses +flowers @outside 72 | 2 x 2011-08-08 tend the garden @outside 73 | 0 x 2011-12-05 smell the coffee +wakeup 74 | -- 75 | TODO: 3 of 5 tasks shown 76 | DONE: 1 of 2 tasks shown 77 | total 4 of 7 tasks shown 78 | 79 | >>> todo.sh -p listall breakfast 80 | 0 x 2011-12-01 eat breakfast 81 | -- 82 | TODO: 0 of 5 tasks shown 83 | DONE: 1 of 2 tasks shown 84 | total 1 of 7 tasks shown 85 | 86 | >>> todo.sh -p listall doesnotmatch 87 | -- 88 | TODO: 0 of 5 tasks shown 89 | DONE: 0 of 2 tasks shown 90 | total 0 of 7 tasks shown 91 | EOF 92 | 93 | cat >> done.txt <>> todo.sh -p listall 101 | 5 (A) stop 102 | 3 notice the sunflowers 103 | 1 smell the uppercase Roses +flowers @outside 104 | 0 x 2010-01-01 old task 1 105 | 0 x 2010-01-01 old task 2 106 | 0 x 2010-01-01 old task 3 107 | 0 x 2010-01-01 old task 4 108 | 2 x 2011-08-08 tend the garden @outside 109 | 0 x 2011-12-01 eat breakfast 110 | 0 x 2011-12-05 smell the coffee +wakeup 111 | 4 x 2011-12-26 go outside +wakeup 112 | -- 113 | TODO: 5 of 5 tasks shown 114 | DONE: 6 of 6 tasks shown 115 | total 11 of 11 tasks shown 116 | 117 | >>> TODOTXT_VERBOSE=0 todo.sh add new task 1 118 | 119 | >>> TODOTXT_VERBOSE=0 todo.sh add new task 2 120 | 121 | >>> TODOTXT_VERBOSE=0 todo.sh add new task 3 122 | 123 | >>> TODOTXT_VERBOSE=0 todo.sh add new task 4 124 | 125 | >>> TODOTXT_VERBOSE=0 todo.sh add new task 5 126 | 127 | >>> todo.sh -p listall 128 | 05 (A) stop 129 | 06 new task 1 130 | 07 new task 2 131 | 08 new task 3 132 | 09 new task 4 133 | 10 new task 5 134 | 03 notice the sunflowers 135 | 01 smell the uppercase Roses +flowers @outside 136 | 00 x 2010-01-01 old task 1 137 | 00 x 2010-01-01 old task 2 138 | 00 x 2010-01-01 old task 3 139 | 00 x 2010-01-01 old task 4 140 | 02 x 2011-08-08 tend the garden @outside 141 | 00 x 2011-12-01 eat breakfast 142 | 00 x 2011-12-05 smell the coffee +wakeup 143 | 04 x 2011-12-26 go outside +wakeup 144 | -- 145 | TODO: 10 of 10 tasks shown 146 | DONE: 6 of 6 tasks shown 147 | total 16 of 16 tasks shown 148 | EOF 149 | 150 | test_done 151 | -------------------------------------------------------------------------------- /tests/t9999-testsuite_example.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test_description='basic tests imported from previous framework 4 | ' 5 | . ./test-lib.sh 6 | 7 | cat > todo.txt <>> todo.sh -p list 15 | 2 (A) notice the sunflowers 16 | 1 (B) smell the uppercase Roses +flowers @outside 17 | 4 smell the coffee +wakeup 18 | 3 stop 19 | -- 20 | TODO: 4 of 4 tasks shown 21 | 22 | >>> todo.sh -p list +flowers 23 | 1 (B) smell the uppercase Roses +flowers @outside 24 | -- 25 | TODO: 1 of 4 tasks shown 26 | 27 | >>> todo.sh -p list flowers 28 | 2 (A) notice the sunflowers 29 | 1 (B) smell the uppercase Roses +flowers @outside 30 | -- 31 | TODO: 2 of 4 tasks shown 32 | 33 | >>> todo.sh -p list flowers out 34 | 1 (B) smell the uppercase Roses +flowers @outside 35 | -- 36 | TODO: 1 of 4 tasks shown 37 | 38 | >>> todo.sh -a do 2 39 | 2 x 2009-02-13 notice the sunflowers 40 | TODO: 2 marked as done. 41 | 42 | >>> todo.sh -p list 43 | 1 (B) smell the uppercase Roses +flowers @outside 44 | 4 smell the coffee +wakeup 45 | 3 stop 46 | 2 x 2009-02-13 notice the sunflowers 47 | -- 48 | TODO: 4 of 4 tasks shown 49 | 50 | >>> todo.sh add "make the coffee +wakeup" 51 | 5 make the coffee +wakeup 52 | TODO: 5 added. 53 | 54 | >>> todo.sh -p list coffee 55 | 5 make the coffee +wakeup 56 | 4 smell the coffee +wakeup 57 | -- 58 | TODO: 2 of 5 tasks shown 59 | 60 | >>> todo.sh add "visit http://example.com" 61 | 6 visit http://example.com 62 | TODO: 6 added. 63 | 64 | >>> todo.sh -p list 65 | 1 (B) smell the uppercase Roses +flowers @outside 66 | 5 make the coffee +wakeup 67 | 4 smell the coffee +wakeup 68 | 3 stop 69 | 6 visit http://example.com 70 | 2 x 2009-02-13 notice the sunflowers 71 | -- 72 | TODO: 6 of 6 tasks shown 73 | 74 | >>> todo.sh archive 75 | x 2009-02-13 notice the sunflowers 76 | TODO: $HOME/todo.txt archived. 77 | 78 | >>> todo.sh -p list 79 | 1 (B) smell the uppercase Roses +flowers @outside 80 | 4 make the coffee +wakeup 81 | 3 smell the coffee +wakeup 82 | 2 stop 83 | 5 visit http://example.com 84 | -- 85 | TODO: 5 of 5 tasks shown 86 | 87 | >>> todo.sh report 88 | TODO: $HOME/todo.txt does not contain any done tasks. 89 | 2009-02-13T04:40:00 5 1 90 | TODO: Report file updated. 91 | 92 | >>> todo.sh append g a 93 | usage: todo.sh append NR "TEXT TO APPEND" 94 | === 1 95 | 96 | >>> todo.sh append 2 and think 97 | 2 stop and think 98 | 99 | >>> todo.sh -p list 100 | 1 (B) smell the uppercase Roses +flowers @outside 101 | 4 make the coffee +wakeup 102 | 3 smell the coffee +wakeup 103 | 2 stop and think 104 | 5 visit http://example.com 105 | -- 106 | TODO: 5 of 5 tasks shown 107 | 108 | >>> todo.sh append 10 "hej!" 109 | TODO: No task 10. 110 | === 1 111 | 112 | >>> todo.sh -p list 113 | 1 (B) smell the uppercase Roses +flowers @outside 114 | 4 make the coffee +wakeup 115 | 3 smell the coffee +wakeup 116 | 2 stop and think 117 | 5 visit http://example.com 118 | -- 119 | TODO: 5 of 5 tasks shown 120 | 121 | >>> todo.sh do 10 122 | TODO: No task 10. 123 | === 1 124 | 125 | >>> todo.sh -p list 126 | 1 (B) smell the uppercase Roses +flowers @outside 127 | 4 make the coffee +wakeup 128 | 3 smell the coffee +wakeup 129 | 2 stop and think 130 | 5 visit http://example.com 131 | -- 132 | TODO: 5 of 5 tasks shown 133 | 134 | >>> todo.sh add "the coffee +wakeup" 135 | 6 the coffee +wakeup 136 | TODO: 6 added. 137 | 138 | >>> todo.sh -p list 139 | 1 (B) smell the uppercase Roses +flowers @outside 140 | 4 make the coffee +wakeup 141 | 3 smell the coffee +wakeup 142 | 2 stop and think 143 | 6 the coffee +wakeup 144 | 5 visit http://example.com 145 | -- 146 | TODO: 6 of 6 tasks shown 147 | 148 | >>> todo.sh prepend 6 "make" 149 | 6 make the coffee +wakeup 150 | 151 | >>> todo.sh -p list 152 | 1 (B) smell the uppercase Roses +flowers @outside 153 | 4 make the coffee +wakeup 154 | 6 make the coffee +wakeup 155 | 3 smell the coffee +wakeup 156 | 2 stop and think 157 | 5 visit http://example.com 158 | -- 159 | TODO: 6 of 6 tasks shown 160 | 161 | >>> todo.sh remdup 162 | Usage: todo.sh [-fhpantvV] [-d todo_config] action [task_number] [task_description] 163 | Try 'todo.sh -h' for more information. 164 | === 1 165 | EOF 166 | 167 | test_done 168 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Makefile for todo.txt 3 | # 4 | 5 | SHELL = /bin/sh 6 | 7 | INSTALL = /usr/bin/install 8 | INSTALL_PROGRAM = $(INSTALL) 9 | INSTALL_DATA = $(INSTALL) -m 644 10 | 11 | prefix = /usr/local 12 | 13 | # ifdef check allows the user to pass custom dirs 14 | # as per the README 15 | 16 | # The directory to install todo.sh in. 17 | ifdef INSTALL_DIR 18 | bindir = $(INSTALL_DIR) 19 | else 20 | bindir = $(prefix)/bin 21 | endif 22 | DEST_COMMAND = $(DESTDIR)$(bindir)/todo.sh 23 | 24 | # The directory to install the config file in. 25 | ifdef CONFIG_DIR 26 | sysconfdir = $(CONFIG_DIR) 27 | else 28 | sysconfdir = $(prefix)/etc 29 | endif 30 | DEST_CONFIG = $(DESTDIR)$(sysconfdir)/todo/config 31 | 32 | ifdef BASH_COMPLETION 33 | datarootdir = $(BASH_COMPLETION) 34 | else 35 | datarootdir = $(prefix)/share/bash-completion/completions 36 | endif 37 | DEST_COMPLETION = $(DESTDIR)$(datarootdir)/todo.sh 38 | 39 | # generate list of targets from this Makefile 40 | # looks for any lowercase target with a double hash mark (##) on the same line 41 | # and uses the inline comment as the target description 42 | .PHONY: help 43 | .DEFAULT: help 44 | help: ## list public targets 45 | @echo 46 | @echo todo.txt Makefile 47 | @echo 48 | @sed -ne '/^[a-z%-]\+:.*##/ s/:.*##/\t/p' $(word 1, $(MAKEFILE_LIST)) \ 49 | | column -t -s ' ' 50 | @echo 51 | 52 | # Dynamically detect/generate version file as necessary 53 | # This file will define a variable called VERSION used in 54 | # both todo.sh and this Makefile. 55 | VERSION-FILE: 56 | @./GEN-VERSION-FILE 57 | -include VERSION-FILE 58 | 59 | # dist/build directory name 60 | DISTNAME=todo.txt_cli-$(VERSION) 61 | 62 | # files to copy unmodified into the dist directory 63 | SRC_FILES := todo.cfg todo_completion 64 | 65 | # path of SRC_FILES in the dist directory 66 | OUTPUT_FILES := $(patsubst %, $(DISTNAME)/%, $(SRC_FILES)) 67 | 68 | # all dist files 69 | DISTFILES := $(OUTPUT_FILES) $(DISTNAME)/todo.sh 70 | 71 | # create the dist directory 72 | $(DISTNAME): VERSION-FILE 73 | mkdir -p $(DISTNAME) 74 | 75 | # copy SRC_FILES to the dist directory 76 | $(OUTPUT_FILES): $(DISTNAME)/%: % 77 | cp -f $(*) $(DISTNAME)/ 78 | 79 | # generate todo.sh 80 | $(DISTNAME)/todo.sh: VERSION-FILE 81 | sed -e 's/@DEV_VERSION@/'$(VERSION)'/' todo.sh > $(DISTNAME)/todo.sh 82 | chmod +x $(DISTNAME)/todo.sh 83 | 84 | .PHONY: build 85 | build: $(DISTNAME) $(DISTFILES) ## create the dist directory and files 86 | 87 | .PHONY: dist 88 | dist: build ## create the compressed release files 89 | tar cf $(DISTNAME).tar $(DISTNAME) 90 | gzip -f -9 $(DISTNAME).tar 91 | zip -r -9 $(DISTNAME).zip $(DISTNAME) 92 | rm -r $(DISTNAME) 93 | 94 | .PHONY: clean 95 | clean: test-pre-clean VERSION-FILE ## remove dist directory and all release files 96 | rm -rf $(DISTNAME) 97 | rm -f $(DISTNAME).tar.gz $(DISTNAME).zip 98 | 99 | .PHONY: install 100 | install: build installdirs ## local package install 101 | $(INSTALL_PROGRAM) $(DISTNAME)/todo.sh $(DEST_COMMAND) 102 | $(INSTALL_DATA) $(DISTNAME)/todo_completion $(DEST_COMPLETION) 103 | [ -e $(DEST_CONFIG) ] || \ 104 | sed "s/^\(export[ \t]*TODO_DIR=\).*/\1~\/.todo/" $(DISTNAME)/todo.cfg > $(DEST_CONFIG) 105 | 106 | .PHONY: uninstall 107 | uninstall: ## uninstall package 108 | rm -f $(DEST_COMMAND) 109 | rm -f $(DEST_COMPLETION) 110 | rm -f $(DEST_CONFIG) 111 | 112 | rmdir $(DESTDIR)$(datarootdir) 2>/dev/null || : 113 | rmdir $(DESTDIR)$(sysconfdir)/todo 114 | 115 | # create local installation directories 116 | .PHONY: installdirs 117 | installdirs: 118 | mkdir -p $(DESTDIR)$(bindir) \ 119 | $(DESTDIR)$(sysconfdir)/todo \ 120 | $(DESTDIR)$(datarootdir) 121 | 122 | # 123 | # Testing 124 | # 125 | TESTS = $(wildcard tests/t[0-9][0-9][0-9][0-9]-*.sh) 126 | #TEST_OPTIONS=--verbose 127 | 128 | # remove test detritus 129 | test-pre-clean: 130 | rm -rf tests/test-results "tests/trash directory"* 131 | 132 | # run tests and generate test result files 133 | aggregate-results: $(TESTS) 134 | 135 | $(TESTS): test-pre-clean 136 | cd tests && ./$(notdir $@) $(TEST_OPTIONS) 137 | 138 | # run tests, print a test result summary, and remove generated test results 139 | test: aggregate-results ## run tests 140 | tests/aggregate-results.sh tests/test-results/t*-* 141 | rm -rf tests/test-results 142 | 143 | # Force tests to get run every time 144 | .PHONY: test test-pre-clean aggregate-results $(TESTS) 145 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [![todo.txt-cli](http://todotxt.org/images/todotxt_logo_2012.png)][website] 2 | 3 | > A simple and extensible shell script for managing your todo.txt file. 4 | 5 | ![CI](https://github.com/todotxt/todo.txt-cli/workflows/CI/badge.svg) 6 | [![GitHub issues](https://img.shields.io/github/issues/todotxt/todo.txt-cli.svg)](https://github.com/todotxt/todo.txt-cli/issues) 7 | [![GitHub forks](https://img.shields.io/github/forks/todotxt/todo.txt-cli.svg)](https://github.com/todotxt/todo.txt-cli/network) 8 | [![GitHub stars](https://img.shields.io/github/stars/todotxt/todo.txt-cli.svg)](https://github.com/todotxt/todo.txt-cli/stargazers) 9 | [![GitHub license](https://img.shields.io/github/license/todotxt/todo.txt-cli.svg)](https://raw.githubusercontent.com/todotxt/todo.txt-cli/master/LICENSE) 10 | [![Gitter](https://badges.gitter.im/join_chat.svg)](https://gitter.im/todotxt/todo.txt-cli) 11 | 12 | ![gif](./.github/example.gif) 13 | 14 | *Read our [contributing guide][CONTRIBUTING] if you're looking to contribute (issues/PRs/etc).* 15 | 16 | 17 | ## Installation 18 | 19 | ### Download 20 | Download the latest stable [release][release] for use on your desktop or server. 21 | 22 | ### OS X / macOS 23 | 24 | ```shell 25 | brew install todo-txt 26 | 27 | cp -n $(brew --prefix)/opt/todo-txt/todo.cfg ~/.todo.cfg 28 | ``` 29 | 30 | **Note**: The `-n` flag for `cp` makes sure you do not overwrite an existing file. 31 | 32 | ### Linux 33 | 34 | #### From command line 35 | 36 | ```shell 37 | make 38 | make install 39 | make test 40 | ``` 41 | 42 | *NOTE:* Makefile defaults to several default paths for installed files. Adjust to your system: 43 | 44 | - `INSTALL_DIR`: PATH for executables (default `/usr/local/bin`) 45 | - `CONFIG_DIR`: PATH for the `todo/config` configuration template (default `/usr/local/etc`) 46 | - `BASH_COMPLETION`: PATH for autocompletion scripts (default to `/usr/local/share/bash-completion/completions`) 47 | 48 | ```shell 49 | # Note: Showcasing config overrides for legacy locations; NOT recommended! 50 | make install CONFIG_DIR=/etc INSTALL_DIR=/usr/bin BASH_COMPLETION=/etc/bash_completion.d 51 | ``` 52 | 53 | #### Arch Linux (AUR) 54 | 55 | https://aur.archlinux.org/packages/todotxt/ 56 | 57 | 58 | ## Configuration 59 | 60 | No configuration is required; however, most users tweak the default settings (e.g. relocating the todo.txt directory to a subdirectory of the user's home directory, or onto a cloud drive (via the `TODO_DIR` variable)), modify the colors, add additional highlighting of projects, contexts, dates, and so on. A configuration template with a commented-out list of all available options is included. 61 | It is recommended to _copy_ that template into one of the locations listed by `todo.sh help` on `-d CONFIG_FILE`, even if it is installed in the global configuration location (`/etc/todo/config`). 62 | 63 | ## Usage 64 | ```shell 65 | todo.sh [-fhpantvV] [-d todo_config] action [task_number] [task_description] 66 | ``` 67 | 68 | For example, to add a todo item, you can do: 69 | 70 | ```shell 71 | todo.sh add "THING I NEED TO DO +project @context" 72 | ``` 73 | ### `replace` 74 | Replaces task on line NR with UPDATED TODO. 75 | 76 | ```shell 77 | todo.sh replace NR "UPDATED TODO" 78 | ``` 79 | ### `report` 80 | Adds the number of open tasks and done tasks to report.txt. 81 | 82 | ```shell 83 | todo.sh report 84 | ``` 85 | 86 | Read about all the possible commands in the [USAGE][USAGE] file. 87 | 88 | 89 | ## Release History 90 | 91 | See [CHANGELOG.md][CHANGELOG] 92 | 93 | 94 | ## Support 95 | 96 | - [Github Discussions](https://github.com/todotxt/todo.txt-cli/discussions) 97 | - [Stack Overflow](https://stackoverflow.com/questions/tagged/todotxt) 98 | - [Twitter](https://twitter.com/todotxt) 99 | 100 | 101 | ## Code of Conduct 102 | 103 | [Contributor Code of Conduct][CODE_OF_CONDUCT]. By participating in this project you agree to abide by its terms. 104 | 105 | ## Contributing 106 | 107 | We welcome all contributions. First read our [Contributor Code of Conduct][CODE_OF_CONDUCT] and then get started [contributing][CONTRIBUTING]. 108 | 109 | ## License 110 | 111 | GNU General Public License v3.0 © [todo.txt org][github] 112 | 113 | 114 | 115 | [release]: https://github.com/todotxt/todo.txt-cli/releases 116 | [website]: http://todotxt.org/ 117 | [github]: https://github.com/todotxt 118 | [USAGE]: ./USAGE.md 119 | [CHANGELOG]: ./CHANGELOG.md 120 | [CODE_OF_CONDUCT]: .github/CODE_OF_CONDUCT.md 121 | [CONTRIBUTING]: .github/CONTRIBUTING.md 122 | -------------------------------------------------------------------------------- /tests/t1320-listproj.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test_description='listproj functionality 4 | 5 | This test checks basic project listing functionality 6 | ' 7 | . ./test-lib.sh 8 | 9 | cat > todo.txt < output && ! test -s output 16 | ' 17 | 18 | cat > todo.txt <>> todo.sh listproj 27 | +1 28 | +p2 29 | +prj03 30 | +prj04 31 | +prj05+prj06 32 | EOF 33 | 34 | cat > todo.txt <>> todo.sh listproj 41 | +prj01 42 | +prj02 43 | +prj03 44 | EOF 45 | 46 | cat > todo.txt <>> todo.sh listproj 53 | +prj01 54 | +prj02 55 | EOF 56 | 57 | cat > todo.txt <>> todo.sh listproj 64 | +landscape 65 | +roses 66 | +shared 67 | +sunflowers 68 | EOF 69 | 70 | test_todo_session 'listproj with context' <>> todo.sh listproj @garden 72 | +landscape 73 | +shared 74 | +sunflowers 75 | EOF 76 | 77 | cat > todo.txt <>> todo.sh listproj 91 | +flowers 92 | +roses 93 | EOF 94 | 95 | cat > todo.txt <>> todo.sh listproj 102 | +1 103 | +sunflowers 104 | EOF 105 | test_todo_session 'listproj limiting to alphabetic characters' <>> TODOTXT_SIGIL_VALID_PATTERN='[a-zA-Z]\{1,\}' todo.sh listproj 107 | +sunflowers 108 | EOF 109 | test_todo_session 'listproj allowing brackets around projects' <>> TODOTXT_SIGIL_BEFORE_PATTERN='\[\{0,1\}' TODOTXT_SIGIL_AFTER_PATTERN='\]\{0,1\}' todo.sh listproj 111 | +1 112 | +gardening 113 | +landscape 114 | +sunflowers 115 | EOF 116 | 117 | cat > todo.txt < "$TEST_TODO_CUSTOM" 124 | cat >> "$TEST_TODO_CUSTOM" <<'EOF' 125 | export DEFAULT='' 126 | export PRI_B='' 127 | export PRI_C='' 128 | export TODOTXT_FINAL_FILTER='grep -i roses' 129 | EOF 130 | test_todo_session 'listproj with context special cases' <>> todo.sh -+ -d "$TEST_TODO_CUSTOM" listproj @garden 132 | +landscape 133 | +shared 134 | +sunflowers 135 | EOF 136 | 137 | cat > todo.txt < done.txt <>> TODOTXT_SOURCEVAR=\$DONE_FILE todo.sh listproj 146 | +done01 147 | +done02 148 | EOF 149 | test_todo_session 'listproj from done tasks with filtering' <<'EOF' 150 | >>> TODOTXT_SOURCEVAR=\$DONE_FILE todo.sh listproj Special 151 | +done01 152 | EOF 153 | test_todo_session 'listproj from combined open + done tasks' <<'EOF' 154 | >>> TODOTXT_SOURCEVAR='("$TODO_FILE" "$DONE_FILE")' todo.sh listproj 155 | +done01 156 | +done02 157 | +prj01 158 | EOF 159 | 160 | test_todo_session 'listproj with GREP_OPTIONS disruption' <<'EOF' 161 | >>> GREP_OPTIONS=-n todo.sh listproj 162 | +prj01 163 | EOF 164 | 165 | test_done 166 | -------------------------------------------------------------------------------- /tests/t1800-del.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test_description='basic del functionality 4 | ' 5 | . ./test-lib.sh 6 | 7 | SPACE=' ' 8 | 9 | test_todo_session 'del usage' <>> todo.sh del B 11 | usage: todo.sh del NR [TERM] 12 | === 1 13 | EOF 14 | 15 | test_todo_session 'del nonexistant item' <>> todo.sh -f del 42 17 | TODO: No task 42. 18 | === 1 19 | 20 | >>> todo.sh -f del 42 Roses 21 | TODO: No task 42. 22 | === 1 23 | EOF 24 | 25 | cat > todo.txt <>> todo.sh -p list 32 | 2 (A) notice the sunflowers 33 | 1 (B) smell the uppercase Roses +flowers @outside 34 | 3 stop 35 | -- 36 | TODO: 3 of 3 tasks shown 37 | 38 | >>> todo.sh -f del 1 39 | 1 (B) smell the uppercase Roses +flowers @outside 40 | TODO: 1 deleted. 41 | 42 | >>> todo.sh -p list 43 | 2 (A) notice the sunflowers 44 | 3 stop 45 | -- 46 | TODO: 2 of 2 tasks shown 47 | EOF 48 | 49 | cat > todo.txt <>> todo.sh -p list 56 | 2 (A) notice the sunflowers 57 | 1 (B) smell the uppercase Roses +flowers @outside 58 | 3 stop 59 | -- 60 | TODO: 3 of 3 tasks shown 61 | 62 | >>> printf n | todo.sh del 1 63 | \\ 64 | TODO: No tasks were deleted. 65 | === 1 66 | 67 | >>> todo.sh -p list 68 | 2 (A) notice the sunflowers 69 | 1 (B) smell the uppercase Roses +flowers @outside 70 | 3 stop 71 | -- 72 | TODO: 3 of 3 tasks shown 73 | 74 | >>> printf x | todo.sh del 1 75 | \\ 76 | TODO: No tasks were deleted. 77 | === 1 78 | 79 | >>> echo | todo.sh del 1 80 | \\ 81 | TODO: No tasks were deleted. 82 | === 1 83 | 84 | >>> printf y | todo.sh del 1 85 | \\ 86 | 1 (B) smell the uppercase Roses +flowers @outside 87 | TODO: 1 deleted. 88 | 89 | >>> todo.sh -p list 90 | 2 (A) notice the sunflowers 91 | 3 stop 92 | -- 93 | TODO: 2 of 2 tasks shown 94 | EOF 95 | 96 | cat > todo.txt <>> todo.sh -f del 1 103 | 1 (B) smell the uppercase Roses +flowers @outside 104 | TODO: 1 deleted. 105 | 106 | >>> todo.sh -f del 1 107 | TODO: No task 1. 108 | === 1 109 | 110 | >>> todo.sh add A new task 111 | 4 A new task 112 | TODO: 4 added. 113 | 114 | >>> todo.sh -p list 115 | 2 (A) notice the sunflowers 116 | 4 A new task 117 | 3 stop 118 | -- 119 | TODO: 3 of 3 tasks shown 120 | 121 | >>> todo.sh -f -n del 2 122 | 2 (A) notice the sunflowers 123 | TODO: 2 deleted. 124 | 125 | >>> todo.sh add Another new task 126 | 3 Another new task 127 | TODO: 3 added. 128 | 129 | >>> todo.sh -p list 130 | 2 A new task 131 | 3 Another new task 132 | 1 stop 133 | -- 134 | TODO: 3 of 3 tasks shown 135 | EOF 136 | 137 | cat > todo.txt <>> todo.sh -p list 144 | 2 (A) notice the sunflowers 145 | 1 (B) smell the uppercase Roses +flowers @outside 146 | 3 (C) stop 147 | -- 148 | TODO: 3 of 3 tasks shown 149 | 150 | >>> todo.sh del 1 uppercase 151 | 1 (B) smell the uppercase Roses +flowers @outside 152 | TODO: Removed 'uppercase' from task. 153 | 1 (B) smell the Roses +flowers @outside 154 | 155 | >>> todo.sh -p list 156 | 2 (A) notice the sunflowers 157 | 1 (B) smell the Roses +flowers @outside 158 | 3 (C) stop 159 | -- 160 | TODO: 3 of 3 tasks shown 161 | 162 | >>> todo.sh del 1 "the Roses" 163 | 1 (B) smell the Roses +flowers @outside 164 | TODO: Removed 'the Roses' from task. 165 | 1 (B) smell +flowers @outside 166 | 167 | >>> todo.sh del 1 m 168 | 1 (B) smell +flowers @outside 169 | TODO: Removed 'm' from task. 170 | 1 (B) sell +flowers @outside 171 | 172 | >>> todo.sh del 1 @outside 173 | 1 (B) sell +flowers @outside 174 | TODO: Removed '@outside' from task. 175 | 1 (B) sell +flowers 176 | 177 | >>> todo.sh del 1 sell 178 | 1 (B) sell +flowers 179 | TODO: Removed 'sell' from task. 180 | 1 (B) +flowers 181 | EOF 182 | 183 | cat > todo.txt <>> todo.sh del 1 dung 190 | 1 (B) smell the uppercase Roses +flowers @outside 191 | TODO: 'dung' not found; no removal done. 192 | === 1 193 | 194 | >>> todo.sh -p list 195 | 2 (A) notice the sunflowers 196 | 1 (B) smell the uppercase Roses +flowers @outside 197 | 3 (C) stop 198 | -- 199 | TODO: 3 of 3 tasks shown 200 | EOF 201 | 202 | test_done 203 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | :+1::tada: First off, thanks for taking the time to contribute! :tada::+1: 4 | 5 | It's people like you that make [todo.txt] such a great tool. 6 | 7 | The following is a set of guidelines for contributing to [todo.txt] and its packages. These are mostly guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request. 8 | 9 | Following these guidelines helps to communicate that you respect the time of the developers managing and developing this open source project. In return, they should reciprocate that respect in addressing your issue, assessing changes, and helping you finalize your pull requests. 10 | 11 | [todo.txt] is an open source project and we love to receive contributions from our community — you! There are many ways to contribute, from writing tutorials or blog posts, improving the documentation, submitting bug reports and feature requests or writing code which can be incorporated into [todo.txt] itself. 12 | 13 | Please, don't use the issue tracker for support questions. Check whether our [Gitter.im] channel can help with your issue. Stack Overflow is also worth considering. 14 | 15 | # Ground Rules 16 | 17 | ## Responsibilities 18 | 19 | - Be welcoming to newcomers and encourage diverse new contributors from all backgrounds. See our [Code of Conduct]. 20 | - Ensure cross-platform compatibility for every change that's accepted. Windows, Mac, Linux. 21 | - Create issues for any major changes and enhancements that you wish to make. Discuss things transparently and get community feedback. 22 | - Don't add any classes to the codebase unless absolutely needed. Err on the side of using functions. 23 | - Keep feature versions as small as possible, preferably one new feature per version. 24 | 25 | # Your First Contribution 26 | 27 | Unsure where to begin contributing? You can start by looking through these beginner and help-wanted issues: 28 | 29 | - Beginner issues - issues which should only require a few lines of code, and a test or two. 30 | - Help wanted issues - issues which should be a bit more involved than beginner issues. 31 | 32 | Both issue lists are sorted by total number of comments. While not perfect, number of comments is a reasonable proxy for impact a given change will have. 33 | 34 | At this point, you're ready to make your changes! Feel free to ask for help; everyone is a beginner at first :smile_cat: 35 | 36 | If a maintainer asks you to "rebase" your PR, they're saying that a lot of code has changed, and that you need to update your branch so it's easier to merge. 37 | 38 | # Getting started 39 | 40 | For something that is bigger than a one or two line fix: 41 | 42 | 1. Create your own fork of the code. 43 | 1. Do the changes in your fork. 44 | 1. If you like the change and think the project could use it: 45 | - Be sure you have followed the code style for the project. 46 | - Note the [Code of Conduct]. 47 | 48 | As a rule of thumb, changes are obvious fixes if they do not introduce any new functionality or creative thinking. As long as the change does not affect functionality, some likely examples include the following: 49 | 50 | - Spelling / grammar fixes 51 | - Typo correction, white space and formatting changes 52 | - Comment clean up 53 | - Bug fixes that change default return values or error codes stored in constants 54 | - Adding logging messages or debugging output 55 | - Changes to ‘metadata’ files like .gitignore, build scripts, etc. 56 | - Moving source files from one directory or package to another 57 | 58 | # How to report a bug 59 | 60 | ## Security Vulnerability 61 | 62 | If you find a security vulnerability, do NOT open an issue. Get ahold of the maintainers personally. 63 | 64 | In order to determine whether you are dealing with a security issue, ask yourself these two questions: 65 | 66 | - Can I access something that's not mine, or something I shouldn't have access to? 67 | - Can I disable something for other people? 68 | 69 | If the answer to either of those two questions are "yes", then you're probably dealing with a security issue. Note that even if you answer "no" to both questions, you may still be dealing with a security issue, so if you're unsure, just email us directly. 70 | 71 | ## Bug 72 | 73 | When filing an issue, make sure to answer these five questions: 74 | 75 | 1. What version of shell are you using (`echo $0` or `$(echo $SHELL) --version)`)? 76 | 1. What operating system and processor architecture are you using? 77 | 1. What did you do? 78 | 1. What did you expect to see? 79 | 1. What did you see instead? 80 | 81 | # How to suggest a feature or enhancement 82 | 83 | The [todo.txt] philosophy is to provide a plain-text, software-agnostic way to keep track of your tasks. 84 | 85 | If you find yourself wishing for a feature that doesn't exist, you are probably not alone. There are bound to be others out there with similar needs. Many of the features that todo.txt-cli has today have been added because our users saw the need. Open an issue on our issues list on GitHub which describes the feature you would like to see, why you need it, and how it should work. 86 | 87 | # Code review process 88 | 89 | The core team looks at Pull Requests on a regular basis. After feedback has been given we expect responses within two weeks. After two weeks we may close the pull request if it isn't showing any activity. 90 | 91 | # Community 92 | 93 | You can chat with the core team on https://gitter.im/todotxt/. 94 | 95 | [todo.txt]: https://github.com/todotxt/ 96 | [Code of Conduct]: ./CODE_OF_CONDUCT.md 97 | [Gitter.im]: https://gitter.im/todotxt/ 98 | -------------------------------------------------------------------------------- /tests/t1100-replace.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test_description='basic replace functionality 4 | 5 | Ensure we can replace items successfully. 6 | ' 7 | . ./test-lib.sh 8 | 9 | # 10 | # Set up the basic todo.txt 11 | # 12 | todo.sh add notice the daisies > /dev/null 13 | 14 | test_todo_session 'replace usage' <>> todo.sh replace adf asdfa 16 | === 1 17 | usage: todo.sh replace NR "UPDATED ITEM" 18 | EOF 19 | 20 | test_todo_session 'basic replace' <>> todo.sh replace 1 "smell the cows" 22 | 1 notice the daisies 23 | TODO: Replaced task with: 24 | 1 smell the cows 25 | 26 | >>> todo.sh list 27 | 1 smell the cows 28 | -- 29 | TODO: 1 of 1 tasks shown 30 | 31 | >>> todo.sh replace 1 smell the roses 32 | 1 smell the cows 33 | TODO: Replaced task with: 34 | 1 smell the roses 35 | 36 | >>> todo.sh list 37 | 1 smell the roses 38 | -- 39 | TODO: 1 of 1 tasks shown 40 | EOF 41 | 42 | cat > todo.txt <>> todo.sh replace 10 "hej!" 50 | === 1 51 | TODO: No task 10. 52 | EOF 53 | 54 | test_todo_session 'replace in multi-item file' <>> todo.sh replace 1 smell the cheese 56 | 1 smell the cows 57 | TODO: Replaced task with: 58 | 1 smell the cheese 59 | 60 | >>> todo.sh replace 3 jump on hay 61 | 3 thrash some hay 62 | TODO: Replaced task with: 63 | 3 jump on hay 64 | 65 | >>> todo.sh replace 4 collect the eggs 66 | 4 chase the chickens 67 | TODO: Replaced task with: 68 | 4 collect the eggs 69 | EOF 70 | 71 | echo '(A) collect the eggs' > todo.txt 72 | test_todo_session 'replace with priority' <>> todo.sh replace 1 "collect the bread" 74 | 1 (A) collect the eggs 75 | TODO: Replaced task with: 76 | 1 (A) collect the bread 77 | 78 | >>> todo.sh replace 1 collect the eggs 79 | 1 (A) collect the bread 80 | TODO: Replaced task with: 81 | 1 (A) collect the eggs 82 | EOF 83 | 84 | echo 'jump on hay' > todo.txt 85 | test_todo_session 'replace with &' <>> todo.sh replace 1 "thrash the hay & thrash the wheat" 87 | 1 jump on hay 88 | TODO: Replaced task with: 89 | 1 thrash the hay & thrash the wheat 90 | EOF 91 | 92 | echo 'jump on hay' > todo.txt 93 | test_todo_session 'replace with spaces' <>> todo.sh replace 1 "notice the three spaces" 95 | 1 jump on hay 96 | TODO: Replaced task with: 97 | 1 notice the three spaces 98 | EOF 99 | 100 | cat > todo.txt <>> todo.sh replace 1 "~@#$%^&*()-_=+[{]}|;:',<.>/?" 108 | 1 smell the cows 109 | TODO: Replaced task with: 110 | 1 ~@#$%^&*()-_=+[{]}|;:',<.>/? 111 | 112 | >>> todo.sh replace 2 '\`!\\"' 113 | 2 grow some corn 114 | TODO: Replaced task with: 115 | 2 \`!\\" 116 | 117 | >>> todo.sh list 118 | 4 chase the chickens 119 | 3 thrash some hay 120 | 2 \`!\\" 121 | 1 ~@#$%^&*()-_=+[{]}|;:',<.>/? 122 | -- 123 | TODO: 4 of 4 tasks shown 124 | EOF 125 | 126 | cat /dev/null > todo.txt 127 | test_todo_session 'replace handling prepended date on add' <>> todo.sh -t add "new task" 129 | 1 2009-02-13 new task 130 | TODO: 1 added. 131 | 132 | >>> todo.sh replace 1 this is just a new one 133 | 1 2009-02-13 new task 134 | TODO: Replaced task with: 135 | 1 2009-02-13 this is just a new one 136 | 137 | >>> todo.sh replace 1 2010-07-04 this also has a new date 138 | 1 2009-02-13 this is just a new one 139 | TODO: Replaced task with: 140 | 1 2010-07-04 this also has a new date 141 | EOF 142 | 143 | cat /dev/null > todo.txt 144 | test_todo_session 'replace handling prepended priority on add' <>> todo.sh -t add "new task" 146 | 1 2009-02-13 new task 147 | TODO: 1 added. 148 | 149 | >>> todo.sh replace 1 '(B) this also has a priority now' 150 | 1 2009-02-13 new task 151 | TODO: Replaced task with: 152 | 1 (B) 2009-02-13 this also has a priority now 153 | EOF 154 | 155 | cat /dev/null > todo.txt 156 | test_todo_session 'replace handling priority and prepended date on add' <>> todo.sh -t add "new task" 158 | 1 2009-02-13 new task 159 | TODO: 1 added. 160 | 161 | >>> todo.sh pri 1 A 162 | 1 (A) 2009-02-13 new task 163 | TODO: 1 prioritized (A). 164 | 165 | >>> todo.sh replace 1 this is just a new one 166 | 1 (A) 2009-02-13 new task 167 | TODO: Replaced task with: 168 | 1 (A) 2009-02-13 this is just a new one 169 | EOF 170 | 171 | cat /dev/null > todo.txt 172 | test_todo_session 'replace handling prepended priority and date on add' <>> todo.sh -t add "new task" 174 | 1 2009-02-13 new task 175 | TODO: 1 added. 176 | 177 | >>> todo.sh replace 1 '(C) 2010-07-04 this also has a priority and new date' 178 | 1 2009-02-13 new task 179 | TODO: Replaced task with: 180 | 1 (C) 2010-07-04 this also has a priority and new date 181 | EOF 182 | 183 | echo '(A) 2009-02-13 this is just a new one' > todo.txt 184 | test_todo_session 'replace with prepended date replaces existing date' <>> todo.sh replace 1 2010-07-04 this also has a new date 186 | 1 (A) 2009-02-13 this is just a new one 187 | TODO: Replaced task with: 188 | 1 (A) 2010-07-04 this also has a new date 189 | EOF 190 | 191 | echo '(A) 2009-02-13 this is just a new one' > todo.txt 192 | test_todo_session 'replace with prepended priority replaces existing priority' <>> todo.sh replace 1 '(B) this also has a new priority' 194 | 1 (A) 2009-02-13 this is just a new one 195 | TODO: Replaced task with: 196 | 1 (B) 2009-02-13 this also has a new priority 197 | EOF 198 | 199 | echo '2009-02-13 this is just a new one' > todo.txt 200 | test_todo_session 'replace with prepended priority and date replaces existing date' <>> todo.sh replace 1 '(B) 2010-07-04 this also has a new date' 202 | 1 2009-02-13 this is just a new one 203 | TODO: Replaced task with: 204 | 1 (B) 2010-07-04 this also has a new date 205 | EOF 206 | 207 | 208 | echo '(A) 2009-02-13 this is just a new one' > todo.txt 209 | test_todo_session 'replace with prepended priority and date replaces existing priority and date' <>> todo.sh replace 1 '(B) 2010-07-04 this also has a new prio+date' 211 | 1 (A) 2009-02-13 this is just a new one 212 | TODO: Replaced task with: 213 | 1 (B) 2010-07-04 this also has a new prio+date 214 | EOF 215 | 216 | test_done 217 | -------------------------------------------------------------------------------- /todo_completion: -------------------------------------------------------------------------------- 1 | # bash completion for todo.txt-cli 2 | 3 | # Check for bash 4 | [ -z "$BASH_VERSION" ] && return 5 | 6 | _todo() 7 | { 8 | local cur prev opts 9 | COMPREPLY=() 10 | cur="${COMP_WORDS[COMP_CWORD]}" 11 | prev="${COMP_WORDS[COMP_CWORD-1]}" 12 | 13 | local -r OPTS="-@ -@@ -+ -++ -d -f -h -p -P -PP -a -n -t -v -vv -V -x" 14 | local -r COMMANDS="\ 15 | add a addto addm append app archive command del \ 16 | rm depri dp do help list ls listaddons listall lsa listcon \ 17 | lsc listfile lf listpri lsp listproj lsprj move \ 18 | mv prepend prep pri p replace report shorthelp" 19 | local -r MOVE_COMMAND_PATTERN='move|mv' 20 | 21 | local _todo_sh=${_todo_sh:-${COMP_WORDS[0]}} 22 | local completions 23 | if [ "$COMP_CWORD" -eq 1 ]; then 24 | completions="$COMMANDS $(eval TODOTXT_VERBOSE=0 "$_todo_sh" command listaddons 2>/dev/null) $OPTS" 25 | elif [[ $COMP_CWORD -gt 2 && ( \ 26 | "${COMP_WORDS[COMP_CWORD-2]}" =~ ^($MOVE_COMMAND_PATTERN${_todo_file2_actions:+|${_todo_file2_actions}})$ || \ 27 | "${COMP_WORDS[COMP_CWORD-3]}" =~ ^($MOVE_COMMAND_PATTERN${_todo_file3_actions:+|${_todo_file3_actions}})$ ) ]]; then 28 | # "move NR DEST [SRC]" has file arguments on positions 2 and 3. 29 | completions=$(eval TODOTXT_VERBOSE=0 $_todo_sh command listfile 2>/dev/null) 30 | else 31 | case "$prev" in 32 | command) 33 | completions=$COMMANDS;; 34 | help) 35 | completions="$COMMANDS $(eval TODOTXT_VERBOSE=0 "$_todo_sh" command listaddons 2>/dev/null)";; 36 | -*) completions="$COMMANDS $(eval TODOTXT_VERBOSE=0 "$_todo_sh" command listaddons 2>/dev/null) $OPTS";; 37 | *) if [[ "$prev" =~ ^(addto|listfile|lf${_todo_file1_actions:+|${_todo_file1_actions}})$ ]]; then 38 | completions=$(eval TODOTXT_VERBOSE=0 "$_todo_sh" command listfile 2>/dev/null) 39 | else 40 | case "$cur" in 41 | +*) completions=$(eval TODOTXT_VERBOSE=0 "$_todo_sh" command listproj 2>/dev/null) 42 | COMPREPLY=( $(compgen -W "$completions" -- "$cur")) 43 | [ ${#COMPREPLY[@]} -gt 0 ] && return 0 44 | # Fall back to projects extracted from done tasks. 45 | completions=$(eval 'TODOTXT_VERBOSE=0 TODOTXT_SOURCEVAR=\$DONE_FILE' "$_todo_sh" command listproj 2>/dev/null) 46 | ;; 47 | @*) completions=$(eval TODOTXT_VERBOSE=0 "$_todo_sh" command listcon 2>/dev/null) 48 | COMPREPLY=( $(compgen -W "$completions" -- "$cur")) 49 | [ ${#COMPREPLY[@]} -gt 0 ] && return 0 50 | # Fall back to contexts extracted from done tasks. 51 | completions=$(eval 'TODOTXT_VERBOSE=0 TODOTXT_SOURCEVAR=\$DONE_FILE' "$_todo_sh" command listcon 2>/dev/null) 52 | ;; 53 | *) if [[ "$cur" =~ ^[0-9]+$ ]]; then 54 | declare -a sedTransformations=( 55 | # Remove the (padded) task number; we prepend the 56 | # user-provided $cur instead. 57 | -e 's/^ *[0-9]\{1,\} //' 58 | # Remove the timestamp prepended by the -t option, 59 | # but keep any priority (as it's short and may 60 | # provide useful context). 61 | -e 's/^\((.) \)\{0,1\}[0-9]\{2,4\}-[0-9]\{2\}-[0-9]\{2\} /\1/' 62 | # Remove the done date and (if there) the timestamp. 63 | # Keep the "x" (as it's short and may provide useful 64 | # context) 65 | -e 's/^\([xX] \)\([0-9]\{2,4\}-[0-9]\{2\}-[0-9]\{2\} \)\{1,2\}/\1/' 66 | # Remove any trailing whitespace; the Bash 67 | # completion inserts a trailing space itself. 68 | -e 's/[[:space:]]*$//' 69 | # Finally, limit the output to a single line just as 70 | # a safety check of the ls action output. 71 | -e '1q' 72 | ) 73 | local todo 74 | todo=$( \ 75 | eval TODOTXT_VERBOSE=0 "$_todo_sh" '-@ -+ -p -x command ls "^ *${cur} "' 2>/dev/null | \ 76 | sed "${sedTransformations[@]}" \ 77 | ) 78 | # Append task text as a shell comment. This 79 | # completion can be a safety check before a 80 | # destructive todo.txt operation. 81 | [ -n "$todo" ] && COMPREPLY[0]="$cur # $todo" 82 | return 0 83 | else 84 | return 0 85 | fi 86 | ;; 87 | esac 88 | fi 89 | ;; 90 | esac 91 | fi 92 | 93 | COMPREPLY=( $(compgen -W "$completions" -- "$cur")) 94 | return 0 95 | } 96 | complete -F _todo todo.sh 97 | 98 | # If you define an alias (e.g. "t") to todo.sh, you need to explicitly enable 99 | # completion for it, too: 100 | #complete -F _todo t 101 | # It is recommended to put this line next to your alias definition in your 102 | # ~/.bashrc (or wherever else you're defining your alias). If you simply 103 | # uncomment it here, you will need to redo this on every todo.txt update! 104 | 105 | # The completion uses the alias itself, so any custom arguments (like a custom 106 | # configuration (-d "$HOME/todo2.cfg")) are used there as well. 107 | # If you don't want this, or need to further tweak the todo.sh command that's 108 | # used by the completion, you can add and use a wrapper completion function that 109 | # redefines _todo_sh before invoking _todo(): 110 | #_todo_tweak() 111 | #{ 112 | # local _todo_sh='todo.sh -d "$HOME/todo-tweaked.cfg"' 113 | # _todo "$@" 114 | #} 115 | #complete -F _todo_tweak todo.sh 116 | -------------------------------------------------------------------------------- /tests/t1330-ls-highlighting.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | test_description='list highlighting 4 | 5 | This test checks the highlighting (with colors) of prioritized tasks. 6 | ' 7 | . ./test-lib.sh 8 | 9 | TEST_TODO_=todo.cfg 10 | 11 | # 12 | # check the highlighting of prioritized tasks 13 | # 14 | cat > todo.txt <>> todo.sh ls 26 | 1 (A) @con01 +prj01 -- Some project 01 task, pri A 27 | 2 (B) @con02 +prj02 -- Some project 02 task, pri B 28 | 3 (C) @con01 +prj01 -- Some project 01 task, pri C 29 | 4 (D) @con02 +prj02 -- Some project 02 task, pri D 30 | 5 (E) @con01 +prj01 -- Some project 01 task, pri E 31 | 6 (Z) @con02 +prj02 -- Some project 02 task, pri Z 32 | 7 @con01 +prj01 -- Some project 01 task, no priority 33 | 8 @con02 +prj02 -- Some project 02 task, no priority 34 | -- 35 | TODO: 8 of 8 tasks shown 36 | EOF 37 | 38 | # 39 | # check changing the color definitions into something other than ANSI color 40 | # escape sequences 41 | # 42 | TEST_TODO_CUSTOM=todo-custom.cfg 43 | cat todo.cfg > "$TEST_TODO_CUSTOM" 44 | cat >> "$TEST_TODO_CUSTOM" <<'EOF' 45 | export YELLOW='${color yellow}' 46 | export GREEN='${color green}' 47 | export LIGHT_BLUE='${color LightBlue}' 48 | export WHITE='${color white}' 49 | export DEFAULT='${color}' 50 | export PRI_A=$YELLOW 51 | export PRI_B=$GREEN 52 | export PRI_C=$LIGHT_BLUE 53 | export PRI_X=$WHITE 54 | EOF 55 | test_todo_session 'customized highlighting' <<'EOF' 56 | >>> todo.sh -d "$TEST_TODO_CUSTOM" ls 57 | ${color yellow}1 (A) @con01 +prj01 -- Some project 01 task, pri A${color} 58 | ${color green}2 (B) @con02 +prj02 -- Some project 02 task, pri B${color} 59 | ${color LightBlue}3 (C) @con01 +prj01 -- Some project 01 task, pri C${color} 60 | ${color white}4 (D) @con02 +prj02 -- Some project 02 task, pri D${color} 61 | ${color white}5 (E) @con01 +prj01 -- Some project 01 task, pri E${color} 62 | ${color white}6 (Z) @con02 +prj02 -- Some project 02 task, pri Z${color} 63 | 7 @con01 +prj01 -- Some project 01 task, no priority 64 | 8 @con02 +prj02 -- Some project 02 task, no priority 65 | -- 66 | TODO: 8 of 8 tasks shown 67 | EOF 68 | 69 | # 70 | # check defining highlightings for more priorities than the default A, B, C 71 | # 72 | TEST_TODO_ADDITIONAL=todo-additional.cfg 73 | cat todo.cfg > "$TEST_TODO_ADDITIONAL" 74 | cat >> "$TEST_TODO_ADDITIONAL" <<'EOF' 75 | export PRI_E=$BROWN 76 | export PRI_Z=$LIGHT_PURPLE 77 | EOF 78 | test_todo_session 'additional highlighting pri E+Z' <<'EOF' 79 | >>> todo.sh -d "$TEST_TODO_ADDITIONAL" ls 80 | 1 (A) @con01 +prj01 -- Some project 01 task, pri A 81 | 2 (B) @con02 +prj02 -- Some project 02 task, pri B 82 | 3 (C) @con01 +prj01 -- Some project 01 task, pri C 83 | 4 (D) @con02 +prj02 -- Some project 02 task, pri D 84 | 5 (E) @con01 +prj01 -- Some project 01 task, pri E 85 | 6 (Z) @con02 +prj02 -- Some project 02 task, pri Z 86 | 7 @con01 +prj01 -- Some project 01 task, no priority 87 | 8 @con02 +prj02 -- Some project 02 task, no priority 88 | -- 89 | TODO: 8 of 8 tasks shown 90 | EOF 91 | 92 | # check changing the fallback highlighting for undefined priorities 93 | # 94 | TEST_TODO_PRI_X=todo-pri-x.cfg 95 | cat todo.cfg > "$TEST_TODO_PRI_X" 96 | cat >> "$TEST_TODO_PRI_X" <<'EOF' 97 | export PRI_X=$BROWN 98 | EOF 99 | test_todo_session 'different highlighting for pri X' <<'EOF' 100 | >>> todo.sh -d "$TEST_TODO_PRI_X" ls 101 | 1 (A) @con01 +prj01 -- Some project 01 task, pri A 102 | 2 (B) @con02 +prj02 -- Some project 02 task, pri B 103 | 3 (C) @con01 +prj01 -- Some project 01 task, pri C 104 | 4 (D) @con02 +prj02 -- Some project 02 task, pri D 105 | 5 (E) @con01 +prj01 -- Some project 01 task, pri E 106 | 6 (Z) @con02 +prj02 -- Some project 02 task, pri Z 107 | 7 @con01 +prj01 -- Some project 01 task, no priority 108 | 8 @con02 +prj02 -- Some project 02 task, no priority 109 | -- 110 | TODO: 8 of 8 tasks shown 111 | EOF 112 | 113 | # check highlighting of done (but not yet archived) tasks 114 | # 115 | cat > todo.txt <>> todo.sh -a do 2 124 | 2 x 2009-02-13 remove1 125 | TODO: 2 marked as done. 126 | 127 | >>> todo.sh list 128 | 1 (A) smell the uppercase Roses +flowers @outside 129 | 3 notice the sunflowers 130 | 4 remove2 131 | 5 stop 132 | 2 x 2009-02-13 remove1 133 | -- 134 | TODO: 5 of 5 tasks shown 135 | 136 | >>> todo.sh -a do 4 137 | 4 x 2009-02-13 remove2 138 | TODO: 4 marked as done. 139 | 140 | >>> todo.sh list 141 | 1 (A) smell the uppercase Roses +flowers @outside 142 | 3 notice the sunflowers 143 | 5 stop 144 | 2 x 2009-02-13 remove1 145 | 4 x 2009-02-13 remove2 146 | -- 147 | TODO: 5 of 5 tasks shown 148 | EOF 149 | 150 | # check highlighting with hidden contexts/projects 151 | # 152 | cat > todo.txt <