From bf1bf1ae8423fffa395d70e79ba0385cdc4e1faf Mon Sep 17 00:00:00 2001 From: Ingo Karkat Date: Tue, 31 Mar 2020 01:13:29 +0200 Subject: [PATCH] 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 --- tests/t1310-listcon.sh | 41 +++++++++++++++++++++++++++++++++++++++++ tests/t1320-listproj.sh | 27 +++++++++++++++++++++++++++ todo.sh | 14 +++++++++++++- 3 files changed, 81 insertions(+), 1 deletion(-) diff --git a/tests/t1310-listcon.sh b/tests/t1310-listcon.sh index 9e44def..4294508 100755 --- a/tests/t1310-listcon.sh +++ b/tests/t1310-listcon.sh @@ -65,6 +65,47 @@ test_todo_session 'listcon with project' < todo.txt <>> todo.sh listcon +@GinaTrapani +@home) +@x +@y +EOF +test_todo_session 'listcon limiting to multi-character sequences' <>> TODOTXT_SIGIL_VALID_PATTERN='.\{2,\}' todo.sh listcon +@GinaTrapani +@home) +EOF +test_todo_session 'listcon allowing w: marker before contexts' <>> TODOTXT_SIGIL_BEFORE_PATTERN='\(w:\)\{0,1\}' todo.sh listcon +@GinaTrapani +@OtherContributors +@home) +@x +@y +EOF +test_todo_session 'listcon allowing parentheses around contexts' <>> 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' <>> 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 < todo.txt <>> todo.sh listproj ++1 ++sunflowers +EOF +test_todo_session 'listproj limiting to alphabetic characters' <>> TODOTXT_SIGIL_VALID_PATTERN='[a-zA-Z]\{1,\}' todo.sh listproj ++sunflowers +EOF +test_todo_session 'listproj allowing brackets around projects' <>> TODOTXT_SIGIL_BEFORE_PATTERN='\[\{0,1\}' TODOTXT_SIGIL_AFTER_PATTERN='\]\{0,1\}' todo.sh listproj ++1 ++gardening ++landscape ++sunflowers +EOF + +cat > todo.txt < "$TEST_TODO_CUSTOM" cat >> "$TEST_TODO_CUSTOM" <<'EOF' diff --git a/todo.sh b/todo.sh index 39a6ee3..671ee48 100755 --- a/todo.sh +++ b/todo.sh @@ -149,6 +149,9 @@ help() TODOTXT_SORT_COMMAND="sort ..." customize list output TODOTXT_FINAL_FILTER="sed ..." customize list after color, P@+ hiding 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 @@ -620,6 +623,9 @@ TODOTXT_SORT_COMMAND=${TODOTXT_SORT_COMMAND:-env LC_COLLATE=C sort -f -k2} TODOTXT_DISABLE_FILTER=${TODOTXT_DISABLE_FILTER:-} TODOTXT_FINAL_FILTER=${TODOTXT_FINAL_FILTER:-cat} 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 "${!TODOTXT_@}" @@ -1037,7 +1043,13 @@ listWordsWithSigil() FILE=$TODO_FILE [ "$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