na 1.2.4 → 1.2.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +31 -0
- data/Gemfile.lock +1 -1
- data/README.md +54 -10
- data/bin/na +102 -58
- data/lib/na/action.rb +20 -6
- data/lib/na/next_action.rb +17 -7
- data/lib/na/prompt.rb +43 -6
- data/lib/na/version.rb +1 -1
- data/src/README.md +41 -4
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f912e92e3b61231275ab69102ce1dc2c1073f0417c5904409234ceaac96e0f1e
|
4
|
+
data.tar.gz: a1906bf77861faa3dd80dec19c813a09871c1582f7e9ca60aad1cabebece4858
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 887e0052681ee2ed7035aea0d7b4c8509be0e54f2699a8718350caec92632954fc0fa14ffcdfa8263f5bf03d2d0083ef5baaa6b89a17f314bef3b52a49243582
|
7
|
+
data.tar.gz: 3922599c050aadd8dd09de10904d9e245e7bc547bc75aa0eb985d94be14f04489adfccef17950fc3ffccfbd49d8fc723031bc20ff96a16f523bbec1a8b9f6341
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,34 @@
|
|
1
|
+
### 1.2.6
|
2
|
+
|
3
|
+
2022-10-26 10:50
|
4
|
+
|
5
|
+
#### NEW
|
6
|
+
|
7
|
+
- Pass notes to STDIN using piped input when using the `--note` switch
|
8
|
+
- `--notes` switch for next, find, and tagged to include action notes in output
|
9
|
+
|
10
|
+
#### IMPROVED
|
11
|
+
|
12
|
+
- Update na saved examples and documentation
|
13
|
+
- Better handling of unknown commands, affecting `na -a ACTION` and `na SAVED_SEARCH`
|
14
|
+
- Additional help documentation and examples
|
15
|
+
- Updated documentation
|
16
|
+
- If a todo query contains only a negative, display all non-matching todos
|
17
|
+
- Don't display readline prompts if not a TTY
|
18
|
+
- Prompt hook generator recognizes when a global file is being used and modifies prompt hooks to search for project name or tag based on the value of `--cwd_as`.
|
19
|
+
|
20
|
+
#### FIXED
|
21
|
+
|
22
|
+
- Debug messages showing when not using --debug
|
23
|
+
|
24
|
+
### 1.2.5
|
25
|
+
|
26
|
+
2022-10-26 07:39
|
27
|
+
|
28
|
+
#### FIXED
|
29
|
+
|
30
|
+
- Error with add command
|
31
|
+
|
1
32
|
### 1.2.4
|
2
33
|
|
3
34
|
2022-10-26 07:28
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -9,12 +9,12 @@
|
|
9
9
|
_If you're one of the rare people like me who find this useful, feel free to
|
10
10
|
[buy me some coffee][donate]._
|
11
11
|
|
12
|
-
The current version of `na` is 1.2.
|
12
|
+
The current version of `na` is 1.2.6
|
13
13
|
.
|
14
14
|
|
15
15
|
`na` ("next action") is a command line tool 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.
|
16
16
|
|
17
|
-
Used with Taskpaper files, it can add new
|
17
|
+
Used with Taskpaper files, it can add new action items quickly from the command line, automatically tagging them as next actions. It can also mark actions as completed, delete them, archive them, and move them between projects.
|
18
18
|
|
19
19
|
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). See the [Prompt Hooks](#prompt-hooks) section for details.
|
20
20
|
|
@@ -53,6 +53,16 @@ If found, it will try to locate an `Inbox:` project, or create one if it doesn't
|
|
53
53
|
|
54
54
|
You can mark todos as complete, delete them, add and remove tags, change priority, and even move them between projects with the `na update` command.
|
55
55
|
|
56
|
+
### Terminology
|
57
|
+
|
58
|
+
**Todo**: Refers to a todo file, usually a TaskPaper document
|
59
|
+
|
60
|
+
**Project**: Refers to a project within the TaskPaper document, specified by an alphanumeric name (spaces allowed) followed by a colon. Projects can be nested by indenting a tab beyond the parent projects indentation.
|
61
|
+
|
62
|
+
**Action**: Refers to an individual task, specified by a line starting with a hyphen (`-`)
|
63
|
+
|
64
|
+
**Note**: Refers to lines appearing between action lines that start without hyphens. The note is attached to the preceding action regardless of indentation.
|
65
|
+
|
56
66
|
### Usage
|
57
67
|
|
58
68
|
```
|
@@ -63,7 +73,7 @@ SYNOPSIS
|
|
63
73
|
na [global options] command [command options] [arguments...]
|
64
74
|
|
65
75
|
VERSION
|
66
|
-
1.2.
|
76
|
+
1.2.6
|
67
77
|
|
68
78
|
GLOBAL OPTIONS
|
69
79
|
-a, --[no-]add - Add a next action (deprecated, for backwards compatibility)
|
@@ -105,6 +115,12 @@ Example: `na add This feature @idea I have`
|
|
105
115
|
|
106
116
|
If you run the `add` command with no arguments, you'll be asked for input on the command line.
|
107
117
|
|
118
|
+
###### Adding notes
|
119
|
+
|
120
|
+
Use the `--note` switch to add a note. If STDIN (piped) input is present when this switch is used, it will be included in the note. A prompt will be displayed for adding additional notes, which will be appended to any STDIN note passed. Press CTRL-d to end editing and save the note.
|
121
|
+
|
122
|
+
Notes are not displayed by the `next/tagged/find` commands unless `--notes` is specified.
|
123
|
+
|
108
124
|
```
|
109
125
|
NAME
|
110
126
|
add - Add a new next action
|
@@ -122,7 +138,7 @@ COMMAND OPTIONS
|
|
122
138
|
-f, --file=PATH - Specify the file to which the task should be added (default: none)
|
123
139
|
--finish, --done - Mark task as @done with date
|
124
140
|
--in, --todo=TODO_FILE - Add to a known todo file, partial matches allowed (default: none)
|
125
|
-
-n, --note - Prompt for additional notes
|
141
|
+
-n, --note - Prompt for additional notes. STDIN input (piped) will be treated as a note if present.
|
126
142
|
-p, --priority=PRIO - Add a priority level 1-5 (default: 0)
|
127
143
|
-t, --tag=TAG - Use a tag other than the default next action tag (default: none)
|
128
144
|
--to, --project, --proj=PROJECT - Add action to specific project (default: Inbox)
|
@@ -133,7 +149,7 @@ EXAMPLES
|
|
133
149
|
# Add a new action to the Inbox, including a tag
|
134
150
|
na add "A cool feature I thought of @idea"
|
135
151
|
|
136
|
-
# Add a new action to the Inbox, set its @priority to 4, and prompt for an additional note
|
152
|
+
# Add a new action to the Inbox, set its @priority to 4, and prompt for an additional note.
|
137
153
|
na add "A bug I need to fix" -p 4 -n
|
138
154
|
|
139
155
|
# A parenthetical at the end of an action is interpreted as a note
|
@@ -190,6 +206,7 @@ COMMAND OPTIONS
|
|
190
206
|
--[no-]done - Include @done actions
|
191
207
|
-e, --regex - Interpret search pattern as regular expression
|
192
208
|
--in=TODO_PATH - Show actions from a specific todo file in history. May use wildcards (* and ?) (default: none)
|
209
|
+
--[no-]notes - Include notes in output
|
193
210
|
-o, --or - Combine search tokens with OR, displaying actions matching ANY of the terms
|
194
211
|
--proj, --project=PROJECT[/SUBPROJECT] - Show actions from a specific project (default: none)
|
195
212
|
--save=TITLE - Save this search for future use (default: none)
|
@@ -232,6 +249,8 @@ Examples:
|
|
232
249
|
- `na next -d 3` (list all next actions in the current directory and look for additional files 3 levels deep from there)
|
233
250
|
- `na next marked2` (show next actions from another directory you've previously used na on)
|
234
251
|
|
252
|
+
To see all next actions across all known todos, use `na next "*"`. You can combine multiple arguments to see actions across multiple todos, e.g. `na next marked nvultra`.
|
253
|
+
|
235
254
|
```
|
236
255
|
NAME
|
237
256
|
next - Show next actions
|
@@ -247,6 +266,7 @@ COMMAND OPTIONS
|
|
247
266
|
-d, --depth=DEPTH - Recurse to depth (default: none)
|
248
267
|
--[no-]done - Include @done actions
|
249
268
|
--in, --todo=TODO_FILE - Display matches from a known todo file (may be used more than once, default: none)
|
269
|
+
--[no-]notes - Include notes in output
|
250
270
|
--proj, --project=PROJECT[/SUBPROJECT] - Show actions from a specific project (default: none)
|
251
271
|
-t, --tag=TAG - Alternate tag to search for (default: none)
|
252
272
|
|
@@ -290,6 +310,9 @@ Search names can be partially matched when calling them, so if you have a search
|
|
290
310
|
|
291
311
|
Run `na saved` without an argument to list your saved searches.
|
292
312
|
|
313
|
+
> As a shortcut, if `na` is run with one argument that matches the name of a saved search, it will execute that search, so running `na maybe` is the same as running `na saved maybe`.
|
314
|
+
|
315
|
+
|
293
316
|
```
|
294
317
|
NAME
|
295
318
|
saved - Execute a saved search
|
@@ -307,9 +330,13 @@ COMMAND OPTIONS
|
|
307
330
|
|
308
331
|
EXAMPLES
|
309
332
|
|
310
|
-
na
|
333
|
+
na tagged "+maybe,+priority<=3" --save maybelater
|
311
334
|
|
312
|
-
na saved
|
335
|
+
na saved maybelater
|
336
|
+
|
337
|
+
na saved maybe
|
338
|
+
|
339
|
+
na maybe
|
313
340
|
|
314
341
|
na saved
|
315
342
|
```
|
@@ -339,6 +366,7 @@ COMMAND OPTIONS
|
|
339
366
|
-d, --depth=DEPTH - Recurse to depth (default: none)
|
340
367
|
--[no-]done - Include @done actions
|
341
368
|
--in, --todo=TODO_FILE - Display matches from a known todo file (may be used more than once, default: none)
|
369
|
+
--[no-]notes - Include notes in output
|
342
370
|
--proj, --project=PROJECT[/SUBPROJECT] - Show actions from a specific project (default: none)
|
343
371
|
-t, --tag=TAG - Alternate tag to search for (default: none)
|
344
372
|
|
@@ -382,11 +410,27 @@ You can specify a particular todo file using `--file PATH` or any todo from hist
|
|
382
410
|
|
383
411
|
If more than one file is matched, a menu will be presented, multiple selections allowed. If multiple actions match the search within the selected file(s), a menu will be presented. If you have fzf installed, you can select one action to update with return, or use tab to mark multiple tasks to which the action will be applied. With gum you can use j, k, and x to mark multiple actions. Use the `--all` switch to force operation on all matched tasks, skipping the menu.
|
384
412
|
|
385
|
-
Any time an update action is carried out, a backup of the file before modification will be made in the same directory with a `.` prepended and `.bak` appended (e.g. `marked.taskpaper` is copied to `.marked.taskpaper.bak`). Only one undo step is available, but if something goes wrong (and this feature is still experimental, so be wary), you can just copy the "
|
413
|
+
Any time an update action is carried out, a backup of the file before modification will be made in the same directory with a `.` prepended and `.bak` appended (e.g. `marked.taskpaper` is copied to `.marked.taskpaper.bak`). Only one undo step is available, but if something goes wrong (and this feature is still experimental, so be wary), you can just copy the ".bak" file back to the original.
|
414
|
+
|
415
|
+
###### Marking a task as complete
|
416
|
+
|
417
|
+
You can mark an action complete using `--finish`, which will add a dated @done tag to the action. You can also mark it @done and immediately move it to the Archive project using `--archive`.
|
418
|
+
|
419
|
+
If you just want the action to stop appearing as a "next action," you can remove the next action tag using `--remove na` (or whatever your next action tag is configured as).
|
420
|
+
|
421
|
+
If you want to permanently delete an action, use `--delete` to remove it entirely.
|
422
|
+
|
423
|
+
###### Moving between projects
|
386
424
|
|
387
425
|
You can specify a new project for an action (moving it) with `--proj PROJECT_PATH`. A project path is hierarchical, with each level separated by a colon or slash. If the project path provided roughly matches an existing project, e.g. "mark:bug" would match "Marked:Bugs", then that project will be used. If no match is found, na will offer to generate a new project/hierarchy for the path provided. Strings will be exact but the first letter will be uppercased.
|
388
426
|
|
389
|
-
|
427
|
+
###### Adding notes
|
428
|
+
|
429
|
+
Use the `--note` switch to add a note. If STDIN (piped) input is present when this switch is used, it will be included in the note. A prompt will be displayed for adding additional notes, which will be appended to any STDIN note passed. Press CTRL-d to end editing and save the note.
|
430
|
+
|
431
|
+
Notes are not displayed by the `next/tagged/find` commands unless `--notes` is specified.
|
432
|
+
|
433
|
+
See the help output for a list of all available actions.
|
390
434
|
|
391
435
|
```
|
392
436
|
NAME
|
@@ -410,7 +454,7 @@ COMMAND OPTIONS
|
|
410
454
|
-f, --finish - Add a @done tag to action
|
411
455
|
--file=PATH - Specify the file to search for the task (default: none)
|
412
456
|
--in, --todo=TODO_FILE - Use a known todo file, partial matches allowed (default: none)
|
413
|
-
-n, --note - Prompt for additional notes. Input will be appended to any existing note.
|
457
|
+
-n, --note - Prompt for additional notes. Input will be appended to any existing note. If STDIN input (piped) is detected, it will be used as a note.
|
414
458
|
-o, --overwrite - Overwrite note instead of appending
|
415
459
|
-p, --priority=PRIO - Add/change a priority level 1-5 (default: 0)
|
416
460
|
-r, --remove=TAG - Remove a tag to the action (may be used more than once, default: none)
|
data/bin/na
CHANGED
@@ -4,6 +4,7 @@
|
|
4
4
|
$LOAD_PATH.unshift File.join(__dir__, '..', 'lib')
|
5
5
|
require 'gli'
|
6
6
|
require 'na'
|
7
|
+
require 'fcntl'
|
7
8
|
|
8
9
|
# Main application
|
9
10
|
class App
|
@@ -63,7 +64,7 @@ class App
|
|
63
64
|
flag %i[d depth], type: :integer, must_match: /^[1-9]$/
|
64
65
|
|
65
66
|
desc 'Display verbose output'
|
66
|
-
switch %i[debug]
|
67
|
+
switch %i[debug], default_value: false
|
67
68
|
|
68
69
|
desc 'Show next actions'
|
69
70
|
long_desc 'Next actions are actions which contain the next action tag (default @na),
|
@@ -94,6 +95,9 @@ class App
|
|
94
95
|
c.arg_name 'PROJECT[/SUBPROJECT]'
|
95
96
|
c.flag %i[proj project]
|
96
97
|
|
98
|
+
c.desc 'Include notes in output'
|
99
|
+
c.switch %i[notes], negatable: true, default_value: false
|
100
|
+
|
97
101
|
c.desc 'Include @done actions'
|
98
102
|
c.switch %i[done]
|
99
103
|
|
@@ -102,8 +106,8 @@ class App
|
|
102
106
|
cmd = ['add']
|
103
107
|
cmd.push('--note') if global_options[:note]
|
104
108
|
cmd.concat(['--priority', global_options[:priority]]) if global_options[:priority]
|
105
|
-
cmd.push(
|
106
|
-
|
109
|
+
cmd.push(NA.command_line) if NA.command_line.count > 1
|
110
|
+
cmd.unshift(*NA.globals)
|
107
111
|
exit run(cmd)
|
108
112
|
end
|
109
113
|
|
@@ -141,7 +145,7 @@ class App
|
|
141
145
|
project: options[:project],
|
142
146
|
require_na: require_na)
|
143
147
|
|
144
|
-
NA.output_actions(actions, depth, files: files)
|
148
|
+
NA.output_actions(actions, depth, files: files, notes: options[:notes])
|
145
149
|
end
|
146
150
|
end
|
147
151
|
|
@@ -156,11 +160,11 @@ class App
|
|
156
160
|
command :add do |c|
|
157
161
|
c.example 'na add "A cool feature I thought of @idea"', desc: 'Add a new action to the Inbox, including a tag'
|
158
162
|
c.example 'na add "A bug I need to fix" -p 4 -n',
|
159
|
-
desc: 'Add a new action to the Inbox, set its @priority to 4, and prompt for an additional note'
|
163
|
+
desc: 'Add a new action to the Inbox, set its @priority to 4, and prompt for an additional note.'
|
160
164
|
c.example 'na add "An action item (with a note)"',
|
161
165
|
desc: 'A parenthetical at the end of an action is interpreted as a note'
|
162
166
|
|
163
|
-
c.desc 'Prompt for additional notes'
|
167
|
+
c.desc 'Prompt for additional notes. STDIN input (piped) will be treated as a note if present.'
|
164
168
|
c.switch %i[n note], negatable: false
|
165
169
|
|
166
170
|
c.desc 'Add a priority level 1-5'
|
@@ -205,9 +209,8 @@ class App
|
|
205
209
|
if NA.global_file
|
206
210
|
target = File.expand_path(NA.global_file)
|
207
211
|
unless File.exist?(target)
|
208
|
-
|
209
|
-
res
|
210
|
-
if res =~ /y/i
|
212
|
+
res = NA.yn(NA::Color.template('{by}Specified file not found, create it'), default: true)
|
213
|
+
if res
|
211
214
|
basename = File.basename(target, ".#{NA.extension}")
|
212
215
|
NA.create_todo(target, basename)
|
213
216
|
else
|
@@ -218,9 +221,8 @@ class App
|
|
218
221
|
elsif options[:file]
|
219
222
|
target = File.expand_path(options[:file])
|
220
223
|
unless File.exist?(target)
|
221
|
-
|
222
|
-
res
|
223
|
-
if res =~ /y/i
|
224
|
+
res = NA.yn(NA::Color.template('{by}Specified file not found, create it'), default: true)
|
225
|
+
if res
|
224
226
|
basename = File.basename(target, ".#{NA.extension}")
|
225
227
|
NA.create_todo(target, basename)
|
226
228
|
else
|
@@ -231,10 +233,11 @@ class App
|
|
231
233
|
elsif options[:todo]
|
232
234
|
todo = []
|
233
235
|
options[:todo].split(/ *, */).each do |a|
|
234
|
-
m = a.match(/^(?<req
|
236
|
+
m = a.match(/^(?<req>[+\-!])?(?<tok>.*?)$/)
|
235
237
|
todo.push({
|
236
238
|
token: m['tok'],
|
237
|
-
required: !m['req'].nil?
|
239
|
+
required: all_req || (!m['req'].nil? && m['req'] == '+'),
|
240
|
+
negate: !m['req'].nil? && m['req'] =~ /[!\-]/
|
238
241
|
})
|
239
242
|
end
|
240
243
|
dirs = NA.match_working_dir(todo)
|
@@ -259,9 +262,8 @@ class App
|
|
259
262
|
else
|
260
263
|
files = NA.find_files(depth: options[:depth])
|
261
264
|
if files.count.zero?
|
262
|
-
|
263
|
-
res
|
264
|
-
if res =~ /y/i
|
265
|
+
res = NA.yn(NA::Color.template('{by}No todo file found, create one'), default: true)
|
266
|
+
if res
|
265
267
|
basename = File.expand_path('.').split('/').last
|
266
268
|
target = "#{basename}.#{NA.extension}"
|
267
269
|
NA.create_todo(target, basename)
|
@@ -277,9 +279,9 @@ class App
|
|
277
279
|
|
278
280
|
action = if args.count.positive?
|
279
281
|
args.join(' ').strip
|
280
|
-
elsif TTY::Which.exist?('gum')
|
282
|
+
elsif $stdin.isatty && TTY::Which.exist?('gum')
|
281
283
|
`gum input --placeholder "Enter a task" --char-limit=500 --width=#{TTY::Screen.columns}`.strip
|
282
|
-
|
284
|
+
elsif $stdin.isatty
|
283
285
|
puts NA::Color.template('{bm}Enter task:{x}')
|
284
286
|
reader.read_line(NA::Color.template('{by}> {bw}')).strip
|
285
287
|
end
|
@@ -310,9 +312,12 @@ class App
|
|
310
312
|
|
311
313
|
action = "#{action.gsub(/#{na_tag}\b/, '')}#{na_tag}"
|
312
314
|
|
313
|
-
|
315
|
+
stdin_note = NA.stdin ? NA.stdin.split("\n") : []
|
316
|
+
|
317
|
+
line_note = if options[:note] && $stdin.isatty
|
318
|
+
puts stdin_note unless stdin_note.nil?
|
314
319
|
if TTY::Which.exist?('gum')
|
315
|
-
args = ['--placeholder "Enter
|
320
|
+
args = ['--placeholder "Enter additional note, CTRL-d to save"']
|
316
321
|
args << '--char-limit 0'
|
317
322
|
args << '--width $(tput cols)'
|
318
323
|
`gum write #{args.join(' ')}`.strip.split("\n")
|
@@ -322,9 +327,9 @@ class App
|
|
322
327
|
end
|
323
328
|
end
|
324
329
|
|
325
|
-
note =
|
330
|
+
note = stdin_note.empty? ? [] : stdin_note
|
331
|
+
note.concat(split_note) unless split_note.nil?
|
326
332
|
note.concat(line_note) unless line_note.nil?
|
327
|
-
note = [] if note.empty?
|
328
333
|
|
329
334
|
NA.add_action(target, options[:project], action, note, finish: options[:finish], append: append)
|
330
335
|
end
|
@@ -337,12 +342,15 @@ class App
|
|
337
342
|
allow you to pick which file to act on.'
|
338
343
|
arg_name 'ACTION'
|
339
344
|
command %i[update] do |c|
|
340
|
-
c.example 'na update --remove na "An existing task"',
|
345
|
+
c.example 'na update --remove na "An existing task"',
|
346
|
+
desc: 'Find "An existing task" action and remove the @na tag from it'
|
341
347
|
c.example 'na update --tag waiting "A bug I need to fix" -p 4 -n',
|
342
348
|
desc: 'Find "A bug..." action, add @waiting, add/update @priority(4), and prompt for an additional note'
|
343
|
-
c.example 'na update --archive My cool action',
|
349
|
+
c.example 'na update --archive My cool action',
|
350
|
+
desc: 'Add @done to "My cool action" and immediately move to Archive'
|
344
351
|
|
345
|
-
c.desc 'Prompt for additional notes. Input will be appended to any existing note.
|
352
|
+
c.desc 'Prompt for additional notes. Input will be appended to any existing note.
|
353
|
+
If STDIN input (piped) is detected, it will be used as a note.'
|
346
354
|
c.switch %i[n note], negatable: false
|
347
355
|
|
348
356
|
c.desc 'Overwrite note instead of appending'
|
@@ -411,14 +419,14 @@ class App
|
|
411
419
|
|
412
420
|
action = if args.count.positive?
|
413
421
|
args.join(' ').strip
|
414
|
-
elsif TTY::Which.exist?('gum') && options[:tagged].empty?
|
422
|
+
elsif $stdin.isatty && TTY::Which.exist?('gum') && options[:tagged].empty?
|
415
423
|
options = [
|
416
424
|
%(--placeholder "Enter a task to search for"),
|
417
425
|
'--char-limit=500',
|
418
426
|
"--width=#{TTY::Screen.columns}"
|
419
427
|
]
|
420
428
|
`gum input #{options.join(' ')}`.strip
|
421
|
-
elsif options[:tagged].empty?
|
429
|
+
elsif $stdin.isatty && options[:tagged].empty?
|
422
430
|
puts NA::Color.template('{bm}Enter search string:{x}')
|
423
431
|
reader.read_line(NA::Color.template('{by}> {bw}')).strip
|
424
432
|
end
|
@@ -467,7 +475,10 @@ class App
|
|
467
475
|
add_tags = options[:tag].map { |t| t.sub(/^@/, '').wildcard_to_rx }
|
468
476
|
remove_tags = options[:remove].map { |t| t.sub(/^@/, '').wildcard_to_rx }
|
469
477
|
|
470
|
-
|
478
|
+
stdin_note = NA.stdin ? NA.stdin.split("\n") : []
|
479
|
+
|
480
|
+
line_note = if options[:note] && $stdin.isatty
|
481
|
+
puts stdin_note unless stdin_note.nil?
|
471
482
|
if TTY::Which.exist?('gum')
|
472
483
|
args = ['--placeholder "Enter a note, CTRL-d to save"']
|
473
484
|
args << '--char-limit 0'
|
@@ -479,7 +490,8 @@ class App
|
|
479
490
|
end
|
480
491
|
end
|
481
492
|
|
482
|
-
note =
|
493
|
+
note = stdin_note.empty? ? [] : stdin_note
|
494
|
+
note.concat(line_note) unless line_note.nil? || line_note.empty?
|
483
495
|
|
484
496
|
target_proj = if options[:project]
|
485
497
|
options[:project]
|
@@ -497,10 +509,11 @@ class App
|
|
497
509
|
elsif options[:todo]
|
498
510
|
todo = []
|
499
511
|
options[:todo].split(/ *, */).each do |a|
|
500
|
-
m = a.match(/^(?<req
|
512
|
+
m = a.match(/^(?<req>[+\-!])?(?<tok>.*?)$/)
|
501
513
|
todo.push({
|
502
514
|
token: m['tok'],
|
503
|
-
required: !m['req'].nil?
|
515
|
+
required: all_req || (!m['req'].nil? && m['req'] == '+'),
|
516
|
+
negate: !m['req'].nil? && m['req'] =~ /[!\-]/
|
504
517
|
})
|
505
518
|
end
|
506
519
|
dirs = NA.match_working_dir(todo)
|
@@ -568,6 +581,9 @@ class App
|
|
568
581
|
c.arg_name 'TODO_PATH'
|
569
582
|
c.flag %i[in]
|
570
583
|
|
584
|
+
c.desc 'Include notes in output'
|
585
|
+
c.switch %i[notes], negatable: true, default_value: false
|
586
|
+
|
571
587
|
c.desc 'Combine search tokens with OR, displaying actions matching ANY of the terms'
|
572
588
|
c.switch %i[o or], negatable: false
|
573
589
|
|
@@ -619,10 +635,11 @@ class App
|
|
619
635
|
if options[:in]
|
620
636
|
todo = []
|
621
637
|
options[:in].split(/ *, */).each do |a|
|
622
|
-
m = a.match(/^(?<req
|
638
|
+
m = a.match(/^(?<req>[+\-!])?(?<tok>.*?)$/)
|
623
639
|
todo.push({
|
624
640
|
token: m['tok'],
|
625
|
-
required: !m['req'].nil?
|
641
|
+
required: all_req || (!m['req'].nil? && m['req'] == '+'),
|
642
|
+
negate: !m['req'].nil? && m['req'] =~ /[!\-]/
|
626
643
|
})
|
627
644
|
end
|
628
645
|
end
|
@@ -641,7 +658,7 @@ class App
|
|
641
658
|
[tokens]
|
642
659
|
end
|
643
660
|
|
644
|
-
NA.output_actions(actions, depth, files: files, regexes: regexes)
|
661
|
+
NA.output_actions(actions, depth, files: files, regexes: regexes, notes: options[:notes])
|
645
662
|
end
|
646
663
|
end
|
647
664
|
|
@@ -669,6 +686,9 @@ class App
|
|
669
686
|
c.arg_name 'TODO_PATH'
|
670
687
|
c.flag %i[in]
|
671
688
|
|
689
|
+
c.desc 'Include notes in output'
|
690
|
+
c.switch %i[notes], negatable: true, default_value: false
|
691
|
+
|
672
692
|
c.desc 'Combine tags with OR, displaying actions matching ANY of the tags'
|
673
693
|
c.switch %i[o or], negatable: false
|
674
694
|
|
@@ -721,10 +741,11 @@ class App
|
|
721
741
|
if options[:in]
|
722
742
|
todo = []
|
723
743
|
options[:in].split(/ *, */).each do |a|
|
724
|
-
m = a.match(/^(?<req
|
744
|
+
m = a.match(/^(?<req>[+\-!])?(?<tok>.*?)$/)
|
725
745
|
todo.push({
|
726
746
|
token: m['tok'],
|
727
|
-
required: !m['req'].nil?
|
747
|
+
required: all_req || (!m['req'].nil? && m['req'] == '+'),
|
748
|
+
negate: !m['req'].nil? && m['req'] =~ /[!\-]/
|
728
749
|
})
|
729
750
|
end
|
730
751
|
end
|
@@ -737,7 +758,7 @@ class App
|
|
737
758
|
project: options[:project],
|
738
759
|
require_na: false)
|
739
760
|
regexes = tags.delete_if { |token| token[:negate] }.map { |token| token[:token] }
|
740
|
-
NA.output_actions(actions, depth, files: files, regexes: regexes)
|
761
|
+
NA.output_actions(actions, depth, files: files, regexes: regexes, notes: options[:notes])
|
741
762
|
end
|
742
763
|
end
|
743
764
|
|
@@ -751,17 +772,17 @@ class App
|
|
751
772
|
reader = TTY::Reader.new
|
752
773
|
if args.count.positive?
|
753
774
|
project = args.join(' ')
|
754
|
-
|
775
|
+
elsif
|
755
776
|
project = File.expand_path('.').split('/').last
|
756
|
-
project = reader.read_line(NA::Color.template('{y}Project name {bw}> {x}'), value: project).strip
|
777
|
+
project = reader.read_line(NA::Color.template('{y}Project name {bw}> {x}'), value: project).strip if $stdin.isatty
|
757
778
|
end
|
758
779
|
|
759
780
|
target = "#{project}.#{NA.extension}"
|
760
781
|
|
761
782
|
if File.exist?(target)
|
762
|
-
|
763
|
-
|
764
|
-
|
783
|
+
res = NA.yn(NA::Color.template("{r}File {bw}#{target}{r} already exists, overwrite it"), default: false)
|
784
|
+
Process.exit 1 unless res
|
785
|
+
|
765
786
|
end
|
766
787
|
|
767
788
|
NA.create_todo(target, project)
|
@@ -942,8 +963,12 @@ class App
|
|
942
963
|
long_desc 'Run without argument to list saved searches'
|
943
964
|
arg_name 'SEARCH_TITLE', optional: true
|
944
965
|
command %i[saved] do |c|
|
945
|
-
c.example 'na
|
946
|
-
c.example 'na saved
|
966
|
+
c.example 'na tagged "+maybe,+priority<=3" --save maybelater', description: 'save a search called "maybelater"'
|
967
|
+
c.example 'na saved maybelater', description: 'perform the search named "maybelater"'
|
968
|
+
c.example 'na saved maybe',
|
969
|
+
description: 'perform the search named "maybelater", assuming no other searches match "may"'
|
970
|
+
c.example 'na maybe',
|
971
|
+
description: 'na run with no command and a single argument automatically performs a matching saved search'
|
947
972
|
c.example 'na saved', description: 'list available searches'
|
948
973
|
|
949
974
|
c.desc 'Open the saved search file in $EDITOR'
|
@@ -953,18 +978,14 @@ class App
|
|
953
978
|
c.switch %i[d delete]
|
954
979
|
|
955
980
|
c.action do |_global_options, options, args|
|
956
|
-
if options[:edit]
|
957
|
-
NA.edit_searches
|
958
|
-
end
|
981
|
+
NA.edit_searches if options[:edit]
|
959
982
|
|
960
983
|
searches = NA.load_searches
|
961
984
|
if args.empty?
|
962
985
|
NA.notify("{bg}Saved searches stored in {bw}#{NA.database_path(file: 'saved_searches.yml')}")
|
963
986
|
NA.notify(searches.map { |k, v| "{y}#{k}: {w}#{v}" }.join("\n"), exit_code: 0)
|
964
987
|
else
|
965
|
-
if options[:delete]
|
966
|
-
NA.delete_search(args)
|
967
|
-
end
|
988
|
+
NA.delete_search(args) if options[:delete]
|
968
989
|
|
969
990
|
keys = searches.keys.delete_if { |k| k !~ /#{args[0]}/ }
|
970
991
|
NA.notify("{r}Search #{args[0]} not found", exit_code: 1) if keys.empty?
|
@@ -988,6 +1009,7 @@ class App
|
|
988
1009
|
global[:cwd_as] =~ /^p/ ? :project : :tag
|
989
1010
|
end
|
990
1011
|
NA.weed_cache_file
|
1012
|
+
NA.notify("{dw}{ globals: #{NA.globals}, command_line: #{NA.command_line}, @command: #{@command}}", debug: true)
|
991
1013
|
true
|
992
1014
|
end
|
993
1015
|
|
@@ -998,10 +1020,21 @@ class App
|
|
998
1020
|
on_error do |exception|
|
999
1021
|
case exception
|
1000
1022
|
when GLI::UnknownCommand
|
1001
|
-
|
1002
|
-
|
1023
|
+
if NA.command_line.count == 1
|
1024
|
+
cmd = ['saved']
|
1025
|
+
cmd.concat(ARGV.unshift(NA.command_line[0]))
|
1003
1026
|
|
1004
|
-
|
1027
|
+
exit run(cmd)
|
1028
|
+
elsif NA.globals.include?('-a') || NA.globals.include?('--add')
|
1029
|
+
cmd = ['add']
|
1030
|
+
cmd.concat(NA.command_line)
|
1031
|
+
NA.globals.delete('-a')
|
1032
|
+
NA.globals.delete('--add')
|
1033
|
+
cmd.unshift(*NA.globals)
|
1034
|
+
|
1035
|
+
exit run(cmd)
|
1036
|
+
end
|
1037
|
+
true
|
1005
1038
|
when SystemExit
|
1006
1039
|
false
|
1007
1040
|
else
|
@@ -1010,9 +1043,20 @@ class App
|
|
1010
1043
|
end
|
1011
1044
|
end
|
1012
1045
|
|
1013
|
-
NA.
|
1014
|
-
NA.
|
1015
|
-
|
1016
|
-
|
1046
|
+
NA.stdin = $stdin.read.strip if $stdin.stat.size.positive? || $stdin.fcntl(Fcntl::F_GETFL, 0).zero?
|
1047
|
+
NA.stdin = nil unless NA.stdin && NA.stdin.length.positive?
|
1048
|
+
|
1049
|
+
NA.globals = []
|
1050
|
+
NA.command_line = []
|
1051
|
+
in_globals = true
|
1052
|
+
ARGV.each do |arg|
|
1053
|
+
if arg =~ /^-/ && in_globals
|
1054
|
+
NA.globals.push(arg)
|
1055
|
+
else
|
1056
|
+
NA.command_line.push(arg)
|
1057
|
+
in_globals = false
|
1058
|
+
end
|
1059
|
+
end
|
1060
|
+
@command = NA.command_line[0]
|
1017
1061
|
|
1018
1062
|
exit App.run(ARGV)
|
data/lib/na/action.rb
CHANGED
@@ -2,9 +2,9 @@
|
|
2
2
|
|
3
3
|
module NA
|
4
4
|
class Action < Hash
|
5
|
-
attr_reader :file, :project, :parent, :tags, :line
|
5
|
+
attr_reader :file, :project, :parent, :tags, :line
|
6
6
|
|
7
|
-
attr_accessor :action
|
7
|
+
attr_accessor :action, :note
|
8
8
|
|
9
9
|
def initialize(file, project, parent, action, idx, note = [])
|
10
10
|
super()
|
@@ -19,7 +19,12 @@ module NA
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def to_s
|
22
|
-
|
22
|
+
note = if @note.count.positive?
|
23
|
+
"\n#{@note.join("\n")}"
|
24
|
+
else
|
25
|
+
''
|
26
|
+
end
|
27
|
+
"(#{@file}:#{@line}) #{@project}:#{@parent.join('>')} | #{@action}#{@note}"
|
23
28
|
end
|
24
29
|
|
25
30
|
def inspect
|
@@ -28,10 +33,11 @@ module NA
|
|
28
33
|
@project: #{@project}
|
29
34
|
@parent: #{@parent.join('>')}
|
30
35
|
@action: #{@action}
|
36
|
+
@note: #{@note}
|
31
37
|
EOINSPECT
|
32
38
|
end
|
33
39
|
|
34
|
-
def pretty(extension: 'taskpaper', template: {}, regexes: [])
|
40
|
+
def pretty(extension: 'taskpaper', template: {}, regexes: [], notes: false)
|
35
41
|
default_template = {
|
36
42
|
file: '{xbk}',
|
37
43
|
parent: '{c}',
|
@@ -41,7 +47,8 @@ module NA
|
|
41
47
|
tags: '{m}',
|
42
48
|
value_parens: '{m}',
|
43
49
|
values: '{y}',
|
44
|
-
output: '%filename%parents| %action'
|
50
|
+
output: '%filename%parents| %action',
|
51
|
+
note: '{dw}'
|
45
52
|
}
|
46
53
|
template = default_template.merge(template)
|
47
54
|
|
@@ -58,6 +65,12 @@ module NA
|
|
58
65
|
file_tpl = "#{template[:file]}#{file} {x}"
|
59
66
|
filename = NA::Color.template(file_tpl)
|
60
67
|
|
68
|
+
note = if notes && @note.count.positive?
|
69
|
+
NA::Color.template("\n#{@note.map { |l| " #{template[:note]}• #{l}{x}" }.join("\n")}")
|
70
|
+
else
|
71
|
+
''
|
72
|
+
end
|
73
|
+
|
61
74
|
action = NA::Color.template("#{template[:action]}#{@action.sub(/ @#{NA.na_tag}\b/, '')}{x}")
|
62
75
|
action = action.highlight_tags(color: template[:tags],
|
63
76
|
parens: template[:value_parens],
|
@@ -67,7 +80,8 @@ module NA
|
|
67
80
|
NA::Color.template(template[:output].gsub(/%filename/, filename)
|
68
81
|
.gsub(/%project/, project)
|
69
82
|
.gsub(/%parents?/, parents)
|
70
|
-
.gsub(/%action/, action.highlight_search(regexes))
|
83
|
+
.gsub(/%action/, action.highlight_search(regexes))
|
84
|
+
.gsub(/%note/, note)).gsub(/\\\{/, '{')
|
71
85
|
end
|
72
86
|
|
73
87
|
def tags_match?(any: [], all: [], none: [])
|
data/lib/na/next_action.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
# Next Action methods
|
4
4
|
module NA
|
5
5
|
class << self
|
6
|
-
attr_accessor :verbose, :extension, :na_tag, :command_line, :globals, :global_file, :cwd_is, :cwd
|
6
|
+
attr_accessor :verbose, :extension, :na_tag, :command_line, :globals, :global_file, :cwd_is, :cwd, :stdin
|
7
7
|
|
8
8
|
##
|
9
9
|
## Output to STDERR
|
@@ -14,7 +14,7 @@ module NA
|
|
14
14
|
## @param debug [Boolean] only display message if running :verbose
|
15
15
|
##
|
16
16
|
def notify(msg, exit_code: false, debug: false)
|
17
|
-
return if debug && NA.verbose
|
17
|
+
return if debug && !NA.verbose
|
18
18
|
|
19
19
|
$stderr.puts NA::Color.template("{x}#{msg}{x}")
|
20
20
|
Process.exit exit_code if exit_code
|
@@ -316,6 +316,7 @@ module NA
|
|
316
316
|
contents = target.read_file.split(/\n/)
|
317
317
|
|
318
318
|
if add.is_a?(Action)
|
319
|
+
add_tag ||= []
|
319
320
|
action = process_action(add, priority: priority, finish: finish, add_tag: add_tag, remove_tag: remove_tag)
|
320
321
|
|
321
322
|
projects = find_projects(target)
|
@@ -397,6 +398,7 @@ module NA
|
|
397
398
|
contents.insert(target_line, "#{indent}\t- #{action.action}#{note}")
|
398
399
|
end
|
399
400
|
end
|
401
|
+
|
400
402
|
backup_file(target)
|
401
403
|
File.open(target, 'w') { |f| f.puts contents.join("\n") }
|
402
404
|
|
@@ -437,7 +439,7 @@ module NA
|
|
437
439
|
## @param files [Array] The files actions originally came from
|
438
440
|
## @param regexes [Array] The regexes used to gather actions
|
439
441
|
##
|
440
|
-
def output_actions(actions, depth, files: nil, regexes: [])
|
442
|
+
def output_actions(actions, depth, files: nil, regexes: [], notes: false)
|
441
443
|
return if files.nil?
|
442
444
|
|
443
445
|
template = if files.count.positive?
|
@@ -455,10 +457,11 @@ module NA
|
|
455
457
|
else
|
456
458
|
'%parent%action'
|
457
459
|
end
|
460
|
+
template += '%note' if notes
|
458
461
|
|
459
462
|
files.map { |f| notify("{dw}#{f}", debug: true) } if files
|
460
463
|
|
461
|
-
puts(actions.map { |action| action.pretty(template: { output: template }, regexes: regexes) })
|
464
|
+
puts(actions.map { |action| action.pretty(template: { output: template }, regexes: regexes, notes: notes) })
|
462
465
|
end
|
463
466
|
|
464
467
|
##
|
@@ -751,9 +754,10 @@ module NA
|
|
751
754
|
## @param target [String] The file to back up
|
752
755
|
##
|
753
756
|
def backup_file(target)
|
754
|
-
|
755
|
-
|
756
|
-
FileUtils.cp(target,
|
757
|
+
file = ".#{File.basename(target)}.bak"
|
758
|
+
backup = File.join(File.dirname(target), file)
|
759
|
+
FileUtils.cp(target, backup)
|
760
|
+
NA.notify("{dw}Backup file created at #{backup}", debug: true)
|
757
761
|
end
|
758
762
|
|
759
763
|
##
|
@@ -780,6 +784,12 @@ module NA
|
|
780
784
|
required = search.filter { |s| s[:required] }.map { |t| t[:token] }
|
781
785
|
negated = search.filter { |s| s[:negate] }.map { |t| t[:token] }
|
782
786
|
|
787
|
+
optional.push('*') if required.count.zero? && negated.count.positive?
|
788
|
+
if required == negated
|
789
|
+
required = ['*']
|
790
|
+
optional = ['*']
|
791
|
+
end
|
792
|
+
|
783
793
|
NA.notify("{dw}Optional directory regex: {x}#{optional.map(&:dir_to_rx)}", debug: true)
|
784
794
|
NA.notify("{dw}Required directory regex: {x}#{required.map(&:dir_to_rx)}", debug: true)
|
785
795
|
NA.notify("{dw}Negated directory regex: {x}#{negated.map { |t| t.dir_to_rx(distance: 1, require_last: false) }}", debug: true)
|
data/lib/na/prompt.rb
CHANGED
@@ -7,22 +7,59 @@ module NA
|
|
7
7
|
def prompt_hook(shell)
|
8
8
|
case shell
|
9
9
|
when :zsh
|
10
|
+
cmd = if NA.global_file
|
11
|
+
case NA.cwd_is
|
12
|
+
when :project
|
13
|
+
'na next --proj $(basename "$PWD")'
|
14
|
+
when :tag
|
15
|
+
'na tagged $(basename "$PWD")'
|
16
|
+
else
|
17
|
+
NA.notify('When using a global file, a prompt hook requires `--cwd_as [tag|project]`', exit_code: 1)
|
18
|
+
end
|
19
|
+
else
|
20
|
+
'na next'
|
21
|
+
end
|
10
22
|
<<~EOHOOK
|
11
23
|
# zsh prompt hook for na
|
12
|
-
chpwd() {
|
24
|
+
chpwd() { #{cmd} }
|
13
25
|
EOHOOK
|
14
26
|
when :fish
|
27
|
+
cmd = if NA.global_file
|
28
|
+
case NA.cwd_is
|
29
|
+
when :project
|
30
|
+
'na next --proj (basename "$PWD")'
|
31
|
+
when :tag
|
32
|
+
'na tagged (basename "$PWD")'
|
33
|
+
else
|
34
|
+
NA.notify('When using a global file, a prompt hook requires `--cwd_as [tag|project]`', exit_code: 1)
|
35
|
+
end
|
36
|
+
else
|
37
|
+
'na next'
|
38
|
+
end
|
15
39
|
<<~EOHOOK
|
16
40
|
# Fish Prompt Command
|
17
41
|
function __should_na --on-variable PWD
|
18
|
-
test -s (basename $PWD)".#{NA.extension}" &&
|
42
|
+
test -s (basename $PWD)".#{NA.extension}" && #{cmd}
|
19
43
|
end
|
20
44
|
EOHOOK
|
21
45
|
when :bash
|
46
|
+
cmd = if NA.global_file
|
47
|
+
case NA.cwd_is
|
48
|
+
when :project
|
49
|
+
'na next --proj $(basename "$PWD")'
|
50
|
+
when :tag
|
51
|
+
'na tagged $(basename "$PWD")'
|
52
|
+
else
|
53
|
+
NA.notify('When using a global file, a prompt hook requires `--cwd_as [tag|project]`', exit_code: 1)
|
54
|
+
end
|
55
|
+
else
|
56
|
+
'na next'
|
57
|
+
end
|
58
|
+
|
22
59
|
<<~EOHOOK
|
23
60
|
# Bash PROMPT_COMMAND for na
|
24
61
|
last_command_was_cd() {
|
25
|
-
[[ $(history 1|sed -e "s/^[ ]*[0-9]*[ ]*//") =~ ^((cd|z|j|jump|g|f|pushd|popd|exit)([ ]|$)) ]] &&
|
62
|
+
[[ $(history 1|sed -e "s/^[ ]*[0-9]*[ ]*//") =~ ^((cd|z|j|jump|g|f|pushd|popd|exit)([ ]|$)) ]] && #{cmd}
|
26
63
|
}
|
27
64
|
if [[ -z "$PROMPT_COMMAND" ]]; then
|
28
65
|
PROMPT_COMMAND="eval 'last_command_was_cd'"
|
@@ -46,7 +83,7 @@ module NA
|
|
46
83
|
def show_prompt_hook(shell)
|
47
84
|
file = prompt_file(shell)
|
48
85
|
|
49
|
-
|
86
|
+
NA.notify("{bw}# Add this to {y}#{file}{x}")
|
50
87
|
puts prompt_hook(shell)
|
51
88
|
end
|
52
89
|
|
@@ -54,8 +91,8 @@ module NA
|
|
54
91
|
file = prompt_file(shell)
|
55
92
|
|
56
93
|
File.open(File.expand_path(file), 'a') { |f| f.puts prompt_hook(shell) }
|
57
|
-
|
58
|
-
|
94
|
+
NA.notify("{y}Added {bw}#{shell}{xy} prompt hook to {bw}#{file}{xy}.{x}")
|
95
|
+
NA.notify("{y}You may need to close the current terminal and open a new one to enable the script.{x}")
|
59
96
|
end
|
60
97
|
end
|
61
98
|
end
|
data/lib/na/version.rb
CHANGED
data/src/README.md
CHANGED
@@ -9,11 +9,11 @@
|
|
9
9
|
_If you're one of the rare people like me who find this useful, feel free to
|
10
10
|
[buy me some coffee][donate]._
|
11
11
|
|
12
|
-
The current version of `na` is <!--VER-->1.2.
|
12
|
+
The current version of `na` is <!--VER-->1.2.5<!--END VER-->.
|
13
13
|
|
14
14
|
`na` ("next action") is a command line tool 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.
|
15
15
|
|
16
|
-
Used with Taskpaper files, it can add new
|
16
|
+
Used with Taskpaper files, it can add new action items quickly from the command line, automatically tagging them as next actions. It can also mark actions as completed, delete them, archive them, and move them between projects.
|
17
17
|
|
18
18
|
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). See the [Prompt Hooks](#prompt-hooks) section for details.
|
19
19
|
|
@@ -52,6 +52,16 @@ If found, it will try to locate an `Inbox:` project, or create one if it doesn't
|
|
52
52
|
|
53
53
|
You can mark todos as complete, delete them, add and remove tags, change priority, and even move them between projects with the `na update` command.
|
54
54
|
|
55
|
+
### Terminology
|
56
|
+
|
57
|
+
**Todo**: Refers to a todo file, usually a TaskPaper document
|
58
|
+
|
59
|
+
**Project**: Refers to a project within the TaskPaper document, specified by an alphanumeric name (spaces allowed) followed by a colon. Projects can be nested by indenting a tab beyond the parent projects indentation.
|
60
|
+
|
61
|
+
**Action**: Refers to an individual task, specified by a line starting with a hyphen (`-`)
|
62
|
+
|
63
|
+
**Note**: Refers to lines appearing between action lines that start without hyphens. The note is attached to the preceding action regardless of indentation.
|
64
|
+
|
55
65
|
### Usage
|
56
66
|
|
57
67
|
```
|
@@ -66,6 +76,12 @@ Example: `na add This feature @idea I have`
|
|
66
76
|
|
67
77
|
If you run the `add` command with no arguments, you'll be asked for input on the command line.
|
68
78
|
|
79
|
+
###### Adding notes
|
80
|
+
|
81
|
+
Use the `--note` switch to add a note. If STDIN (piped) input is present when this switch is used, it will be included in the note. A prompt will be displayed for adding additional notes, which will be appended to any STDIN note passed. Press CTRL-d to end editing and save the note.
|
82
|
+
|
83
|
+
Notes are not displayed by the `next/tagged/find` commands unless `--notes` is specified.
|
84
|
+
|
69
85
|
```
|
70
86
|
@cli(bundle exec bin/na help add)
|
71
87
|
```
|
@@ -100,6 +116,8 @@ Examples:
|
|
100
116
|
- `na next -d 3` (list all next actions in the current directory and look for additional files 3 levels deep from there)
|
101
117
|
- `na next marked2` (show next actions from another directory you've previously used na on)
|
102
118
|
|
119
|
+
To see all next actions across all known todos, use `na next "*"`. You can combine multiple arguments to see actions across multiple todos, e.g. `na next marked nvultra`.
|
120
|
+
|
103
121
|
```
|
104
122
|
@cli(bundle exec bin/na help next)
|
105
123
|
```
|
@@ -120,6 +138,9 @@ Search names can be partially matched when calling them, so if you have a search
|
|
120
138
|
|
121
139
|
Run `na saved` without an argument to list your saved searches.
|
122
140
|
|
141
|
+
> As a shortcut, if `na` is run with one argument that matches the name of a saved search, it will execute that search, so running `na maybe` is the same as running `na saved maybe`.
|
142
|
+
<!--JEKYLL{:.tip}-->
|
143
|
+
|
123
144
|
```
|
124
145
|
@cli(bundle exec bin/na help saved)
|
125
146
|
```
|
@@ -158,11 +179,27 @@ You can specify a particular todo file using `--file PATH` or any todo from hist
|
|
158
179
|
|
159
180
|
If more than one file is matched, a menu will be presented, multiple selections allowed. If multiple actions match the search within the selected file(s), a menu will be presented. If you have fzf installed, you can select one action to update with return, or use tab to mark multiple tasks to which the action will be applied. With gum you can use j, k, and x to mark multiple actions. Use the `--all` switch to force operation on all matched tasks, skipping the menu.
|
160
181
|
|
161
|
-
Any time an update action is carried out, a backup of the file before modification will be made in the same directory with a `.` prepended and `.bak` appended (e.g. `marked.taskpaper` is copied to `.marked.taskpaper.bak`). Only one undo step is available, but if something goes wrong (and this feature is still experimental, so be wary), you can just copy the "
|
182
|
+
Any time an update action is carried out, a backup of the file before modification will be made in the same directory with a `.` prepended and `.bak` appended (e.g. `marked.taskpaper` is copied to `.marked.taskpaper.bak`). Only one undo step is available, but if something goes wrong (and this feature is still experimental, so be wary), you can just copy the ".bak" file back to the original.
|
183
|
+
|
184
|
+
###### Marking a task as complete
|
185
|
+
|
186
|
+
You can mark an action complete using `--finish`, which will add a dated @done tag to the action. You can also mark it @done and immediately move it to the Archive project using `--archive`.
|
187
|
+
|
188
|
+
If you just want the action to stop appearing as a "next action," you can remove the next action tag using `--remove na` (or whatever your next action tag is configured as).
|
189
|
+
|
190
|
+
If you want to permanently delete an action, use `--delete` to remove it entirely.
|
191
|
+
|
192
|
+
###### Moving between projects
|
162
193
|
|
163
194
|
You can specify a new project for an action (moving it) with `--proj PROJECT_PATH`. A project path is hierarchical, with each level separated by a colon or slash. If the project path provided roughly matches an existing project, e.g. "mark:bug" would match "Marked:Bugs", then that project will be used. If no match is found, na will offer to generate a new project/hierarchy for the path provided. Strings will be exact but the first letter will be uppercased.
|
164
195
|
|
165
|
-
|
196
|
+
###### Adding notes
|
197
|
+
|
198
|
+
Use the `--note` switch to add a note. If STDIN (piped) input is present when this switch is used, it will be included in the note. A prompt will be displayed for adding additional notes, which will be appended to any STDIN note passed. Press CTRL-d to end editing and save the note.
|
199
|
+
|
200
|
+
Notes are not displayed by the `next/tagged/find` commands unless `--notes` is specified.
|
201
|
+
|
202
|
+
See the help output for a list of all available actions.
|
166
203
|
|
167
204
|
```
|
168
205
|
@cli(bundle exec bin/na help update)
|