Compare commits

..

7 Commits

Author SHA1 Message Date
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
3 changed files with 158 additions and 96 deletions

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

@@ -67,6 +67,10 @@ export REPORT_FILE="$TODO_DIR/report.txt"
# export COLOR_PROJECT=$RED # export COLOR_PROJECT=$RED
# export COLOR_CONTEXT=$RED # export COLOR_CONTEXT=$RED
# ... and for date extensions (due:yyyy-mm-dd, t:yyyy-mm-dd and again:X)
#
# export COLOR_DATEEXT=$LIGHT_BLUE
# === BEHAVIOR === # === BEHAVIOR ===
## customize list output ## customize list output

217
todo.sh
View File

@@ -1,4 +1,4 @@
#! /bin/bash #!/usr/bin/env bash
# === HEAVY LIFTING === # === HEAVY LIFTING ===
shopt -s extglob extquote shopt -s extglob extquote
@@ -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...]
@@ -134,7 +134,7 @@ help()
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,6 +142,7 @@ 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
@@ -200,6 +201,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.
@@ -237,10 +239,10 @@ actionsHelp()
Displays all the lines in SRC file located in the todo.txt directory, Displays all the lines in SRC file located in the todo.txt directory,
sorted by priority with line numbers. If TERM specified, lists sorted by priority with line numbers. If TERM specified, lists
all lines that contain TERM(s) in SRC file. Hides all tasks that all lines that contain TERM(s) in SRC file. Hides all tasks that
contain TERM(s) preceded by a minus sign (i.e. -TERM). contain TERM(s) preceded by a minus sign (i.e. -TERM).
Without any arguments, the names of all text files in the todo.txt Without any arguments, the names of all text files in the todo.txt
directory are listed. directory are listed.
listpri [PRIORITIES] [TERM...] listpri [PRIORITIES] [TERM...]
lsp [PRIORITIES] [TERM...] lsp [PRIORITIES] [TERM...]
Displays all tasks prioritized PRIORITIES. Displays all tasks prioritized PRIORITIES.
@@ -248,7 +250,7 @@ actionsHelp()
If no PRIORITIES specified, lists all prioritized tasks. If no PRIORITIES specified, lists all prioritized tasks.
If TERM specified, lists only prioritized tasks that contain TERM(s). If TERM specified, lists only prioritized tasks that contain TERM(s).
Hides all tasks that contain TERM(s) preceded by a minus sign Hides all tasks that contain TERM(s) preceded by a minus sign
(i.e. -TERM). (i.e. -TERM).
listproj [TERM...] listproj [TERM...]
lsprj [TERM...] lsprj [TERM...]
@@ -292,7 +294,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 +302,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 +320,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
@@ -376,8 +378,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 +405,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 +430,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 +440,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 +451,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)
@@ -473,7 +476,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 +485,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,20 +493,20 @@ 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
do do
case $Option in case $Option in
'@' ) '@')
## HIDE_CONTEXT_NAMES starts at zero (false); increment it to one ## HIDE_CONTEXT_NAMES starts at zero (false); increment it to one
## (true) the first time this flag is seen. Each time the flag ## (true) the first time this flag is seen. Each time the flag
## is seen after that, increment it again so that an even ## is seen after that, increment it again so that an even
## 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
@@ -511,14 +515,14 @@ do
export HIDE_CONTEXTS_SUBSTITUTION='[[:space:]]@[[:graph:]]\{1,\}' export HIDE_CONTEXTS_SUBSTITUTION='[[:space:]]@[[:graph:]]\{1,\}'
fi fi
;; ;;
'+' ) '+')
## HIDE_PROJECT_NAMES starts at zero (false); increment it to one ## HIDE_PROJECT_NAMES starts at zero (false); increment it to one
## (true) the first time this flag is seen. Each time the flag ## (true) the first time this flag is seen. Each time the flag
## is seen after that, increment it again so that an even ## is seen after that, increment it again so that an even
## 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
@@ -527,45 +531,45 @@ do
export HIDE_PROJECTS_SUBSTITUTION='[[:space:]][+][[:graph:]]\{1,\}' export HIDE_PROJECTS_SUBSTITUTION='[[:space:]][+][[:graph:]]\{1,\}'
fi fi
;; ;;
a ) a)
OVR_TODOTXT_AUTO_ARCHIVE=0 OVR_TODOTXT_AUTO_ARCHIVE=0
;; ;;
A ) A)
OVR_TODOTXT_AUTO_ARCHIVE=1 OVR_TODOTXT_AUTO_ARCHIVE=1
;; ;;
c ) c)
OVR_TODOTXT_PLAIN=0 OVR_TODOTXT_PLAIN=0
;; ;;
d ) d)
TODOTXT_CFG_FILE=$OPTARG TODOTXT_CFG_FILE=$OPTARG
;; ;;
f ) f)
OVR_TODOTXT_FORCE=1 OVR_TODOTXT_FORCE=1
;; ;;
h ) h)
# Short-circuit option parsing and forward to the action. # Short-circuit option parsing and forward to the action.
# Cannot just invoke shorthelp() because we need the configuration # Cannot just invoke shorthelp() because we need the configuration
# processed to locate the add-on actions directory. # processed to locate the add-on actions directory.
set -- '-h' 'shorthelp' set -- '-h' 'shorthelp'
OPTIND=2 OPTIND=2
;; ;;
n ) n)
OVR_TODOTXT_PRESERVE_LINE_NUMBERS=0 OVR_TODOTXT_PRESERVE_LINE_NUMBERS=0
;; ;;
N ) N)
OVR_TODOTXT_PRESERVE_LINE_NUMBERS=1 OVR_TODOTXT_PRESERVE_LINE_NUMBERS=1
;; ;;
p ) p)
OVR_TODOTXT_PLAIN=1 OVR_TODOTXT_PLAIN=1
;; ;;
P ) P)
## HIDE_PRIORITY_LABELS starts at zero (false); increment it to one ## HIDE_PRIORITY_LABELS starts at zero (false); increment it to one
## (true) the first time this flag is seen. Each time the flag ## (true) the first time this flag is seen. Each time the flag
## is seen after that, increment it again so that an even ## is seen after that, increment it again so that an even
## 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
@@ -574,24 +578,27 @@ do
export HIDE_PRIORITY_SUBSTITUTION="([A-Z])[[:space:]]" export HIDE_PRIORITY_SUBSTITUTION="([A-Z])[[:space:]]"
fi fi
;; ;;
t ) t)
OVR_TODOTXT_DATE_ON_ADD=1 OVR_TODOTXT_DATE_ON_ADD=1
;; ;;
T ) T)
OVR_TODOTXT_DATE_ON_ADD=0 OVR_TODOTXT_DATE_ON_ADD=0
;; ;;
v ) v)
: $(( TODOTXT_VERBOSE++ )) : $(( TODOTXT_VERBOSE++ ))
;; ;;
V ) V)
version version
;; ;;
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}
@@ -601,6 +608,7 @@ 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:-}
@@ -608,7 +616,7 @@ 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}
# Export all TODOTXT_* variables # Export all TODOTXT_* variables
export ${!TODOTXT_@} export "${!TODOTXT_@}"
# Default color map # Default color map
export NONE='' export NONE=''
@@ -636,9 +644,10 @@ 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 and dateext colors.
export COLOR_PROJECT=$NONE export COLOR_PROJECT=$NONE
export COLOR_CONTEXT=$NONE export COLOR_CONTEXT=$NONE
export COLOR_DATEEXT=$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
@@ -695,7 +704,7 @@ export SENTENCE_DELIMITERS=',.:;'
} }
if [ -z "$TODO_ACTIONS_DIR" -o ! -d "$TODO_ACTIONS_DIR" ] if [ -z "$TODO_ACTIONS_DIR" ] || [ ! -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
@@ -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,16 +771,19 @@ 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" [ -f "$TODO_FILE" ] || [ -c "$TODO_FILE" ] || > "$TODO_FILE"
[ -f "$DONE_FILE" -o -c "$DONE_FILE" ] || > "$DONE_FILE" [ -f "$DONE_FILE" ] || [ -c "$DONE_FILE" ] || > "$DONE_FILE"
[ -f "$REPORT_FILE" -o -c "$REPORT_FILE" ] || > "$REPORT_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
@@ -786,12 +801,17 @@ _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
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 +879,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 +939,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,6 +965,9 @@ _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) : "")
gsub(/[ \t][ \t]*/, "\n&\n") gsub(/[ \t][ \t]*/, "\n&\n")
len = split($0, words, /\n/) len = split($0, words, /\n/)
@@ -954,7 +977,9 @@ _format()
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 { } else if (words[i] ~ /^(due|t|again):/) {
printf "%s", dtx_beg words[i] dtx_end
} else {
printf "%s", words[i] printf "%s", words[i]
} }
} }
@@ -970,11 +995,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
} }
@@ -992,7 +1017,7 @@ listWordsWithSigil()
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 +1028,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 $?
@@ -1038,7 +1063,7 @@ case $action in
input=$* input=$*
fi fi
# Set Internal Field Seperator as newline so we can # Set Internal Field Seperator as newline so we can
# loop across multiple lines # loop across multiple lines
SAVEIFS=$IFS SAVEIFS=$IFS
IFS=$'\n' IFS=$'\n'
@@ -1082,8 +1107,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 +1120,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
;; ;;
@@ -1119,12 +1144,12 @@ case $action in
if [ "$ANSWER" = "y" ]; then 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 +1158,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 +1188,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 +1200,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 +1215,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."
@@ -1249,7 +1274,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 +1288,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 +1311,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" "$@"
;; ;;
@@ -1315,14 +1340,14 @@ case $action in
if [ "$ANSWER" = "y" ]; then 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
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
@@ -1338,7 +1363,7 @@ case $action in
"pri" | "p" ) "pri" | "p" )
item=$2 item=$2
newpri=$( printf "%s\n" "$3" | tr 'a-z' 'A-Z' ) newpri=$( printf "%s\n" "$3" | tr '[:lower:]' '[:upper:]' )
errmsg="usage: $TODO_SH pri ITEM# PRIORITY errmsg="usage: $TODO_SH pri ITEM# PRIORITY
note: PRIORITY must be anywhere from A to Z." note: PRIORITY must be anywhere from A to Z."
@@ -1353,9 +1378,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
@@ -1389,12 +1414,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 +1472,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