Compare commits

..

47 Commits

Author SHA1 Message Date
Florian Tham
e6d80bac04 merge upstream/master 2024-02-29 15:07:09 +01:00
Edwin Kofler
fd753c6c2e style: Fix typo in pull request template (#420) 2023-08-16 14:09:15 -05:00
Ingo Karkat
c8fa5f1ebc Fix failing MacOS 11 tests and remove obsolete build platforms
Integrated via #415

Merge branch 'chrysle:fix-macos-11-tests'
2023-06-30 17:10:37 +02:00
Ingo Karkat
aa38153586 Housekeeping: Remove obsolete build platforms
GitHub runners for Ubuntu 18.04 and MacOS 10.15 are not available any longer.
2023-06-30 16:59:44 +02:00
chrysle
b10904bb20 Remove hacks 2023-06-30 15:11:44 +02:00
chrysle
ef5b71496d Fix macOS tests 2023-06-30 15:05:39 +02:00
Ali Karbassi
ea32af34e6 Updated GitHub Actions Environments (#372)
Rather than `*-latest`, I'm specifying specific environments.
2021-12-02 15:49:42 -06:00
Lawrence Liu
d0075e4d57 Different folder to copy ~/.todo.cfg for macOS on arm/x86 CPU (#369) 2021-11-19 07:48:16 -06:00
a1346054
2d70a0aadf Minor fixes identified through shellcheck and other tools (#350)
* fix whitespace

* fix spelling

* fix whitespace

* unify headers of tests

* fix some issues in tests, identified by shellcheck

* fix bash completions

bash completion files are not supposed to be executable

* fix some issues identified by shellcheck

Co-authored-by: Ali Karbassi <ali@karbassi.com>
2021-08-09 15:03:49 -05:00
Ingo Karkat
ee94a3fac5 Return from user prompt without requiring Enter (#354)
* Tests: Add coverage for del / move without -f, but with prompting

Supplying the user confirmation via "yes".

* Cosmetics: Align inconsistent spacing for before (y/n) prompt

* Refactoring: Extract confirm() function

The user confirmation query had been duplicated (once) in the code.

* Refactoring: confirm(): Leave early if forced

* Return from user prompt without requiring Enter

By just reading a single character (y for yes, anything else: no).



* Tests: Ensure that only a single "y" concludes the confirmation

By switching from "yes" (that endlessly prints newline-separated "y"s) to "printf y".

* t1800-del: Add coverage for negative confirmation

Negative means "anything but y", so "n", "x", and Enter all apply.

* Cosmetics: Add trailing space after (y/n) prompt

So that the user's typed answer is not recorded directly after it, but with separation: "Foo? (y/n) y" instead of "Foo? (y/n)y".

*Compatibility: "read -N 1" is only available in Bash 4.1+

Mac OS still ships with Bash 3.2 :-( Fall back to the original prompting that requires conclusion via Enter then.
Note: Even though the tests use "printf y", this still gets accepted, as there'll be EOF after that. In real use (when stdin from the terminal stays open), a concluding Enter is mandatory, though.

Closes #152
2021-08-06 15:05:11 -05:00
Keith
587833bb4e Default to user writable directory in config (#148)
When a user installs from a package manager (MacPorts, Homebrew, `yum`, etc.), the `todo.sh` script is installed into a restricted folder.  This means that the result of `$(basename "$0")` is a directory where the user cannot write without elevated permissions.  This generates additional noise when the user first runs `todo.sh -h`.  An alternative is to default to the user's personal directory which is known to exist and will be writable by the user.
2021-08-06 09:14:25 -05:00
Tim
eb7feaefb5 Fix problem with spaces in directory path (#276)
If the current directory had spaces in the directory path, this script would fail.
That has been fixed by appropriate use of quotes.

Co-authored-by: Tim Learmont <learmont@NocturnalAviation.com>
Co-authored-by: Ali Karbassi <ali@karbassi.com>
2021-08-03 18:11:27 -05:00
Wallysson
7501d37b45 use builtin "command -v" instead of which (#308) 2021-08-03 18:10:28 -05:00
Ingo Karkat
6ea2b5ae6d Mention all (also XDG) config file locations in help for -d (#343)
* Refactoring: Replace serial checks for `TODOTXT_CFG_FILE` and `TODO_ACTIONS_DIR` with loops

Two fallbacks (like for the actions dir) may still be fine, but we're now supporting so many config locations that a loop is much shorter, and the various locations are much easier to see.

For consistency, also apply this to the actions dir lookup, although it's less of a problem there.

* Refactoring: Apply the first default for `TODOTXT_CFG_FILE` also in the loop

There's no need to handle this separately; either an exported environment variable already exists, or it got assigned via `-d CONFIG_FILE`, or the `test -e` will fail on an empty (or bad non-existing) value, and we enter the fallback loop.

* Mention the actual config file locations in the help for `-d`

Extract the list of default locations into a `configFileLocations` array and join that into a string that then gets interpolated into the help output for `-d` (that so far only mentioned the first default location).

* Comments: Don't favor a single config location in the requirement

* Documentation: Mention `~/.todo/config` as just one of the defaults

As there are several others, now shown in the help for `-d`.

I don't want to duplicate the entire list here, as there's a high risk of those lists diverging.

Fixes #342
2021-08-03 18:06:10 -05:00
Paul Mansfield
353db49814 Allow multiple priorities on single run (#346)
Uses current priority logic and option tests just running multiple times until item and priority pairs are exhausted or stops on first error.

Tests for multiple priorities, multiple re-prioritization and a couple of errors.
2021-08-03 18:03:20 -05:00
Ingo Karkat
f884f73297 TESTSFIX: t0000-config.sh may unintentionally pick up existing user config in $XDG_CONFIG_HOME/todo/config (#349)
* TESTSFIX: t0000-config.sh may unintentionally pick up existing user config in `$XDG_CONFIG_HOME/todo/config`

This corner case was missed when the XDG alternative config location was introduced, likely because the variable isn't set by default on Ubuntu or Mac OS, and none of the developers had a config there.

HOME is already redirected to the current working directory; as `XDG_CONFIG_HOME` is just a config alternative that has a fallback to `$HOME/.config`, simply unset it.

Fixes #347

* TESTSFIX: User add-ons that override built-in actions may break tests

If `TODO_ACTIONS_DIR` is already defined, the defaulting in todo.sh are skipped. The user may have custom add-ons that override built-in actions; any incompatible behavior would negatively affect the tests then.

By setting the variable to the first default location, we avoid this interference.
2021-08-03 17:57:31 -05:00
Ali Karbassi
e4103a8e23 Add Ubuntu 18 to tests (#351) 2021-08-03 17:53:35 -05:00
Ingo Karkat
77c1f34609 Documentation: Clarify basic regexp syntax of TERM in todo.sh list (#335)
* Documentation: Clarify basic regexp syntax of TERM in todo.sh list

And give hints about escaping.
Issue raised by https://github.com/todotxt/todo.txt-cli/discussions/334

* Documentation: Correct quoting in todo.sh help list

Though the double quoting doesn't do harm when the single backslash is followed by the | character (\| is no valid escape sequence), it's technically more correct to use single quotes, and also is more in line with the quoting advice given directly below it.
2021-03-13 13:32:40 -06:00
Ali Karbassi
71b3991daf Gitter chat to Github Discussions 2020-12-11 13:07:11 -06:00
Tyler Szabo
6188785e48 Fix tests on Debian (#326)
Corrected an additional regex to match tags on mawk 1.3.3 in Debian
2020-12-04 15:32:53 -06:00
Daniel M
797604e2b6 Fixed tests on ubuntu #317 (#322)
Tests failed on Ubuntu due to regular expression - corrected regex and now it works.
2020-11-20 20:33:06 -06:00
Oleg Zaytsev
7bac9d861b s/GREY/GRAY/ in todo.cfg (#320)
`GRAY` is the spelling used in every other place in this repository.
2020-10-22 00:36:05 -05:00
Ali Karbassi
ae1f241887 Update zip file creation to use native zip command. (#319)
Fixes #318
2020-09-10 13:12:04 -05:00
Ali Karbassi
7f3ad0d361 Update changelog. Tag v2.12.0 2020-08-11 23:36:30 -05:00
Ali Karbassi
ce38bea819 Add note in README to copy config file (#316)
Fixes #252 (by adding a note to README)
2020-08-11 23:03:05 -05:00
Jonas Stehli
da45b0f637 Change Arch Linux AUR link (#310)
there is a second version that is much more popular, why not link that one?
2020-06-09 17:05:06 -05:00
Luilver
ddc560c6b9 Fix #306 (#307) 2020-05-25 10:41:09 -05:00
Ingo Karkat
bf1bf1ae84 ENH: Allow to customize what can be before / inside / after +project and @context (#271)
* ENH: Allow to customize what can be before / inside / after +project and @context

I noticed that todo.sh mistakenly picks up some random stuff as projects and contexts. The todo.txt specification is very lenient in what makes those (allowing any length of non-whitespace characters), but in practice, every user has its own idea of the set of used words. This change allows (expert) users to tweak the pattern (via TODOTXT_SIGIL_VALID_PATTERN), to be able to reduce the amount of "false positives" that listproj and listcon show.
Additionally, there's a (mainly unspecified) extension mechanism in the form of key:value, which often is used to implement custom "markers", like w:something to make a task blocked and waiting for "something". It would be nice to be able to refer to @contexts (and maybe also +projects), but the default syntax (which requires whitespace around those) doesn't allow it, and these context then don't show up in searches, which is unfortunate. The added TODOTXT_SIGIL_BEFORE_PATTERN and TODOTXT_SIGIL_AFTER_PATTERN allow to tweak the syntax to accommodate this.
The implementation just exchanges grep with a corresponding sed pipeline step, which shouldn't negatively affect the performance at all (as sed is one of the main commands used thoughout the script), but which allows for the additional matching flexibility.

* FIX: Compatibility: sed \? multi not supported on MacOS

Use the POSIX \{0,1\} instead.

* FIX: Compatibility: sed \| multi not supported on MacOS

Concatenate both alternatives as optional matches; this is only an approximation but satisfies the test case here. It would probably be better if the entire sed code used extended regular expression syntax (-E) instead of basic ones (-e), but that change would also affect all add-ons. As this is an optional customization feature, uses who really need this either also have to work around, or supply a GNU sed port on MacOS.

* FIX: Compatibility: sed \+ multi not supported on MacOS

Use the POSIX \{1,\} instead.

Co-authored-by: Ali Karbassi <ali@karbassi.com>
2020-03-30 18:13:29 -05:00
Ingo Karkat
177432ec94 ENH: Enable file completion for add-on actions via _todo_file{1,2,3}_actions (#270)
* Refactoring: Use regular expression match instead of case globbing for actions taking a SRC argument

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

* Refactoring: Move the anchoring and grouping out of MOVE_COMMAND_PATTERN

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

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

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

In order to configure the add-on completion, the corresponding configuration variable has to be defined in the user's shell (e.g. via ~/.bashrc):
_todo_file1_actions='myaction|anotheraction'
2020-03-30 17:44:50 -05:00
Ali Karbassi
abdbe5371c Clean up files (#302) 2020-03-29 21:26:56 -05:00
Ali Karbassi
1378c97d80 Allow setting of bash completion path (#301)
Fixes #242
2020-03-29 14:53:42 -05:00
85
3d308a6f79 Minimal config file / default filenames (todo.txt, done.txt, report.txt) (#289)
* Set default files name

* Add test for minimal config file
2020-03-29 14:33:16 -05:00
LeLobster
c6d290b5fb Fix the Makefile to work with the install instructions in the README (#259)
* Fix the Makefile to work with the install instructions in the README

* Put back DEST_DIR

* Add simple ifdef checks to see if the user has set custom dirs via the commandline

* Update README to match Makefile
2020-03-29 14:29:40 -05:00
Tiziano Zito
355166da67 Highlighting of dates, metadata and item numbers (#264)
* add highlighting of dates, item numbers, and metadata

* add test for highlighting of dates, item numbers, and metadata

Co-authored-by: Ali Karbassi <ali@karbassi.com>
2020-03-29 14:20:06 -05:00
Ingo Karkat
20317b6321 Refactoring: Extract the many complex sed arguments into sedTransformations array and move the comments closer (#273)
There's too much distance between the comments that describe the various transformations that are done on the referenced task, and the corresponding sed expressions.
By using a local Bash array, we can collect the arguments and have the comments close by.

Co-authored-by: Ali Karbassi <ali@karbassi.com>
2020-03-29 12:27:25 -05:00
Ingo Karkat
861ad5ec41 Fix/noeol (#295)
* Handle missing EOL in todo.txt

This can happen easily with certain editors (such as Mousepad) that do not automatically add a newline character at the end of a file.
In _addto(), ensure a trailing newline via sed (taken from https://unix.stackexchange.com/a/31955/18876).

Fixes #294

* Tests: Add basic coverage of move

* Handle missing EOL in todo.txt for move, too

This can happen easily with certain editors (such as Mousepad) that do not automatically add a newline character at the end of a file.

* Refactoring: Extract fixMissingEndOfLine()

* FIX: Compatibility: sed \+ multi not supported on MacOS

Use the POSIX \{1,\} instead.

Co-authored-by: Ali Karbassi <ali@karbassi.com>
2020-03-29 12:03:33 -05:00
Ali Karbassi
13b451b81d Add support for macOS catalina date (#300)
Co-authored-by: Benoit Sagols <benoit.sagols@gmail.com>
2020-03-29 10:27:43 -05:00
Ali Karbassi
34d31ef45a Fix macOS 10.15 date test (#299)
- In macOS 10.15, the `date` command adds a "-R" flag. This can be seen in the default error display. Since the flags have changed, the grep command to find which version of macOS date binary we have. Because of this change, we need to do our own check for macOS 10.15.

- Remove windows from the github actions as this tool is not for Windows, currently.
2020-03-27 21:32:29 -05:00
Ali Karbassi
8901db8bdd Add multiple environments (#298) 2020-03-27 20:13:02 -05:00
Ali Karbassi
c9540122e6 Create GitHub action to run tests (#296)
* Create GitHub Action
* Remove travis yml to move to github actions.
* Update CI badge in README
2020-03-27 19:44:45 -05:00
Florian Tham
19dde076cf remove accidentally commited swap file 2018-11-06 11:08:01 +01:00
Florian Tham
3bc3616651 optionally colorized date extensions (due, threshold and again) 2018-11-06 10:58:18 +01:00
kh80
d589fd0570 Add 'done' option as alias of 'do' (#169) 2018-04-11 13:34:19 -05:00
tpikonen
7a30199fe0 Cleanup (#247)
- Fixed: Reduce shellcheck warnings.
- Fixed: Remove trailing whitespace.
- Fixed: Double quote to prevent globbing and word splitting. [SC2086]
- Fixed: Invalid flags are not handled. [SC2220]
- Fixed: Cleaned up string replaces.
2018-04-04 19:33:09 -05:00
tpikonen
867ade5701 new: Add default priority variable TODOTXT_PRIORITY_ON_ADD. (#246)
Adds the config / env variable `TODOTXT_PRIORITY_ON_ADD`, which when set to one of the capital letters `A` to `Z` is given as a priority to a new task, if a priority is not given on command line.
2018-03-28 16:58:48 -05:00
Anton Ermolenko
14f5de1579 interpreter reference update to be portable (#160) 2018-03-28 16:09:07 -05:00
Guilherme Reis
7ec2a1263e Read the task's name and uses as default (#249)
Read the task's name and uses as default, so the user can read the previous task's name.

Thanks @guifeliper
2018-03-26 13:23:27 -05:00
51 changed files with 1002 additions and 434 deletions

View File

@@ -93,5 +93,5 @@ The core team looks at Pull Requests on a regular basis. After feedback has been
You can chat with the core team on https://gitter.im/todotxt/. You can chat with the core team on https://gitter.im/todotxt/.
[todo.txt]: https://github.com/todotxt/ [todo.txt]: https://github.com/todotxt/
[Code of Conduct]: /CODE_OF_CONDUCT.md [Code of Conduct]: ./CODE_OF_CONDUCT.md
[Gitter.im]: https://gitter.im/todotxt/ [Gitter.im]: https://gitter.im/todotxt/

View File

@@ -3,7 +3,7 @@
- [ ] Fork [the repository](https://github.com/todotxt/todo.txt-cli) and create your branch from `master`. - [ ] Fork [the repository](https://github.com/todotxt/todo.txt-cli) and create your branch from `master`.
- [ ] If you've added code that should be tested, add tests! - [ ] If you've added code that should be tested, add tests!
- [ ] Ensure the test suite passes. - [ ] Ensure the test suite passes.
- [ ] Format your code with [ShellCheck](https://www.shellcheck.net/). - [ ] Lint your code with [ShellCheck](https://www.shellcheck.net/).
- [ ] Include a human-readable description of what the pull request is trying to accomplish. - [ ] Include a human-readable description of what the pull request is trying to accomplish.
- [ ] Steps for the reviewer(s) on how they can manually QA the changes. - [ ] Steps for the reviewer(s) on how they can manually QA the changes.
- [ ] Have a `fixes #XX` reference to the issue that this pull request fixes. - [ ] Have a `fixes #XX` reference to the issue that this pull request fixes.

20
.github/workflows/tests.yml vendored Normal file
View File

@@ -0,0 +1,20 @@
name: CI
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
test:
strategy:
matrix:
platform: [ubuntu-20.04, macos-11]
runs-on: ${{ matrix.platform }}
steps:
- uses: actions/checkout@v2
- run: make
- run: make dist
- run: make test

View File

@@ -1,6 +0,0 @@
# Note: "shell" would be more appropriate
language: python
install: make dist && sudo make install
script: make test

View File

@@ -1,4 +1,5 @@
# Changelog # Changelog
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
@@ -6,14 +7,38 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
## [Unreleased] ## [Unreleased]
## [2.11.0] - 2018-03-26 ## [2.12.0] - 2020-08-11
### Added
- Added support for `$XDG_CONFIG_HOME` config file/actions location
- Created [CODE_OF_CONDUCT.md](/CODE_OF_CONDUCT.md) ([#217])
- Created [CHANGELOG.md](/CHANGELOG.md) ([#218])
### Added
- Added default priority variable `TODOTXT_PRIORITY_ON_ADD` ([#246])
- Added `done` option as alias of `do` ([#169])
- Added macOS 10.15.x support ([#300])
- Highlighting of dates, metadata and item numbers ([#264])
- Minimal config file / default filenames (todo.txt, done.txt, report.txt) ([#289])
- Enable file completion for add-on actions via `_todo_file{1,2,3}_actions` ([#270])
- Allow to customize what can be before / inside / after `+project` and `@context` ([#271])
### Changed ### Changed
- Read the task's name and uses as default ([#249])
- Updated interpreter reference to use environment variable ([#160])
- Allow setting of bash completion path ([#301])
### Fixes
- Fixed no end-of-line bug. Supports todos with no end-of-line. ([#295])
## [2.11.0] - 2018-03-26
### Added
- Added support for `$XDG_CONFIG_HOME` config file/actions location
- Created [CODE_OF_CONDUCT.md](.github/CODE_OF_CONDUCT.md) ([#217])
- Created [CHANGELOG.md](/CHANGELOG.md) ([#218])
### Changed
- Updated `add` command to accept lowercase priority ([#230]) - Updated `add` command to accept lowercase priority ([#230])
- Clean tests and version file in Makefile. Don't ignore errors in tests. - Clean tests and version file in Makefile. Don't ignore errors in tests.
- Updated [README.md](/README.md) ([#219]) - Updated [README.md](/README.md) ([#219])
@@ -21,12 +46,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Set the executable bit when preparing releases ([#156]) - Set the executable bit when preparing releases ([#156])
### Fixes ### Fixes
- Update links to use https - Update links to use https
- Suppress todo.sh error messages when invoked during completion ([#8]) - Suppress todo.sh error messages when invoked during completion ([#8])
## [2.10.0] - 2013-12-06 ## [2.10.0] - 2013-12-06
### Added ### Added
- Enable term filtering for listcon. - Enable term filtering for listcon.
- Add make install command. - Add make install command.
- Enable use of global config file in `/etc/todo/config`. `make install` installs a global config file. - Enable use of global config file in `/etc/todo/config`. `make install` installs a global config file.
@@ -39,30 +66,37 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Place add-ons in subfolders (for easier git clone). - Place add-ons in subfolders (for easier git clone).
### Changed ### Changed
- Improve code commenting/documentation. - Improve code commenting/documentation.
- Refactor code for speed/better organization. - Refactor code for speed/better organization.
- Improve test coverage and test library. - Improve test coverage and test library.
### Removed ### Removed
- Removed add date from line completion, ie, `todo.sh ls 10[tab]`. - Removed add date from line completion, ie, `todo.sh ls 10[tab]`.
### Fixed ### Fixed
- Properly replace date when replacing task with priority and date. - Properly replace date when replacing task with priority and date.
- Handle `-h`, `shorthelp`, and `help` when a Fatal Error happens. - Handle `-h`, `shorthelp`, and `help` when a Fatal Error happens.
- Fix `todo_completion` problem with Bash 3.1. - Fix `todo_completion` problem with Bash 3.1.
## [2.9.0] - 2012-04-08 ## [2.9.0] - 2012-04-08
### Added ### Added
- Added tab auto-completion of projects and contexts from `todo.txt` and `done.txt`. Type `@<Tab>` or `+<Tab>` while entering a task. - Added tab auto-completion of projects and contexts from `todo.txt` and `done.txt`. Type `@<Tab>` or `+<Tab>` while entering a task.
- Added new listaddons command displays installed addons. - Added new listaddons command displays installed addons.
- List priorities within a range using listpri. For example, to see tasks prioritized A-B, use `todo.sh listpri A-B` - List priorities within a range using listpri. For example, to see tasks prioritized A-B, use `todo.sh listpri A-B`
### Fixed ### Fixed
- Fixed various cosmetic issues, bugs, and added developer test library enhancements. - Fixed various cosmetic issues, bugs, and added developer test library enhancements.
## [2.8.0] - 2011-09-13 ## [2.8.0] - 2011-09-13
### Added ### Added
- `listpri`/`lsp` now filters by term. For example, `todo.sh lsp A book` will only return tasks prioritized `A` with the word book in them. - `listpri`/`lsp` now filters by term. For example, `todo.sh lsp A book` will only return tasks prioritized `A` with the word book in them.
- Added support for todo directory paths with spaces in them. - Added support for todo directory paths with spaces in them.
- Tasks with priority included and auto prepend date on (`-t`) get the date where expected. - Tasks with priority included and auto prepend date on (`-t`) get the date where expected.
@@ -70,6 +104,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Made more parameters available to offer more control to custom actions (`-c`, `-A`, `-N`, `-T`) - Made more parameters available to offer more control to custom actions (`-c`, `-A`, `-N`, `-T`)
### Changed ### Changed
- Improved portability for Dropbox or USB key users. If not specified, todo.sh checks for a config file in its own directory; default todo.txt location is todo.sh's directory. - Improved portability for Dropbox or USB key users. If not specified, todo.sh checks for a config file in its own directory; default todo.txt location is todo.sh's directory.
- Improved script performance thanks to optimized code - Improved script performance thanks to optimized code
- Exposed `cleaninput()` for use in addons - Exposed `cleaninput()` for use in addons
@@ -80,6 +115,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Cleaner, simpler, modernized, optimized code - Cleaner, simpler, modernized, optimized code
### Fixed ### Fixed
- Custom action output no longer prefaced by `TODO:` so it's easier to see when the core script vs. addon is performing an action - Custom action output no longer prefaced by `TODO:` so it's easier to see when the core script vs. addon is performing an action
- `listpri` complains if specified priority is invalid - `listpri` complains if specified priority is invalid
- Don't abort task listing when items contain certain escape sequences (`\c \033`) - Don't abort task listing when items contain certain escape sequences (`\c \033`)
@@ -87,31 +123,37 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Don't delete `|` (pipe) from task input - Don't delete `|` (pipe) from task input
- `-+` and `-@` no longer break task coloring if context or project appears at the end of the line - `-+` and `-@` no longer break task coloring if context or project appears at the end of the line
## [2.7.0] - 2010-08-03 ## [2.7.0] - 2010-08-03
### Added ### Added
- Added generalization of the _PRI_X_ color support to all priorities - Added generalization of the _PRI_X_ color support to all priorities
- Added highlighting of done, but not yet archived tasks via *COLOR_DONE* - Added highlighting of done, but not yet archived tasks via _COLOR_DONE_
- Color map (BLACK, ...) now supports spaces in the color definitions, making it possible to override the default ANSI escape codes with e.g. Conky tags (`${color black}`) - Color map (BLACK, ...) now supports spaces in the color definitions, making it possible to override the default ANSI escape codes with e.g. Conky tags (`${color black}`)
### Changed ### Changed
- Cleanup: help messages, consistent output messages - Cleanup: help messages, consistent output messages
- Exporting `die()` function for use in custom commands - Exporting `die()` function for use in custom commands
- `prepend` and `replace` actions keep prepended date, `append` considers sentence delimiters - `prepend` and `replace` actions keep prepended date, `append` considers sentence delimiters
- Tests: several regression tests added - Tests: several regression tests added
## [2.6.0] - 2010-05-11 ## [2.6.0] - 2010-05-11
### Added ### Added
- Added a case for the fixed replace command. - Added a case for the fixed replace command.
### Changed ### Changed
- Changed odd tabs to spaces. - Changed odd tabs to spaces.
- Faster help/useage document outputs. - Faster help/usage document outputs.
- Consolidated `TODOTXT_VERBOSE` tests. - Consolidated `TODOTXT_VERBOSE` tests.
- Refactored various add functionality to one function. - Refactored various add functionality to one function.
- Updated `_list()` output to match updated `addto`. - Updated `_list()` output to match updated `addto`.
### Fixed ### Fixed
- Quoting regexp to parse properly. - Quoting regexp to parse properly.
- Fixed erroneous hide/show comments. - Fixed erroneous hide/show comments.
- Correctly fixed regexp quoting issue for bash v3.1.x and v3.2.x. - Correctly fixed regexp quoting issue for bash v3.1.x and v3.2.x.
@@ -120,7 +162,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Fixed bug for replace command. - Fixed bug for replace command.
## [2.5.0] - 2010-05-05 ## [2.5.0] - 2010-05-05
### Added ### Added
- Support use of `$HOME/.todo/` for all todo.sh configuration - Support use of `$HOME/.todo/` for all todo.sh configuration
- Added new multiple do capability to help message - Added new multiple do capability to help message
- Added option to disable final filter - Added option to disable final filter
@@ -130,9 +174,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Added some additional mappings, plus a project context - Added some additional mappings, plus a project context
### Changed ### Changed
- Added 'silent' to a bunch of calls - Added 'silent' to a bunch of calls
### Fixed ### Fixed
- Fixing prepend and priority issue. - Fixing prepend and priority issue.
- Replace with `priority` set - Replace with `priority` set
- Multiple `do` items - Multiple `do` items
@@ -144,19 +190,22 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Tasks whose `ID` begins with `0` ought to be ignored. - Tasks whose `ID` begins with `0` ought to be ignored.
- Fixed auto-complete function name for contexts - Fixed auto-complete function name for contexts
## [2.4.0] - 2009-05-11 ## [2.4.0] - 2009-05-11
### Added ### Added
- Added support for `TODOTXT_FINAL_FILTER` to provide a final custom list filter. - Added support for `TODOTXT_FINAL_FILTER` to provide a final custom list filter.
- Added support for custom sorting (can set in `todo.cfg`) - Added support for custom sorting (can set in `todo.cfg`)
- Added parameterize for `.todo.actions.d` directory - Added parameterize for `.todo.actions.d` directory
### Removed ### Removed
- Removed annoying trailing space on `pri` tasks - Removed annoying trailing space on `pri` tasks
- Don't set colors in default `todo.cfg`. - Don't set colors in default `todo.cfg`.
- Don't set sort command in default `todo.cfg`. - Don't set sort command in default `todo.cfg`.
### Fixed ### Fixed
- `listcon` and `listproj` now work correctly on Mac OS X 10.5 - `listcon` and `listproj` now work correctly on Mac OS X 10.5
- `pri` accepted priorities of more than a single letter - `pri` accepted priorities of more than a single letter
- Support commands combination for `TODOTXT_SORT_COMMAND`; e.g. piped commands can be used: `export TODOTXT_SORT_COMMAND=" env LC_COLLATE=C sort -f -k2 - | grep -m 10 ."` - Support commands combination for `TODOTXT_SORT_COMMAND`; e.g. piped commands can be used: `export TODOTXT_SORT_COMMAND=" env LC_COLLATE=C sort -f -k2 - | grep -m 10 ."`
@@ -165,7 +214,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Now throws an error if you try to prioritize with more than one letter, ie, `todo.sh pri AA` doesn't work any more. - Now throws an error if you try to prioritize with more than one letter, ie, `todo.sh pri AA` doesn't work any more.
## [2.3.0] - 2009-04-02 ## [2.3.0] - 2009-04-02
### Added ### Added
- Added hide priority, context, and projects options now enabled `-P`, `-@` and `-+` - Added hide priority, context, and projects options now enabled `-P`, `-@` and `-+`
- Enabled recursive call of todo.sh from add-ons - Enabled recursive call of todo.sh from add-ons
- Exported variables for use in add-ons - Exported variables for use in add-ons
@@ -174,34 +225,40 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Added Makefile dist infrastructure for versioned releases in Downloads area on GitHub - Added Makefile dist infrastructure for versioned releases in Downloads area on GitHub
### Changed ### Changed
- Separated `_list` function for reuse by various versions of list command to reduce duplicate code - Separated `_list` function for reuse by various versions of list command to reduce duplicate code
- Set `ls` as the default action - Set `ls` as the default action
## [2.2.0] - 2009-03-?? ## [2.2.0] - 2009-03-??
### Fixed ### Fixed
- For awhile here during the GitHub transition, we stripped the version number from todo.sh and updated it kind of willy-nilly, so we're back-versioning all unversioned copies v 2.2. - For awhile here during the GitHub transition, we stripped the version number from todo.sh and updated it kind of willy-nilly, so we're back-versioning all unversioned copies v 2.2.
## [2.1.0] - 2009-02-23 ## [2.1.0] - 2009-02-23
### Added ### Added
- Added "pluggability" with `~/.todo.actions.d/` support (via [Tammy and Ed](http://tech.groups.yahoo.com/group/todotxt/message/1739)) - Added "pluggability" with `~/.todo.actions.d/` support (via [Tammy and Ed](http://tech.groups.yahoo.com/group/todotxt/message/1739))
- Added `-t` param, off by default. When specified, it automatically prepends the current date to new todo's on add - Added `-t` param, off by default. When specified, it automatically prepends the current date to new todo's on add
- Searches for more Unix-y `~/.todo.cfg` if `~/todo.cfg` doesn't exist (via [Ed](http://tech.groups.yahoo.com/group/todotxt/message/1767)) - Searches for more Unix-y `~/.todo.cfg` if `~/todo.cfg` doesn't exist (via [Ed](http://tech.groups.yahoo.com/group/todotxt/message/1767))
### Fixed ### Fixed
- Corrected "ambiguous redirect" bug with done file (via [Jeff](http://tech.groups.yahoo.com/group/todotxt/message/1764)) - Corrected "ambiguous redirect" bug with done file (via [Jeff](http://tech.groups.yahoo.com/group/todotxt/message/1764))
- Corrected usage and help message with new params - Corrected usage and help message with new params
- Corrected config file miscomment about colors - Corrected config file miscomment about colors
## [2.0.1] - 2009-02-17 ## [2.0.1] - 2009-02-17
### Fixed ### Fixed
- Restored `-d` parameter functionality broken in 2.0 (d'oh, thanks Jason, you made the changelog! ) - Restored `-d` parameter functionality broken in 2.0 (d'oh, thanks Jason, you made the changelog! )
## [2.0.0] - 2009-02-17 ## [2.0.0] - 2009-02-17
### Added ### Added
- Added `addto [DEST] "Text to add"` will append text to any file in the todo directory, like `ideas.txt` or `maybelater.txt`. - Added `addto [DEST] "Text to add"` will append text to any file in the todo directory, like `ideas.txt` or `maybelater.txt`.
- Added `mv # [DEST]` will move a task from `todo.txt` to another file `[DEST]` in the todo directory, like if you decide your `"Learn French"` task should go into your `maybelater.txt` file. - Added `mv # [DEST]` will move a task from `todo.txt` to another file `[DEST]` in the todo directory, like if you decide your `"Learn French"` task should go into your `maybelater.txt` file.
- `depri #` removes priority from a task. - `depri #` removes priority from a task.
@@ -212,76 +269,92 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Auto-archive on task completion is now on by default; can be turned off with `-a` parameter. - Auto-archive on task completion is now on by default; can be turned off with `-a` parameter.
### Changed ### Changed
- Separated config file into a non hidden dot file. - Separated config file into a non hidden dot file.
### Fixed ### Fixed
- Better error handling throughout for all commands. - Better error handling throughout for all commands.
- Archive now defrags the file (removes blank lines; see line preservation option.) - Archive now defrags the file (removes blank lines; see line preservation option.)
- Using `/bin/bash` instead of `/bin/sh` - Using `/bin/bash` instead of `/bin/sh`
## [1.7.3] - 2006-07-29 ## [1.7.3] - 2006-07-29
### Added ### Added
- Added short action aliases `add/a`, `list/ls`, `listpri/lsp`, `listall/lsa`, `prepend/prep`, `append/app`, `del/rm` - Added short action aliases `add/a`, `list/ls`, `listpri/lsp`, `listall/lsa`, `prepend/prep`, `append/app`, `del/rm`
## [1.7.2] - 2006-07-28 ## [1.7.2] - 2006-07-28
### Added ### Added
- `listpri` automatically capitalizes lowercase priorities - `listpri` automatically capitalizes lowercase priorities
- `listpri` now displays friendly error message, and the # of tasks returned in verbose mode - `listpri` now displays friendly error message, and the # of tasks returned in verbose mode
### Changed ### Changed
- `do` action removes priority from task automatically - `do` action removes priority from task automatically
Update: Update:
### Fixed ### Fixed
- Actions are now case-insensitive (ie, `todo.sh Add` will work) - Actions are now case-insensitive (ie, `todo.sh Add` will work)
## [1.7.1] - 2006-07-21 ## [1.7.1] - 2006-07-21
### Changed ### Changed
- I'm a big dummy and didn't keep track of what I fixed here. Sorry! - I'm a big dummy and didn't keep track of what I fixed here. Sorry!
## [1.7.0] - 2006-07-19 ## [1.7.0] - 2006-07-19
### Added ### Added
- Interactive `add`, `append`, `prepend`, and `replace` (tx, Ben!) - Interactive `add`, `append`, `prepend`, and `replace` (tx, Ben!)
- Action `listall` displays tasks from both todo.txt and done.txt - Action `listall` displays tasks from both todo.txt and done.txt
- Option `-f` forces delete action and disables interactive input (for todobot.pl) - Option `-f` forces delete action and disables interactive input (for todobot.pl)
- Option `-h` displays full help message. - Option `-h` displays full help message.
### Deprecated ### Deprecated
- Option `-q` deprecated; Use `-v` to turn on verbose mode - Option `-q` deprecated; Use `-v` to turn on verbose mode
### Changed ### Changed
- A very short version of usage message displays by default instead of the long version. - A very short version of usage message displays by default instead of the long version.
- Comment in info about `.todo` file being required - Comment in info about `.todo` file being required
### Fixed ### Fixed
- No colors display for done tasks (tx, Tanja!) - No colors display for done tasks (tx, Tanja!)
- Sort is now case-insensitive (tx, Lonnie!) - Sort is now case-insensitive (tx, Lonnie!)
## [1.6.3] - 2006-07-06 ## [1.6.3] - 2006-07-06
### Added ### Added
- Line numbers now padded, up to 100 characters. (tx, Tanja!) - Line numbers now padded, up to 100 characters. (tx, Tanja!)
## [1.6.2] - 2006-07-05 ## [1.6.2] - 2006-07-05
### Fixed ### Fixed
- Windows config files with spaces now work (tx Ron) - Windows config files with spaces now work (tx Ron)
## [1.6.1] - 2006-07-05 ## [1.6.1] - 2006-07-05
### Changed ### Changed
- The default location of your `.todo` file is now `$HOME/.todo` - The default location of your `.todo` file is now `$HOME/.todo`
### Fixed ### Fixed
- No colors mode (`-p`) now works as expected - No colors mode (`-p`) now works as expected
## [1.6.0] - 2006-07-04 ## [1.6.0] - 2006-07-04
### Added ### Added
- Action `prepend` adds text to an item at the beginning of the line. - Action `prepend` adds text to an item at the beginning of the line.
- Configuration file is now separated from script into `.todo` file - Configuration file is now separated from script into `.todo` file
- Specify a config file other than `.todo` using the `-d` option - Specify a config file other than `.todo` using the `-d` option
@@ -289,89 +362,107 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Option `-V` shows version and license information. - Option `-V` shows version and license information.
### Changed ### Changed
- The option to turn off colors is now `-p` (no longer `-nc` as in 1.5.2) - The option to turn off colors is now `-p` (no longer `-nc` as in 1.5.2)
## [1.5.2] - 2006-06-26 ## [1.5.2] - 2006-06-26
### Fixed ### Fixed
- Items that start with `x ` (an x with a space after) are archived now to avoid lines that start with a word like `xander` from being archived. (tx, Tannie!) - Items that start with `x ` (an x with a space after) are archived now to avoid lines that start with a word like `xander` from being archived. (tx, Tannie!)
- Report now only archives items that start with `x ` as well. - Report now only archives items that start with `x ` as well.
## [1.5.1] - 2006-06-26 ## [1.5.1] - 2006-06-26
### Fixed ### Fixed
- Items with an `x` in them at all were being deleted on archive with 1.5; all fixed now. - Items with an `x` in them at all were being deleted on archive with 1.5; all fixed now.
## [1.5.0] - 2006-06-24 ## [1.5.0] - 2006-06-24
### Added ### Added
- Option to turn off colors (to avoid characters in piped text files or IM bot), ie `todo.sh -nc [COMMAND]` - Option to turn off colors (to avoid characters in piped text files or IM bot), ie `todo.sh -nc [COMMAND]`
- A date is added to a completed todo, ie `x 2006-06-24` (tx SETH) - A date is added to a completed todo, ie `x 2006-06-24` (tx SETH)
- Action `remdup` removes exact duplicate lines from todo.txt (tx Tannie) - Action `remdup` removes exact duplicate lines from todo.txt (tx Tannie)
- Action `del` removes any blank lines from todo.txt (tx Tannie) - Action `del` removes any blank lines from todo.txt (tx Tannie)
### Changed ### Changed
- Using `sed -i` instead of copying tmp file (tx Tannie) - Using `sed -i` instead of copying tmp file (tx Tannie)
### Fixed ### Fixed
- Colors show in OS/X 10.4 (tx SETH & misha) - Colors show in OS/X 10.4 (tx SETH & misha)
## [1.4.0] - 2006-06-17 ## [1.4.0] - 2006-06-17
### Added ### Added
- Tasks are color-coded by priority in Cygwin (Thanks, Abraham, Manuel and Luis!) - Tasks are color-coded by priority in Cygwin (Thanks, Abraham, Manuel and Luis!)
### Changed ### Changed
- Switched endless `if-then` to a `case` statement, and tightened up `wc -l` regex. (Thanks, Sash!) - Switched endless `if-then` to a `case` statement, and tightened up `wc -l` regex. (Thanks, Sash!)
### Fixed ### Fixed
- If you `replace`/`do`/`append` to a non-existent task, your todo.txt is no longer overwritten and the error is handled gracefully. (Thanks, Scott!) - If you `replace`/`do`/`append` to a non-existent task, your todo.txt is no longer overwritten and the error is handled gracefully. (Thanks, Scott!)
## [1.3.0] - 2006-05-29 ## [1.3.0] - 2006-05-29
### Added ### Added
- Displays the number of newly added todo (Thanks, Amy!) - Displays the number of newly added todo (Thanks, Amy!)
- Confirms whether or not you really want to delete a todo - Confirms whether or not you really want to delete a todo
- Displays success messages and confirmations on `append`, `replace`, `do`, etc. - Displays success messages and confirmations on `append`, `replace`, `do`, etc.
- Added licensing information in comments. GPL, baby! - Added licensing information in comments. GPL, baby!
### Changed ### Changed
- Alphabetized command workflow in if/then construction - Alphabetized command workflow in if/then construction
- Tightened up `sed` commands, removed unnecessary `grep`s and `cat`s (Thanks, Sash!) - Tightened up `sed` commands, removed unnecessary `grep`s and `cat`s (Thanks, Sash!)
- Stripped whitespace around number lines from wc results - Stripped whitespace around number lines from wc results
### Removed ### Removed
- Removed filenames from `report.txt` format, for easier graphing or Excel imports. - Removed filenames from `report.txt` format, for easier graphing or Excel imports.
### Fixed ### Fixed
- Todos are now sorted alphabetically when listed by a term. (ie: `todo list flowers) - Todos are now sorted alphabetically when listed by a term. (ie: `todo list flowers)
## [1.2.0] - 2006-05-15 ## [1.2.0] - 2006-05-15
### Added ### Added
- `list` is case insenstive. ie, `todo list Mac` will match lines with "mac" and "Mac"
- `list` is case insensitive. ie, `todo list Mac` will match lines with "mac" and "Mac"
### Changed ### Changed
- `todo list` matches multiple [TERM]s. ie, `todo list mac offline` will match all lines that contain the words "mac" and "offline" - `todo list` matches multiple [TERM]s. ie, `todo list mac offline` will match all lines that contain the words "mac" and "offline"
- `repri` and `pri` actions combined into `pri` action (Thanks Mike!) - `repri` and `pri` actions combined into `pri` action (Thanks Mike!)
- Quotes no longer required with `add` and `replace` (Thanks Karl!) - Quotes no longer required with `add` and `replace` (Thanks Karl!)
- Any priority added to a todo must be uppercase to preserve sort order, enforced now. ie `todo pri 1 a` will return a usage error. - Any priority added to a todo must be uppercase to preserve sort order, enforced now. ie `todo pri 1 a` will return a usage error.
### Fixed ### Fixed
- File "sanity checks" and cleanup function, test script and various fantastic stylistic improvements added. Extra big thanks to Karl! - File "sanity checks" and cleanup function, test script and various fantastic stylistic improvements added. Extra big thanks to Karl!
## [1.1.0] - 2006-05-12 ## [1.1.0] - 2006-05-12
### Added ### Added
- Supports file paths with spaces (ie `C:\Documents and Settings\gina\todo.txt`) - Supports file paths with spaces (ie `C:\Documents and Settings\gina\todo.txt`)
## 1.0.0 - 2006-05-11 ## 1.0.0 - 2006-05-11
### Added ### Added
- Consolidated into one master script with usage notes and released. - Consolidated into one master script with usage notes and released.
[Unreleased]: https://github.com/todotxt/todo.txt-cli/compare/v2.12.0...HEAD
[Unreleased]: https://github.com/todotxt/todo.txt-cli/compare/v2.11.0...HEAD [2.12.0]: https://github.com/todotxt/todo.txt-cli/compare/v2.11.0...v2.12.0
[2.11.0]: https://github.com/todotxt/todo.txt-cli/compare/v2.10.0...v2.11.0 [2.11.0]: https://github.com/todotxt/todo.txt-cli/compare/v2.10.0...v2.11.0
[2.10.0]: https://github.com/todotxt/todo.txt-cli/compare/v2.9.0...v2.10.0 [2.10.0]: https://github.com/todotxt/todo.txt-cli/compare/v2.9.0...v2.10.0
[2.9.0]: https://github.com/todotxt/todo.txt-cli/compare/v2.8.0...v2.9.0 [2.9.0]: https://github.com/todotxt/todo.txt-cli/compare/v2.8.0...v2.9.0
@@ -400,11 +491,21 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
[1.3.0]: https://github.com/todotxt/todo.txt-cli/compare/v1.2.0...v1.3.0 [1.3.0]: https://github.com/todotxt/todo.txt-cli/compare/v1.2.0...v1.3.0
[1.2.0]: https://github.com/todotxt/todo.txt-cli/compare/v1.1.0...v1.2.0 [1.2.0]: https://github.com/todotxt/todo.txt-cli/compare/v1.1.0...v1.2.0
[1.1.0]: https://github.com/todotxt/todo.txt-cli/compare/v1.0.0...v1.1.0 [1.1.0]: https://github.com/todotxt/todo.txt-cli/compare/v1.0.0...v1.1.0
[#230]: https://github.com/todotxt/todo.txt-cli/pull/230
[#228]: https://github.com/todotxt/todo.txt-cli/pull/228
[#219]: https://github.com/todotxt/todo.txt-cli/pull/219
[#218]: https://github.com/todotxt/todo.txt-cli/pull/218
[#217]: https://github.com/todotxt/todo.txt-cli/pull/217
[#156]: https://github.com/todotxt/todo.txt-cli/pull/156
[#8]: https://github.com/todotxt/todo.txt-cli/pull/8 [#8]: https://github.com/todotxt/todo.txt-cli/pull/8
[#156]: https://github.com/todotxt/todo.txt-cli/pull/156
[#160]: https://github.com/todotxt/todo.txt-cli/pull/160
[#169]: https://github.com/todotxt/todo.txt-cli/pull/169
[#217]: https://github.com/todotxt/todo.txt-cli/pull/217
[#218]: https://github.com/todotxt/todo.txt-cli/pull/218
[#219]: https://github.com/todotxt/todo.txt-cli/pull/219
[#228]: https://github.com/todotxt/todo.txt-cli/pull/228
[#230]: https://github.com/todotxt/todo.txt-cli/pull/230
[#246]: https://github.com/todotxt/todo.txt-cli/pull/246
[#249]: https://github.com/todotxt/todo.txt-cli/pull/249
[#264]: https://github.com/todotxt/todo.txt-cli/pull/264
[#270]: https://github.com/todotxt/todo.txt-cli/pull/270
[#271]: https://github.com/todotxt/todo.txt-cli/pull/271
[#289]: https://github.com/todotxt/todo.txt-cli/pull/289
[#295]: https://github.com/todotxt/todo.txt-cli/pull/295
[#300]: https://github.com/todotxt/todo.txt-cli/pull/300
[#301]: https://github.com/todotxt/todo.txt-cli/pull/301

View File

@@ -34,5 +34,3 @@ test "$VN" = "$VC" || {
echo >&2 "VERSION=$VN" echo >&2 "VERSION=$VN"
echo "VERSION=$VN" >$VF echo "VERSION=$VN" >$VF
} }

View File

@@ -10,13 +10,28 @@ INSTALL_DATA = $(INSTALL) -m 644
prefix = /usr/local prefix = /usr/local
# ifdef check allows the user to pass custom dirs
# as per the README
# The directory to install todo.sh in. # The directory to install todo.sh in.
ifdef INSTALL_DIR
bindir = $(INSTALL_DIR)
else
bindir = $(prefix)/bin bindir = $(prefix)/bin
endif
# The directory to install the config file in. # The directory to install the config file in.
ifdef CONFIG_DIR
sysconfdir = $(CONFIG_DIR)
else
sysconfdir = $(prefix)/etc sysconfdir = $(prefix)/etc
endif
datarootdir = $(prefix)/share ifdef BASH_COMPLETION
datarootdir = $(BASH_COMPLETION)
else
datarootdir = $(prefix)/share/bash_completion.d
endif
# Dynamically detect/generate version file as necessary # Dynamically detect/generate version file as necessary
# This file will define a variable called VERSION. # This file will define a variable called VERSION.
@@ -37,9 +52,9 @@ dist: $(DISTFILES) todo.sh
cp -f $(DISTFILES) $(DISTNAME)/ cp -f $(DISTFILES) $(DISTNAME)/
sed -e 's/@DEV_VERSION@/'$(VERSION)'/' todo.sh > $(DISTNAME)/todo.sh sed -e 's/@DEV_VERSION@/'$(VERSION)'/' todo.sh > $(DISTNAME)/todo.sh
chmod +x $(DISTNAME)/todo.sh chmod +x $(DISTNAME)/todo.sh
tar cf $(DISTNAME).tar $(DISTNAME)/ tar cf $(DISTNAME).tar $(DISTNAME)
gzip -f -9 $(DISTNAME).tar gzip -f -9 $(DISTNAME).tar
zip -9r $(DISTNAME).zip $(DISTNAME)/ zip -r -9 $(DISTNAME).zip $(DISTNAME)
rm -r $(DISTNAME) rm -r $(DISTNAME)
.PHONY: clean .PHONY: clean
@@ -49,22 +64,22 @@ clean: test-pre-clean
install: installdirs install: installdirs
$(INSTALL_PROGRAM) todo.sh $(DESTDIR)$(bindir)/todo.sh $(INSTALL_PROGRAM) todo.sh $(DESTDIR)$(bindir)/todo.sh
$(INSTALL_DATA) todo_completion $(DESTDIR)$(datarootdir)/bash_completion.d/todo $(INSTALL_DATA) todo_completion $(DESTDIR)$(datarootdir)/todo
[ -e $(DESTDIR)$(sysconfdir)/todo/config ] || \ [ -e $(DESTDIR)$(sysconfdir)/todo/config ] || \
sed "s/^\(export[ \t]*TODO_DIR=\).*/\1~\/.todo/" todo.cfg > $(DESTDIR)$(sysconfdir)/todo/config sed "s/^\(export[ \t]*TODO_DIR=\).*/\1~\/.todo/" todo.cfg > $(DESTDIR)$(sysconfdir)/todo/config
uninstall: uninstall:
rm -f $(DESTDIR)$(bindir)/todo.sh rm -f $(DESTDIR)$(bindir)/todo.sh
rm -f $(DESTDIR)$(datarootdir)/bash_completion.d/todo rm -f $(DESTDIR)$(datarootdir)/todo
rm -f $(DESTDIR)$(sysconfdir)/todo/config rm -f $(DESTDIR)$(sysconfdir)/todo/config
rmdir $(DESTDIR)$(datarootdir)/bash_completion.d rmdir $(DESTDIR)$(datarootdir)
rmdir $(DESTDIR)$(sysconfdir)/todo rmdir $(DESTDIR)$(sysconfdir)/todo
installdirs: installdirs:
mkdir -p $(DESTDIR)$(bindir) \ mkdir -p $(DESTDIR)$(bindir) \
$(DESTDIR)$(sysconfdir)/todo \ $(DESTDIR)$(sysconfdir)/todo \
$(DESTDIR)$(datarootdir)/bash_completion.d $(DESTDIR)$(datarootdir)
# #
# Testing # Testing
@@ -86,3 +101,4 @@ test: aggregate-results
# Force tests to get run every time # Force tests to get run every time
.PHONY: test test-pre-clean aggregate-results $(TESTS) .PHONY: test test-pre-clean aggregate-results $(TESTS)

View File

@@ -2,7 +2,7 @@
> A simple and extensible shell script for managing your todo.txt file. > A simple and extensible shell script for managing your todo.txt file.
[![Build Status](https://travis-ci.org/todotxt/todo.txt-cli.svg?branch=master)](https://travis-ci.org/todotxt/todo.txt-cli) ![CI](https://github.com/todotxt/todo.txt-cli/workflows/CI/badge.svg)
[![GitHub issues](https://img.shields.io/github/issues/todotxt/todo.txt-cli.svg)](https://github.com/todotxt/todo.txt-cli/issues) [![GitHub issues](https://img.shields.io/github/issues/todotxt/todo.txt-cli.svg)](https://github.com/todotxt/todo.txt-cli/issues)
[![GitHub forks](https://img.shields.io/github/forks/todotxt/todo.txt-cli.svg)](https://github.com/todotxt/todo.txt-cli/network) [![GitHub forks](https://img.shields.io/github/forks/todotxt/todo.txt-cli.svg)](https://github.com/todotxt/todo.txt-cli/network)
[![GitHub stars](https://img.shields.io/github/stars/todotxt/todo.txt-cli.svg)](https://github.com/todotxt/todo.txt-cli/stargazers) [![GitHub stars](https://img.shields.io/github/stars/todotxt/todo.txt-cli.svg)](https://github.com/todotxt/todo.txt-cli/stargazers)
@@ -11,7 +11,7 @@
![gif](./.github/example.gif) ![gif](./.github/example.gif)
*Read our [contributing guide](CONTRIBUTING.md) if you're looking to contribute (issues/PRs/etc).* *Read our [contributing guide][CONTRIBUTING] if you're looking to contribute (issues/PRs/etc).*
## Installation ## Installation
@@ -23,8 +23,16 @@ Download the latest stable [release][release] for use on your desktop or server.
```shell ```shell
brew install todo-txt brew install todo-txt
# For macOS on x86 CPU
cp -n /usr/local/opt/todo-txt/todo.cfg ~/.todo.cfg
# For macOS on arm CPU
cp -n /opt/homebrew/opt/todo-txt/todo.cfg ~/.todo.cfg
``` ```
**Note**: The `-n` flag for `cp` makes sure you do not overwrite an existing file.
### Linux ### Linux
#### From command line #### From command line
@@ -42,12 +50,12 @@ make test
- `BASH_COMPLETION`: PATH for autocompletion scripts (default to /etc/bash_completion.d) - `BASH_COMPLETION`: PATH for autocompletion scripts (default to /etc/bash_completion.d)
```shell ```shell
make install CONFIG_DIR=/etc INSTALL_DIR=/usr/bin BASH_COMPLETION_DIR=/usr/share/bash-completion/completions make install CONFIG_DIR=/etc INSTALL_DIR=/usr/bin BASH_COMPLETION=/usr/share/bash-completion/completions
``` ```
#### Arch Linux (AUR) #### Arch Linux (AUR)
https://aur.archlinux.org/packages/todotxt-git/ https://aur.archlinux.org/packages/todotxt/
## Usage ## Usage
@@ -71,8 +79,8 @@ See [CHANGELOG.md][CHANGELOG]
## Support ## Support
- [Github Discussions](https://github.com/todotxt/todo.txt-cli/discussions)
- [Stack Overflow](https://stackoverflow.com/questions/tagged/todotxt) - [Stack Overflow](https://stackoverflow.com/questions/tagged/todotxt)
- [Gitter chat](https://gitter.im/todotxt/todo.txt-cli)
- [Twitter](https://twitter.com/todotxt) - [Twitter](https://twitter.com/todotxt)
@@ -82,7 +90,7 @@ See [CHANGELOG.md][CHANGELOG]
## Contributing ## Contributing
We welcome all contributations. First read our [Contributor Code of Conduct][CODE_OF_CONDUCT] and then get started [contributing][CONTRIBUTING]. We welcome all contributions. First read our [Contributor Code of Conduct][CODE_OF_CONDUCT] and then get started [contributing][CONTRIBUTING].
## License ## License
@@ -91,9 +99,9 @@ GNU General Public License v3.0 © [todo.txt org][github]
[release]: https://github.com/todotxt/todo.txt-cli/releases [release]: https://github.com/todotxt/todo.txt-cli/releases
[website]: http://todotxt.org [website]: http://todotxt.org/
[github]: https://github.com/todotxt [github]: https://github.com/todotxt
[USAGE]: ./USAGE.md [USAGE]: ./USAGE.md
[CHANGELOG]: ./CHANGELOG.md [CHANGELOG]: ./CHANGELOG.md
[CODE_OF_CONDUCT]: ./CODE_OF_CONDUCT.md [CODE_OF_CONDUCT]: .github/CODE_OF_CONDUCT.md
[CONTRIBUTING]: ./CONTRIBUTING.md [CONTRIBUTING]: .github/CONTRIBUTING.md

View File

@@ -104,7 +104,7 @@ todo.sh help [ACTION...]
Displays all tasks that contain TERM(s) sorted by priority with line numbers. Each task must match all TERM(s) (logical AND); to display tasks that contain any TERM (logical OR), use `"TERM1\|TERM2\|..."` (with quotes), or `TERM1\\|TERM2` (unquoted). Hides all tasks that contain TERM(s) preceded by a minus sign (i.e. `-TERM`). Displays all tasks that contain TERM(s) sorted by priority with line numbers. Each task must match all TERM(s) (logical AND); to display tasks that contain any TERM (logical OR), use `"TERM1\|TERM2\|..."` (with quotes), or `TERM1\\|TERM2` (unquoted). Hides all tasks that contain TERM(s) preceded by a minus sign (i.e. `-TERM`).
If no TERM specified, lists entire todo.txt. If no TERM specified, lists entire todo.txt.
```shell ```shell
todo.sh list [TERM...] todo.sh list [TERM...]
todo.sh ls [TERM...] todo.sh ls [TERM...]
@@ -221,7 +221,7 @@ Hide project names in list output. Use twice to show project names (default).
Color mode Color mode
### `-d CONFIG_FILE` ### `-d CONFIG_FILE`
Use a configuration file other than the default `~/.todo/config` Use a configuration file other than one of the defaults (e.g. `~/.todo/config`)
### `-f` ### `-f`
Forces actions without confirmation or interactive input. Forces actions without confirmation or interactive input.

View File

@@ -266,7 +266,7 @@ and the dates and timestamps will be artificially fixed.
Then the session can be used to make a unit test thanks to Then the session can be used to make a unit test thanks to
test_todo_session, see the existing tests as examples. test_todo_session, see the existing tests as examples.
Be careful to replace all occurences of the full path to the test Be careful to replace all occurrences of the full path to the test
directory by $HOME as testshell.sh will explain you when you execute it directory by $HOME as testshell.sh will explain you when you execute it
otherwise the tests will work properly only on your own computer. otherwise the tests will work properly only on your own computer.

View File

@@ -21,7 +21,7 @@ make_action_in_folder()
{ {
unset TODO_ACTIONS_DIR unset TODO_ACTIONS_DIR
[ -d .todo.actions.d ] || mkdir .todo.actions.d [ -d .todo.actions.d ] || mkdir .todo.actions.d
mkdir .todo.actions.d/$1 mkdir ".todo.actions.d/$1"
cat > ".todo.actions.d/$1/$1" <<EOF cat > ".todo.actions.d/$1/$1" <<EOF
#!/bin/bash #!/bin/bash
[ "\$1" = "usage" ] && { [ "\$1" = "usage" ] && {

View File

@@ -67,15 +67,15 @@ do
'') '')
continue ;; continue ;;
fixed) fixed)
fixed=$(($fixed + $value)) ;; fixed=$((fixed + $value)) ;;
success) success)
success=$(($success + $value)) ;; success=$((success + $value)) ;;
failed) failed)
failed=$(($failed + $value)) ;; failed=$((failed + $value)) ;;
broken) broken)
broken=$(($broken + $value)) ;; broken=$((broken + $value)) ;;
total) total)
total=$(($total + $value)) ;; total=$((total + $value)) ;;
esac esac
done <"$file" done <"$file"
done done

View File

@@ -79,4 +79,18 @@ test_expect_success 'config file (env variable)' '
test_cmp expect output && test -f used_config test_cmp expect output && test -f used_config
' '
cat > minimal.cfg <<EOF
export TODO_DIR=.
touch used_config
EOF
rm -f used_config
test_expect_success 'config file (minimal)' '
mkdir .todo
cp minimal.cfg .todo/config
todo.sh > output;
test_cmp expect output && test -f used_config &&
rm -rf .todo
'
test_done test_done

View File

@@ -59,7 +59,6 @@ test_expect_success 'null list filter' '
todo.sh listall filter > output && test_cmp expect output todo.sh listall filter > output && test_cmp expect output
' '
# #
# lsc|listcon # lsc|listcon
# #

View File

@@ -110,4 +110,17 @@ TODO: 1 added.
-- --
TODO: 1 of 1 tasks shown TODO: 1 of 1 tasks shown
EOF EOF
echo -n 'this is a first task without newline' > todo.txt
test_todo_session 'add to file without EOL' <<EOF
>>> todo.sh add "a second task"
2 a second task
TODO: 2 added.
>>> todo.sh list
2 a second task
1 this is a first task without newline
--
TODO: 2 of 2 tasks shown
EOF

33
tests/t1040-add-priority.sh Executable file
View File

@@ -0,0 +1,33 @@
#!/bin/bash
test_description='test the priority on add feature'
. ./test-lib.sh
## Normal use case
echo "export TODOTXT_PRIORITY_ON_ADD=A" >> todo.cfg
test_todo_session 'config file priority' <<EOF
>>> todo.sh add take out the trash
1 (A) take out the trash
TODO: 1 added.
>>> todo.sh -p list
1 (A) take out the trash
--
TODO: 1 of 1 tasks shown
EOF
## Wrong value in config var
echo "export TODOTXT_PRIORITY_ON_ADD=1" >> todo.cfg
test_todo_session 'config file wrong priority' <<EOF
>>> todo.sh add fail to take out the trash
=== 1
TODOTXT_PRIORITY_ON_ADD should be a capital letter from A to Z (it is now "1").
>>> todo.sh -p list
=== 1
TODOTXT_PRIORITY_ON_ADD should be a capital letter from A to Z (it is now "1").
EOF
test_done

View File

@@ -6,7 +6,7 @@ test_description='basic priority functionality
test_todo_session 'priority usage' <<EOF test_todo_session 'priority usage' <<EOF
>>> todo.sh pri B B >>> todo.sh pri B B
usage: todo.sh pri ITEM# PRIORITY usage: todo.sh pri ITEM# PRIORITY[, ITEM# PRIORITY, ...]
note: PRIORITY must be anywhere from A to Z. note: PRIORITY must be anywhere from A to Z.
=== 1 === 1
EOF EOF
@@ -100,4 +100,39 @@ TODO: 2 already prioritized (A).
-- --
TODO: 3 of 3 tasks shown TODO: 3 of 3 tasks shown
EOF EOF
cat > todo.txt <<EOF
smell the uppercase Roses +flowers @outside
notice the sunflowers
stop
EOF
test_todo_session 'multiple priority' <<EOF
>>> todo.sh pri 1 A 2 B
1 (A) smell the uppercase Roses +flowers @outside
TODO: 1 prioritized (A).
2 (B) notice the sunflowers
TODO: 2 prioritized (B).
EOF
test_todo_session 'multiple reprioritize' <<EOF
>>> todo.sh pri 1 Z 2 X
1 (Z) smell the uppercase Roses +flowers @outside
TODO: 1 re-prioritized from (A) to (Z).
2 (X) notice the sunflowers
TODO: 2 re-prioritized from (B) to (X).
EOF
test_todo_session 'multiple prioritize error' <<EOF
>>> todo.sh pri 1 B 4 B
=== 1
1 (B) smell the uppercase Roses +flowers @outside
TODO: 1 re-prioritized from (Z) to (B).
TODO: No task 4.
>>> todo.sh pri 1 C 4 B 3 A
=== 1
1 (C) smell the uppercase Roses +flowers @outside
TODO: 1 re-prioritized from (B) to (C).
TODO: No task 4.
EOF
test_done test_done

View File

@@ -1,5 +1,4 @@
#!/bin/bash #!/bin/bash
#
test_description='list functionality test_description='list functionality
@@ -162,7 +161,6 @@ TODO: 1 of 5 tasks shown
TODO: 1 of 5 tasks shown TODO: 1 of 5 tasks shown
EOF EOF
# #
# check the x command line option # check the x command line option
# #

View File

@@ -1,5 +1,4 @@
#!/bin/bash #!/bin/bash
#
test_description='listcon functionality test_description='listcon functionality
@@ -65,6 +64,47 @@ test_todo_session 'listcon with project' <<EOF
@garden @garden
EOF EOF
cat > todo.txt <<EOF
(B) +math (@school or @home) integrate @x and @y
(C) say thanks @GinaTrapani w:@OtherContributors
stop
EOF
test_todo_session 'listcon with default configuration' <<EOF
>>> todo.sh listcon
@GinaTrapani
@home)
@x
@y
EOF
test_todo_session 'listcon limiting to multi-character sequences' <<EOF
>>> TODOTXT_SIGIL_VALID_PATTERN='.\{2,\}' todo.sh listcon
@GinaTrapani
@home)
EOF
test_todo_session 'listcon allowing w: marker before contexts' <<EOF
>>> TODOTXT_SIGIL_BEFORE_PATTERN='\(w:\)\{0,1\}' todo.sh listcon
@GinaTrapani
@OtherContributors
@home)
@x
@y
EOF
test_todo_session 'listcon allowing parentheses around contexts' <<EOF
>>> TODOTXT_SIGIL_BEFORE_PATTERN='(\{0,1\}' TODOTXT_SIGIL_AFTER_PATTERN=')\{0,1\}' todo.sh listcon
@GinaTrapani
@home
@school
@x
@y
EOF
test_todo_session 'listcon with all customizations combined' <<EOF
>>> TODOTXT_SIGIL_VALID_PATTERN='.\{2,\}' TODOTXT_SIGIL_BEFORE_PATTERN='\(w:\)\{0,1\}\((\)\{0,1\}' TODOTXT_SIGIL_AFTER_PATTERN=')\{0,1\}' todo.sh listcon
@GinaTrapani
@OtherContributors
@home
@school
EOF
cat > todo.txt <<EOF cat > todo.txt <<EOF
@con01 -- Some context 1 task @con01 -- Some context 1 task
EOF EOF

View File

@@ -1,5 +1,4 @@
#!/bin/bash #!/bin/bash
#
test_description='listproj functionality test_description='listproj functionality
@@ -75,6 +74,33 @@ test_todo_session 'listproj with context' <<EOF
+sunflowers +sunflowers
EOF EOF
cat > todo.txt <<EOF
(B) give a +1 to this project
(C) notice the sunflowers +sunflowers [+gardening] [+landscape]
stop
EOF
test_todo_session 'listproj with default configuration' <<EOF
>>> todo.sh listproj
+1
+sunflowers
EOF
test_todo_session 'listproj limiting to alphabetic characters' <<EOF
>>> TODOTXT_SIGIL_VALID_PATTERN='[a-zA-Z]\{1,\}' todo.sh listproj
+sunflowers
EOF
test_todo_session 'listproj allowing brackets around projects' <<EOF
>>> TODOTXT_SIGIL_BEFORE_PATTERN='\[\{0,1\}' TODOTXT_SIGIL_AFTER_PATTERN='\]\{0,1\}' todo.sh listproj
+1
+gardening
+landscape
+sunflowers
EOF
cat > todo.txt <<EOF
(B) smell the uppercase Roses +roses @outside +shared
(C) notice the sunflowers +sunflowers @garden +shared +landscape
stop
EOF
TEST_TODO_CUSTOM=todo-custom.cfg TEST_TODO_CUSTOM=todo-custom.cfg
cat todo.cfg > "$TEST_TODO_CUSTOM" cat todo.cfg > "$TEST_TODO_CUSTOM"
cat >> "$TEST_TODO_CUSTOM" <<'EOF' cat >> "$TEST_TODO_CUSTOM" <<'EOF'
@@ -90,7 +116,6 @@ test_todo_session 'listproj with context special cases' <<EOF
+sunflowers +sunflowers
EOF EOF
cat > todo.txt <<EOF cat > todo.txt <<EOF
+prj01 -- Some project 1 task +prj01 -- Some project 1 task
EOF EOF

View File

@@ -1,5 +1,4 @@
#!/bin/bash #!/bin/bash
#
test_description='list highlighting test_description='list highlighting

View File

@@ -1,5 +1,4 @@
#!/bin/bash #!/bin/bash
#
test_description='list with escape sequences test_description='list with escape sequences

View File

@@ -1,5 +1,4 @@
#!/bin/bash #!/bin/bash
#
test_description='highlighting projects and contexts test_description='highlighting projects and contexts

View File

@@ -0,0 +1,43 @@
#!/bin/bash
test_description='highlighting date, item numbers and metadata
This test checks the highlighting (with colors) of dates, item numbers and metadata
'
. ./test-lib.sh
# Tasks with dates and metadata
cat > todo.txt <<EOF
2018-11-11 task with date
task with metadata due:2018-12-31
task without date and without metadata
EOF
# config file specifying COLOR_PROJECT and COLOR_CONTEXT
#
TEST_TODO_LABEL_COLORS=todo-colors.cfg
cat todo.cfg > "$TEST_TODO_LABEL_COLORS"
echo "export COLOR_DATE='\\\\033[0;31m'" >>"$TEST_TODO_LABEL_COLORS"
echo "export COLOR_META='\\\\033[0;32m'" >>"$TEST_TODO_LABEL_COLORS"
echo "export COLOR_NUMBER='\\\\033[0;34m'" >>"$TEST_TODO_LABEL_COLORS"
test_todo_session 'highlighting for date, item numbers and metadata' <<'EOF'
>>> todo.sh -d "$TEST_TODO_LABEL_COLORS" ls
1 2018-11-11 task with date
2 task with metadata due:2018-12-31
3 task without date and without metadata
--
TODO: 3 of 3 tasks shown
EOF
test_todo_session 'suppressing highlighting for date, item numbers and metadata' <<'EOF'
>>> todo.sh -p -d "$TEST_TODO_LABEL_COLORS" ls
1 2018-11-11 task with date
2 task with metadata due:2018-12-31
3 task without date and without metadata
--
TODO: 3 of 3 tasks shown
EOF
test_done

View File

@@ -83,4 +83,5 @@ TODO: 3 marked as done.
>>> todo.sh -a do 3 >>> todo.sh -a do 3
TODO: 3 is already marked done. TODO: 3 is already marked done.
EOF EOF
test_done test_done

View File

@@ -4,6 +4,8 @@ test_description='basic del functionality
' '
. ./test-lib.sh . ./test-lib.sh
SPACE=' '
test_todo_session 'del usage' <<EOF test_todo_session 'del usage' <<EOF
>>> todo.sh del B >>> todo.sh del B
usage: todo.sh del ITEM# [TERM] usage: todo.sh del ITEM# [TERM]
@@ -44,6 +46,50 @@ TODO: 1 deleted.
TODO: 2 of 2 tasks shown TODO: 2 of 2 tasks shown
EOF EOF
cat > todo.txt <<EOF
(B) smell the uppercase Roses +flowers @outside
(A) notice the sunflowers
stop
EOF
test_todo_session 'del with confirmation' <<EOF
>>> todo.sh -p list
2 (A) notice the sunflowers
1 (B) smell the uppercase Roses +flowers @outside
3 stop
--
TODO: 3 of 3 tasks shown
>>> printf n | todo.sh del 1
Delete '(B) smell the uppercase Roses +flowers @outside'? (y/n)$SPACE
TODO: No tasks were deleted.
>>> todo.sh -p list
2 (A) notice the sunflowers
1 (B) smell the uppercase Roses +flowers @outside
3 stop
--
TODO: 3 of 3 tasks shown
>>> printf x | todo.sh del 1
Delete '(B) smell the uppercase Roses +flowers @outside'? (y/n)$SPACE
TODO: No tasks were deleted.
>>> echo | todo.sh del 1
Delete '(B) smell the uppercase Roses +flowers @outside'? (y/n)$SPACE
TODO: No tasks were deleted.
>>> printf y | todo.sh del 1
Delete '(B) smell the uppercase Roses +flowers @outside'? (y/n)$SPACE
1 (B) smell the uppercase Roses +flowers @outside
TODO: 1 deleted.
>>> todo.sh -p list
2 (A) notice the sunflowers
3 stop
--
TODO: 2 of 2 tasks shown
EOF
cat > todo.txt <<EOF cat > todo.txt <<EOF
(B) smell the uppercase Roses +flowers @outside (B) smell the uppercase Roses +flowers @outside
(A) notice the sunflowers (A) notice the sunflowers

102
tests/t1850-move.sh Executable file
View File

@@ -0,0 +1,102 @@
#!/bin/bash
test_description='basic move functionality
'
. ./test-lib.sh
SPACE=' '
cat > todo.txt <<EOF
(B) smell the uppercase Roses +flowers @outside
(A) notice the sunflowers
EOF
cat > done.txt <<EOF
x 2009-02-13 make the coffee +wakeup
x 2009-02-13 smell the coffee +wakeup
EOF
test_todo_session 'basic move with implicit source' <<EOF
>>> todo.sh -f move 1 done.txt | sed "s#'[^']\{1,\}/\([^/']\{1,\}\)'#'\1'#g"
1 (B) smell the uppercase Roses +flowers @outside
TODO: 1 moved from 'todo.txt' to 'done.txt'.
>>> todo.sh -p ls
2 (A) notice the sunflowers
--
TODO: 1 of 1 tasks shown
>>> todo.sh -p listfile done.txt
3 (B) smell the uppercase Roses +flowers @outside
1 x 2009-02-13 make the coffee +wakeup
2 x 2009-02-13 smell the coffee +wakeup
--
DONE: 3 of 3 tasks shown
EOF
cat > todo.txt <<EOF
(B) smell the uppercase Roses +flowers @outside
(A) notice the sunflowers
EOF
cat > done.txt <<EOF
x 2009-02-13 make the coffee +wakeup
x 2009-02-13 smell the coffee +wakeup
EOF
test_todo_session 'basic move with confirmation' <<EOF
>>> 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'
Move '(B) smell the uppercase Roses +flowers @outside' from todo.txt to done.txt? (y/n)$SPACE
1 (B) smell the uppercase Roses +flowers @outside
TODO: 1 moved from 'todo.txt' to 'done.txt'.
>>> todo.sh -p ls
2 (A) notice the sunflowers
--
TODO: 1 of 1 tasks shown
>>> todo.sh -p listfile done.txt
3 (B) smell the uppercase Roses +flowers @outside
1 x 2009-02-13 make the coffee +wakeup
2 x 2009-02-13 smell the coffee +wakeup
--
DONE: 3 of 3 tasks shown
EOF
test_todo_session 'basic move with passed source' <<EOF
>>> todo.sh -f move 2 todo.txt done.txt | sed "s#'[^']\{1,\}/\([^/']\{1,\}\)'#'\1'#g"
2 x 2009-02-13 smell the coffee +wakeup
TODO: 2 moved from 'done.txt' to 'todo.txt'.
>>> todo.sh -p ls
2 (A) notice the sunflowers
3 x 2009-02-13 smell the coffee +wakeup
--
TODO: 2 of 2 tasks shown
>>> todo.sh -p listfile done.txt
3 (B) smell the uppercase Roses +flowers @outside
1 x 2009-02-13 make the coffee +wakeup
--
DONE: 2 of 2 tasks shown
EOF
echo -n 'this is a first task without newline' > todo.txt
cat > done.txt <<EOF
x 2009-02-13 make the coffee +wakeup
x 2009-02-13 smell the coffee +wakeup
EOF
test_todo_session 'move to destination without EOL' <<EOF
>>> todo.sh -f move 2 todo.txt done.txt | sed "s#'[^']\{1,\}/\([^/']\{1,\}\)'#'\1'#g"
2 x 2009-02-13 smell the coffee +wakeup
TODO: 2 moved from 'done.txt' to 'todo.txt'.
>>> todo.sh -p ls
1 this is a first task without newline
2 x 2009-02-13 smell the coffee +wakeup
--
TODO: 2 of 2 tasks shown
>>> todo.sh -p listfile done.txt
1 x 2009-02-13 make the coffee +wakeup
--
DONE: 1 of 1 tasks shown
EOF
test_done

View File

@@ -1,5 +1,4 @@
#!/bin/bash #!/bin/bash
#
test_description='help functionality test_description='help functionality

View File

@@ -1,5 +1,4 @@
#!/bin/bash #!/bin/bash
#
test_description='shorthelp functionality test_description='shorthelp functionality
@@ -36,7 +35,6 @@ test_todo_session 'shorthelp output with custom action' <<EOF
See "help" for more details. See "help" for more details.
EOF EOF
# Verify that custom configuration is actually processed (when the -d option # Verify that custom configuration is actually processed (when the -d option
# precedes the -h option) by specifying a different actions directory and moving # precedes the -h option) by specifying a different actions directory and moving
# our custom action there. The help output should mention the "Add-On Actions". # our custom action there. The help output should mention the "Add-On Actions".

View File

@@ -1,5 +1,4 @@
#!/bin/bash #!/bin/bash
#
test_description='todo.sh configuration with a sole todo.txt data file. test_description='todo.sh configuration with a sole todo.txt data file.

View File

@@ -1,5 +1,4 @@
#!/bin/bash #!/bin/bash
#
test_description='Bash completion functionality test_description='Bash completion functionality

View File

@@ -1,5 +1,4 @@
#!/bin/bash #!/bin/bash
#
test_description='Bash context completion functionality test_description='Bash context completion functionality

View File

@@ -1,5 +1,4 @@
#!/bin/bash #!/bin/bash
#
test_description='Bash project completion functionality test_description='Bash project completion functionality

View File

@@ -1,5 +1,4 @@
#!/bin/bash #!/bin/bash
#
test_description='Bash task number completion functionality test_description='Bash task number completion functionality

View File

@@ -1,5 +1,4 @@
#!/bin/bash #!/bin/bash
#
test_description='Bash todo file completion functionality test_description='Bash todo file completion functionality

View File

@@ -1,5 +1,4 @@
#!/bin/bash #!/bin/bash
#
test_description='Bash add-on action completion functionality test_description='Bash add-on action completion functionality

View File

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

View File

@@ -1,5 +1,4 @@
#!/bin/bash #!/bin/bash
#
test_description='Bash completion with different path functionality test_description='Bash completion with different path functionality
@@ -28,8 +27,6 @@ _todo2()
test_todo_custom_completion _todo2 'all todo2 contexts' 'todo2 list @' '@garden @outdoor @outside' test_todo_custom_completion _todo2 'all todo2 contexts' 'todo2 list @' '@garden @outdoor @outside'
# Remove the test environment's bin directory from the PATH, so that our test # Remove the test environment's bin directory from the PATH, so that our test
# executable must be launched with an explicit path. # executable must be launched with an explicit path.
PATH=${PATH##"${PWD}/bin:"} PATH=${PATH##"${PWD}/bin:"}

View File

@@ -1,5 +1,4 @@
#!/bin/bash #!/bin/bash
#
test_description='Bash completion with different aliases functionality test_description='Bash completion with different aliases functionality
@@ -46,7 +45,6 @@ test_todo_session 'todo 1 and 2 contexts' <<EOF
@oriental @oriental
EOF EOF
# Define a second completion function that injects the different configuration # Define a second completion function that injects the different configuration
# file. In real use, this would be installed via # file. In real use, this would be installed via
# complete -F _todo2 todo2 # complete -F _todo2 todo2

View File

@@ -1,5 +1,4 @@
#!/bin/bash #!/bin/bash
#
test_description='Bash help completion functionality test_description='Bash help completion functionality

View File

@@ -172,12 +172,12 @@ test_set_editor () {
# the text_expect_* functions instead. # the text_expect_* functions instead.
test_ok_ () { test_ok_ () {
test_success=$(($test_success + 1)) test_success=$((test_success + 1))
say_color "" " ok $test_count: $@" say_color "" " ok $test_count: $@"
} }
test_failure_ () { test_failure_ () {
test_failure=$(($test_failure + 1)) test_failure=$((test_failure + 1))
say_color error "FAIL $test_count: $1" say_color error "FAIL $test_count: $1"
shift shift
echo "$@" echo "$@"
@@ -185,12 +185,12 @@ test_failure_ () {
} }
test_known_broken_ok_ () { test_known_broken_ok_ () {
test_fixed=$(($test_fixed+1)) test_fixed=$((test_fixed + 1))
say_color "" " FIXED $test_count: $@" say_color "" " FIXED $test_count: $@"
} }
test_known_broken_failure_ () { test_known_broken_failure_ () {
test_broken=$(($test_broken+1)) test_broken=$((test_broken + 1))
say_color skip " still broken $test_count: $@" say_color skip " still broken $test_count: $@"
} }
@@ -206,7 +206,7 @@ test_run_ () {
} }
test_skip () { test_skip () {
test_count=$(($test_count+1)) test_count=$((test_count + 1))
to_skip= to_skip=
for skp in $SKIP_TESTS for skp in $SKIP_TESTS
do do
@@ -364,7 +364,7 @@ test_external_without_stderr () {
test_ok_ "$descr" test_ok_ "$descr"
else else
if [ "$verbose" = t ]; then if [ "$verbose" = t ]; then
output=`echo; echo Stderr is:; cat "$stderr"` output=$(echo; echo Stderr is:; cat "$stderr")
else else
output= output=
fi fi
@@ -414,12 +414,12 @@ test_done () {
mkdir -p "$test_results_dir" mkdir -p "$test_results_dir"
test_results_path="$test_results_dir/${0%.sh}-$$" test_results_path="$test_results_dir/${0%.sh}-$$"
echo "total $test_count" >> $test_results_path echo "total $test_count" >> "$test_results_path"
echo "success $test_success" >> $test_results_path echo "success $test_success" >> "$test_results_path"
echo "fixed $test_fixed" >> $test_results_path echo "fixed $test_fixed" >> "$test_results_path"
echo "broken $test_broken" >> $test_results_path echo "broken $test_broken" >> "$test_results_path"
echo "failed $test_failure" >> $test_results_path echo "failed $test_failure" >> "$test_results_path"
echo "" >> $test_results_path echo "" >> "$test_results_path"
if test "$test_fixed" != 0 if test "$test_fixed" != 0
then then
@@ -428,7 +428,7 @@ test_done () {
if test "$test_broken" != 0 if test "$test_broken" != 0
then then
say_color error "still have $test_broken known breakage(s)" say_color error "still have $test_broken known breakage(s)"
msg="remaining $(($test_count-$test_broken)) test(s)" msg="remaining $((test_count - test_broken)) test(s)"
else else
msg="$test_count test(s)" msg="$test_count test(s)"
fi fi
@@ -471,12 +471,12 @@ rm -fr "$test" || {
test_init_todo () { test_init_todo () {
test "$#" = 1 || test "$#" = 1 ||
error "bug in the test script: not 1 parameter to test_init_todo" error "bug in the test script: not 1 parameter to test_init_todo"
owd=`pwd` owd=$(pwd)
root="$1" root="$1"
mkdir -p "$root" mkdir -p "$root"
cd "$root" || error "Cannot setup todo dir in $root" cd "$root" || error "Cannot setup todo dir in $root"
# Initialize the configuration file. Carefully quoted. # Initialize the configuration file. Carefully quoted.
sed -e 's|TODO_DIR=.*$|TODO_DIR="'"$TEST_DIRECTORY/$test"'"|' $TEST_DIRECTORY/../todo.cfg > todo.cfg sed -e 's|TODO_DIR=.*$|TODO_DIR="'"$TEST_DIRECTORY/$test"'"|' "$TEST_DIRECTORY/../todo.cfg" > todo.cfg
# Install latest todo.sh # Install latest todo.sh
mkdir bin mkdir bin
@@ -500,7 +500,7 @@ test_init_todo () {
#date: illegal option -- - #date: illegal option -- -
#usage: date [-jnu] [-d dst] [-r seconds] [-t west] [-v[+|-]val[ymwdHMS]] ... #usage: date [-jnu] [-d dst] [-r seconds] [-t west] [-v[+|-]val[ymwdHMS]] ...
# [-f fmt date | [[[mm]dd]HH]MM[[cc]yy][.ss]] [+format] # [-f fmt date | [[[mm]dd]HH]MM[[cc]yy][.ss]] [+format]
elif date --version 2>&1 | grep -q -e "-jnu"; then elif date --version 2>&1 | grep -q -e "-jnR\?u"; then
DATE_STYLE=Mac10.5 DATE_STYLE=Mac10.5
# on Mac OS X 10.4: # on Mac OS X 10.4:
#date --version #date --version
@@ -548,7 +548,7 @@ test_init_todo () {
# Usage: test_tick [increment] # Usage: test_tick [increment]
test_tick () { test_tick () {
TODO_TEST_TIME=$(($TODO_TEST_TIME + ${1:-86400})) TODO_TEST_TIME=$((TODO_TEST_TIME + ${1:-86400}))
} }
# Generate and run a series of tests based on a transcript. # Generate and run a series of tests based on a transcript.
@@ -581,14 +581,14 @@ test_todo_session () {
status=${line#=== } status=${line#=== }
;; ;;
"") "")
if [ ! -z "$cmd" ]; then if [ -n "$cmd" ]; then
if [ $status = 0 ]; then if [ "$status" = 0 ]; then
test_expect_output "$1 $subnum" "$cmd" test_expect_output "$1 $subnum" "$cmd"
else else
test_expect_code_and_output "$status" "$1 $subnum" "$cmd" test_expect_code_and_output "$status" "$1 $subnum" "$cmd"
fi fi
subnum=$(($subnum + 1)) subnum=$((subnum + 1))
cmd="" cmd=""
status=0 status=0
> expect > expect
@@ -602,8 +602,8 @@ test_todo_session () {
;; ;;
esac esac
done done
if [ ! -z "$cmd" ]; then if [ -n "$cmd" ]; then
if [ $status = 0 ]; then if [ "$status" = 0 ]; then
test_expect_output "$1 $subnum" "$cmd" test_expect_output "$1 $subnum" "$cmd"
else else
test_expect_code_and_output "$status" "$1 $subnum" "$cmd" test_expect_code_and_output "$status" "$1 $subnum" "$cmd"
@@ -645,7 +645,7 @@ test_todo_custom_completion () {
SAVEIFS=$IFS SAVEIFS=$IFS
IFS=' ' set -- $2 IFS=' ' set -- $2
COMP_WORDS=("$@") COMP_WORDS=("$@")
COMP_CWORD=$(($# - $offset)) COMP_CWORD=$(($# - offset))
IFS=' ' eval "set -- $expected" IFS=' ' eval "set -- $expected"
EXPECT=("$@") EXPECT=("$@")
@@ -693,6 +693,13 @@ cd -P "$test" || exit 1
# but use something specified by the framework. # but use something specified by the framework.
HOME=$(pwd) HOME=$(pwd)
export HOME export HOME
# Unset XDG_CONFIG_HOME as that is used as a config alternative.
unset XDG_CONFIG_HOME
# User add-ons may override built-in commands; these could have incompatible
# behavior that makes the tests fail. Avoid picking up user add-ons by
# explicitly configuring the first default location (which with the redirected
# HOME lies within the test directory and usually does not exist).
export TODO_ACTIONS_DIR="$HOME/.todo/actions"
this_test=${0##*/} this_test=${0##*/}
this_test=${this_test%%-*} this_test=${this_test%%-*}

View File

@@ -2,7 +2,7 @@
# Your todo.txt directory (this should be an absolute path) # Your todo.txt directory (this should be an absolute path)
#export TODO_DIR="/Users/gina/Documents/todo" #export TODO_DIR="/Users/gina/Documents/todo"
export TODO_DIR=$(dirname "$0") export TODO_DIR=${HOME:-$USERPROFILE}
# Your todo/done/report.txt locations # Your todo/done/report.txt locations
export TODO_FILE="$TODO_DIR/todo.txt" export TODO_FILE="$TODO_DIR/todo.txt"
@@ -62,10 +62,21 @@ export REPORT_FILE="$TODO_DIR/report.txt"
# #
# export COLOR_DONE=$LIGHT_GREY # export COLOR_DONE=$LIGHT_GREY
# There is highlighting for projects and contexts. # There is highlighting for projects, contexts, dates, and item numbers.
# #
# export COLOR_PROJECT=$RED # export COLOR_PROJECT=$RED
# export COLOR_CONTEXT=$RED # export COLOR_CONTEXT=$RED
# export COLOR_DATE=$BLUE
# export COLOR_NUMBER=$LIGHT_GREY
# There is highlighting for metadata key:value pairs e.g.
# DUE:2006-08-01 or note:MYNOTE
#
# export COLOR_META=$CYAN
# ... and for date extensions (due:yyyy-mm-dd, t:yyyy-mm-dd and again:X)
#
# export COLOR_DATEEXT=$LIGHT_BLUE
# === BEHAVIOR === # === BEHAVIOR ===

363
todo.sh
View File

@@ -1,10 +1,10 @@
#! /bin/bash #!/usr/bin/env bash
# === HEAVY LIFTING === # === HEAVY LIFTING ===
shopt -s extglob extquote shopt -s extglob extquote
# NOTE: Todo.sh requires the .todo/config configuration file to run. # NOTE: Todo.sh requires a configuration file to run.
# Place the .todo/config file in your home directory or use the -d option for a custom location. # Place it in one of the default locations or use the -d option for a custom location.
[ -f VERSION-FILE ] && . VERSION-FILE || VERSION="@DEV_VERSION@" [ -f VERSION-FILE ] && . VERSION-FILE || VERSION="@DEV_VERSION@"
version() { version() {
@@ -51,7 +51,7 @@ shorthelp()
deduplicate deduplicate
del|rm ITEM# [TERM] del|rm ITEM# [TERM]
depri|dp ITEM#[, ITEM#, ITEM#, ...] depri|dp ITEM#[, ITEM#, ITEM#, ...]
do ITEM#[, ITEM#, ITEM#, ...] done|do ITEM#[, ITEM#, ITEM#, ...]
help [ACTION...] help [ACTION...]
list|ls [TERM...] list|ls [TERM...]
listall|lsa [TERM...] listall|lsa [TERM...]
@@ -62,7 +62,7 @@ shorthelp()
listproj|lsprj [TERM...] listproj|lsprj [TERM...]
move|mv ITEM# DEST [SRC] move|mv ITEM# DEST [SRC]
prepend|prep ITEM# "TEXT TO PREPEND" prepend|prep ITEM# "TEXT TO PREPEND"
pri|p ITEM# PRIORITY pri|p ITEM# PRIORITY[, ITEM# PRIORITY, ...]
replace ITEM# "UPDATED TODO" replace ITEM# "UPDATED TODO"
report report
shorthelp shorthelp
@@ -83,6 +83,8 @@ shorthelp()
help() help()
{ {
local indentedJoinedConfigFileLocations
printf -v indentedJoinedConfigFileLocations ' %s\n' "${configFileLocations[@]}"
cat <<-EndOptionsHelp cat <<-EndOptionsHelp
Usage: $oneline_usage Usage: $oneline_usage
@@ -96,7 +98,8 @@ help()
-c -c
Color mode Color mode
-d CONFIG_FILE -d CONFIG_FILE
Use a configuration file other than the default ~/.todo/config Use a configuration file other than one of the defaults:
$indentedJoinedConfigFileLocations
-f -f
Forces actions without confirmation or interactive input Forces actions without confirmation or interactive input
-h -h
@@ -131,10 +134,9 @@ help()
-x -x
Disables TODOTXT_FINAL_FILTER Disables TODOTXT_FINAL_FILTER
EndOptionsHelp EndOptionsHelp
[ $TODOTXT_VERBOSE -gt 1 ] && cat <<-'EndVerboseHelp' [ "$TODOTXT_VERBOSE" -gt 1 ] && cat <<-'EndVerboseHelp'
Environment variables: Environment variables:
TODOTXT_AUTO_ARCHIVE is same as option -a (0)/-A (1) TODOTXT_AUTO_ARCHIVE is same as option -a (0)/-A (1)
TODOTXT_CFG_FILE=CONFIG_FILE is same as option -d CONFIG_FILE TODOTXT_CFG_FILE=CONFIG_FILE is same as option -d CONFIG_FILE
@@ -142,13 +144,16 @@ help()
TODOTXT_PRESERVE_LINE_NUMBERS is same as option -n (0)/-N (1) TODOTXT_PRESERVE_LINE_NUMBERS is same as option -n (0)/-N (1)
TODOTXT_PLAIN is same as option -p (1)/-c (0) TODOTXT_PLAIN is same as option -p (1)/-c (0)
TODOTXT_DATE_ON_ADD is same as option -t (1)/-T (0) TODOTXT_DATE_ON_ADD is same as option -t (1)/-T (0)
TODOTXT_PRIORITY_ON_ADD=pri default priority A-Z
TODOTXT_VERBOSE=1 is same as option -v TODOTXT_VERBOSE=1 is same as option -v
TODOTXT_DISABLE_FILTER=1 is same as option -x TODOTXT_DISABLE_FILTER=1 is same as option -x
TODOTXT_DEFAULT_ACTION="" run this when called with no arguments TODOTXT_DEFAULT_ACTION="" run this when called with no arguments
TODOTXT_SORT_COMMAND="sort ..." customize list output TODOTXT_SORT_COMMAND="sort ..." customize list output
TODOTXT_FINAL_FILTER="sed ..." customize list after color, P@+ hiding TODOTXT_FINAL_FILTER="sed ..." customize list after color, P@+ hiding
TODOTXT_SOURCEVAR=\$DONE_FILE use another source for listcon, listproj TODOTXT_SOURCEVAR=\$DONE_FILE use another source for listcon, listproj
TODOTXT_SIGIL_BEFORE_PATTERN="" optionally allow chars preceding +p / @c
TODOTXT_SIGIL_VALID_PATTERN=.* tweak the allowed chars for +p and @c
TODOTXT_SIGIL_AFTER_PATTERN="" optionally allow chars after +p / @c
EndVerboseHelp EndVerboseHelp
actionsHelp actionsHelp
@@ -200,6 +205,7 @@ actionsHelp()
Deprioritizes (removes the priority) from the task(s) Deprioritizes (removes the priority) from the task(s)
on line ITEM# in todo.txt. on line ITEM# in todo.txt.
done ITEM#[, ITEM#, ITEM#, ...]
do ITEM#[, ITEM#, ITEM#, ...] do ITEM#[, ITEM#, ITEM#, ...]
Marks task(s) on line ITEM# as done in todo.txt. Marks task(s) on line ITEM# as done in todo.txt.
@@ -212,9 +218,13 @@ actionsHelp()
Displays all tasks that contain TERM(s) sorted by priority with line Displays all tasks that contain TERM(s) sorted by priority with line
numbers. Each task must match all TERM(s) (logical AND); to display numbers. Each task must match all TERM(s) (logical AND); to display
tasks that contain any TERM (logical OR), use tasks that contain any TERM (logical OR), use
"TERM1\|TERM2\|..." (with quotes), or TERM1\\\|TERM2 (unquoted). 'TERM1\|TERM2\|...' (with quotes), or TERM1\\\|TERM2 (unquoted).
Hides all tasks that contain TERM(s) preceded by a Hides all tasks that contain TERM(s) preceded by a
minus sign (i.e. -TERM). If no TERM specified, lists entire todo.txt. minus sign (i.e. -TERM).
TERM(s) are grep-style basic regular expressions; for literal matching,
put a single backslash before any [ ] \ $ * . ^ and enclose the entire
TERM in single quotes, or use double backslashes and extra shell-quoting.
If no TERM specified, lists entire todo.txt.
listall [TERM...] listall [TERM...]
lsa [TERM...] lsa [TERM...]
@@ -292,7 +302,7 @@ addonHelp()
didPrintAddonActionsHeader= didPrintAddonActionsHeader=
for action in "$TODO_ACTIONS_DIR"/* for action in "$TODO_ACTIONS_DIR"/*
do do
if [ -f "$action" -a -x "$action" ]; then if [ -f "$action" ] && [ -x "$action" ]; then
if [ ! "$didPrintAddonActionsHeader" ]; then if [ ! "$didPrintAddonActionsHeader" ]; then
cat <<-EndAddonActionsHeader cat <<-EndAddonActionsHeader
Add-on Actions: Add-on Actions:
@@ -300,14 +310,14 @@ addonHelp()
didPrintAddonActionsHeader=1 didPrintAddonActionsHeader=1
fi fi
"$action" usage "$action" usage
elif [ -d "$action" -a -x "$action/$(basename $action)" ]; then elif [ -d "$action" ] && [ -x "$action"/"$(basename "$action")" ]; then
if [ ! "$didPrintAddonActionsHeader" ]; then if [ ! "$didPrintAddonActionsHeader" ]; then
cat <<-EndAddonActionsHeader cat <<-EndAddonActionsHeader
Add-on Actions: Add-on Actions:
EndAddonActionsHeader EndAddonActionsHeader
didPrintAddonActionsHeader=1 didPrintAddonActionsHeader=1
fi fi
"$action/$(basename $action)" usage "$action"/"$(basename "$action")" usage
fi fi
done done
fi fi
@@ -318,10 +328,10 @@ actionUsage()
for actionName for actionName
do do
action="${TODO_ACTIONS_DIR}/${actionName}" action="${TODO_ACTIONS_DIR}/${actionName}"
if [ -f "$action" -a -x "$action" ]; then if [ -f "$action" ] && [ -x "$action" ]; then
"$action" usage "$action" usage
elif [ -d "$action" -a -x "$action/$(basename $action)" ]; then elif [ -d "$action" ] && [ -x "$action"/"$(basename "$action")" ]; then
"$action/$(basename $action)" usage "$action"/"$(basename "$action")" usage
else else
builtinActionUsage=$(actionsHelp | sed -n -e "/^ ${actionName//\//\\/} /,/^\$/p" -e "/^ ${actionName//\//\\/}$/,/^\$/p") builtinActionUsage=$(actionsHelp | sed -n -e "/^ ${actionName//\//\\/} /,/^\$/p" -e "/^ ${actionName//\//\\/}$/,/^\$/p")
if [ "$builtinActionUsage" ]; then if [ "$builtinActionUsage" ]; then
@@ -350,6 +360,20 @@ die()
exit 1 exit 1
} }
confirm()
{
[ $TODOTXT_FORCE = 0 ] || return 0
printf %s "${1:?}? (y/n) "
local readArgs=(-e -r)
[ -n "${BASH_VERSINFO:-}" ] && [ \( ${BASH_VERSINFO[0]} -eq 4 -a ${BASH_VERSINFO[1]} -ge 1 \) -o ${BASH_VERSINFO[0]} -gt 4 ] &&
readArgs+=(-N 1) # Bash 4.1+ supports -N nchars
local answer
read "${readArgs[@]}" answer
echo
[ "$answer" = "y" ]
}
cleaninput() cleaninput()
{ {
# Parameters: When $1 = "for sed", performs additional escaping for use # Parameters: When $1 = "for sed", performs additional escaping for use
@@ -376,8 +400,9 @@ getPrefix()
# Parameters: $1: todo file; empty means $TODO_FILE. # Parameters: $1: todo file; empty means $TODO_FILE.
# Returns: Uppercase FILE prefix to be used in place of "TODO:" where # Returns: Uppercase FILE prefix to be used in place of "TODO:" where
# a different todo file can be specified. # a different todo file can be specified.
local base=$(basename "${1:-$TODO_FILE}") local base
echo "${base%%.[^.]*}" | tr 'a-z' 'A-Z' base=$(basename "${1:-$TODO_FILE}")
echo "${base%%.[^.]*}" | tr '[:lower:]' '[:upper:]'
} }
getTodo() getTodo()
@@ -402,8 +427,8 @@ getNewtodo()
# Postcondition: $newtodo contains task text. # Postcondition: $newtodo contains task text.
local item=$1 local item=$1
[ -z "$item" ] && die 'Programming error: $item should exist.' [ -z "$item" ] && die "Programming error: $item should exist."
[ "${item//[0-9]/}" ] && die 'Programming error: $item should be numeric.' [ "${item//[0-9]/}" ] && die "Programming error: $item should be numeric."
newtodo=$(sed "$item!d" "${2:-$TODO_FILE}") newtodo=$(sed "$item!d" "${2:-$TODO_FILE}")
[ -z "$newtodo" ] && die "$(getPrefix "$2"): No updated task $item." [ -z "$newtodo" ] && die "$(getPrefix "$2"): No updated task $item."
@@ -427,7 +452,7 @@ replaceOrPrepend()
if [[ -z "$1" && $TODOTXT_FORCE = 0 ]]; then if [[ -z "$1" && $TODOTXT_FORCE = 0 ]]; then
echo -n "$querytext" echo -n "$querytext"
read -e -r input read -r -i "$todo" -e input
else else
input=$* input=$*
fi fi
@@ -437,7 +462,7 @@ replaceOrPrepend()
priority=$(sed -e "$item!d" -e "${item}s/${priAndDateExpr}.*/\\1/" "$TODO_FILE") priority=$(sed -e "$item!d" -e "${item}s/${priAndDateExpr}.*/\\1/" "$TODO_FILE")
prepdate=$(sed -e "$item!d" -e "${item}s/${priAndDateExpr}.*/\\2/" "$TODO_FILE") prepdate=$(sed -e "$item!d" -e "${item}s/${priAndDateExpr}.*/\\2/" "$TODO_FILE")
if [ "$prepdate" -a "$action" = "replace" ] && [ "$(echo "$input"|sed -e "s/${priAndDateExpr}.*/\\1\\2/")" ]; then if [ "$prepdate" ] && [ "$action" = "replace" ] && [ "$(echo "$input"|sed -e "s/${priAndDateExpr}.*/\\1\\2/")" ]; then
# If the replaced text starts with a [priority +] date, it will replace # If the replaced text starts with a [priority +] date, it will replace
# the existing date, too. # the existing date, too.
prepdate= prepdate=
@@ -448,7 +473,7 @@ replaceOrPrepend()
# date again. # date again.
cleaninput "for sed" cleaninput "for sed"
sed -i.bak -e "$item s/^${priority}${prepdate}//" -e "$item s|^.*|${priority}${prepdate}${input}${backref}|" "$TODO_FILE" sed -i.bak -e "$item s/^${priority}${prepdate}//" -e "$item s|^.*|${priority}${prepdate}${input}${backref}|" "$TODO_FILE"
if [ $TODOTXT_VERBOSE -gt 0 ]; then if [ "$TODOTXT_VERBOSE" -gt 0 ]; then
getNewtodo "$item" getNewtodo "$item"
case "$action" in case "$action" in
replace) replace)
@@ -463,6 +488,13 @@ replaceOrPrepend()
fi fi
} }
fixMissingEndOfLine()
{
# Parameters: $1: todo file; empty means $TODO_FILE.
todo_path="${1:-$TODO_FILE}"
[[ -f $todo_path && $(tail -c1 "$todo_path") ]] && echo "" >> "$todo_path"
}
uppercasePriority() uppercasePriority()
{ {
# Precondition: $input contains task text for which to uppercase priority. # Precondition: $input contains task text for which to uppercase priority.
@@ -473,7 +505,7 @@ uppercasePriority()
do do
upperPriority="${upperPriority};s/^[(]${lower[i]}[)]/(${upper[i]})/" upperPriority="${upperPriority};s/^[(]${lower[i]}[)]/(${upper[i]})/"
done done
input=$(echo "$input" | sed $upperPriority) input=$(echo "$input" | sed "$upperPriority")
} }
#Preserving environment variables so they don't get clobbered by the config file #Preserving environment variables so they don't get clobbered by the config file
@@ -482,6 +514,7 @@ OVR_TODOTXT_FORCE="$TODOTXT_FORCE"
OVR_TODOTXT_PRESERVE_LINE_NUMBERS="$TODOTXT_PRESERVE_LINE_NUMBERS" OVR_TODOTXT_PRESERVE_LINE_NUMBERS="$TODOTXT_PRESERVE_LINE_NUMBERS"
OVR_TODOTXT_PLAIN="$TODOTXT_PLAIN" OVR_TODOTXT_PLAIN="$TODOTXT_PLAIN"
OVR_TODOTXT_DATE_ON_ADD="$TODOTXT_DATE_ON_ADD" OVR_TODOTXT_DATE_ON_ADD="$TODOTXT_DATE_ON_ADD"
OVR_TODOTXT_PRIORITY_ON_ADD="$TODOTXT_PRIORITY_ON_ADD"
OVR_TODOTXT_DISABLE_FILTER="$TODOTXT_DISABLE_FILTER" OVR_TODOTXT_DISABLE_FILTER="$TODOTXT_DISABLE_FILTER"
OVR_TODOTXT_VERBOSE="$TODOTXT_VERBOSE" OVR_TODOTXT_VERBOSE="$TODOTXT_VERBOSE"
OVR_TODOTXT_DEFAULT_ACTION="$TODOTXT_DEFAULT_ACTION" OVR_TODOTXT_DEFAULT_ACTION="$TODOTXT_DEFAULT_ACTION"
@@ -489,7 +522,7 @@ OVR_TODOTXT_SORT_COMMAND="$TODOTXT_SORT_COMMAND"
OVR_TODOTXT_FINAL_FILTER="$TODOTXT_FINAL_FILTER" OVR_TODOTXT_FINAL_FILTER="$TODOTXT_FINAL_FILTER"
# Prevent GREP_OPTIONS from malforming grep's output # Prevent GREP_OPTIONS from malforming grep's output
GREP_OPTIONS="" export GREP_OPTIONS=""
# == PROCESS OPTIONS == # == PROCESS OPTIONS ==
while getopts ":fhpcnNaAtTvVx+@Pd:" Option while getopts ":fhpcnNaAtTvVx+@Pd:" Option
@@ -502,7 +535,7 @@ do
## number shows context names and an odd number hides context ## number shows context names and an odd number hides context
## names. ## names.
: $(( HIDE_CONTEXT_NAMES++ )) : $(( HIDE_CONTEXT_NAMES++ ))
if [ $(( $HIDE_CONTEXT_NAMES % 2 )) -eq 0 ] if [ $(( HIDE_CONTEXT_NAMES % 2 )) -eq 0 ]
then then
## Zero or even value -- show context names ## Zero or even value -- show context names
unset HIDE_CONTEXTS_SUBSTITUTION unset HIDE_CONTEXTS_SUBSTITUTION
@@ -518,7 +551,7 @@ do
## number shows project names and an odd number hides project ## number shows project names and an odd number hides project
## names. ## names.
: $(( HIDE_PROJECT_NAMES++ )) : $(( HIDE_PROJECT_NAMES++ ))
if [ $(( $HIDE_PROJECT_NAMES % 2 )) -eq 0 ] if [ $(( HIDE_PROJECT_NAMES % 2 )) -eq 0 ]
then then
## Zero or even value -- show project names ## Zero or even value -- show project names
unset HIDE_PROJECTS_SUBSTITUTION unset HIDE_PROJECTS_SUBSTITUTION
@@ -565,7 +598,7 @@ do
## number shows priority labels and an odd number hides priority ## number shows priority labels and an odd number hides priority
## labels. ## labels.
: $(( HIDE_PRIORITY_LABELS++ )) : $(( HIDE_PRIORITY_LABELS++ ))
if [ $(( $HIDE_PRIORITY_LABELS % 2 )) -eq 0 ] if [ $(( HIDE_PRIORITY_LABELS % 2 )) -eq 0 ]
then then
## Zero or even value -- show priority labels ## Zero or even value -- show priority labels
unset HIDE_PRIORITY_SUBSTITUTION unset HIDE_PRIORITY_SUBSTITUTION
@@ -589,26 +622,32 @@ do
x) x)
OVR_TODOTXT_DISABLE_FILTER=1 OVR_TODOTXT_DISABLE_FILTER=1
;; ;;
*)
usage
;;
esac esac
done done
shift $(($OPTIND - 1)) shift $((OPTIND - 1))
# defaults if not yet defined # defaults if not yet defined
TODOTXT_VERBOSE=${TODOTXT_VERBOSE:-1} TODOTXT_VERBOSE=${TODOTXT_VERBOSE:-1}
TODOTXT_PLAIN=${TODOTXT_PLAIN:-0} TODOTXT_PLAIN=${TODOTXT_PLAIN:-0}
TODOTXT_CFG_FILE=${TODOTXT_CFG_FILE:-$HOME/.todo/config}
TODOTXT_FORCE=${TODOTXT_FORCE:-0} TODOTXT_FORCE=${TODOTXT_FORCE:-0}
TODOTXT_PRESERVE_LINE_NUMBERS=${TODOTXT_PRESERVE_LINE_NUMBERS:-1} TODOTXT_PRESERVE_LINE_NUMBERS=${TODOTXT_PRESERVE_LINE_NUMBERS:-1}
TODOTXT_AUTO_ARCHIVE=${TODOTXT_AUTO_ARCHIVE:-1} TODOTXT_AUTO_ARCHIVE=${TODOTXT_AUTO_ARCHIVE:-1}
TODOTXT_DATE_ON_ADD=${TODOTXT_DATE_ON_ADD:-0} TODOTXT_DATE_ON_ADD=${TODOTXT_DATE_ON_ADD:-0}
TODOTXT_PRIORITY_ON_ADD=${TODOTXT_PRIORITY_ON_ADD:-}
TODOTXT_DEFAULT_ACTION=${TODOTXT_DEFAULT_ACTION:-} TODOTXT_DEFAULT_ACTION=${TODOTXT_DEFAULT_ACTION:-}
TODOTXT_SORT_COMMAND=${TODOTXT_SORT_COMMAND:-env LC_COLLATE=C sort -f -k2} TODOTXT_SORT_COMMAND=${TODOTXT_SORT_COMMAND:-env LC_COLLATE=C sort -f -k2}
TODOTXT_DISABLE_FILTER=${TODOTXT_DISABLE_FILTER:-} TODOTXT_DISABLE_FILTER=${TODOTXT_DISABLE_FILTER:-}
TODOTXT_FINAL_FILTER=${TODOTXT_FINAL_FILTER:-cat} TODOTXT_FINAL_FILTER=${TODOTXT_FINAL_FILTER:-cat}
TODOTXT_GLOBAL_CFG_FILE=${TODOTXT_GLOBAL_CFG_FILE:-/etc/todo/config} TODOTXT_GLOBAL_CFG_FILE=${TODOTXT_GLOBAL_CFG_FILE:-/etc/todo/config}
TODOTXT_SIGIL_BEFORE_PATTERN=${TODOTXT_SIGIL_BEFORE_PATTERN:-} # Allow any other non-whitespace entity before +project and @context; should be an optional match; example: \(w:\)\{0,1\} to allow w:@context.
TODOTXT_SIGIL_VALID_PATTERN=${TODOTXT_SIGIL_VALID_PATTERN:-.*} # Limit the valid characters (from the default any non-whitespace sequence) for +project and @context; example: [a-zA-Z]\{3,\} to only allow alphabetic ones that are at least three characters long.
TODOTXT_SIGIL_AFTER_PATTERN=${TODOTXT_SIGIL_AFTER_PATTERN:-} # Allow any other non-whitespace entity after +project and @context; should be an optional match; example: )\{0,1\} to allow (with the corresponding TODOTXT_SIGIL_BEFORE_PATTERN) enclosing in parentheses.
# Export all TODOTXT_* variables # Export all TODOTXT_* variables
export ${!TODOTXT_@} export "${!TODOTXT_@}"
# Default color map # Default color map
export NONE='' export NONE=''
@@ -636,9 +675,13 @@ export PRI_B=$GREEN # color for B priority
export PRI_C=$LIGHT_BLUE # color for C priority export PRI_C=$LIGHT_BLUE # color for C priority
export PRI_X=$WHITE # color unless explicitly defined export PRI_X=$WHITE # color unless explicitly defined
# Default project and context colors. # Default project, context, date, item number, and metadata key:value pairs colors.
export COLOR_PROJECT=$NONE export COLOR_PROJECT=$NONE
export COLOR_CONTEXT=$NONE export COLOR_CONTEXT=$NONE
export COLOR_DATE=$NONE
export COLOR_DATEEXT=$NONE
export COLOR_NUMBER=$NONE
export COLOR_META=$NONE
# Default highlight colors. # Default highlight colors.
export COLOR_DONE=$LIGHT_GREY # color for done (but not yet archived) tasks export COLOR_DONE=$LIGHT_GREY # color for done (but not yet archived) tasks
@@ -649,78 +692,44 @@ export COLOR_DONE=$LIGHT_GREY # color for done (but not yet archived) tasks
# (todo.sh add 42 ", foo") syntactically correct. # (todo.sh add 42 ", foo") syntactically correct.
export SENTENCE_DELIMITERS=',.:;' export SENTENCE_DELIMITERS=',.:;'
[ -e "$TODOTXT_CFG_FILE" ] || { configFileLocations=(
CFG_FILE_ALT="$HOME/todo.cfg" "$HOME/.todo/config"
"$HOME/todo.cfg"
"$HOME/.todo.cfg"
"${XDG_CONFIG_HOME:-$HOME/.config}/todo/config"
"$(dirname "$0")/todo.cfg"
"$TODOTXT_GLOBAL_CFG_FILE"
)
[ -e "$TODOTXT_CFG_FILE" ] || for CFG_FILE_ALT in "${configFileLocations[@]}"
do
if [ -e "$CFG_FILE_ALT" ] if [ -e "$CFG_FILE_ALT" ]
then then
TODOTXT_CFG_FILE="$CFG_FILE_ALT" TODOTXT_CFG_FILE="$CFG_FILE_ALT"
break
fi fi
} done
[ -e "$TODOTXT_CFG_FILE" ] || { if [ -z "$TODO_ACTIONS_DIR" ] || [ ! -d "$TODO_ACTIONS_DIR" ]
CFG_FILE_ALT="$HOME/.todo.cfg"
if [ -e "$CFG_FILE_ALT" ]
then
TODOTXT_CFG_FILE="$CFG_FILE_ALT"
fi
}
[ -e "$TODOTXT_CFG_FILE" ] || {
CFG_FILE_ALT="${XDG_CONFIG_HOME:-$HOME/.config}/todo/config"
if [ -e "$CFG_FILE_ALT" ]
then
TODOTXT_CFG_FILE="$CFG_FILE_ALT"
fi
}
[ -e "$TODOTXT_CFG_FILE" ] || {
CFG_FILE_ALT=$(dirname "$0")"/todo.cfg"
if [ -e "$CFG_FILE_ALT" ]
then
TODOTXT_CFG_FILE="$CFG_FILE_ALT"
fi
}
[ -e "$TODOTXT_CFG_FILE" ] || {
CFG_FILE_ALT="$TODOTXT_GLOBAL_CFG_FILE"
if [ -e "$CFG_FILE_ALT" ]
then
TODOTXT_CFG_FILE="$CFG_FILE_ALT"
fi
}
if [ -z "$TODO_ACTIONS_DIR" -o ! -d "$TODO_ACTIONS_DIR" ]
then then
TODO_ACTIONS_DIR="$HOME/.todo/actions" TODO_ACTIONS_DIR="$HOME/.todo/actions"
export TODO_ACTIONS_DIR export TODO_ACTIONS_DIR
fi fi
[ -d "$TODO_ACTIONS_DIR" ] || { [ -d "$TODO_ACTIONS_DIR" ] || for TODO_ACTIONS_DIR_ALT in \
TODO_ACTIONS_DIR_ALT="$HOME/.todo.actions.d" "$HOME/.todo.actions.d" \
"${XDG_CONFIG_HOME:-$HOME/.config}/todo/actions"
do
if [ -d "$TODO_ACTIONS_DIR_ALT" ] if [ -d "$TODO_ACTIONS_DIR_ALT" ]
then then
TODO_ACTIONS_DIR="$TODO_ACTIONS_DIR_ALT" TODO_ACTIONS_DIR="$TODO_ACTIONS_DIR_ALT"
break
fi fi
} done
[ -d "$TODO_ACTIONS_DIR" ] || {
TODO_ACTIONS_DIR_ALT="${XDG_CONFIG_HOME:-$HOME/.config}/todo/actions"
if [ -d "$TODO_ACTIONS_DIR_ALT" ]
then
TODO_ACTIONS_DIR="$TODO_ACTIONS_DIR_ALT"
fi
}
# === SANITY CHECKS (thanks Karl!) === # === SANITY CHECKS (thanks Karl!) ===
[ -r "$TODOTXT_CFG_FILE" ] || dieWithHelp "$1" "Fatal Error: Cannot read configuration file $TODOTXT_CFG_FILE" [ -r "$TODOTXT_CFG_FILE" ] || dieWithHelp "$1" "Fatal Error: Cannot read configuration file ${TODOTXT_CFG_FILE:-${configFileLocations[0]}}"
. "$TODOTXT_CFG_FILE" . "$TODOTXT_CFG_FILE"
@@ -740,6 +749,9 @@ fi
if [ -n "$OVR_TODOTXT_DATE_ON_ADD" ] ; then if [ -n "$OVR_TODOTXT_DATE_ON_ADD" ] ; then
TODOTXT_DATE_ON_ADD="$OVR_TODOTXT_DATE_ON_ADD" TODOTXT_DATE_ON_ADD="$OVR_TODOTXT_DATE_ON_ADD"
fi fi
if [ -n "$OVR_TODOTXT_PRIORITY_ON_ADD" ] ; then
TODOTXT_PRIORITY_ON_ADD="$OVR_TODOTXT_PRIORITY_ON_ADD"
fi
if [ -n "$OVR_TODOTXT_DISABLE_FILTER" ] ; then if [ -n "$OVR_TODOTXT_DISABLE_FILTER" ] ; then
TODOTXT_DISABLE_FILTER="$OVR_TODOTXT_DISABLE_FILTER" TODOTXT_DISABLE_FILTER="$OVR_TODOTXT_DISABLE_FILTER"
fi fi
@@ -759,22 +771,32 @@ fi
ACTION=${1:-$TODOTXT_DEFAULT_ACTION} ACTION=${1:-$TODOTXT_DEFAULT_ACTION}
[ -z "$ACTION" ] && usage [ -z "$ACTION" ] && usage
[ -d "$TODO_DIR" ] || mkdir -p $TODO_DIR 2> /dev/null || dieWithHelp "$1" "Fatal Error: $TODO_DIR is not a directory" [ -d "$TODO_DIR" ] || mkdir -p "$TODO_DIR" 2> /dev/null || dieWithHelp "$1" "Fatal Error: $TODO_DIR is not a directory"
( cd "$TODO_DIR" ) || dieWithHelp "$1" "Fatal Error: Unable to cd to $TODO_DIR" ( cd "$TODO_DIR" ) || dieWithHelp "$1" "Fatal Error: Unable to cd to $TODO_DIR"
[ -z "$TODOTXT_PRIORITY_ON_ADD" ] \
|| echo "$TODOTXT_PRIORITY_ON_ADD" | grep -q "^[A-Z]$" \
|| die "TODOTXT_PRIORITY_ON_ADD should be a capital letter from A to Z (it is now \"$TODOTXT_PRIORITY_ON_ADD\")."
[ -f "$TODO_FILE" -o -c "$TODO_FILE" ] || > "$TODO_FILE" [ -z "$TODO_FILE" ] && TODO_FILE="$TODO_DIR/todo.txt"
[ -f "$DONE_FILE" -o -c "$DONE_FILE" ] || > "$DONE_FILE" [ -z "$DONE_FILE" ] && DONE_FILE="$TODO_DIR/done.txt"
[ -f "$REPORT_FILE" -o -c "$REPORT_FILE" ] || > "$REPORT_FILE" [ -z "$REPORT_FILE" ] && REPORT_FILE="$TODO_DIR/report.txt"
[ -f "$TODO_FILE" ] || [ -c "$TODO_FILE" ] || > "$TODO_FILE"
[ -f "$DONE_FILE" ] || [ -c "$DONE_FILE" ] || > "$DONE_FILE"
[ -f "$REPORT_FILE" ] || [ -c "$REPORT_FILE" ] || > "$REPORT_FILE"
if [ $TODOTXT_PLAIN = 1 ]; then if [ $TODOTXT_PLAIN = 1 ]; then
for clr in ${!PRI_@}; do for clr in ${!PRI_@}; do
export $clr=$NONE export "$clr"="$NONE"
done done
PRI_X=$NONE PRI_X=$NONE
DEFAULT=$NONE DEFAULT=$NONE
COLOR_DONE=$NONE COLOR_DONE=$NONE
COLOR_PROJECT=$NONE COLOR_PROJECT=$NONE
COLOR_CONTEXT=$NONE COLOR_CONTEXT=$NONE
COLOR_DATE=$NONE
COLOR_NUMBER=$NONE
COLOR_META=$NONE
fi fi
[[ "$HIDE_PROJECTS_SUBSTITUTION" ]] && COLOR_PROJECT="$NONE" [[ "$HIDE_PROJECTS_SUBSTITUTION" ]] && COLOR_PROJECT="$NONE"
@@ -786,12 +808,18 @@ _addto() {
cleaninput cleaninput
uppercasePriority uppercasePriority
if [[ $TODOTXT_DATE_ON_ADD = 1 ]]; then if [[ "$TODOTXT_DATE_ON_ADD" -eq 1 ]]; then
now=$(date '+%Y-%m-%d') now=$(date '+%Y-%m-%d')
input=$(echo "$input" | sed -e 's/^\(([A-Z]) \)\{0,1\}/\1'"$now /") input=$(echo "$input" | sed -e 's/^\(([A-Z]) \)\{0,1\}/\1'"$now /")
fi fi
if [[ -n "$TODOTXT_PRIORITY_ON_ADD" ]]; then
if ! echo "$input" | grep -q '^([A-Z])'; then
input=$(echo -n "($TODOTXT_PRIORITY_ON_ADD) " ; echo "$input")
fi
fi
fixMissingEndOfLine "$file"
echo "$input" >> "$file" echo "$input" >> "$file"
if [ $TODOTXT_VERBOSE -gt 0 ]; then if [ "$TODOTXT_VERBOSE" -gt 0 ]; then
TASKNUM=$(sed -n '$ =' "$file") TASKNUM=$(sed -n '$ =' "$file")
echo "$TASKNUM $input" echo "$TASKNUM $input"
echo "$(getPrefix "$file"): $TASKNUM added." echo "$(getPrefix "$file"): $TASKNUM added."
@@ -859,7 +887,7 @@ _list() {
_format "$src" '' "$@" _format "$src" '' "$@"
if [ $TODOTXT_VERBOSE -gt 0 ]; then if [ "$TODOTXT_VERBOSE" -gt 0 ]; then
echo "--" echo "--"
echo "$(getPrefix "$src"): ${NUMTASKS:-0} of ${TOTALTASKS:-0} tasks shown" echo "$(getPrefix "$src"): ${NUMTASKS:-0} of ${TOTALTASKS:-0} tasks shown"
fi fi
@@ -919,7 +947,7 @@ _format()
s/^ /00/; s/^ /00/;
s/^ /0/; s/^ /0/;
''' \ ''' \
| eval ${TODOTXT_SORT_COMMAND} \ | eval "${TODOTXT_SORT_COMMAND}" \
| awk ''' | awk '''
function highlight(colorVar, color) { function highlight(colorVar, color) {
color = ENVIRON[colorVar] color = ENVIRON[colorVar]
@@ -945,15 +973,35 @@ _format()
ctx_beg = highlight("COLOR_CONTEXT") ctx_beg = highlight("COLOR_CONTEXT")
ctx_end = (ctx_beg ? (highlight("DEFAULT") clr) : "") ctx_end = (ctx_beg ? (highlight("DEFAULT") clr) : "")
dtx_beg = highlight("COLOR_DATEEXT")
dtx_end = (dtx_beg ? (highlight("DEFAULT") clr) : "")
dat_beg = highlight("COLOR_DATE")
dat_end = (dat_beg ? (highlight("DEFAULT") clr) : "")
num_beg = highlight("COLOR_NUMBER")
num_end = (num_beg ? (highlight("DEFAULT") clr) : "")
met_beg = highlight("COLOR_META")
met_end = (met_beg ? (highlight("DEFAULT") clr) : "")
gsub(/[ \t][ \t]*/, "\n&\n") gsub(/[ \t][ \t]*/, "\n&\n")
len = split($0, words, /\n/) len = split($0, words, /\n/)
printf "%s", clr printf "%s", clr
for (i = 1; i <= len; ++i) { for (i = 1; i <= len; ++i) {
if (words[i] ~ /^[+].*[A-Za-z0-9_]$/) { if (i == 1 && words[i] ~ /^[0-9]+$/ ) {
printf "%s", num_beg words[i] num_end
} else if (words[i] ~ /^[+].*[A-Za-z0-9_]$/) {
printf "%s", prj_beg words[i] prj_end printf "%s", prj_beg words[i] prj_end
} else if (words[i] ~ /^[@].*[A-Za-z0-9_]$/) { } else if (words[i] ~ /^[@].*[A-Za-z0-9_]$/) {
printf "%s", ctx_beg words[i] ctx_end printf "%s", ctx_beg words[i] ctx_end
} else if (words[i] ~ /^(due|t|again):/) {
printf "%s", dtx_beg words[i] dtx_end
} else if (words[i] ~ /^(19|20)[0-9][0-9]-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])$/) {
printf "%s", dat_beg words[i] dat_end
} else if (words[i] ~ /^[A-Za-z0-9]+:[^ ]+$/) {
printf "%s", met_beg words[i] met_end
} else { } else {
printf "%s", words[i] printf "%s", words[i]
} }
@@ -970,11 +1018,11 @@ _format()
) )
[ "$filtered_items" ] && echo "$filtered_items" [ "$filtered_items" ] && echo "$filtered_items"
if [ $TODOTXT_VERBOSE -gt 0 ]; then if [ "$TODOTXT_VERBOSE" -gt 0 ]; then
NUMTASKS=$( echo -n "$filtered_items" | sed -n '$ =' ) NUMTASKS=$( echo -n "$filtered_items" | sed -n '$ =' )
TOTALTASKS=$( echo -n "$items" | sed -n '$ =' ) TOTALTASKS=$( echo -n "$items" | sed -n '$ =' )
fi fi
if [ $TODOTXT_VERBOSE -gt 1 ]; then if [ "$TODOTXT_VERBOSE" -gt 1 ]; then
echo "TODO DEBUG: Filter Command was: ${filter_command:-cat}" echo "TODO DEBUG: Filter Command was: ${filter_command:-cat}"
fi fi
} }
@@ -986,13 +1034,19 @@ listWordsWithSigil()
FILE=$TODO_FILE FILE=$TODO_FILE
[ "$TODOTXT_SOURCEVAR" ] && eval "FILE=$TODOTXT_SOURCEVAR" [ "$TODOTXT_SOURCEVAR" ] && eval "FILE=$TODOTXT_SOURCEVAR"
eval "$(filtercommand 'cat "${FILE[@]}"' '' "$@")" | grep -o "[^ ]*${sigil}[^ ]\\+" | grep "^$sigil" | sort -u eval "$(filtercommand 'cat "${FILE[@]}"' '' "$@")" \
| grep -o "[^ ]*${sigil}[^ ]\\+" \
| sed -n \
-e "s#^${TODOTXT_SIGIL_BEFORE_PATTERN//#/\\#}##" \
-e "s#${TODOTXT_SIGIL_AFTER_PATTERN//#/\\#}\$##" \
-e "/^${sigil}${TODOTXT_SIGIL_VALID_PATTERN//\//\\/}$/p" \
| sort -u
} }
export -f cleaninput getPrefix getTodo getNewtodo shellquote filtercommand _list listWordsWithSigil getPadding _format die export -f cleaninput getPrefix getTodo getNewtodo shellquote filtercommand _list listWordsWithSigil getPadding _format die
# == HANDLE ACTION == # == HANDLE ACTION ==
action=$( printf "%s\n" "$ACTION" | tr 'A-Z' 'a-z' ) action=$( printf "%s\n" "$ACTION" | tr '[:upper:]' '[:lower:]' )
## If the first argument is "command", run the rest of the arguments ## If the first argument is "command", run the rest of the arguments
## using todo.sh builtins. ## using todo.sh builtins.
@@ -1003,12 +1057,12 @@ then
## Get rid of "command" from arguments list ## Get rid of "command" from arguments list
shift shift
## Reset action to new first argument ## Reset action to new first argument
action=$( printf "%s\n" "$1" | tr 'A-Z' 'a-z' ) action=$( printf "%s\n" "$1" | tr '[:upper:]' '[:lower:]' )
elif [ -d "$TODO_ACTIONS_DIR/$action" -a -x "$TODO_ACTIONS_DIR/$action/$action" ] elif [ -d "$TODO_ACTIONS_DIR/$action" ] && [ -x "$TODO_ACTIONS_DIR/$action/$action" ]
then then
"$TODO_ACTIONS_DIR/$action/$action" "$@" "$TODO_ACTIONS_DIR/$action/$action" "$@"
exit $? exit $?
elif [ -d "$TODO_ACTIONS_DIR" -a -x "$TODO_ACTIONS_DIR/$action" ] elif [ -d "$TODO_ACTIONS_DIR" ] && [ -x "$TODO_ACTIONS_DIR/$action" ]
then then
"$TODO_ACTIONS_DIR/$action" "$@" "$TODO_ACTIONS_DIR/$action" "$@"
exit $? exit $?
@@ -1043,7 +1097,7 @@ case $action in
SAVEIFS=$IFS SAVEIFS=$IFS
IFS=$'\n' IFS=$'\n'
# Treat each line seperately # Treat each line separately
for line in $input ; do for line in $input ; do
_addto "$TODO_FILE" "$line" _addto "$TODO_FILE" "$line"
done done
@@ -1082,8 +1136,8 @@ case $action in
esac esac
cleaninput "for sed" cleaninput "for sed"
if sed -i.bak $item" s|^.*|&${appendspace}${input}|" "$TODO_FILE"; then if sed -i.bak "${item} s|^.*|&${appendspace}${input}|" "$TODO_FILE"; then
if [ $TODOTXT_VERBOSE -gt 0 ]; then if [ "$TODOTXT_VERBOSE" -gt 0 ]; then
getNewtodo "$item" getNewtodo "$item"
echo "$item $newtodo" echo "$item $newtodo"
fi fi
@@ -1095,10 +1149,10 @@ case $action in
"archive" ) "archive" )
# defragment blank lines # defragment blank lines
sed -i.bak -e '/./!d' "$TODO_FILE" sed -i.bak -e '/./!d' "$TODO_FILE"
[ $TODOTXT_VERBOSE -gt 0 ] && grep "^x " "$TODO_FILE" [ "$TODOTXT_VERBOSE" -gt 0 ] && grep "^x " "$TODO_FILE"
grep "^x " "$TODO_FILE" >> "$DONE_FILE" grep "^x " "$TODO_FILE" >> "$DONE_FILE"
sed -i.bak '/^x /d' "$TODO_FILE" sed -i.bak '/^x /d' "$TODO_FILE"
if [ $TODOTXT_VERBOSE -gt 0 ]; then if [ "$TODOTXT_VERBOSE" -gt 0 ]; then
echo "TODO: $TODO_FILE archived." echo "TODO: $TODO_FILE archived."
fi fi
;; ;;
@@ -1110,21 +1164,15 @@ case $action in
getTodo "$item" getTodo "$item"
if [ -z "$3" ]; then if [ -z "$3" ]; then
if [ $TODOTXT_FORCE = 0 ]; then if confirm "Delete '$todo'"; then
echo "Delete '$todo'? (y/n)"
read -e -r ANSWER
else
ANSWER="y"
fi
if [ "$ANSWER" = "y" ]; then
if [ $TODOTXT_PRESERVE_LINE_NUMBERS = 0 ]; then if [ $TODOTXT_PRESERVE_LINE_NUMBERS = 0 ]; then
# delete line (changes line numbers) # delete line (changes line numbers)
sed -i.bak -e $item"s/^.*//" -e '/./!d' "$TODO_FILE" sed -i.bak -e "${item}s/^.*//" -e '/./!d' "$TODO_FILE"
else else
# leave blank line behind (preserves line numbers) # leave blank line behind (preserves line numbers)
sed -i.bak -e $item"s/^.*//" "$TODO_FILE" sed -i.bak -e "${item}s/^.*//" "$TODO_FILE"
fi fi
if [ $TODOTXT_VERBOSE -gt 0 ]; then if [ "$TODOTXT_VERBOSE" -gt 0 ]; then
echo "$item $todo" echo "$item $todo"
echo "TODO: $item deleted." echo "TODO: $item deleted."
fi fi
@@ -1133,18 +1181,18 @@ case $action in
fi fi
else else
sed -i.bak \ sed -i.bak \
-e $item"s/^\((.) \)\{0,1\} *$3 */\1/g" \ -e "${item}s/^\((.) \)\{0,1\} *$3 */\1/g" \
-e $item"s/ *$3 *\$//g" \ -e "${item}s/ *$3 *\$//g" \
-e $item"s/ *$3 */ /g" \ -e "${item}s/ *$3 */ /g" \
-e $item"s/ *$3 */ /g" \ -e "${item}s/ *$3 */ /g" \
-e $item"s/$3//g" \ -e "${item}s/$3//g" \
"$TODO_FILE" "$TODO_FILE"
getNewtodo "$item" getNewtodo "$item"
if [ "$todo" = "$newtodo" ]; then if [ "$todo" = "$newtodo" ]; then
[ $TODOTXT_VERBOSE -gt 0 ] && echo "$item $todo" [ "$TODOTXT_VERBOSE" -gt 0 ] && echo "$item $todo"
die "TODO: '$3' not found; no removal done." die "TODO: '$3' not found; no removal done."
fi fi
if [ $TODOTXT_VERBOSE -gt 0 ]; then if [ "$TODOTXT_VERBOSE" -gt 0 ]; then
echo "$item $todo" echo "$item $todo"
echo "TODO: Removed '$3' from task." echo "TODO: Removed '$3' from task."
echo "$item $newtodo" echo "$item $newtodo"
@@ -1163,8 +1211,8 @@ case $action in
getTodo "$item" getTodo "$item"
if [[ "$todo" = \(?\)\ * ]]; then if [[ "$todo" = \(?\)\ * ]]; then
sed -i.bak -e $item"s/^(.) //" "$TODO_FILE" sed -i.bak -e "${item}s/^(.) //" "$TODO_FILE"
if [ $TODOTXT_VERBOSE -gt 0 ]; then if [ "$TODOTXT_VERBOSE" -gt 0 ]; then
getNewtodo "$item" getNewtodo "$item"
echo "$item $newtodo" echo "$item $newtodo"
echo "TODO: $item deprioritized." echo "TODO: $item deprioritized."
@@ -1175,7 +1223,7 @@ case $action in
done done
;; ;;
"do" ) "do" | "done" )
errmsg="usage: $TODO_SH do ITEM#[, ITEM#, ITEM#, ...]" errmsg="usage: $TODO_SH do ITEM#[, ITEM#, ITEM#, ...]"
# shift so we get arguments to the do request # shift so we get arguments to the do request
shift; shift;
@@ -1190,9 +1238,9 @@ case $action in
if [ "${todo:0:2}" != "x " ]; then if [ "${todo:0:2}" != "x " ]; then
now=$(date '+%Y-%m-%d') now=$(date '+%Y-%m-%d')
# remove priority once item is done # remove priority once item is done
sed -i.bak $item"s/^(.) //" "$TODO_FILE" sed -i.bak "${item}s/^(.) //" "$TODO_FILE"
sed -i.bak $item"s|^|x $now |" "$TODO_FILE" sed -i.bak "${item}s|^|x $now |" "$TODO_FILE"
if [ $TODOTXT_VERBOSE -gt 0 ]; then if [ "$TODOTXT_VERBOSE" -gt 0 ]; then
getNewtodo "$item" getNewtodo "$item"
echo "$item $newtodo" echo "$item $newtodo"
echo "TODO: $item marked as done." echo "TODO: $item marked as done."
@@ -1216,7 +1264,7 @@ case $action in
actionUsage "$@" actionUsage "$@"
else else
if [ -t 1 ] ; then # STDOUT is a TTY if [ -t 1 ] ; then # STDOUT is a TTY
if which "${PAGER:-less}" >/dev/null 2>&1; then if command -v "${PAGER:-less}" >/dev/null 2>&1; then
# we have a working PAGER (or less as a default) # we have a working PAGER (or less as a default)
help | "${PAGER:-less}" && exit 0 help | "${PAGER:-less}" && exit 0
fi fi
@@ -1227,7 +1275,7 @@ case $action in
"shorthelp" ) "shorthelp" )
if [ -t 1 ] ; then # STDOUT is a TTY if [ -t 1 ] ; then # STDOUT is a TTY
if which "${PAGER:-less}" >/dev/null 2>&1; then if command -v "${PAGER:-less}" >/dev/null 2>&1; then
# we have a working PAGER (or less as a default) # we have a working PAGER (or less as a default)
shorthelp | "${PAGER:-less}" && exit 0 shorthelp | "${PAGER:-less}" && exit 0
fi fi
@@ -1249,7 +1297,7 @@ case $action in
post_filter_command="${post_filter_command:-}${post_filter_command:+ | }awk -v TOTAL=$TOTAL -v PADDING=$PADDING '{ \$1 = sprintf(\"%\" PADDING \"d\", (\$1 > TOTAL ? 0 : \$1)); print }' " post_filter_command="${post_filter_command:-}${post_filter_command:+ | }awk -v TOTAL=$TOTAL -v PADDING=$PADDING '{ \$1 = sprintf(\"%\" PADDING \"d\", (\$1 > TOTAL ? 0 : \$1)); print }' "
cat "$TODO_FILE" "$DONE_FILE" | TODOTXT_VERBOSE=0 _format '' "$PADDING" "$@" cat "$TODO_FILE" "$DONE_FILE" | TODOTXT_VERBOSE=0 _format '' "$PADDING" "$@"
if [ $TODOTXT_VERBOSE -gt 0 ]; then if [ "$TODOTXT_VERBOSE" -gt 0 ]; then
TDONE=$( sed -n '$ =' "$DONE_FILE" ) TDONE=$( sed -n '$ =' "$DONE_FILE" )
TASKNUM=$(TODOTXT_PLAIN=1 TODOTXT_VERBOSE=0 _format "$TODO_FILE" 1 "$@" | sed -n '$ =') TASKNUM=$(TODOTXT_PLAIN=1 TODOTXT_VERBOSE=0 _format "$TODO_FILE" 1 "$@" | sed -n '$ =')
DONENUM=$(TODOTXT_PLAIN=1 TODOTXT_VERBOSE=0 _format "$DONE_FILE" 1 "$@" | sed -n '$ =') DONENUM=$(TODOTXT_PLAIN=1 TODOTXT_VERBOSE=0 _format "$DONE_FILE" 1 "$@" | sed -n '$ =')
@@ -1263,8 +1311,8 @@ case $action in
"listfile" | "lf" ) "listfile" | "lf" )
shift ## Was listfile, next $1 is file name shift ## Was listfile, next $1 is file name
if [ $# -eq 0 ]; then if [ $# -eq 0 ]; then
[ $TODOTXT_VERBOSE -gt 0 ] && echo "Files in the todo.txt directory:" [ "$TODOTXT_VERBOSE" -gt 0 ] && echo "Files in the todo.txt directory:"
cd "$TODO_DIR" && ls -1 *.txt cd "$TODO_DIR" && ls -1 -- *.txt
else else
FILE="$1" FILE="$1"
shift ## Was filename; next $1 is first search term shift ## Was filename; next $1 is first search term
@@ -1286,7 +1334,7 @@ case $action in
"listpri" | "lsp" ) "listpri" | "lsp" )
shift ## was "listpri", new $1 is priority to list or first TERM shift ## was "listpri", new $1 is priority to list or first TERM
pri=$(printf "%s\n" "$1" | tr 'a-z' 'A-Z' | grep -e '^[A-Z]$' -e '^[A-Z]-[A-Z]$') && shift || pri="A-Z" pri=$(printf "%s\n" "$1" | tr '[:lower:]' '[:upper:]' | grep -e '^[A-Z]$' -e '^[A-Z]-[A-Z]$') && shift || pri="A-Z"
post_filter_command="${post_filter_command:-}${post_filter_command:+ | }grep '^ *[0-9]\+ ([${pri}]) '" post_filter_command="${post_filter_command:-}${post_filter_command:+ | }grep '^ *[0-9]\+ ([${pri}]) '"
_list "$TODO_FILE" "$@" _list "$TODO_FILE" "$@"
;; ;;
@@ -1306,23 +1354,18 @@ case $action in
getTodo "$item" "$src" getTodo "$item" "$src"
[ -z "$todo" ] && die "$item: No such item in $src." [ -z "$todo" ] && die "$item: No such item in $src."
if [ $TODOTXT_FORCE = 0 ]; then if confirm "Move '$todo' from $src to $dest"; then
echo "Move '$todo' from $src to $dest? (y/n)"
read -e -r ANSWER
else
ANSWER="y"
fi
if [ "$ANSWER" = "y" ]; then
if [ $TODOTXT_PRESERVE_LINE_NUMBERS = 0 ]; then if [ $TODOTXT_PRESERVE_LINE_NUMBERS = 0 ]; then
# delete line (changes line numbers) # delete line (changes line numbers)
sed -i.bak -e $item"s/^.*//" -e '/./!d' "$src" sed -i.bak -e "${item}s/^.*//" -e '/./!d' "$src"
else else
# leave blank line behind (preserves line numbers) # leave blank line behind (preserves line numbers)
sed -i.bak -e $item"s/^.*//" "$src" sed -i.bak -e "${item}s/^.*//" "$src"
fi fi
fixMissingEndOfLine "$dest"
echo "$todo" >> "$dest" echo "$todo" >> "$dest"
if [ $TODOTXT_VERBOSE -gt 0 ]; then if [ "$TODOTXT_VERBOSE" -gt 0 ]; then
echo "$item $todo" echo "$item $todo"
echo "TODO: $item moved from '$src' to '$dest'." echo "TODO: $item moved from '$src' to '$dest'."
fi fi
@@ -1337,13 +1380,15 @@ case $action in
;; ;;
"pri" | "p" ) "pri" | "p" )
item=$2 shift
newpri=$( printf "%s\n" "$3" | tr 'a-z' 'A-Z' ) while [ "$#" -gt 0 ] ; do
item=$1
newpri=$( printf "%s\n" "$2" | tr '[:lower:]' '[:upper:]' )
errmsg="usage: $TODO_SH pri ITEM# PRIORITY errmsg="usage: $TODO_SH pri ITEM# PRIORITY[, ITEM# PRIORITY, ...]
note: PRIORITY must be anywhere from A to Z." note: PRIORITY must be anywhere from A to Z."
[ "$#" -ne 3 ] && die "$errmsg" [ "$#" -lt 2 ] && die "$errmsg"
[[ "$newpri" = @([A-Z]) ]] || die "$errmsg" [[ "$newpri" = @([A-Z]) ]] || die "$errmsg"
getTodo "$item" getTodo "$item"
@@ -1353,9 +1398,9 @@ note: PRIORITY must be anywhere from A to Z."
fi fi
if [ "$oldpri" != "$newpri" ]; then if [ "$oldpri" != "$newpri" ]; then
sed -i.bak -e $item"s/^(.) //" -e $item"s/^/($newpri) /" "$TODO_FILE" sed -i.bak -e "${item}s/^(.) //" -e "${item}s/^/($newpri) /" "$TODO_FILE"
fi fi
if [ $TODOTXT_VERBOSE -gt 0 ]; then if [ "$TODOTXT_VERBOSE" -gt 0 ]; then
getNewtodo "$item" getNewtodo "$item"
echo "$item $newtodo" echo "$item $newtodo"
if [ "$oldpri" != "$newpri" ]; then if [ "$oldpri" != "$newpri" ]; then
@@ -1369,6 +1414,8 @@ note: PRIORITY must be anywhere from A to Z."
if [ "$oldpri" = "$newpri" ]; then if [ "$oldpri" = "$newpri" ]; then
echo "TODO: $item already prioritized ($newpri)." echo "TODO: $item already prioritized ($newpri)."
fi fi
shift; shift
done
;; ;;
"replace" ) "replace" )
@@ -1389,12 +1436,12 @@ note: PRIORITY must be anywhere from A to Z."
LASTDATA=${LASTREPORT#* } # Strip timestamp. LASTDATA=${LASTREPORT#* } # Strip timestamp.
if [ "$LASTDATA" = "$NEWDATA" ]; then if [ "$LASTDATA" = "$NEWDATA" ]; then
echo "$LASTREPORT" echo "$LASTREPORT"
[ $TODOTXT_VERBOSE -gt 0 ] && echo "TODO: Report file is up-to-date." [ "$TODOTXT_VERBOSE" -gt 0 ] && echo "TODO: Report file is up-to-date."
else else
NEWREPORT="$(date +%Y-%m-%dT%T) ${NEWDATA}" NEWREPORT="$(date +%Y-%m-%dT%T) ${NEWDATA}"
echo "${NEWREPORT}" >> "$REPORT_FILE" echo "${NEWREPORT}" >> "$REPORT_FILE"
echo "${NEWREPORT}" echo "${NEWREPORT}"
[ $TODOTXT_VERBOSE -gt 0 ] && echo "TODO: Report file updated." [ "$TODOTXT_VERBOSE" -gt 0 ] && echo "TODO: Report file updated."
fi fi
;; ;;
@@ -1447,9 +1494,9 @@ note: PRIORITY must be anywhere from A to Z."
cd "$TODO_ACTIONS_DIR" || exit $? cd "$TODO_ACTIONS_DIR" || exit $?
for action in * for action in *
do do
if [ -f "$action" -a -x "$action" ]; then if [ -f "$action" ] && [ -x "$action" ]; then
echo "$action" echo "$action"
elif [ -d "$action" -a -x "$action/$action" ]; then elif [ -d "$action" ] && [ -x "$action/$action" ]; then
echo "$action" echo "$action"
fi fi
done done

View File

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