├── index.md ├── readme.md └── na /index.md: -------------------------------------------------------------------------------- 1 | `na` is a bash function designed to make it easy to see what your next actions are for any project, right from the command line. It works with TaskPaper-formatted files (but any plain text format will do), looking for `@na` tags (or whatever you specify) in todo files in your current folder. 2 | 3 | Used with Taskpaper files, it can add new todo items quickly from the command line, automatically tagging them as next actions. 4 | 5 | It can also auto-display next actions when you enter a project directory, automatically locating any todo files and listing their next actions when you `cd` to the project (optionally recursive). 6 | 7 | ## Features 8 | 9 | You can list next actions in files in the current directory by typing `na`. By default, `na` looks for `*.taskpaper` files and extracts items tagged `@na` and not `@done`. All of these can be changed in the configuration. 10 | 11 | ### Easy matching 12 | 13 | `na` features intelligent project matching. Every time it locates a todo file, it adds the project to the database. Once a project is recorded, you can list its actions by using any portion of the parent directories names. If your project is in `~/Sites/dev/markedapp`, you could quickly list its next actions by typing `na dev mark`. It will always look for the shortest match. 14 | 15 | ### Recursion 16 | 17 | `na` can also recurse subdirectories to find all todo files in child folders as well. Use the `-r` switch to do a recursive search on the current directory. `na -r` with no arguments will recurse from your current location, looking for todo files in all subdirectories. 18 | 19 | Maximum depth for recursion can be controlled in the config (default is `4`). `na -r` can take a path or project title fragments as arguments as well, and will recurse from the matched directory. A configuration option allows you to have the auto-display recurse by default. 20 | 21 | ### Adding todos 22 | 23 | You can also quickly add todo items from the command line with the `-a` switch. The script will look for a file in the current directory called `todo.taskpaper` (or whatever extension you've set). 24 | 25 | If found, it will try to locate an `Inbox:` project, or create one if it doesn't exist. Any arguments after `-a` will be combined to create a new task in TaskPaper format. They will automatically be assigned as next actions (tagged `@na`) and will show up when `na` lists the tasks for the project. 26 | 27 | ## Installation 28 | 29 | 1. Get the script here: 30 | 2. Place `na.sh` on your disk. You can put it in your home folder, but the location doesn't matter, as long as you adjust the path accordingly (see the next step) 31 | 3. Add this line to your `~/.bash_profile` 32 | 33 | [[ -s "$HOME/scripts/na.sh" ]] && source "$HOME/na.sh" 34 | 35 | *The cache of used directories is stored in `~/.tdlist`. I haven't made this configurable yet.* 36 | 37 | ## Usage 38 | 39 | -r recurse 3 directories deep and concatenate all $NA_TODO_EXT files 40 | -a [todo] add a todo to todo.$NA_TODO_EXT in the current dir 41 | -n with -a, prompt for a note after reading task 42 | -t specify an alternate tag (default @na) 43 | pass empty quotes to apply no automatic tag 44 | -p [X] add a @priority(X) tag (with -a) 45 | -v search for tag with specific value (requires -t) 46 | -h show a brief help message 47 | 48 | - **Add todos** 49 | - `na -a ["todo item"]`: add new todo to project's `.taskpaper` file inbox in the current folder 50 | - If no "todo item" is specified, it will prompt you for input 51 | - `-n`: used with -a, prompt for a note after reading task 52 | - `-t`: specify an alternate tag (default @na) 53 | + Pass empty quotes to apply no automatic tag 54 | + You can add additional @tags in the task description 55 | - `-p [X]` add a @priority(X) tag 56 | - **List todos** 57 | - `na` lists all next actions in the current folder's taskpaper file 58 | - na caches folders it's used in, so you can use an optional argument to match the dirname of another folder (`na marked`) 59 | - `-t` (without `-a`) search for a specific tag 60 | + `-v` search for a tag with a specific value, e.g. `na -t priority -v 5` 61 | - `-p` (without `-a`) search for items with a specific priority value (shortcut for `na -t priority -v X`) 62 | - `-r` (recurse and concatenate `@na` in todo files up to 3 levels deep, works with optional argument to list another folder) 63 | - for `na` and `na -r`, additional arguments are parsed for best (and shortest) project match 64 | - **Auto-list todos when changing directory** 65 | - only triggers on directory change command (`cd`,`z`,`j`,`g`,`f`) 66 | - turn off auto-display entirely in the config 67 | - set whether or not to auto-display recursively in the config 68 | - **Help** 69 | - `-h` (display help) 70 | 71 | ### Examples 72 | 73 | - `na`: list next actions in the current directory 74 | - `na -r`: list next actions recursively from the current directory 75 | - `na ~`: list next actions in your home folder 76 | - `na -r ~` list next actions recursively from home 77 | - `na dev mark`: list next actions in a project located in `~/Sites/dev/marked2app` 78 | - `na -a "Update documentation"`: create a new next action in the `Inbox:` project of `todo.taskpaper` in the current folder 79 | 80 | ## Configuration 81 | 82 | You can configure `na` by setting environment variables before you source it. 83 | 84 | Here are the default values, for reference: 85 | 86 | export NA_TODO_EXT=taskpaper 87 | export NA_NEXT_TAG=@na 88 | export NA_DONE_TAG=@done 89 | export NA_MAX_DEPTH=3 90 | export NA_AUTO_LIST_FOR_DIR=1 # 0 to disable 91 | export NA_AUTO_LIST_IS_RECURSIVE=0 92 | [[ -s "$HOME/scripts/na.sh" ]] && source "$HOME/na.sh" 93 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | `na` is a script designed to make it easy to see what your next actions are for any project, right from the command line. It works with TaskPaper-formatted files (but any plain text format will do), looking for `@na` tags (or whatever you specify) in todo files in your current folder. 2 | 3 | Used with Taskpaper files, it can add new todo items quickly from the command line, automatically tagging them as next actions. 4 | 5 | It can also auto-display next actions when you enter a project directory, automatically locating any todo files and listing their next actions when you `cd` to the project (optionally recursive). 6 | 7 | ### Features 8 | 9 | You can list next actions in files in the current directory by typing `na`. By default, `na` looks for `*.taskpaper` files and extracts items tagged `@na` and not `@done`. All of these can be changed in the configuration. 10 | 11 | #### Easy matching 12 | 13 | `na` features intelligent project matching. Every time it locates a todo file, it adds the project to the database. Once a project is recorded, you can list its actions by using any portion of the parent directories names. If your project is in `~/Sites/dev/markedapp`, you could quickly list its next actions by typing `na dev mark`. It will always look for the shortest match. 14 | 15 | #### Recursion 16 | 17 | `na` can also recurse subdirectories to find all todo files in child folders as well. Use the `-r` switch to do a recursive search on the current directory. `na -r` with no arguments will recurse from your current location, looking for todo files in all subdirectories. 18 | 19 | Maximum depth for recursion can be controlled in the config (default is `4`). `na -r` can take a path or project title fragments as arguments as well, and will recurse from the matched directory. A configuration option allows you to have the auto-display recurse by default. 20 | 21 | #### Adding todos 22 | 23 | You can also quickly add todo items from the command line with the `-a` switch. The script will look for a file in the current directory called `todo.taskpaper` (or whatever extension you've set). 24 | 25 | If found, it will try to locate an `Inbox:` project, or create one if it doesn't exist. Any arguments after `-a` will be combined to create a new task in TaskPaper format. They will automatically be assigned as next actions (tagged `@na`) and will show up when `na` lists the tasks for the project. 26 | 27 | ### Installation 28 | 29 | 1. Get the script here: 30 | 2. Place `na` in a folder in your path and ensure that it's executable with `chmod a+x /path/to/na`. 31 | 32 | *The cache of used directories is stored in `~/.tdlist`. I haven't made this configurable yet.* 33 | 34 | ### Usage 35 | 36 | -r recurse 3 directories deep and concatenate all $NA_TODO_EXT files 37 | -a [todo] add a todo to todo.$NA_TODO_EXT in the current dir 38 | -n with -a, prompt for a note after reading task 39 | -t specify an alternate tag (default @na) 40 | pass empty quotes to apply no automatic tag 41 | -p [X] add a @priority(X) tag (with -a) 42 | -v search for tag with specific value (requires -t) 43 | -h show a brief help message 44 | 45 | - **Add todos** 46 | - `na -a ["todo item"]`: add new todo to project's `.taskpaper` file inbox in the current folder 47 | - If no "todo item" is specified, it will prompt you for input 48 | - `-n`: used with -a, prompt for a note after reading task 49 | - `-t`: specify an alternate tag (default @na) 50 | + Pass empty quotes to apply no automatic tag 51 | + You can add additional @tags in the task description 52 | - `-p [X]` add a @priority(X) tag 53 | - **List todos** 54 | - `na` lists all next actions in the current folder's taskpaper file 55 | - na caches folders it's used in, so you can use an optional argument to match the dirname of another folder (`na marked`) 56 | - `-t` (without `-a`) search for a specific tag 57 | + `-v` search for a tag with a specific value, e.g. `na -t priority -v 5` 58 | - `-p` (without `-a`) search for items with a specific priority value (shortcut for `na -t priority -v X`) 59 | - `-r` (recurse and concatenate `@na` in todo files up to 3 levels deep, works with optional argument to list another folder) 60 | - for `na` and `na -r`, additional arguments are parsed for best (and shortest) project match 61 | - **Auto-list todos when changing directory** 62 | - only triggers on directory change command (`cd`,`z`,`j`,`g`,`f`) 63 | - turn off auto-display entirely in the config 64 | - set whether or not to auto-display recursively in the config 65 | - **Help** 66 | - `-h` (display help) 67 | 68 | #### Examples 69 | 70 | - `na`: list next actions in the current directory 71 | - `na -r`: list next actions recursively from the current directory 72 | - `na ~`: list next actions in your home folder 73 | - `na -r ~` list next actions recursively from home 74 | - `na dev mark`: list next actions in a project located in `~/Sites/dev/marked2app` 75 | - `na -a "Update documentation"`: create a new next action in the `Inbox:` project of `todo.taskpaper` in the current folder 76 | 77 | ### Configuration 78 | 79 | You can configure `na` by setting environment variables before you source it. 80 | 81 | Here are the default values, for reference: 82 | 83 | export NA_TODO_EXT=taskpaper 84 | export NA_NEXT_TAG=@na 85 | export NA_DONE_TAG=@done 86 | export NA_MAX_DEPTH=3 87 | 88 | ### Auto-listing todos on PWD change 89 | 90 | You can add a prompt command to your shell to have na automatically list your next actions when you `cd` into a directory. Add the appropriate command to your login file for your shell: 91 | 92 | Bash (in ~/.bash_profile): 93 | 94 | ```bash 95 | if [[ -z "$PROMPT_COMMAND" ]]; then 96 | PROMPT_COMMAND="eval 'na --prompt'" 97 | else 98 | echo $PROMPT_COMMAND | grep -v -q "na --prompt" && PROMPT_COMMAND="$PROMPT_COMMAND;"'eval "na --prompt"' 99 | fi 100 | ``` 101 | 102 | Fish (in ~/.config/fish/conf.d/*.fish): 103 | 104 | ```fish 105 | function __should_na --on-variable PWD 106 | # function __should_na --on-event fish_prompt 107 | test -s (basename $PWD)".taskpaper" && na 108 | end 109 | ``` 110 | 111 | Zsh (in ~/.zshrc): 112 | 113 | ```zsh 114 | chpwd() { na } 115 | ``` 116 | 117 | 118 | ### Misc 119 | 120 | If you have [gum](https://github.com/charmbracelet/gum) installed, na will use it for command line input when adding tasks and notes. 121 | -------------------------------------------------------------------------------- /na: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # 88888b. 8888b. 4 | # 888 "88b "88b 5 | # 888 888.d888888 6 | # 888 888888 888 7 | # 888 888"Y888888 8 | # 9 | # Brett Terpstra 2017 10 | 11 | # `na` is a bash function designed to make it easy to see what your next actions are for any project, 12 | # right from the command line. It works with TaskPaper-format files (but any plain text format will do), 13 | # looking for @na tags (or whatever you specify) in todo files in your current folder. It can also 14 | # auto-display next actions when you enter a project directory, automatically locating any todo files and 15 | # listing their next actions when you `cd` to the project (optionally recursive). 16 | # 17 | # na -h for help 18 | 19 | # NA_TODO_EXT Must be set to something to limit text searches 20 | : ${NA_TODO_EXT:="taskpaper"} 21 | : ${NA_NEXT_TAG="@na"} 22 | : ${NA_DONE_TAG:="@done"} 23 | : ${NA_MAX_DEPTH:=3} 24 | 25 | _USE_GUM=false 26 | which gum &>/dev/null 27 | [[ $? == 0 ]] && _USE_GUM=true 28 | : ${NA_USE_GUM:=$_USE_GUM} 29 | 30 | function na() { 31 | local DKGRAY="\033[1;30m" 32 | local GREEN="\033[0;32m" 33 | local DEFAULT="\033[0;39m" 34 | local CYAN="\033[0;36m" 35 | local YELLOW="\033[0;33m" 36 | IFS="" read -r -d '' helpstring <&2; return;; 77 | t) 78 | if [[ $2 != '' && $2 =~ ^[^\-] ]]; then 79 | shift; altTag="@${1#@}" 80 | else 81 | altTag='' 82 | fi 83 | ;; 84 | v) 85 | if [[ $2 != '' && $2 =~ ^[^\-] ]]; then 86 | shift; [[ $1 != '' ]] && tagValue=$1 87 | fi 88 | ;; 89 | *) fnd+="$1 "; break;; # unknown option detected 90 | esac; opt="${opt:1}"; done;; 91 | *) fnd+="$1 ";; 92 | esac; shift; done 93 | fi 94 | 95 | if [[ $altTag == '' && $add -ne 0 ]]; then 96 | taskTag='' 97 | elif [[ $altTag != 0 && ${#altTag} -gt 0 ]]; then 98 | taskTag=$altTag 99 | else 100 | taskTag=$NA_NEXT_TAG 101 | fi 102 | 103 | if [[ $add -eq 1 ]]; then 104 | if [[ $priority -gt 0 ]]; then 105 | taskTag="@priority(${priority}) $taskTag" 106 | fi 107 | else 108 | if [[ $priority -gt 0 ]]; then 109 | taskTag="@priority(${priority})" 110 | fi 111 | fi 112 | 113 | if [[ -n $tagValue && $tagValue != '' ]]; then 114 | taskTag="$taskTag(${tagValue})" 115 | fi 116 | 117 | if [[ $add -eq 0 && ${#fnd} -eq 0 && $recurse -eq 0 ]]; then 118 | # Do an ls to see if there are any matching files 119 | CHKFILES=$(ls -C1 *.$NA_TODO_EXT 2> /dev/null | wc -l) 120 | if [[ $CHKFILES -ne 0 ]]; then 121 | echo -en $GREEN 122 | 123 | echo -e "$(grep -Eh "(^\t*-|: *@.*$)" *.$NA_TODO_EXT \ 124 | | grep -h "$taskTag" \ 125 | | grep -v "$NA_DONE_TAG" \ 126 | | awk '{gsub(/(^[ \t\-]+| '"$(echo "$taskTag"|sed -E 's/([\(\)])/\\\1/g')"')/, "")};1' \ 127 | | sed -E "s/(@[^\(]*)((\()([^\)]*)(\)))/\\$CYAN\1\3\\$YELLOW\4\\$CYAN\5\\$GREEN/g")" 128 | echo "`pwd`" >> ~/.tdlist 129 | sort -u ~/.tdlist -o ~/.tdlist 130 | fi 131 | return 132 | fi 133 | 134 | if [[ $recurse -eq 1 && ${#fnd} -eq 0 ]]; then # if the only argument is -r 135 | # echo -en $GREEN 136 | dirlist=$(find . -name "*.$NA_TODO_EXT" -maxdepth $NA_MAX_DEPTH -exec grep -H "$taskTag" {} \; | grep -v "$NA_DONE_TAG") 137 | _na_fix_output "$dirlist" 138 | elif [[ $add -eq 1 ]]; then # if the argument is -a 139 | if [[ $fnd == '' ]]; then 140 | if $QQ_USE_GUM; then 141 | fnd=$(gum input --placeholder "Enter a task") 142 | else 143 | read -p "Task: " fnd # No text given for the task, read from STDIN 144 | fi 145 | fi 146 | if [[ $fnd != '' ]]; then # if there is text to add as a todo item 147 | task=$fnd 148 | if [[ $note -eq 1 ]]; then 149 | if $NA_USE_GUM; then 150 | taskNote=$(gum write --placeholder "Enter a note" --width $(tput cols) --char-limit 0) 151 | else 152 | echo "Enter a note, use ^d to end: " 153 | taskNote=$(cat) 154 | fi 155 | fi 156 | 157 | targetcount=$(ls -C1 *.$NA_TODO_EXT 2> /dev/null | wc -l | tr -d " ") 158 | if [[ $targetcount == "0" ]]; then 159 | local proj=${PWD##*/} 160 | local newfile="${proj}.${NA_TODO_EXT}" 161 | echo "Creating new todo file: $newfile" 162 | target="$newfile" 163 | if [ ! -e $target ]; then 164 | touch $target 165 | echo -e "Inbox:\n$proj:\n\tNew Features:\n\tIdeas:\n\tBugs:\nArchive:\nSearch Definitions:\n\tTop Priority @search(@priority = 5 and not @done)\n\tHigh Priority @search(@priority > 3 and not @done)\n\tMaybe @search(@maybe)\n\tNext @search(@na and not @done and not project = \"Archive\")\n" >> $target 166 | fi 167 | else 168 | declare -a fileList=( *\.*$NA_TODO_EXT* ) 169 | if [[ ${#fileList[*]} == 1 ]]; then 170 | target=${fileList[0]} 171 | elif [[ ${#fileList[*]} -gt 1 ]]; then 172 | local counter=1 173 | for f in ${fileList[@]}; do 174 | echo "$counter) $f" 175 | counter=$(( $counter+1 )) 176 | done 177 | if [ $counter -gt 9 ]; then 178 | read -p "Add to which file? " 179 | else 180 | read -n1 -p "Add to which file? " 181 | fi 182 | if [[ $REPLY =~ ^[0-9]+$ ]]; then 183 | target=${fileList[$(($REPLY-1))]} 184 | else 185 | return 186 | fi 187 | fi 188 | fi 189 | /usr/bin/env ruby <