1. #! /bin/bash
  2.  
  3. ### --------
  4. ### Todo-cli v. 0.777.persei8
  5. ### A Super Simple Todo on CLI
  6. ### Created by: Lazy
  7. ### --------
  8.  
  9. ### INITIALIZE
  10.  
  11. OPTIND=1
  12. redo=1
  13. MON=0
  14. DAT=0
  15. MINT=0
  16. HR=0
  17.  
  18.  
  19. ###### FIRST TIME?
  20.  
  21. # Prefered text editor to edit notes with (vim,gedit,sandy etc)
  22.  
  23. FEDITOR="vim"
  24.  
  25. # Locations
  26. TODODIR="/home/$USER"
  27. TODODB="$TODODIR/.TODODB"
  28. #TODODIR=/User/$User  ## OSX Filesystem
  29.  
  30. # HINT: can be used with dropbox for `cloud-based` task list
  31. # TODODIR="/path/to/dropbox/dir"
  32. # TODODB="$TODODIR/.TODODB"
  33.  
  34. ####### END CUSTOM CONFIGURATION
  35.  
  36.  
  37. if [[ -d $TODODB ]]; then
  38. PM=1
  39. else
  40. ## Create appropriate  dirs
  41. mkdir $TODODB
  42. mkdir $TODODB/data
  43. mkdir $TODODB/backup
  44. mkdir "$TODODB/data/notes"
  45. fi
  46.  
  47. if [[ -e "$TODODB/REMTMP" ]]; then
  48. rm "$TODODB/REMTMP"
  49. else
  50. PM=2
  51. fi
  52.  
  53. if [[ -e $TODODB/REMTMP1 ]]; then
  54. rm "$TODODB/REMTMP1"
  55. else
  56. PM=2
  57. fi
  58.  
  59. if [[ -d $TODODB ]]; then
  60. PM=1
  61. else
  62. ## Create appropriate  dirs
  63. mkdir $TODODB
  64. mkdir $TODODB/data
  65. mkdir $TODODB/backup
  66. fi
  67.  
  68. ## END INITIALIZE
  69.  
  70. ## BEGIN DEFINING FUNCTIONS
  71.  
  72. HABITS () {
  73. echo 'What habit? (todo)'
  74. read habit
  75. cale
  76. echo 'How often? [min/hr/day/month/weekday]'
  77. read recc
  78.  
  79. case recc in
  80.     hr)
  81.     errchance=0
  82.     while [[ $errchance -lt 3 ]]; do
  83.         echo "every (0-23) hours?"
  84.         read timeval
  85.         if [[ "$timeval" = *[![:digit:]]* ]]; then
  86.             TIMESCALE=2
  87.             DUECRANK
  88.         else
  89.         echo "Not valid. Try again."
  90.         let errchance=errchance+1
  91.         fi
  92.     done
  93.     ;;
  94.    
  95. esac
  96.  
  97. }
  98.  
  99. DUECRANK () {
  100. #designated cron handler
  101. case TIMESCALE in
  102.     2)
  103.     "* */$timeval * * * notify-send "
  104.     ;;
  105. esac
  106. }
  107.  
  108. TODORM () {
  109. TASKNUM=`awk -F";" '{ print $1 }' $TODODIR/TODO | grep -w $OPTARG`
  110. NOTEX=`awk -F";" '{ print $1 }' "$TODODIR/TODO" | grep -w $OPTARG | awk -F";" -v d=$OPTARG '{ if ( $1 == d )  print $6}' "$TODODIR/TODO"`
  111.                 if [[ "$OPTARG" = "$TASKNUM" ]]; then
  112.                     if [[ "$NOTEX" = "" ]]; then
  113.                     ok=ok
  114.                     else
  115.                     if [[ -a "$TODODB/data/notes/note-$OPTARG" ]]; then
  116.                     rm "$TODODB/data/notes/note-$OPTARG"
  117.                     else
  118.                     ok=ok
  119.                     fi
  120.                     fi
  121.                     grep -wv "^${OPTARG}" $TODODIR/TODO > $TODODIR/TODO.bak
  122.                     cp $TODODIR/TODO.bak $TODODIR/TODO
  123.                     echo "Task No."$TASKNUM" succesfully removed"
  124.                 else
  125.                 echo "Error: Task $OPTARG does not exist"
  126.                 exit
  127.                 fi
  128. }
  129.  
  130. INVALID () {
  131. echo "Invalid option: -$OPTARG"
  132. echo "-h for optionn" || exit 1
  133. }
  134.  
  135. CLEAR () {
  136.     if [[ -a $TODODIR/TODO ]]; then
  137.             touch "$TODODIR/TODOALL.bak"
  138.             cp $TODODIR/TODO $TODODIR/TODOALL.bak
  139.             echo "Back up created:"
  140.             echo "$TODODIR/TODOALL.bak"
  141.             rm $TODODIR/TODO
  142.     elif [[ "$resp" = n || "$resp" = N ]]; then
  143.         echo "Okay."
  144.         exit
  145.     fi
  146. }
  147.  
  148. RESTORE () {
  149. echo "Restoring latest back up..."
  150. if [[ -a ~/TODOALL.bak ]]; then
  151. cp $TODODIR/TODOALL.bak $TODODIR/TODO
  152. echo "Finished"
  153. exit 0
  154. else
  155. echo "No recorded backups"
  156. exit
  157. fi
  158. }
  159.    
  160.  
  161. TODOLIST () {
  162. if [[ -a $TODODIR/TODO ]]; then
  163.  
  164. case $OPTARG in
  165.    full)
  166.        column -t -s ":" "$TODODIR/TODO" | awk -F";" 'BEGIN { print " Created On       To-do                                  Notes"
  167.             print "================  ===================================  =============================" }
  168.           { print $2"    "," "$1"."" ""("$4")["$5"] "$3"       ",$6 }'
  169.     ;;
  170.    q)
  171.     column -t -s ":" "$TODODIR/TODO" | awk  -F";" ' { $8= 0; if ( $6 !="" ) $8 = "+"; else $8= "";
  172. if ( $4 == "high" || $4 == "High" ) print "\033[1;37m" $1"." "\033[0m","\033[0;31m"$8 $3 "\033[0m" ;
  173.     else if ( $4 == "med" || $4 == "Med" ) print "\033[1;37m" $1".","\033[0;32m"$8 $3 "\033[0m" ;
  174.     else if ( $4 == "low" || $4 == "Low") print "\033[1;37m" $1".","\033[0;33m"$8 $3 "\033[0m" ;
  175.     else
  176.        print "\033[1;34m" $1"." "\033[0m",$8 $3 }; '
  177.     ;;
  178.   tree)
  179.     tree=$( awk -F";" '{ print $5 }' "$TODODIR/TODO" | sort | uniq )
  180.     for i in $tree
  181.     do
  182.     echo -e "\e[1;33m[$i]\e[00m"
  183.     awk -F";" '{ $8="0"; $2=""; if ( $6 !="" ) $8 = "+"; else $8= ""; if ( $4 == "high" || $4 == "High") print "\033[1;37m" $1".","\033[0;31m"$8 $3 "\033[0m", $5;
  184.                 else if ( $4 == "med" || $4 == "Med" ) print "\033[1;37m" $1".","\033[0;32m"$8 $3 "\033[0m", $5;
  185.                 else if ( $4 == "low" || $4 == "Low" ) print "\033[1;37m" $1".","\033[0;33m"$8 $3 "\033[0m"m, $5;}' ~/TODO | grep $i | sed -r "s/(^.+) .+$/\1/g"
  186.     echo -e ""
  187.     done
  188.     ;;
  189.   ?)
  190.     echo "Invalid options. -full for full list. -q for quick list. -t tree list."
  191.     exit 0
  192.     ;;
  193.    esac
  194. else
  195. echo TODO file does not exist. Create a new task first.
  196. fi
  197.  
  198. }
  199.  
  200. TODOP () {
  201. touch .TODOTMP; touch .TODOTMP2
  202. TASKNUM=`awk -F";" '{ print $1 }' $TODODIR/TODO | grep -w "$OPTARG"`
  203. if [[ "$OPTARG" = "$TASKNUM" ]]; then
  204.     if [[ "$PRI" = "low"  || "$PRI" = "Low" || "$PRI" = "med" || "$PRI" = "Med" || "$PRI" = "high" || "$PRI" = "High"  ]]; then
  205.             OLD=$(grep -w "$OPTARG" $TODODIR/TODO)
  206.             echo $OLD >> .TODOTMP
  207.             awk ' BEGIN { FS=":"; OFS=":" } { $4="'$PRI'" }1 '  .TODOTMP >.TODOTMP2
  208.             NEW=$(cat .TODOTMP2)
  209.             sed "s/$OLD/$NEW/g" $TODODIR/TODO > TODO.bak
  210.             cp TODO.bak $TODODIR/TODO
  211.             rm .TODOTMP .TODOTMP2
  212.             echo "Task #"$TASKNUM" succesfully reprioritized to $PRI"    
  213.     else
  214.             echo "Error: Valid Priorities are Low, Med, High -- Try again."
  215.             exit 0                                     
  216.     fi
  217. else
  218. echo "Error: Task $OPTARG does not exist" || exit 2
  219. fi
  220. }
  221.  
  222.  
  223. anscheck () {
  224.     if [[ "$ans" == Y || "$ans" == y || "$redo" -lt "3" ]]; then
  225.         echo "FORMAT: Month/Date/Hour/Minute"
  226.         let redo=redo+1
  227.         timecheck
  228.     else
  229.         if [[ "$ans" == N || "$ans" == n ]]; then
  230.         echo "Reminder not set. (Try again... if you wish)"
  231.         fi
  232.     fi
  233.  
  234. }
  235.  
  236. retry () {
  237. if [ "$P1" == "1" ] && [ "$P2" == "1" ] && [ "$P3" == "1" ] && [ "$P4" == "1" ]; then
  238. FU="reminder"
  239. echo "Retry $FU input? (Y/N)"
  240. read ans
  241.     if [ y  = "$ans" ] || [ Y = "$ans" ] && [ "$redo" -lt "3" ]; then
  242.         echo "New Reminder Input (Month/Date/Hour/Minute):"
  243.         let redo=redo+1
  244.     else
  245.         if [ "$ans" = n ] || [ "$ans" = n ]; then
  246.         echo "Reminder not set. (Try again... if you wish)"
  247.         exit 0
  248.         fi
  249.     fi
  250. read newrem
  251. TPARSE
  252. else
  253.     if [[ $P1 == "1" ]]; then
  254.     FU=MON
  255.     echo "Month  must be between (1-12). Retry month input?"
  256.     read ans
  257.            
  258.     if [ y  = "$ans" ] || [ Y = "$ans" ] && [ "$redo" -lt "3" ]; then
  259.         echo "New Month Input (1-12):"
  260.         let redo=redo+1
  261.     else
  262.         if [ "$ans" = n ] || [ "$ans" = n ]; then
  263.         echo "Reminder not set. (Try again... if you wish)"
  264.         exit 0
  265.         fi
  266.     fi
  267.     read MON
  268.     timecheck
  269.     else
  270.         if [[ $P2 == "1" ]]; then
  271.         FU=DAT
  272.         echo "Date must be between (1-31). Retry date input?"
  273.         read ans
  274.            
  275.     if [ y  = "$ans" ] || [ Y = "$ans" ] && [ "$redo" -lt "3" ]; then
  276.         echo "New Hour Input (0-23):"
  277.         let redo=redo+1
  278.     else
  279.         if [ "$ans" = n ] || [ "$ans" = n ]; then
  280.         echo "Reminder not set. (Try again... if you wish)"
  281.         exit 0
  282.         fi
  283.     fi
  284.         read DAT
  285.         timecheck
  286.         else
  287.             if [[ $P3 == "1" ]]; then
  288.             FU=HR
  289.             echo "$FU must be between (0-23). Retry $FU input?"
  290.             read ans
  291.            
  292.     if [ y  = "$ans" ] || [ Y = "$ans" ] && [ "$redo" -lt "3" ]; then
  293.         echo "New Hour Input (0-23):"
  294.         let redo=redo+1
  295.     else
  296.         if [ "$ans" = n ] || [ "$ans" = n ]; then
  297.         echo "Reminder not set. (Try again... if you wish)"
  298.         exit 0
  299.     else
  300.         exit 0
  301.         fi
  302.     fi
  303.             read HR
  304.             timecheck
  305.             else
  306.                 if [[ $P4 == "1" ]]; then
  307.                 FU=MINT
  308.                 echo "$FU must be between (0-59). Retry $FU input?"
  309.                 read ans
  310.                
  311.     if [ y  = "$ans" ] || [ Y = "$ans" ] && [ "$redo" -lt "3" ]; then
  312.         echo "New Minute Input (0-59):"
  313.         let redo=redo+1
  314.     else
  315.         if [ "$ans" = n ] || [ "$ans" = n ]; then
  316.         echo "Reminder not set. (Try again... if you wish)"
  317.         exit 0
  318.     else
  319.         exit 0
  320.     fi
  321.         fi
  322.                 read MINT
  323.                 timecheck
  324.                 fi
  325.             fi
  326.         fi
  327.            
  328.    fi
  329. fi
  330. }
  331.  
  332. timecheck () {
  333. ##checks if time values are sensible
  334. ## Gets input from either REMDUE or RETRY
  335.  
  336.  
  337. if [ $MON -ge 1 ] && [  $MON -le 12 ]; then
  338. P1="2"
  339. else
  340. P1="1"
  341. fi
  342.  
  343. if [ $DAT -ge 1 ] && [ $DAT -le 31 ]; then
  344. P2="2"
  345. else
  346. P2="1"
  347. fi
  348.  
  349. if [ $HR -ge 0 ] && [ $HR -le 23 ]; then
  350. P3="2"
  351. else
  352. P3="1"
  353. fi
  354.  
  355. if [ $MINT -ge "0" ] && [ $MINT -le 59 ]; then
  356. P4="2"
  357. else
  358. P4="1"
  359. fi 
  360.  
  361.  
  362. if [ "$P1" == "2" ] && [ "$P2" == "2" ] && [ "$P3" == "2" ] && [ "$P4" == "2" ]; then
  363. REMDUE
  364. else
  365. retry
  366. fi
  367.    
  368. }
  369.  
  370. REMDUE () {
  371.  
  372. if [[ "$PRI" = high || "$PRI" = High ]]; then
  373. urg=critical
  374. else
  375.     if [[ "$PRI" = med || "$PRI" = Med ]]; then
  376.         urg=normal
  377.     else
  378.         if [[ "$PRI" = low || "$PRI" = Low ]]; then
  379.             urg=low
  380.         fi
  381.     fi
  382. fi
  383.  
  384. #Set REMINDER value in crontab DUE=$(echo "$MON/$DAT/$HR/$MINT")
  385. crontab -l > newcron
  386. echo -e "$MINT $HR $DAT $MON * DISPLAY=:0 /usr/bin/notify-send -u $urg \"Task: $OPTARG - $NOTES\" \n" >> newcron
  387. crontab newcron
  388. rm newcron
  389. }
  390.  
  391. TPARSE () {
  392.  
  393. if [[ $FU == "" ]]; then
  394. #TPARSE=`awk -F";" '{ print $1, $7 }' "$TODODIR/REMTMP" | grep -w "$TEST" | awk '{ print $2 }'`
  395. #echo $TPARSE >> $TODODB/REMTMP
  396. MON=`awk -F"/" '{ print $1 }' $TODODB/REMTMP`
  397. DAT=`awk -F"/" '{ print $2 }' $TODODB/REMTMP`
  398. HR=`awk -F"/" '{ print $3 }' $TODODB/REMTMP`
  399. MINT=`awk -F"/" '{ print $4 }' $TODODB/REMTMP`
  400. #Check if time values are sensible
  401. PM=1
  402. rm $TODODB/REMTMP
  403. timecheck
  404.  
  405. else
  406.     if [[ "$FU" == "reminder" ]]; then
  407.         echo $newrem >> $TODODB/REMTMP1
  408.         MON=`awk -F"/" '{ print $1 }' $TODODB/REMTMP1`
  409.         DAT=`awk -F"/" '{ print $2 }' $TODODB/REMTMP1`
  410.         HR=`awk -F"/" '{ print $3 }' $TODODB/REMTMP1`
  411.         MINT=`awk -F"/" '{ print $4 }' $TODODB/REMTMP1`
  412.         timecheck
  413.         rm $TODODB/REMTMP1
  414.     fi
  415. fi
  416.        
  417.  
  418.  
  419.  
  420. }
  421.  
  422. NOTEVU () {
  423. #TASKNUM=`awk -F";" '{ print $1, ";"$6}' "$TODODIR/TODO"`
  424. NOTZ=`awk -F";" '{ print $1, ";"}' "$TODODIR/TODO" | grep -w $NN | awk -F";" -v d=$NN '{ if ( $1 == d )print $6 }' "$TODODIR/TODO"`
  425. if [[ "$NOTZ" = "" ]]; then
  426. echo  "ERROR: Note doesn't exist..."
  427. else
  428. if [[ "$NOTZ" = "+" ]]; then
  429. NPARSE
  430. else
  431. echo $NOTZ
  432. fi
  433. fi
  434. }
  435.  
  436. NPARSE () {
  437. #MASTER
  438. cat "$TODODB/data/notes/note-$NN"
  439. }
  440.  
  441.  
  442. NODIT () {
  443. noTEST=`awk -F";" '{ print $1 }' "$TODODIR/TODO" | tail -n 1`
  444. number=0
  445. echo "Opening your favourite text editor...."
  446. echo "Opening default template. Hint: This can be changed to you liking"
  447. sleep 1s
  448. #clear previous nunotes
  449. if [[ "$number" = "no$TEST" ]]; then
  450. notename=$noTEST
  451. let 'notename += 1'
  452. else
  453.     notename=$noTEST
  454.     let 'notename += 1'
  455. fi
  456. cp "$TODODB/data/notes/templates/default" "$TODODB/data/notes/note-$notename"
  457. $FEDITOR "$TODODB/data/notes/note-$notename"
  458. }
  459. ### END DEFINING FUNCTIONS ###
  460.  
  461. NOTEDIT () {
  462. if [[ -a "$TODODB/data/notes/note-$NN" ]]; then
  463. echo "Opening your favourite text editor..."
  464. sleep 1s
  465. $FEDITOR "$TODODB/data/notes/note-$NN"
  466. else
  467. NOTZ=`awk -F";" '{ print $1, ";"}' "$TODODIR/TODO" | grep -w $NN | awk -F";" -v d=$NN '{ if ( $1 == d )print $6 }' "$TODODIR/TODO"`
  468. if [[ "$NOTZ" = "" ]]; then
  469.     echo  "ERROR: Note doesn't exist..."
  470.     else
  471.     echo "Old note: $NOTZ"
  472.     echo "Enter new note:"
  473.     read nunote
  474.     sed -i "s/$NOTZ/$nunote/g" "$TODODIR/TODO"
  475.     fi
  476.  
  477. fi
  478. }
  479.  
  480. #Megaman! Execute!
  481. while getopts ":p:e:h?a:l:m:czv" OPTION
  482. do
  483.     case $OPTION in
  484.         p)
  485.        PRI=$3
  486.        TODOP ;;
  487.         e)
  488.             NN=`echo $2`
  489.             NOTEDIT ;;
  490.         h)
  491.        echo "OPTIONS:"
  492.        echo 'todo -a ["Task goes here"] [PRIORITY=low,medium,high] [TREE= any category your task belongs in] [NOTES="+", for detailed additional notes using a text editor. "a quick note", or just use the command line to add note. ] [ REMINDER="MONTH/DATE/HR/MIN", creates a reminder on specified time using notification (email coming soon) ]  -- add a task'
  493.        echo 'todo -l [OPTION]'
  494.        echo '  q    -- shows a numbered list with Priority Colors'
  495.        echo '  full -- shows a full list with creation date'
  496.        echo 'todo -m [Task number] -- remove specified task'
  497.        echo 'todo -p [Task number] [PRIORITY=low,medium,high] -- reprioritize task'
  498.          echo 'todo -v [Task number] -- views task note/details'
  499.          echo 'todo -e [Task number] -- edit selected task note'
  500.        echo 'todo -c -- clears ALL tasks and makes backup at $TODODIR/TODOALL.BAK '
  501.        echo 'todo -z -- restores latest backup' || exit ;;
  502.         a)
  503.          PRI=$3
  504.          BRANCH=$4
  505.          DUE=$6
  506.          NOTES=$5
  507.          number=0      
  508.                 touch "$TODODIR/TODO"
  509.                 date=`date +"%Y-%m-%d"`
  510.                 TEST=`awk -F";" '{ print $1 }' "$TODODIR/TODO" | tail -n 1`
  511.                 declare -i TEST
  512.                
  513.                 if [[ "$PRI" = "" ]]; then
  514.                 PRI=low
  515.                 else
  516.                     if [[ "$PRI" = "low"  || "$PRI" = "Low" || "$PRI" = "med" || "$PRI" = "Med" || "$PRI" = "high" || "$PRI" = "High"  ]]; then
  517.                         PRI=$PRI
  518.                         else
  519.                         echo 'Error: Valid Priorities are Low, Med, High -- Try again.'
  520.                         exit 0
  521.                     fi
  522.                 fi
  523.                 if [[ "$DUE" != "" ]]; then
  524.                     echo "$DUE" >> "$TODODB/REMTMP"
  525.                     TPARSE
  526.                 fi
  527.                 if [[ "$NOTES" == "+" ]]; then
  528.                     NEDIT=1
  529.                     NODIT
  530.                 else
  531.                     if [[ "$NOTES" != "+" ]]; then
  532.                     NOTES=$5
  533.                     fi
  534.                 fi
  535.                 if [[ "$number" = "$TEST" ]]; then
  536.                     echo "$number;$date;$OPTARG;$PRI;$BRANCH;$NOTES;$DUE" >> "$TODODIR/TODO"
  537.                     echo "Task No.$number ($PRI) created"
  538.                 else
  539.                                         let 'TEST += 1'
  540.                                         echo "$TEST;$date;$OPTARG;$PRI;$BRANCH;$NOTES;$DUE" >> "$TODODIR/TODO"
  541.                                         echo "Task No.$TEST ($PRI) succesfully created"
  542.             fi
  543.                 ;;
  544.         l)
  545.             TODOLIST ;;
  546.         m)
  547.             TODORM ;;
  548.         c)
  549.             CLEAR ;;
  550.         z)
  551.             RESTORE ;;
  552.         v)
  553.             NN=`echo $2`
  554.             NOTEVU ;;
  555.         ?)
  556.             INVALID ;;
  557.       :)
  558.         echo 'Option -$OPTARG requires an argument.'
  559.         echo '-h for usage options' || exit 1 ;;
  560.     esac
  561. done