├── .gitignore ├── .tmux ├── README.md └── mit /.gitignore: -------------------------------------------------------------------------------- 1 | ###################### 2 | # OS Generated Files # 3 | ###################### 4 | 5 | .DS_Store 6 | .DS_Store? 7 | ._* 8 | .Spotlight-V100 9 | .Trashes 10 | Icon? 11 | ehthumbs.db 12 | Thumbs.db 13 | -------------------------------------------------------------------------------- /.tmux: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # get session name based on folder 4 | SESSION=`basename $(pwd) | sed 's/\.//g' | tr '[:upper:]' '[:lower:]'` 5 | 6 | # attach if session already exists 7 | if tmux has-session -t $SESSION 2> /dev/null; then 8 | tmux attach -t $SESSION 9 | exit 10 | fi 11 | 12 | # else create a new session 13 | tmux new-session -d -s $SESSION -n vim 14 | 15 | # build out panes 16 | tmux send-keys -t ${SESSION}:vim "vim -c CommandT" Enter 17 | tmux split-window -t ${SESSION}:vim -h 18 | tmux send-keys -t ${SESSION}:vim.2 "git status" Enter 19 | tmux split-window -t ${SESSION}:vim -v -p 60 20 | 21 | # attach to the new session, focus left pane 22 | tmux attach -t ${SESSION}:vim.1 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | MIT (Most Important Task) 2 | ========================= 3 | 4 | ![Version](https://img.shields.io/badge/version-2.0-green.svg) 5 | [![License](https://img.shields.io/badge/license-MIT-blue.svg)](http://opensource.org/licenses/MIT) 6 | 7 | Overview 8 | -------- 9 | 10 | Most Important Tasks addon for todo.txt-cli. 11 | 12 | MIT adds functionality to Gina Trapani's [todo.txt-cli](https://github.com/ginatrapani/todo.txt-cli). MITs are intended to be critical tasks that need to be accomplished on a particular day. You can read more about MITs here: 13 | 14 | * [zenhabits](http://zenhabits.net/purpose-your-day-most-important-task/) 15 | * [lifehacker](http://lifehacker.com/software/top/geek-to-live--control-your-workday-187074.php) 16 | 17 | The MIT plugin also supports assigning tasks to a year, quarter or month. 18 | 19 | Installation 20 | ------------ 21 | 22 | 1. Install and configure [todo.txt-cli](https://github.com/ginatrapani/todo.txt-cli). 23 | 2. Ensure TODO_ACTIONS_DIR is defined in todo.cfg or in your profile. 24 | 3. Place mit in your actions directory. 25 | 4. Ensure mit is executable. 26 | 27 | Bash Completion 28 | --------------- 29 | 30 | If you would like to add some auto completion to MIT as well as for your todo.sh contexts and projects, add the following to your `~/.bash_rc`. This assumes you have aliased `todo.sh` to `t`. 31 | 32 | # todo-txt completion 33 | _todotxtcli() { 34 | local cur=${COMP_WORDS[COMP_CWORD]} 35 | local pre=${COMP_WORDS[COMP_CWORD-1]} 36 | local cst="${COMP_WORDS[COMP_CWORD-2]}_${COMP_WORDS[COMP_CWORD-1]}" 37 | case $pre in 38 | mit ) 39 | COMPREPLY=( $(compgen -W "today tomorrow monday tuesday wednesday thursday friday saturday sunday january february march april may june july august september october november december" -- $cur) ) 40 | ;; 41 | * ) 42 | if [[ $cst =~ ^mv_[0-9]+$ ]]; then 43 | COMPREPLY=( $(compgen -W "today tomorrow monday tuesday wednesday thursday friday saturday sunday january february march april may june july august september october november december" -- $cur) ) 44 | else 45 | COMPREPLY=( $(compgen -W "mit `eval todo.sh lsprj` `eval todo.sh lsc`" -- $cur) ) 46 | fi 47 | ;; 48 | esac 49 | } 50 | complete -F _todotxtcli t 51 | 52 | Usage 53 | ----- 54 | 55 | The mit addon can be used to both view and add MITs. 56 | 57 | __To add mits:__ 58 | 59 | todo.sh mit [DATE|DAY] [task] 60 | 61 | $ todo.sh mit tue buy dog food @chores 62 | 113 {2013.06.04} buy dog food @chores 63 | TODO: 113 added. 64 | $ 65 | 66 | A date or day is required along with the task. The DATE|DAY format is as follows: 67 | 68 | for daily mit's 69 | --------------- 70 | 'today' 71 | 'tomorrow' 72 | day of the week or abbreviation** i.e. monday|mon 73 | YYYY.MM.DD i.e. 2080.01.15 74 | 75 | for yearly mit's 76 | ---------------- 77 | YYYY i.e. 2080 78 | YYYY.00.00 i.e. 2080.00.00 79 | 80 | for quarterly mit's 81 | ------------------- 82 | QN ** i.e. q1 | q4 83 | YYYYQN i.e. 2080q4 84 | YYYY.QN i.e. 2080.Q1 85 | 86 | for monthly mit's 87 | ----------------- 88 | month name or abbreviation** i.e. january|jan 89 | YYYY.MM.00 i.e. 2080.01.00 90 | YYYYMM i.e. 208001 91 | YYYY.MM i.e. 2080.01 92 | 93 | ** Assumes current week|or year, if chosen day|date has already 94 | passed then it will roll to the next upcoming day|date. 95 | 96 | __To view mits:__ 97 | 98 | todo.sh mit [DAY|DATE] [not @context|@context] 99 | 100 | $ todo.sh mit @chores 101 | Tuesday, June 04: 102 | buy dog food @chores (113) 103 | 104 | Specifying a context to filter by is optional but can be helpful if you define MITs for multiple contexts. MITs will be grouped by day with any old incomplete MITs listed under "Past Due:". You can also specify a day or date to narrow the returned MITs. All day/date formats listed above are supported. 105 | 106 | $ todo.sh mit today 107 | watch some videos on youtube (1) 108 | 109 | $ todo.sh mit wed @work 110 | finish tps report @work 111 | 112 | __To move mits:__ 113 | 114 | todo.sh mit mv [ID] [DATE|DAY] 115 | 116 | $ todo.sh mit mv 113 tomorrow 117 | TODO: MIT 'buy dog food @chores' moved to tomorrow. 118 | $ 119 | 120 | As with adding mits dates must be in the format of YYYY.MM.DD, day names are accepted, or you can specify "Today" or "Tomorrow". Thanks to [rcraggs](https://github.com/rcraggs) you can now convert non-mit tasks to mits with the move command as well, the usage is the same. 121 | 122 | __To convert mits to normal tasks:__ 123 | 124 | todo.sh mit rm [ID] 125 | 126 | $ todo.sh mit rm 113 127 | Removed MIT from task 113 128 | $ 129 | 130 | Another bit of functionality provided by [rcraggs](https://github.com/rcraggs) that allows you to convert a mit to a normal task. 131 | 132 | Format 133 | ------ 134 | 135 | MITs are stored directly in the todo.txt file with the following format: 136 | 137 | {YYYY.MM.DD} task info @context # standard mit with set context 138 | {YYYY.QN.DD} task info # a quarterly mit 139 | {YYYY.00.00} task info # a yearly mit 140 | {YYYY.MM.00} task info # a monthly mit 141 | {YYYY.MM.DD} (A) task info @context # prioritized mit with set context 142 | {YYYY.MM.DD} (A) 2013-05-29 task info # mit with priority and date added (-t option) 143 | 144 | 145 | MITs are displayed as follows: 146 | 147 | -------------------------------------------------------------------------------- 148 | . . 149 | . Daily MIT's . 150 | . . 151 | -------------------------------------------------------------------------------- 152 | 153 | Past Due: # all past due items displayed here 154 | mow the lawn @home (13) # task numbers displayed on the end 155 | 156 | Today: 157 | change oil in car (23) 158 | prepare tps report @work (15) 159 | 160 | Wednesday: 161 | buy groceries @shopping (28) 162 | 163 | Monday, December 17: # anything a week out or more gets a date 164 | call mother (30) 165 | 166 | License 167 | ------- 168 | 169 | MIT is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT). 170 | -------------------------------------------------------------------------------- /mit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # MIT 4 | # 5 | # Bash script to add funcitonality to todo.txt cli by Gina Trapani. Most 6 | # Important Tasks (MIT) are intended to be specific todo items associated 7 | # with a specific day. They differ from events in that they do not necessarily 8 | # have a specified time. As a best practice only 3 MITs should be scheduled 9 | # per day. This script is intended to parse the todo.txt file and generate a 10 | # schedule of MITs by day of the week if no arguments are given, or add new 11 | # MITs to the list. 12 | # 13 | # MITs are stored in the following format: 14 | # {YYYY.MM.DD} mit task information 15 | # 16 | # Author(s): Cody Buell 17 | # 18 | # Licensing: GPL, http://www.gnu.org/copyleft/gpl.html 19 | # 20 | # Revisions: 2012.06.27 Framework roughed out. 21 | # 2012.06.28 Initial version completed. 22 | # 2012.06.29 Moved away from using DOY to prevent problems in 23 | # spanning years. 24 | # 2012.07.01 Added ability to move MITs. 25 | # 2012.07.02 Made greps a bit more robust. 26 | # 2012.07.13 Added ability to invert context listings. 27 | # 2012.09.22 Modified greps and seds to handle MITs with priorities. 28 | # 2012.10.29 Merged corrections from 00Davo regarding #2. 29 | # 2012.10.31 Added BSD vs GNU date detection. 30 | # 2013.01.16 Merged enhancements from rcraggs, adding ability to move 31 | # non-mit tasks into a mit and vise versa. Incremented 32 | # version number from 1.1 to 1.2. Setup core functions, 33 | # added short options section and re-arranged accordingly. 34 | # 2013.03.10 Added support for dated tasks per Justin Le's request. 35 | # Incremented version number from 1.2 to 1.3. 36 | # 2015.06.29 Support for GNU Sed 4.2.2. 37 | # 2017.04.20 Added yearly, quarterly and montly mit's 38 | # 39 | # Requisite: todo.sh by Gina Trapanni 40 | # bash > version 4 (or remove the ^ var substitutions for capitalizing 41 | # variables i.e. ${2^} --> $2 42 | # 43 | # Resources: https://github.com/ginatrapani/todo.txt-cli/wiki 44 | # 45 | # Task List: - Add extra check on mit mv to see that it is an MIT being moved. 46 | # - Add ability to add a time {YYYY.MM.DD HH:MMam/pm} 47 | # t mit today@10pm go to work @nasa 48 | # - Fix mv function so that when a task is converted to a mit, the 49 | # whole task name is displayed in the results. Currently it 50 | # snips out the first word. 51 | # - Create brew formula. 52 | # - Rewrite in a speedier language. 53 | # - Date tab hinting, dates with weekday names, on mit creation. 54 | # - Add 't mit [today,tomorrow,dow]' report output. 55 | # - Ability to sort, prioritize and schedule. 56 | # - Add 'events' to mit, non completable items that auto remove after date. 57 | # - Overview to show exact dates for 0 - 14 days out, then by 'this month' then 'next month +' 58 | 59 | ################################################################################ 60 | ################################################################################ 61 | # # 62 | # ENV DETECTION & VAR PREP # 63 | # # 64 | ################################################################################ 65 | ################################################################################ 66 | 67 | if date -v 1d > /dev/null 2>&1; then # detect date version in use 68 | DVER="BSD" # set as bsd date 69 | else # if it isn't bsd then... 70 | DVER="GNU" # set as gnu date 71 | fi 72 | 73 | if sed --version > /dev/null 2>&1; then # detect sed version in use 74 | SEDI="sed -i " # set as gnu sed syntax 75 | else # if it isn't gnu then... 76 | SEDI="sed -i sedbak " # set as bsd sed syntax 77 | fi 78 | 79 | VERSION="2.0" # mit version number 80 | ACTION=$1 # set first argument to action 81 | 82 | shift # shift arguments, exclude todo.sh 83 | 84 | ################################################################################ 85 | ################################################################################ 86 | # # 87 | # USAGE & MESSAGES # 88 | # # 89 | ################################################################################ 90 | ################################################################################ 91 | 92 | usage() { 93 | cat <<-ENDOFUSAGE 94 | 95 | Most Important Tasks (MIT): 96 | 97 | Displays from or adds Most Important Tasks (MIT) to todo.txt file. 98 | 99 | $(basename $0) [-h|--help] [-v|--version] [date|day task] [rm ID] 100 | [not @context|@context] [mv ID DATE|DAY] 101 | 102 | -h, --help Displays help message. 103 | -v, --version Displays version information. 104 | 105 | Accepted DATE|DAY formats: 106 | 107 | for daily mit's 108 | --------------- 109 | 'today' 110 | 'tomorrow' 111 | day of the week or abbreviation** i.e. monday|mon 112 | YYYY.MM.DD i.e. 2080.01.15 113 | 114 | for yearly mit's 115 | ---------------- 116 | YYYY i.e. 2080 117 | YYYY.00.00 i.e. 2080.00.00 118 | 119 | for quarterly mit's 120 | ------------------- 121 | QN ** i.e. q1 | q4 122 | YYYYQN i.e. 2080q4 123 | YYYY.QN i.e. 2080.Q1 124 | 125 | for monthly mit's 126 | ----------------- 127 | month name ore abbreviation** i.e. january|jan 128 | YYYY.MM.00 i.e. 2080.01.00 129 | YYYYMM i.e. 208001 130 | YYYY.MM i.e. 2080.01 131 | 132 | ** Assumes current week|or year, if chosen day|date has already 133 | passed then it will roll to the next upcoming day|date. 134 | 135 | 136 | Examples: 137 | 138 | mit DATE|DAY task 139 | DATE must be in the format of YYYY.MM.DD. 140 | DAY can be full or short day names, today or tomorrow. 141 | 142 | mit DATE|DAY 143 | DATE must be in the format of YYYY.MM.DD. 144 | DAY can be full or short day names, today or tomorrow. 145 | 146 | mit rm ID 147 | Convert the MIT identified by ID to a standard task. 148 | 149 | mit not @context|@context 150 | Displays all MIT's not in or in specified context. 151 | 152 | mit mv ID DATE|DAY 153 | Move the MIT identified by ID to a new day. 154 | DATE must be in the format of YYYY.MM.DD. 155 | DAY can be full or short day names, today or tomorrow. 156 | 157 | mit wed upload code to github 158 | Creates a new MIT for next Wednesday unless the current day 159 | is Wednesday in which case it will be created for today. 160 | 161 | ENDOFUSAGE 162 | exit 163 | } 164 | 165 | error() { 166 | echo "error: $1" 167 | echo "usage: $(basename $0) [-hv] [date|day task] [not @context|@context] [mv ID DATE|DAY]" 168 | } 169 | 170 | version() { 171 | echo "mit version $VERSION" 172 | } 173 | 174 | ################################################################################ 175 | ################################################################################ 176 | # # 177 | # HELPERS # 178 | # # 179 | ################################################################################ 180 | ################################################################################ 181 | 182 | #/ 183 | # Make Day of Week 184 | # 185 | # Returns the day of the week of the specified date. 186 | # 187 | # @param {string} variable to set 188 | # @param {string} YYYY.MM.DD formatted date 189 | # @return {var} name defined by first param, day of week (i.e. Monday) 190 | #/ 191 | 192 | makeDOW() { 193 | if [ $DVER = "BSD" ]; then 194 | eval $1=`date -j -f "%Y.%m.%d" $2 +%A` 195 | else 196 | local DAY=`echo $2 | sed 's/\./\//g'` 197 | eval $1=`date -d $DAY +%A` 198 | fi 199 | } 200 | 201 | #/ 202 | # Make Date 203 | # 204 | # Converts a YYYY.MM.DD date to a more friendly format. 205 | # 206 | # @param {string} variable to set 207 | # @param {string} YYYY.MM.DD formatted date 208 | # @return {var} name defined by first param, formatted date (i.e. Tuesday, Setpember 19th) 209 | #/ 210 | 211 | makeDATE() { 212 | if [ $DVER = "BSD" ]; then 213 | eval $1=`date -j -f "%Y.%m.%d" $2 "+%A', '%B' '%d"` 214 | else 215 | local DAY=`echo $2 | sed 's/\./\//g'` 216 | eval $1=`date -d $DAY "+%A', '%B' '%d"` 217 | fi 218 | } 219 | 220 | #/ 221 | # Make Month 222 | # 223 | # Converts a YYYYMM00 date to a more friendly format. 224 | # 225 | # @param {string} variable to set 226 | # @param {string} YYYYMM00 formatted date 227 | # @return {var} name defined by first param, formatted date (i.e. March 2100) 228 | #/ 229 | 230 | makeMONTH() { 231 | # change the last 0 in second param to 1 else date freaks out 232 | RAWTIME=`echo $2 | sed 's/0$/1/'` 233 | if [ $DVER = "BSD" ]; then 234 | eval $1=`date -j -f "%Y%m%d" $RAWTIME "+%B' '%Y"` 235 | else 236 | eval $1=`date -d $RAWTIME "+%B' '%Y"` 237 | fi 238 | } 239 | 240 | #/ 241 | # Parse Day 242 | # 243 | # Returns the date of the next dow passed as an arg. 244 | # 245 | # @param {string} dow or date diff (i.e. Monday, 1d, etc) 246 | # @return {var} MITDATE -> YYYY.MM.DD formatted date 247 | #/ 248 | 249 | parseDAY() { 250 | if [ $DVER = "BSD" ]; then 251 | # if current dow = mit's dow then put it for 1 week out, needed for bsd date only 252 | [[ $1 =~ `date +%a | tr '[:upper:]' '[:lower:]'` ]] && PUSH='-v +7d' 253 | MITDATE=`date -v +$1 $PUSH +%Y.%m.%d` 254 | else 255 | local dayid=$1 256 | if [ $dayid = "1d" ]; then 257 | dayid="1day" 258 | fi 259 | MITDATE=`date -d +$dayid +%Y.%m.%d` 260 | fi 261 | } 262 | 263 | #/ 264 | # Parse Month 265 | # 266 | # Returns the date of the month passed as an arg. 267 | # 268 | # @param {string} month (i.e. january, feb, etc) 269 | # @return {var} MITDATE -> YYYY.MM.00 formatted date 270 | #/ 271 | 272 | parseMONTH() { 273 | if [ $DVER = "BSD" ]; then 274 | MITDATE=`date -v +$1 +%Y.%m.00` 275 | else 276 | # get current month, strip padding 0's 277 | CURMONTH=`date +%-m` 278 | CURYEAR=`date +%Y` 279 | case $1 in 280 | january|jan ) 281 | SELMONTH=1 282 | ;; 283 | february|feb ) 284 | SELMONTH=2 285 | ;; 286 | march|mar ) 287 | SELMONTH=3 288 | ;; 289 | april|apr ) 290 | SELMONTH=4 291 | ;; 292 | may ) 293 | SELMONTH=5 294 | ;; 295 | june|jun ) 296 | SELMONTH=6 297 | ;; 298 | july|jul ) 299 | SELMONTH=7 300 | ;; 301 | august|aug ) 302 | SELMONTH=8 303 | ;; 304 | september|sep|sept ) 305 | SELMONTH=9 306 | ;; 307 | october|oct ) 308 | SELMONTH=10 309 | ;; 310 | november|nov ) 311 | SELMONTH=11 312 | ;; 313 | december|dec ) 314 | SELMONTH=12 315 | ;; 316 | esac 317 | 318 | # if selected month is already past, pun in next year 319 | [[ $SELMONTH -ge $CURMONTH ]] && { 320 | SELYEAR=$CURYEAR 321 | } || { 322 | SELYEAR=$(($CURYEAR+1)) 323 | } 324 | 325 | # re-pad our selected month 326 | SELMONTH=`echo $SELMONTH | sed 's/^[1-9]$/0&/'` 327 | 328 | # set our mitdate 329 | MITDATE="${SELYEAR}.${SELMONTH}.00" 330 | fi 331 | } 332 | 333 | #/ 334 | # Parse Quarter 335 | # 336 | # Returns the date of the quarter passed as an arg. 337 | # 338 | # @param {string} quarter (i.e. q1, q2, etc) 339 | # @return {var} MITDATE -> YYYY.QN.00 formatted date 340 | #/ 341 | 342 | parseQUARTER() { 343 | 344 | # get the current quarter 345 | case `date +%-m` in 346 | [1-3] ) 347 | CURQUARTER=1 348 | ;; 349 | [4-6] ) 350 | CURQUARTER=2 351 | ;; 352 | [7-9] ) 353 | CURQUARTER=3 354 | ;; 355 | [10-12] ) 356 | CURQUARTER=4 357 | ;; 358 | esac 359 | 360 | CURYEAR=`date +%Y` 361 | SELQUARTER=`echo $1 | sed 's/[^[:digit:]]//'` 362 | 363 | [[ $SELQUARTER -ge $CURQUARTER ]] && { 364 | SELYEAR=$CURYEAR 365 | } || { 366 | SELYEAR=$(($CURYEAR+1)) 367 | } 368 | 369 | MITDATE="${SELYEAR}.Q${SELQUARTER}.00" 370 | } 371 | 372 | ################################################################################ 373 | ################################################################################ 374 | # # 375 | # CORE FUNCTIONS # 376 | # # 377 | ################################################################################ 378 | ################################################################################ 379 | 380 | #/ 381 | # Get MITs 382 | # 383 | # Prints out mit's matching specifind date criteria. 384 | # 385 | # @param {string} bash conditional operator (i.e. -lt|-eq|-gt) 386 | # @param {string} date in YYYY.MM.DD format 387 | # @param {string} mit array to query (years,quarters,months,days) 388 | # @return {void} 389 | #/ 390 | 391 | getMITS() { 392 | 393 | OPERATOR=$1 394 | DATE=$2 395 | ARRAY=$3 396 | case $ARRAY in 397 | years ) 398 | for (( i=0; i < ${#MITTASKSYEAR[@]}; i++ )); do 399 | MITDATE=`echo ${MITTASKSYEAR[$i]} | awk '{print $1}' | sed 's/\.//g'` 400 | MITTASK=`echo ${MITTASKSYEAR[$i]} | awk '{$1 = ""; print}'` 401 | if [ "$MITDATE" $OPERATOR "$DATE" ]; then 402 | echo " $MITTASK" 403 | fi 404 | done 405 | ;; 406 | quarters ) 407 | for (( i=0; i < ${#MITTASKSQUARTER[@]}; i++ )); do 408 | MITDATE=`echo ${MITTASKSQUARTER[$i]} | awk '{print $1}' | sed 's/\.//g'` 409 | case `echo $MITDATE | sed 's/.*[qQ]\([1-4]\).*/\1/'` in 410 | 1 ) 411 | MITDATE=`echo $MITDATE | sed 's/[qQ][1-4]00/0101/'` 412 | ;; 413 | 2 ) 414 | MITDATE=`echo $MITDATE | sed 's/[qQ][1-4]00/0401/'` 415 | ;; 416 | 3 ) 417 | MITDATE=`echo $MITDATE | sed 's/[qQ][1-4]00/0701/'` 418 | ;; 419 | 4 ) 420 | MITDATE=`echo $MITDATE | sed 's/[qQ][1-4]00/1001/'` 421 | ;; 422 | esac 423 | MITTASK=`echo ${MITTASKSQUARTER[$i]} | awk '{$1 = ""; print}'` 424 | if [ "$MITDATE" $OPERATOR "$DATE" ]; then 425 | echo " $MITTASK" 426 | fi 427 | done 428 | ;; 429 | months ) 430 | for (( i=0; i < ${#MITTASKSMONTH[@]}; i++ )); do 431 | MITDATE=`echo ${MITTASKSMONTH[$i]} | awk '{print $1}' | sed 's/\.//g'` 432 | MITTASK=`echo ${MITTASKSMONTH[$i]} | awk '{$1 = ""; print}'` 433 | if [ "$MITDATE" $OPERATOR "$DATE" ]; then 434 | echo " $MITTASK" 435 | fi 436 | done 437 | ;; 438 | days ) 439 | for (( i=0; i < ${#MITTASKSDAY[@]}; i++ )); do 440 | MITDATE=`echo ${MITTASKSDAY[$i]} | awk '{print $1}' | sed 's/\.//g'` 441 | MITTASK=`echo ${MITTASKSDAY[$i]} | awk '{$1 = ""; print}'` 442 | if [ "$MITDATE" $OPERATOR "$DATE" ]; then 443 | echo " $MITTASK" 444 | fi 445 | done 446 | ;; 447 | esac 448 | } 449 | 450 | #/ 451 | # Move MIT 452 | # 453 | # Move mit to another date and print result. 454 | # 455 | # @param {string} task id 456 | # @param {string} date to move to, all parsed options accepted (i.e. tomorrow, mon, YYYY.MM.DD, etc) 457 | # @return {void} 458 | #/ 459 | 460 | moveMIT() { 461 | # check that second argument is an id and a valid one 462 | if [[ $1 =~ ^[0-9]+$ ]]; then 463 | MITTASK=`awk -v ID=$1 'NR==ID {sub(/\{[qQ0-9.]{10}\}/, ""); sub(/^ /, ""); print "\x27"$0"\x27"}' "$TODO_FILE"` 464 | 465 | TASK=`awk -v ID=$1 'NR==ID {print "\x27"$0"\x27"}' "$TODO_FILE"` 466 | # Add a date to this item if there is none so that we can move it. 467 | if [[ ! $TASK =~ \{[0-9]{4}\.[qQ0-9]{2}\.[0-9]{2}\} ]]; then 468 | TODAY="`date +%Y.%m.%d`" 469 | FIRST_PART=`awk '{print $1"\x27"}' <<< $TASK` 470 | SECOND_PART=`awk '{print "\x27"$2"\x27"}' <<< $TASK` 471 | if [[ $FIRST_PART =~ ([A-Z] ) ]]; then 472 | if [[ $SECOND_PART =~ [0-9]{4}-[0-9]{2}-[0-9]{2} ]]; then 473 | $SEDI "$1 s/\(^([A-Z]\{1\} ) [0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\} \)\(.*$\)/\1{$TODAY} \2/" "$TODO_FILE" 474 | else 475 | $SEDI "$1 s/\(^([A-Z]\{1\} ) \)\(.*$\)/\1{$TODAY} \2/" "$TODO_FILE" 476 | fi 477 | elif [[ $FIRST_PART =~ [0-9]{4}-[0-9]{2}-[0-9]{2} ]]; then 478 | $SEDI "$1 s/\(^[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\} \)\(.*$\)/\1{$TODAY} \2/" "$TODO_FILE" 479 | else 480 | $SEDI "$1 s/^/{$TODAY} /" "$TODO_FILE" 481 | fi 482 | fi 483 | 484 | case $2 in 485 | today ) 486 | MITDATE="`date +%Y.%m.%d`" 487 | MOVEDTO="today" 488 | ;; 489 | tomorrow ) 490 | parseDAY 1d 491 | MOVEDTO="tomorrow" 492 | ;; 493 | monday|mon|tuesday|tue|wednesday|wed|thursday|thu|friday|fri|saturday|sat|sunday|sun ) 494 | parseDAY $2 495 | makeDOW DOW $MITDATE 496 | MOVEDTO=$DOW 497 | ;; 498 | [0-9][0-9][0-9][0-9].[0-9][0-9].[0-9][0-9] ) 499 | makeDATE DATE $2 500 | MITDATE=$2 501 | MOVEDTO=$DATE 502 | ;; 503 | # parsing misc quarter values 504 | q[1-4] ) 505 | parseQUARTER $2 506 | MOVEDTO=$2 507 | ;; 508 | # parsing misc month values 509 | january|jan|february|feb|march|mar|april|apr|may|june|jun|july|august|aug|september|sep|sept|october|oct|november|nov|december|dec ) 510 | parseMONTH $2 511 | MOVEDTO=$2 512 | ;; 513 | # parsing a year in YYYY format 514 | [0-9][0-9][0-9][0-9] ) 515 | MITDATE="${MITDATE}.00.00" 516 | MOVEDTO=$2 517 | ;; 518 | * ) 519 | error "invalid date" 520 | exit 521 | ;; 522 | esac 523 | 524 | # run the sed and echo out the status 525 | $SEDI "$1 s/{[0-9]\{4\}\.[qQ0-9][0-9]\.[0-9]\{2\}}/{$MITDATE}/" "$TODO_FILE" 526 | echo "TODO: MIT $MITTASK moved to ${MOVEDTO}." 527 | else 528 | error "invalid task id" 529 | fi 530 | } 531 | 532 | #/ 533 | # Remove MIT 534 | # 535 | # Convert mit to a normal task and print result. 536 | # 537 | # @param {string} task id 538 | # @return {void} 539 | #/ 540 | 541 | removeMIT() { 542 | $SEDI "$1 s/{[0-9]\{4\}\.[qQ0-9]\{2\}\.[0-9]\{2\}}[ ]*//" "$TODO_FILE" 543 | echo "Removed MIT from task $1" 544 | } 545 | 546 | #/ 547 | # Process MITs 548 | # 549 | # Process all the MITs in preparation for printing to screen. 550 | # 551 | # @return {void} 552 | #/ 553 | 554 | processMITs() { 555 | 556 | # define array element separator as newlines 557 | OLDIFS=$IFS 558 | IFS=$'\n' 559 | 560 | # invert search if not is specified before context 561 | if [ "$1" = "not" ]; then 562 | shift 563 | FLAG="-v" 564 | else 565 | FLAG="" 566 | fi 567 | 568 | # pull out MITs from the todo file, clean and sort 569 | # grepping for "X {YYYY.[qQ]MM.DD}", "{YYYY.[qQ]MM.DD}", "X YYYY-MM-DD {YYYY.[qQ]MM.DD}" or "YYYY-MM-DD {YYYY.[qQ]MM.DD}" 570 | NUM='[0-9].* ' # number 571 | PRI='([A-Z]\{1\}) ' # priority 572 | ADD='[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\} ' # assigned due date 573 | MDD='{[0-9]\{4\}\.[qQ0-9][0-9]\.[0-9]\{2\}}' # mit due date 574 | # creat an array with values like YYYY.MM.DD [priority] [task info] [task number] 575 | MITS=(`grep -n "^$PRI$MDD\|^$MDD\|^$PRI$ADD$MDD\|^$ADD$MDD" "$TODO_FILE" | \ 576 | grep $FLAG "$1" | \ 577 | sed -e "s/:/ /;" \ 578 | -e "s/\(^$NUM\)\($PRI\)\($ADD\)\(.*$\)/\1\2\4/" \ 579 | -e "s/\(^$NUM\)\($ADD\)\(.*$\)/\1\3/" \ 580 | -e "s/\(^$NUM\)\($PRI\)\($MDD \)\(.*\)/\1\3\2\4/" \ 581 | -e "s/{//;s/}//" | \ 582 | awk '{s=$1;e=$NF;$1="";$NF=e" ("s")"}1' | \ 583 | sort`) 584 | 585 | # return array element separator to spaces 586 | IFS=$OLDIFS 587 | 588 | # make an array of ordered unique MIT dates YYYY.MM.DD 589 | DATES=(`grep "^$PRI$MDD\|^$MDD\|^$PRI$ADD$MDD\|^$ADD$MDD" "$TODO_FILE" | \ 590 | grep $FLAG "$1" | \ 591 | sed 's/^.*{\([0-9]\{4\}\.[qQ0-9][0-9]\.[0-9]\{2\}\).*$/\1/' | \ 592 | sort | \ 593 | uniq`) 594 | 595 | # bail if there are no mits 596 | if [ "${#DATES[@]}" -eq "0" ]; then 597 | echo "No MITs found." 598 | exit 599 | fi 600 | 601 | # separate out month, quarter, and year formatted dates 602 | MITDAYS=() 603 | MITMONTHS=() 604 | MITQUARTERS=() 605 | MITYEARS=() 606 | for day in ${DATES[@]}; do 607 | # order is important here 608 | case $day in 609 | [0-9][0-9][0-9][0-9].00.00 ) 610 | MITYEARS+=($day) 611 | ;; 612 | [0-9][0-9][0-9][0-9].[0-9][0-9].00 ) 613 | MITMONTHS+=($day) 614 | ;; 615 | [0-9][0-9][0-9][0-9].[qQ][0-9].00 ) 616 | MITQUARTERS+=($day) 617 | ;; 618 | * ) 619 | MITDAYS+=($day) 620 | ;; 621 | esac 622 | done 623 | 624 | # define array element separator as newlines 625 | OLDIFS=$IFS 626 | IFS=$'\n' 627 | 628 | # separate out month, quarter, and year tasks 629 | MITTASKSDAY=() 630 | MITTASKSMONTH=() 631 | MITTASKSQUARTER=() 632 | MITTASKSYEAR=() 633 | for (( i=0; i < ${#MITS[@]}; i++ )); do 634 | MITDATE=`echo ${MITS[$i]} | awk '{print $1}'` 635 | MITTASK=`echo ${MITS[$i]} | awk '{$1 = ""; print}'` 636 | # order is important here 637 | case $MITDATE in 638 | [0-9][0-9][0-9][0-9].00.00 ) 639 | MITTASKSYEAR+=(${MITS[$i]}) 640 | ;; 641 | [0-9][0-9][0-9][0-9].[0-9][0-9].00 ) 642 | MITTASKSMONTH+=(${MITS[$i]}) 643 | ;; 644 | [0-9][0-9][0-9][0-9].[qQ][0-9].00 ) 645 | MITTASKSQUARTER+=(${MITS[$i]}) 646 | ;; 647 | * ) 648 | MITTASKSDAY+=(${MITS[$i]}) 649 | ;; 650 | esac 651 | done 652 | 653 | # return array element separator to spaces 654 | IFS=$OLDIFS 655 | 656 | # get todays date for comparisons later 657 | TODAY=`date +%Y%m%d` 658 | THISYEAR=`date +%Y0000` 659 | THISMONTH=`date +%Y%m00` 660 | case `date +%-m` in 661 | [1-3] ) 662 | THISQUARTER=`date +%Y0101` 663 | ;; 664 | [4-6] ) 665 | THISQUARTER=`date +%Y0401` 666 | ;; 667 | [7-9] ) 668 | THISQUARTER=`date +%Y0701` 669 | ;; 670 | [10-12] ) 671 | THISQUARTER=`date +%Y1001` 672 | ;; 673 | esac 674 | 675 | } 676 | 677 | #/ 678 | # Display MITs 679 | # 680 | # Print out all the mits. 681 | # 682 | # @return {void} 683 | #/ 684 | 685 | displayMITs() { 686 | 687 | # run yearly mit's only if there are some 688 | if [ "${#MITYEARS[@]}" -gt "0" ]; then 689 | echo "" 690 | echo " Yearly MIT's" 691 | echo "--------------------------------------------------------------------------------" 692 | echo "" 693 | 694 | # check for past due yearly mit's 695 | for year in ${MITYEARS[@]}; do 696 | # strip out the .'s between YYYY.00.00 697 | YEAR=`echo $year | sed 's/\.//g'` 698 | # if we find just one past due mit print them all and break out 699 | if [ "$YEAR" -lt "$THISYEAR" ]; then 700 | echo "Past Due:" 701 | getMITS -lt $THISYEAR 702 | echo "" 703 | break 704 | fi 705 | done 706 | 707 | # processing of all other yearly mits 708 | for year in ${MITYEARS[@]}; do 709 | 710 | # get the date and strip out .'s YYYY0000 711 | YEAR=`echo $year | sed 's/\.//g'` 712 | 713 | # find mit's due this year 714 | if [ "$YEAR" -eq "$THISYEAR" ]; then 715 | echo "This Year:" 716 | getMITS -eq $YEAR years 717 | echo "" 718 | 719 | # everything else 720 | elif [ "$YEAR" -gt "$THISYEAR" ]; then 721 | echo "$YEAR:" | sed 's/0000//' 722 | getMITS -eq $YEAR years 723 | echo "" 724 | fi 725 | 726 | done 727 | fi 728 | 729 | # run quarterly mit's only if there are some 730 | if [ "${#MITQUARTERS[@]}" -gt "0" ]; then 731 | echo "" 732 | echo " Quarterly MIT's" 733 | echo "--------------------------------------------------------------------------------" 734 | echo "" 735 | 736 | # check for past due quarterly mit's 737 | for quarter in ${MITQUARTERS[@]}; do 738 | # determine the quarter number 1-4 739 | QN=`echo $quarter | sed 's/.*[qQ]\([1-4]\).*/\1/'` 740 | case $QN in 741 | 1 ) 742 | QUARTER=`echo $quarter | sed 's/[qQ][1-4]\.00/0101/;s/\.//g'` 743 | ;; 744 | 2 ) 745 | QUARTER=`echo $quarter | sed 's/[qQ][1-4]\.00/0401/;s/\.//g'` 746 | ;; 747 | 3 ) 748 | QUARTER=`echo $quarter | sed 's/[qQ][1-4]\.00/0701/;s/\.//g'` 749 | ;; 750 | 4 ) 751 | QUARTER=`echo $quarter | sed 's/[qQ][1-4]\.00/1001/;s/\.//g'` 752 | ;; 753 | esac 754 | # if we find just one past due mit print them all and break out 755 | if [ "$QUARTER" -lt "$THISQUARTER" ]; then 756 | echo "Past Due:" 757 | getMITS -lt $THISQUARTER quarters 758 | echo "" 759 | break 760 | fi 761 | done 762 | 763 | # processing of all other quarterly mits 764 | for quarter in ${MITQUARTERS[@]}; do 765 | 766 | # determine the quarter number 1-4 767 | QN=`echo $quarter | sed 's/.*[qQ]\([1-4]\).*/\1/'` 768 | YR=`echo $quarter | sed 's/\([0-9]\{4\}\).*$/\1/'` 769 | case $QN in 770 | 1 ) 771 | QUARTER=`echo $quarter | sed 's/[qQ][1-4]\.00/0101/;s/\.//g'` 772 | ;; 773 | 2 ) 774 | QUARTER=`echo $quarter | sed 's/[qQ][1-4]\.00/0401/;s/\.//g'` 775 | ;; 776 | 3 ) 777 | QUARTER=`echo $quarter | sed 's/[qQ][1-4]\.00/0701/;s/\.//g'` 778 | ;; 779 | 4 ) 780 | QUARTER=`echo $quarter | sed 's/[qQ][1-4]\.00/1001/;s/\.//g'` 781 | ;; 782 | esac 783 | 784 | # find mit's due this quarter 785 | if [ "$QUARTER" -eq "$THISQUARTER" ]; then 786 | echo "This Quarter:" 787 | getMITS -eq $QUARTER quarters 788 | echo "" 789 | 790 | # everything else 791 | elif [ "$QUARTER" -gt "$THISQUARTER" ]; then 792 | echo "Q$QN $YR:" 793 | getMITS -eq $QUARTER quarters 794 | echo "" 795 | fi 796 | 797 | done 798 | fi 799 | 800 | # run monthly mit's only if there are some 801 | if [ "${#MITMONTHS[@]}" -gt "0" ]; then 802 | echo "" 803 | echo " Monthly MIT's" 804 | echo "--------------------------------------------------------------------------------" 805 | echo "" 806 | 807 | # check for past due monthly mit's 808 | for month in ${MITMONTHS[@]}; do 809 | # strip out the .'s between YYYY.MM.00 810 | MONTH=`echo $month | sed 's/\.//g'` 811 | # if we find just one past due mit print them all and break out 812 | if [ "$MONTH" -lt "$THISMONTH" ]; then 813 | echo "Past Due:" 814 | getMITS -lt $THISMONTH months 815 | echo "" 816 | break 817 | fi 818 | done 819 | 820 | # processing of all other monthly mits 821 | for month in ${MITMONTHS[@]}; do 822 | 823 | # get the date and strip out .'s YYYYMM00 824 | MONTH=`echo $month | sed 's/\.//g'` 825 | 826 | # find mit's due this month 827 | if [ "$MONTH" -eq "$THISMONTH" ]; then 828 | echo "This Month:" 829 | getMITS -eq $MONTH months 830 | echo "" 831 | 832 | # everything else 833 | elif [ "$MONTH" -gt "$THISMONTH" ]; then 834 | makeMONTH PPMONTH $MONTH 835 | echo "$PPMONTH:" 836 | getMITS -eq $MONTH months 837 | echo "" 838 | fi 839 | 840 | done 841 | fi 842 | 843 | # run daily mit's only if there are some 844 | if [ "${#MITDAYS[@]}" -gt "0" ]; then 845 | echo "" 846 | echo " Daily MIT's" 847 | echo "--------------------------------------------------------------------------------" 848 | echo "" 849 | 850 | # check for past due daily mit's 851 | for day in ${MITDAYS[@]}; do 852 | # strip out the .'s between YYYY.MM.DD 853 | DAY=`echo $day | sed 's/\.//g'` 854 | # if we find just one past due mit print them all and break out 855 | if [ "$DAY" -lt "$TODAY" ]; then 856 | echo "Past Due:" 857 | getMITS -lt $TODAY days 858 | echo "" 859 | break 860 | fi 861 | done 862 | 863 | # processing of all other daily mits 864 | for day in ${MITDAYS[@]}; do 865 | 866 | # get the date and strip out .'s YYYYMMDD 867 | DAY=`echo $day | sed 's/\.//g'` 868 | 869 | # how many days out is the mit 870 | DAYSTO=$(( $DAY - $TODAY )) 871 | 872 | # find mit's due today 873 | if [ "$DAY" -eq "$TODAY" ]; then 874 | echo "Today:" 875 | getMITS -eq $DAY days 876 | echo "" 877 | 878 | # anything in the next 7 days 879 | elif [ "$DAYSTO" -gt "0" ] && [ "$DAYSTO" -lt "7" ]; then 880 | makeDOW DOW $day 881 | echo "$DOW:" 882 | getMITS -eq $DAY days 883 | echo "" 884 | 885 | # everything else 886 | elif [ "$DAYSTO" -ge "7" ]; then 887 | makeDATE DATE $day 888 | echo "$DATE:" 889 | getMITS -eq $DAY days 890 | echo "" 891 | fi 892 | 893 | done 894 | fi 895 | 896 | exit 897 | 898 | } 899 | 900 | #/ 901 | # Create MIT 902 | # 903 | # Creat a new MIT record and print result. 904 | # 905 | # @param {string} mit date, all parsed options accepted (i.e. tomorrow, mon, YYYY.MM.DD, etc) 906 | # @param {string}.*$ task to create 907 | # @return {void} 908 | #/ 909 | 910 | createMIT() { 911 | 912 | # grab the passed date and lowecase it 913 | MITDATE=`echo $1 | tr [A-Z] [a-z]` 914 | 915 | # grab the rest of the argumets as the task 916 | shift 917 | MITTASK=$@ 918 | 919 | # get todays date 920 | TODAY=`date +%u` 921 | 922 | # parse the passed date and format the task to be added 923 | # {YYYY.MM.DD} task to be added --> standard mit 924 | # {YYYY.MM.00} task to be added --> montly mit 925 | # {YYYY.00.00} task to be added --> yearly mit 926 | # {YYYY.QN.00} task to be added --> quarterly mit 927 | case $MITDATE in 928 | # parsing 'today' 929 | today ) 930 | TYPE=days 931 | MITDATE=`date +%Y.%m.%d` 932 | ;; 933 | # parsing 'tomorrow' 934 | tomorrow ) 935 | TYPE=days 936 | parseDAY 1d 937 | ;; 938 | # parsing a misc dow values 939 | monday|mon|tuesday|tue|wednesday|wed|thursday|thu|friday|fri|saturday|sat|sunday|sun ) 940 | TYPE=days 941 | parseDAY $MITDATE 942 | ;; 943 | # parsing a full date in YYYY.MM.DD format, a month in YYYY.MM.00 format, or a year in YYYY.00.00 format 944 | [0-9][0-9][0-9][0-9].[0-1][0-9].[0-3][0-9] ) 945 | TYPE=days 946 | ;; 947 | # parsing misc quarter values 948 | q[1-4] ) 949 | TYPE=quarters 950 | parseQUARTER $MITDATE 951 | ;; 952 | # parsing misc month values 953 | january|jan|february|feb|march|mar|april|apr|may|june|jun|july|august|aug|september|sep|sept|october|oct|november|nov|december|dec ) 954 | TYPE=months 955 | parseMONTH $MITDATE 956 | ;; 957 | # parsing a year in YYYY format 958 | [0-9][0-9][0-9][0-9] ) 959 | TYPE=years 960 | MITDATE="${MITDATE}.00.00" 961 | ;; 962 | # parsing a quarter in YYYY.QN format 963 | [0-9][0-9][0-9][0-9].[qQ][1-4] ) 964 | TYPE=quarters 965 | MITDATE="${MITDATE^^}.00" 966 | ;; 967 | # parsing a quarter in YYYYQN format 968 | [0-9][0-9][0-9][0-9][qQ][1-4] ) 969 | TYPE=quarters 970 | MITDATE="`echo $MITDATE | sed 's/^[0-9][0-9][0-9][0-9]/&./;s/q/Q/'`.00" 971 | ;; 972 | # parsing a month in YYYY.MM format 973 | [0-9][0-9][0-9][0-9].[0-1][1-4] ) 974 | TYPE=months 975 | MITDATE="${MITDATE}.00" 976 | ;; 977 | # parsing a month in YYYYMM format 978 | [0-9][0-9][0-9][0-9][0-1][1-4] ) 979 | TYPE=months 980 | MITDATE="`echo $MITDATE | sed 's/^[0-9][0-9][0-9][0-9]/&./'`.00" 981 | ;; 982 | * ) 983 | error "invalid date" 984 | exit 985 | ;; 986 | esac 987 | 988 | # if no task is provided or ?? then show mit's for the requested date, else create mit 989 | if [[ $MITTASK == "" || $MITTASK =~ ^@ ]]; then 990 | QUICKDATE=`echo $MITDATE | sed 's/\.//g'` 991 | processMITs $MITTASK 992 | echo "" 993 | getMITS -eq $QUICKDATE $TYPE 994 | echo "" 995 | else 996 | NEWMIT="{$MITDATE} $MITTASK" 997 | "$TODO_FULL_SH" add $NEWMIT 998 | fi 999 | 1000 | exit 1001 | 1002 | } 1003 | 1004 | ################################################################################ 1005 | ################################################################################ 1006 | # # 1007 | # LONG OPTIONS # 1008 | # # 1009 | ################################################################################ 1010 | ################################################################################ 1011 | 1012 | # display usage 1013 | [ "$ACTION" = "usage" ] || [ x"$1" = x"--help" ] && { 1014 | usage 1015 | exit 1016 | } 1017 | 1018 | # display version 1019 | [ x"$1" = x"--version" ] && { 1020 | version 1021 | exit 1022 | } 1023 | 1024 | # move mit 1025 | [ x"$1" = x"mv" ] && { 1026 | moveMIT $2 $3 1027 | exit 1028 | } 1029 | 1030 | # remove mit 1031 | [ x"$1" = x"rm" ] && { 1032 | removeMIT $2 1033 | exit 1034 | } 1035 | 1036 | ################################################################################ 1037 | ################################################################################ 1038 | # # 1039 | # SHORT OPTIONS # 1040 | # # 1041 | ################################################################################ 1042 | ################################################################################ 1043 | 1044 | while getopts ":hv" Option; do 1045 | case $Option in 1046 | h ) 1047 | usage 1048 | exit 1049 | ;; 1050 | v ) 1051 | version 1052 | exit 1053 | ;; 1054 | : ) 1055 | echo "Option -$OPTARG requires an argument." >&2 1056 | exit 1057 | ;; 1058 | esac 1059 | done 1060 | 1061 | ################################################################################ 1062 | ################################################################################ 1063 | # # 1064 | # RUN IT # 1065 | # # 1066 | ################################################################################ 1067 | ################################################################################ 1068 | 1069 | # if no arguments, or a context / not context passed print mits 1070 | [ -z $1 ] || [[ $1 =~ @.* ]] || [ "$1" = "not" ] && { 1071 | processMITs $@ 1072 | displayMITs 1073 | } 1074 | 1075 | # check if arg is not null and not picked up by an option, create mit 1076 | [ -n "$1" ] && { 1077 | createMIT $@ 1078 | } 1079 | --------------------------------------------------------------------------------