clikan/clikan.sh

275 lines
6.2 KiB
Bash
Executable File

#!/bin/sh
# clikan.sh -- CLI Kanban
ver='2021-02-25/HB9KNS'
conf="${CLIKANCONF:-$HOME/.clikanconf}"
defkanban="$HOME/clikanban.md"
editor="${CLIKANEDIT:-$VISUAL}"
editor="${editor:-$EDITOR}"
editor="${editor:-ed}"
myshell='/bin/sh -c'
filtr='.'
buff=`mktemp -t clikanbXXXXXX` || buff=${TMPDIR:-/tmp}/clikanb$$`date +%S%M%d`
self=`mktemp -t clikantXXXXXX` || self=${TMPDIR:-/tmp}/clikant$$`date +%S%M%d`
chmod 600 $self $buff
: >$self
if test ! -f "$conf"
then cat <<EOT
no config found, generating default config file $conf
and default kanban file $defkanban
(this should happen only once at first use)
EOT
cat <<EOT >"$conf"
# configuration file for $0
# (autogenerated at `date`)
# file name can be defined by env.var CLIKANCONF
#
# prompt is displayed when waiting for command
prompt |<
# maxshow defines the maximum number of cards/lines to be displayed
maxshow 23
# sortdir defines order of non-calendar kanban cards
# and can be one of up, down or none (default)
sortdir up
# kanban defines a kanban file, may be given several times
# kanban /some/path/to/jobkanban.txt
# kanban /another/path/to/privatekanban.md
kanban $defkanban
EOT
if test -f "$defkanban"
then cp "$defkanban" "$defkanban.bak"
echo found existing $defkanban,
echo saved as backup $defkanban.bak
fi
cat <<EOT >"$defkanban"
# my kanban file
* learn to use clikan
- improve clikan
+ install clikan
### titles work as comments
# might be a future card you don't yet want in waiting
EOT
fi
# get lines beginning with a value, and remove that column
# note SPC&TAB in patterns: make sure there is a SPC,
# and that the value is complete
getlines(){
sed -e 's/$/ /' | grep "^$1[ ]" | { while read _ values
# remove trailing added TAB
do echo "${values% }"
done
}
}
# display selection, and put selection list in selection file,
# input through stdin, with lines prepended with index number, TAB and arg1
showselect(){
local i
i=1
: >$self
while read l
do echo $i: $l
echo "$i $1$l" >>$self
i=$(( $i+1 ))
done
}
# get input from selection (showselect must be called before)
getselect(){
if test "$1" != ""
then echo "choice? (default: $1)" >&2
else echo "choice?" >&2
fi
read i
if test "$i" = ""
then echo "$1"
else getlines $i <$self
fi
}
kbs="`getlines kanban <"$conf"`"
currkan="`echo "$kbs" | head -n 1`"
prompt=`getlines prompt <"$conf" | head -n 1`
maxshow=`getlines maxshow <"$conf" | head -n 1`
maxshow=${maxshow:-22}
sortdir=`getlines sortdir <"$conf" | head -n 1`
sortdir=${sortdir:-none}
showprompt(){
if test "$prompt" != ""
then printf '%s ' "$prompt"
fi
}
# conditional sort
condsort(){
case $sortdir in
up) sort ;;
down) sort -r ;;
*) cat ;;
esac
}
# display all 'something' cards
showall(){
local f t ms
ms=$maxshow
case $1 in
d*) f='*' ;;
w*) f='-' ;;
# for archive/done, show a LOT of archived stuff
a*) f='+' ; ms=99999 ;;
*) f='' ;;
esac
echo
echo " $1 // `date`"
if test "$filtr" != "."
then echo " ($filtr)"
fi
if test "$f" = "*"
then t=`date +%m-%d`
# for "doing", sort filtered cards
cat $kbs | grep -e $filtr | getlines "$f" | condsort
# and also display '- ...(MM-DD)...' calendar entries
cat $kbs | grep "^[*+-] .*($t)" | sed -e 's/^. //'
# for waiting and archive, filter but keep saved card order
else cat $kbs | grep -e $filtr | getlines "$f"
# for all cases, select the cards and show the beginning of the list
fi | showselect "$f " | head -n $ms
}
# replace lines (in any kanban) containing some ed pattern
# arg.1=pattern, remainder=new line contents
repline(){
local patt newl
patt="$1"
shift
newl="$*"
for ff in $kbs
do cat "$ff" > $buff
cat $buff | { while read oldl
do if test "`echo \"$oldl\"`" = "$patt"
then echo "$newl"
else echo "$oldl"
fi
done
} > "$ff"
done
}
showhelp(){ cat <<EOH
$0 : command line kanban
($ver)
configuration file: $conf
for help about commands, just hit RETURN
to show configuration, enter 'c'
EOH
read k
case $k in
c*) cat <<EOT
CLIKANCONF=$CLIKANCONF
configfile=$conf
editor=$editor
maxshow=$maxshow
configfile contents:
EOT
sed -e 's/^/ /' $conf
;;
*) cat <<EOH
command keys:
q: quit
d/w/a: show 'doing/waiting(todo)/archive(done)' cards
k: select target kanban for entry of new cards
n: add new card to target kanban, separated by whitespace
(e.g "n buy present!")
done N: archive card N as done
wait N: put card N back to waiting/todo state
do N: put card N into doing state
note: done/wait/do accept several arguments separated by white space
f F: filter cards for grep pattern F (empty='.')
ec: directly edit config file -- DANGER!
ek: directly edit kanban file -- DANGER!
!: execute arguments with "$myshell"
note: if the command does not match any of the
internal commands, and starts with a letter,
you can even omit the leading exclamation mark!
EOH
;;
esac
}
showall doing
showprompt
while read com coa1 coa2 coa3 coar
do case $com in
q) break ;;
d) showall doing ;;
w) showall waiting/todo/backlog ;;
a) showall archived/done ;;
do|wait|done) if test "$coa1" = ""
then echo "card number?"
read coa1
fi
coar=`echo "$coa1 $coa2 $coa3 $coar" | sed -e 's/ *$/ /'`
while test "$coar" != ""
do
coa1=`getlines ${coar%% *} <$self`
stamp=''
case $com in
done) coa2='+'
stamp=`date '+ // %y-%m-%d'`
;;
wait) coa2='-' ;;
*) coa2='*' ;;
esac
coa3=`echo "$coa1" | sed -e "s/^./$coa2/"`
repline "$coa1" "$coa3$stamp"
coar=${coar#* }
done
showall doing
;;
k) echo "$kbs" | showselect
currkan=`getselect $currkan`
showall doing
;;
n) newc=`echo "$coa1 $coa2 $coa3 $coar" | sed -e 's/ *$//'`
if test "$newc" = ""
then
echo enter new card for target $currkan :
read newc
else echo adding card for target $currkan
fi
if test "$newc" != ""
then echo '*' "$newc" >>$currkan
else echo no content found, nothing added
fi
showall doing
;;
ec) echo calling "$editor $conf" ...
"$editor" "$conf"
echo please quit and restart to reload config ;;
ek) echo calling "$editor $currkan" ...
"$editor" "$currkan" ;;
f) filtr="${coa1:-.}"
echo "filtering for grep pattern '$filtr'" ;;
!*) echo
$myshell "${com#!} $coa1 $coa2 $coa3 $coar"
echo ;;
[A-Za-z]*) echo
$myshell "$com $coa1 $coa2 $coa3 $coar"
echo ;;
*) showhelp
showall doing ;;
esac
showprompt
done
echo
rm -f $self $buff