na 1.2.59 → 1.2.61
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +23 -0
- data/Gemfile.lock +1 -1
- data/README.md +15 -4
- data/bin/commands/complete.rb +3 -0
- data/bin/commands/completed.rb +13 -3
- data/bin/commands/edit.rb +4 -0
- data/bin/commands/find.rb +5 -1
- data/bin/commands/next.rb +36 -7
- data/bin/commands/restore.rb +4 -1
- data/bin/commands/tag.rb +4 -0
- data/bin/commands/tagged.rb +4 -0
- data/bin/commands/update.rb +5 -1
- data/lib/na/action.rb +13 -8
- data/lib/na/next_action.rb +4 -2
- data/lib/na/string.rb +2 -0
- data/lib/na/todo.rb +11 -6
- data/lib/na/version.rb +1 -1
- data/src/_README.md +1 -1
- data/test.md +6 -1
- 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: '09631ecb9ed0479927d54375ed9e71807809ab93cd689bac1febde3509b9365f'
|
|
4
|
+
data.tar.gz: 1986fe627277b051a4de6bf879da28771b6ac0c53992bad79f1cecea6c86d2f0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 235b9d00ad77367d9b3c8807091efcae10f84591a712b486d32d661b6b7112a39057c0d614db34e86283b32d3d971f533bfab547ac2744b9768e78d46a18c6a9
|
|
7
|
+
data.tar.gz: 794846444bc772fe26d8f1af069e273ec85e1074657852fd476f03802b33e713b6d985826a83357aa4da211634f33fdb994582c33c026ec36ac1f64188e5268f
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,26 @@
|
|
|
1
|
+
### 1.2.61
|
|
2
|
+
|
|
3
|
+
2023-10-03 12:44
|
|
4
|
+
|
|
5
|
+
#### NEW
|
|
6
|
+
|
|
7
|
+
- `--priority` (`-p`) flag for `na next`, allows you to only display actions matching a certain @priority value. Can be used multiple times, or combine multiple values with a comma. Allows <> comparisons, and if more than one value is provided, automatically does an OR search
|
|
8
|
+
|
|
9
|
+
### 1.2.60
|
|
10
|
+
|
|
11
|
+
2023-10-03 12:31
|
|
12
|
+
|
|
13
|
+
#### NEW
|
|
14
|
+
|
|
15
|
+
- Added `--search_notes` to allow searching of notes when using `find` or `tagged --search`. Defaults to true, can be disabled with `--no-search_notes`
|
|
16
|
+
|
|
17
|
+
#### IMPROVED
|
|
18
|
+
|
|
19
|
+
- Added `--search_notes` to completed, restore, edit, and update
|
|
20
|
+
- Add `--search_notes` to `tag`
|
|
21
|
+
- Add `--search_notes` to `complete`
|
|
22
|
+
- Add `--search_notes` to `next`
|
|
23
|
+
|
|
1
24
|
### 1.2.59
|
|
2
25
|
|
|
3
26
|
2023-10-03 07:43
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
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.61
|
|
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.
|
|
@@ -77,7 +77,7 @@ SYNOPSIS
|
|
|
77
77
|
na [global options] command [command options] [arguments...]
|
|
78
78
|
|
|
79
79
|
VERSION
|
|
80
|
-
1.2.
|
|
80
|
+
1.2.61
|
|
81
81
|
|
|
82
82
|
GLOBAL OPTIONS
|
|
83
83
|
-a, --add - Add a next action (deprecated, for backwards compatibility)
|
|
@@ -190,6 +190,7 @@ COMMAND OPTIONS
|
|
|
190
190
|
-e, --regex - Interpret search pattern as regular expression
|
|
191
191
|
--file=PATH - Specify the file to search for the task (default: none)
|
|
192
192
|
--in, --todo=TODO_FILE - Use a known todo file, partial matches allowed (default: none)
|
|
193
|
+
--[no-]search_notes - Include notes in search (default: enabled)
|
|
193
194
|
--tagged=TAG - Match actions containing tag. Allows value comparisons (may be used more than once, default: none)
|
|
194
195
|
-x, --exact - Match pattern exactly
|
|
195
196
|
|
|
@@ -227,6 +228,7 @@ COMMAND OPTIONS
|
|
|
227
228
|
--omnifocus - Output actions nested by file and project
|
|
228
229
|
--proj, --project=PROJECT[/SUBPROJECT] - Show actions from a specific project (default: none)
|
|
229
230
|
--save=TITLE - Save this search for future use (default: none)
|
|
231
|
+
--[no-]search_notes - Include notes in search (default: enabled)
|
|
230
232
|
--tagged=TAG - Match actions containing tag. Allows value comparisons (may be used more than once, default: none)
|
|
231
233
|
-v, --invert - Show actions not matching search pattern
|
|
232
234
|
-x, --exact - Match pattern exactly
|
|
@@ -288,14 +290,17 @@ COMMAND OPTIONS
|
|
|
288
290
|
-d, --depth=DEPTH - Recurse to depth (default: none)
|
|
289
291
|
--[no-]done - Include @done actions
|
|
290
292
|
--exact - Search query is exact text match (not tokens)
|
|
291
|
-
--
|
|
293
|
+
--file=TODO_FILE - Display matches from specific todo file ([relative] path) (default: none)
|
|
294
|
+
--in, --todo=TODO - Display matches from a known todo file anywhere in history (short name) (may be used more than once, default: none)
|
|
292
295
|
--nest - Output actions nested by file
|
|
293
296
|
--[no-]notes - Include notes in output
|
|
294
297
|
--omnifocus - Output actions nested by file and project
|
|
298
|
+
-p, --prio, --priority=PRIORITY - Match actions with priority, allows <>= comparison (may be used more than once, default: none)
|
|
295
299
|
--proj, --project=PROJECT[/SUBPROJECT] - Show actions from a specific project (default: none)
|
|
296
300
|
--regex - Search query is regular expression
|
|
297
301
|
--save=TITLE - Save this search for future use (default: none)
|
|
298
302
|
--search, --find, --grep=QUERY - Filter results using search terms (may be used more than once, default: none)
|
|
303
|
+
--[no-]search_notes - Include notes in search (default: enabled)
|
|
299
304
|
-t, --tag=TAG - Alternate tag to search for (default: none)
|
|
300
305
|
--tagged=TAG - Match actions containing tag. Allows value comparisons (may be used more than once, default: none)
|
|
301
306
|
|
|
@@ -402,14 +407,17 @@ COMMAND OPTIONS
|
|
|
402
407
|
-d, --depth=DEPTH - Recurse to depth (default: none)
|
|
403
408
|
--[no-]done - Include @done actions
|
|
404
409
|
--exact - Search query is exact text match (not tokens)
|
|
405
|
-
--
|
|
410
|
+
--file=TODO_FILE - Display matches from specific todo file ([relative] path) (default: none)
|
|
411
|
+
--in, --todo=TODO - Display matches from a known todo file anywhere in history (short name) (may be used more than once, default: none)
|
|
406
412
|
--nest - Output actions nested by file
|
|
407
413
|
--[no-]notes - Include notes in output
|
|
408
414
|
--omnifocus - Output actions nested by file and project
|
|
415
|
+
-p, --prio, --priority=PRIORITY - Match actions with priority, allows <>= comparison (may be used more than once, default: none)
|
|
409
416
|
--proj, --project=PROJECT[/SUBPROJECT] - Show actions from a specific project (default: none)
|
|
410
417
|
--regex - Search query is regular expression
|
|
411
418
|
--save=TITLE - Save this search for future use (default: none)
|
|
412
419
|
--search, --find, --grep=QUERY - Filter results using search terms (may be used more than once, default: none)
|
|
420
|
+
--[no-]search_notes - Include notes in search (default: enabled)
|
|
413
421
|
-t, --tag=TAG - Alternate tag to search for (default: none)
|
|
414
422
|
--tagged=TAG - Match actions containing tag. Allows value comparisons (may be used more than once, default: none)
|
|
415
423
|
|
|
@@ -509,6 +517,7 @@ COMMAND OPTIONS
|
|
|
509
517
|
--replace=TEXT - Use with --find to find and replace with new text. Enables --exact when used (default: none)
|
|
510
518
|
--restore - Remove @done tag from action
|
|
511
519
|
--search, --find, --grep=QUERY - Filter results using search terms (may be used more than once, default: none)
|
|
520
|
+
--[no-]search_notes - Include notes in search (default: enabled)
|
|
512
521
|
-t, --tag=TAG - Add a tag to the action, @tag(values) allowed, use multiple times or combine multiple tags with a comma (may be used more than once, default: none)
|
|
513
522
|
--tagged=TAG - Match actions containing tag. Allows value comparisons (may be used more than once, default: none)
|
|
514
523
|
--to, --move=PROJECT - Move action to specific project (default: none)
|
|
@@ -562,6 +571,7 @@ COMMAND OPTIONS
|
|
|
562
571
|
-o, --overwrite - Overwrite note instead of appending
|
|
563
572
|
--proj, --project=PROJECT[/SUBPROJECT] - Affect actions from a specific project (default: none)
|
|
564
573
|
--search, --find, --grep=QUERY - Filter results using search terms (may be used more than once, default: none)
|
|
574
|
+
--[no-]search_notes - Include notes in search (default: enabled)
|
|
565
575
|
--tagged=TAG - Match actions containing tag. Allows value comparisons (may be used more than once, default: none)
|
|
566
576
|
--to, --move=PROJECT - Move action to specific project (default: none)
|
|
567
577
|
-x, --exact - Match pattern exactly
|
|
@@ -632,6 +642,7 @@ COMMAND OPTIONS
|
|
|
632
642
|
--file=PATH - Specify the file to search for the task (default: none)
|
|
633
643
|
--in, --todo=TODO_FILE - Use a known todo file, partial matches allowed (default: none)
|
|
634
644
|
--search, --find, --grep=QUERY - Filter results using search terms (may be used more than once, default: none)
|
|
645
|
+
--[no-]search_notes - Include notes in search (default: enabled)
|
|
635
646
|
--tagged=TAG - Match actions containing tag. Allows value comparisons (may be used more than once, default: none)
|
|
636
647
|
-x, --exact - Match pattern exactly
|
|
637
648
|
|
data/bin/commands/complete.rb
CHANGED
|
@@ -44,6 +44,9 @@ class App
|
|
|
44
44
|
c.arg_name 'QUERY'
|
|
45
45
|
c.flag %i[search find grep], multiple: true
|
|
46
46
|
|
|
47
|
+
c.desc 'Include notes in search'
|
|
48
|
+
c.switch %i[search_notes], negatable: true, default_value: true
|
|
49
|
+
|
|
47
50
|
c.desc 'Match actions containing tag. Allows value comparisons'
|
|
48
51
|
c.arg_name 'TAG'
|
|
49
52
|
c.flag %i[tagged], multiple: true
|
data/bin/commands/completed.rb
CHANGED
|
@@ -44,6 +44,9 @@ class App
|
|
|
44
44
|
c.desc 'Include notes in output'
|
|
45
45
|
c.switch %i[notes], negatable: true, default_value: false
|
|
46
46
|
|
|
47
|
+
c.desc 'Include notes in search'
|
|
48
|
+
c.switch %i[search_notes], negatable: true, default_value: true
|
|
49
|
+
|
|
47
50
|
c.desc 'Show actions from a specific project'
|
|
48
51
|
c.arg_name 'PROJECT[/SUBPROJECT]'
|
|
49
52
|
c.flag %i[proj project]
|
|
@@ -75,9 +78,9 @@ class App
|
|
|
75
78
|
tag_string.concat(options[:tagged]) if options[:tagged]
|
|
76
79
|
|
|
77
80
|
if args.empty?
|
|
78
|
-
cmd_string = %(tagged --done
|
|
81
|
+
cmd_string = %(tagged --done)
|
|
79
82
|
else
|
|
80
|
-
cmd_string = %(find --tagged "#{tag_string.join(',')}" --done
|
|
83
|
+
cmd_string = %(find --tagged "#{tag_string.join(',')}" --done)
|
|
81
84
|
end
|
|
82
85
|
|
|
83
86
|
cmd_string += ' --or' if options[:or]
|
|
@@ -86,13 +89,20 @@ class App
|
|
|
86
89
|
cmd_string += %( --depth #{options[:depth]}) if options[:depth]
|
|
87
90
|
cmd_string += ' --nest' if options[:nest]
|
|
88
91
|
cmd_string += ' --omnifocus' if options[:omnifocus]
|
|
92
|
+
cmd_string += " --#{options[:search_notes] ? 'search_notes' : 'no-search_notes'}"
|
|
89
93
|
cmd_string += " --#{options[:notes] ? 'notes' : 'no-notes' }"
|
|
90
94
|
|
|
95
|
+
if args.empty?
|
|
96
|
+
cmd_string += " #{tag_string.join(',')}"
|
|
97
|
+
else
|
|
98
|
+
cmd_string += " #{args.join(' ')}"
|
|
99
|
+
end
|
|
100
|
+
|
|
91
101
|
if options[:save]
|
|
92
102
|
title = options[:save].gsub(/[^a-z0-9]/, '_').gsub(/_+/, '_')
|
|
93
103
|
NA.save_search(title, cmd_string)
|
|
94
104
|
end
|
|
95
|
-
|
|
105
|
+
puts cmd_string
|
|
96
106
|
exit run(Shellwords.shellsplit(cmd_string))
|
|
97
107
|
end
|
|
98
108
|
end
|
data/bin/commands/edit.rb
CHANGED
|
@@ -39,6 +39,9 @@ class App
|
|
|
39
39
|
c.desc 'Match pattern exactly'
|
|
40
40
|
c.switch %i[x exact], negatable: false
|
|
41
41
|
|
|
42
|
+
c.desc 'Include notes in search'
|
|
43
|
+
c.switch %i[search_notes], negatable: true, default_value: true
|
|
44
|
+
|
|
42
45
|
c.action do |global_options, options, args|
|
|
43
46
|
options[:edit] = true
|
|
44
47
|
action = if args.count.positive?
|
|
@@ -130,6 +133,7 @@ class App
|
|
|
130
133
|
targets.each do |target|
|
|
131
134
|
NA.update_action(target,
|
|
132
135
|
tokens,
|
|
136
|
+
search_note: options[:search_notes],
|
|
133
137
|
done: options[:done],
|
|
134
138
|
edit: options[:edit],
|
|
135
139
|
project: target_proj,
|
data/bin/commands/find.rb
CHANGED
|
@@ -29,6 +29,9 @@ class App
|
|
|
29
29
|
c.desc 'Include notes in output'
|
|
30
30
|
c.switch %i[notes], negatable: true, default_value: false
|
|
31
31
|
|
|
32
|
+
c.desc 'Include notes in search'
|
|
33
|
+
c.switch %i[search_notes], negatable: true, default_value: true
|
|
34
|
+
|
|
32
35
|
c.desc 'Combine search tokens with OR, displaying actions matching ANY of the terms'
|
|
33
36
|
c.switch %i[o or], negatable: false
|
|
34
37
|
|
|
@@ -93,7 +96,7 @@ class App
|
|
|
93
96
|
|
|
94
97
|
search = search.gsub(/ +/, ' ').strip
|
|
95
98
|
|
|
96
|
-
all_req = options[:tagged].join(' ') !~ /[+!-]/ && !options[:or]
|
|
99
|
+
all_req = options[:tagged].join(' ') !~ /(?<=[, ])[+!-]/ && !options[:or]
|
|
97
100
|
tags = []
|
|
98
101
|
options[:tagged].join(',').split(/ *, */).each do |arg|
|
|
99
102
|
m = arg.match(/^(?<req>[+!-])?(?<tag>[^ =<>$~\^]+?) *(?:(?<op>[=<>~]{1,2}|[*$\^]=) *(?<val>.*?))?$/)
|
|
@@ -149,6 +152,7 @@ class App
|
|
|
149
152
|
done: options[:done],
|
|
150
153
|
query: todos,
|
|
151
154
|
search: tokens,
|
|
155
|
+
search_note: options[:search_notes],
|
|
152
156
|
tag: tags,
|
|
153
157
|
negate: options[:invert],
|
|
154
158
|
regex: options[:regex],
|
data/bin/commands/next.rb
CHANGED
|
@@ -22,10 +22,14 @@ class App
|
|
|
22
22
|
c.desc 'Show next actions from all known todo files (in any directory)'
|
|
23
23
|
c.switch %i[all], negatable: false, default_value: false
|
|
24
24
|
|
|
25
|
-
c.desc 'Display matches from a known todo file'
|
|
26
|
-
c.arg_name '
|
|
25
|
+
c.desc 'Display matches from a known todo file anywhere in history (short name)'
|
|
26
|
+
c.arg_name 'TODO'
|
|
27
27
|
c.flag %i[in todo], multiple: true
|
|
28
28
|
|
|
29
|
+
c.desc 'Display matches from specific todo file ([relative] path)'
|
|
30
|
+
c.arg_name 'TODO_FILE'
|
|
31
|
+
c.flag %i[file]
|
|
32
|
+
|
|
29
33
|
c.desc 'Alternate tag to search for'
|
|
30
34
|
c.arg_name 'TAG'
|
|
31
35
|
c.flag %i[t tag]
|
|
@@ -38,10 +42,17 @@ class App
|
|
|
38
42
|
c.arg_name 'TAG'
|
|
39
43
|
c.flag %i[tagged], multiple: true
|
|
40
44
|
|
|
45
|
+
c.desc 'Match actions with priority, allows <>= comparison'
|
|
46
|
+
c.arg_name 'PRIORITY'
|
|
47
|
+
c.flag %i[p prio priority], multiple: true
|
|
48
|
+
|
|
41
49
|
c.desc 'Filter results using search terms'
|
|
42
50
|
c.arg_name 'QUERY'
|
|
43
51
|
c.flag %i[search find grep], multiple: true
|
|
44
52
|
|
|
53
|
+
c.desc 'Include notes in search'
|
|
54
|
+
c.switch %i[search_notes], negatable: true, default_value: true
|
|
55
|
+
|
|
45
56
|
c.desc 'Search query is regular expression'
|
|
46
57
|
c.switch %i[regex], negatable: false
|
|
47
58
|
|
|
@@ -109,6 +120,20 @@ class App
|
|
|
109
120
|
|
|
110
121
|
search = search.gsub(/,/, '').gsub(/ +/, ' ') unless search.nil?
|
|
111
122
|
|
|
123
|
+
if options[:priority].count.positive?
|
|
124
|
+
prios = options[:priority].join(',').split(/,/)
|
|
125
|
+
options[:or] = true if prios.count > 1
|
|
126
|
+
prios.each do |p|
|
|
127
|
+
options[:tagged] << if p =~ /^[<>=]{1,2}/
|
|
128
|
+
"priority#{p}"
|
|
129
|
+
else
|
|
130
|
+
"priority=#{p}"
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
pp options[:tagged]
|
|
136
|
+
|
|
112
137
|
all_req = options[:tagged].join(' ') !~ /(?<=[, ])[+!-]/ && !options[:or]
|
|
113
138
|
tags = []
|
|
114
139
|
options[:tagged].join(',').split(/ *, */).each do |arg|
|
|
@@ -169,13 +194,17 @@ class App
|
|
|
169
194
|
tag << { tag: 'done', value: nil, negate: true } unless options[:done]
|
|
170
195
|
tag.concat(tags)
|
|
171
196
|
|
|
197
|
+
file_path = options[:file] ? File.expand_path(options[:file]) : nil
|
|
198
|
+
|
|
172
199
|
todo = NA::Todo.new({ depth: depth,
|
|
173
200
|
done: options[:done],
|
|
201
|
+
file_path: file_path,
|
|
202
|
+
project: options[:project],
|
|
174
203
|
query: tokens,
|
|
175
|
-
|
|
204
|
+
require_na: require_na,
|
|
176
205
|
search: search_tokens,
|
|
177
|
-
|
|
178
|
-
|
|
206
|
+
search_note: options[:search_notes],
|
|
207
|
+
tag: tag })
|
|
179
208
|
if todo.files.empty? && tokens
|
|
180
209
|
NA.notify("#{NA.theme[:error]}No matches found for #{tokens[0][:token]}.
|
|
181
210
|
Run `na todos` to see available todo files.")
|
|
@@ -183,9 +212,9 @@ class App
|
|
|
183
212
|
NA::Pager.paginate = false if options[:omnifocus]
|
|
184
213
|
todo.actions.output(depth,
|
|
185
214
|
files: todo.files,
|
|
186
|
-
notes: options[:notes],
|
|
187
215
|
nest: options[:nest],
|
|
188
|
-
nest_projects: options[:omnifocus]
|
|
216
|
+
nest_projects: options[:omnifocus],
|
|
217
|
+
notes: options[:notes])
|
|
189
218
|
end
|
|
190
219
|
end
|
|
191
220
|
end
|
data/bin/commands/restore.rb
CHANGED
|
@@ -23,7 +23,7 @@ class App
|
|
|
23
23
|
|
|
24
24
|
c.desc 'Specify the file to search for the task'
|
|
25
25
|
c.arg_name 'PATH'
|
|
26
|
-
c.flag %i[file]
|
|
26
|
+
c.flag %i[file in]
|
|
27
27
|
|
|
28
28
|
c.desc 'Search for files X directories deep'
|
|
29
29
|
c.arg_name 'DEPTH'
|
|
@@ -42,6 +42,9 @@ class App
|
|
|
42
42
|
c.desc 'Match pattern exactly'
|
|
43
43
|
c.switch %i[x exact], negatable: false
|
|
44
44
|
|
|
45
|
+
c.desc 'Include notes in search'
|
|
46
|
+
c.switch %i[search_notes], negatable: true, default_value: true
|
|
47
|
+
|
|
45
48
|
c.action do |global, options, args|
|
|
46
49
|
options[:remove] = ['done']
|
|
47
50
|
options[:done] = true
|
data/bin/commands/tag.rb
CHANGED
|
@@ -46,6 +46,9 @@ class App
|
|
|
46
46
|
c.arg_name 'QUERY'
|
|
47
47
|
c.flag %i[search find grep], multiple: true
|
|
48
48
|
|
|
49
|
+
c.desc 'Include notes in search'
|
|
50
|
+
c.switch %i[search_notes], negatable: true, default_value: true
|
|
51
|
+
|
|
49
52
|
c.desc 'Interpret search pattern as regular expression'
|
|
50
53
|
c.switch %i[e regex], negatable: false
|
|
51
54
|
|
|
@@ -152,6 +155,7 @@ class App
|
|
|
152
155
|
|
|
153
156
|
targets.each do |target|
|
|
154
157
|
NA.update_action(target, tokens,
|
|
158
|
+
search_note: options[:search_notes],
|
|
155
159
|
add_tag: add_tags,
|
|
156
160
|
all: options[:all],
|
|
157
161
|
done: options[:done],
|
data/bin/commands/tagged.rb
CHANGED
|
@@ -40,6 +40,9 @@ class App
|
|
|
40
40
|
c.arg_name 'QUERY'
|
|
41
41
|
c.flag %i[search find grep], multiple: true
|
|
42
42
|
|
|
43
|
+
c.desc 'Include notes in search'
|
|
44
|
+
c.switch %i[search_notes], negatable: true, default_value: true
|
|
45
|
+
|
|
43
46
|
c.desc 'Search query is regular expression'
|
|
44
47
|
c.switch %i[regex], negatable: false
|
|
45
48
|
|
|
@@ -139,6 +142,7 @@ class App
|
|
|
139
142
|
done: options[:done],
|
|
140
143
|
query: todos,
|
|
141
144
|
search: tokens,
|
|
145
|
+
search_note: options[:search_notes],
|
|
142
146
|
tag: tags,
|
|
143
147
|
negate: options[:invert],
|
|
144
148
|
project: options[:project],
|
data/bin/commands/update.rb
CHANGED
|
@@ -87,6 +87,9 @@ class App
|
|
|
87
87
|
c.arg_name 'QUERY'
|
|
88
88
|
c.flag %i[search find grep], multiple: true
|
|
89
89
|
|
|
90
|
+
c.desc 'Include notes in search'
|
|
91
|
+
c.switch %i[search_notes], negatable: true, default_value: true
|
|
92
|
+
|
|
90
93
|
c.desc 'Match actions containing tag. Allows value comparisons'
|
|
91
94
|
c.arg_name 'TAG'
|
|
92
95
|
c.flag %i[tagged], multiple: true
|
|
@@ -103,7 +106,7 @@ class App
|
|
|
103
106
|
c.action do |global_options, options, args|
|
|
104
107
|
reader = TTY::Reader.new
|
|
105
108
|
|
|
106
|
-
args.concat(options[:search])
|
|
109
|
+
args.concat(options[:search]) unless options[:search].nil?
|
|
107
110
|
|
|
108
111
|
append = options[:at] ? options[:at] =~ /^[ae]/i : global_options[:add_at] =~ /^[ae]/i
|
|
109
112
|
|
|
@@ -257,6 +260,7 @@ class App
|
|
|
257
260
|
project: options[:project],
|
|
258
261
|
remove_tag: remove_tags,
|
|
259
262
|
replace: options[:replace],
|
|
263
|
+
search_note: options[:search_notes],
|
|
260
264
|
tagged: tags)
|
|
261
265
|
end
|
|
262
266
|
end
|
data/lib/na/action.rb
CHANGED
|
@@ -140,31 +140,36 @@ module NA
|
|
|
140
140
|
tag_matches_any(any) && tag_matches_all(all) && tag_matches_none(none)
|
|
141
141
|
end
|
|
142
142
|
|
|
143
|
-
def search_match?(any: [], all: [], none: [])
|
|
144
|
-
search_matches_any(any
|
|
143
|
+
def search_match?(any: [], all: [], none: [], include_note: true)
|
|
144
|
+
search_matches_any(any, include_note: include_note) &&
|
|
145
|
+
search_matches_all(all, include_note: include_note) &&
|
|
146
|
+
search_matches_none(none, include_note: include_note)
|
|
145
147
|
end
|
|
146
148
|
|
|
147
149
|
private
|
|
148
150
|
|
|
149
|
-
def search_matches_none(regexes)
|
|
151
|
+
def search_matches_none(regexes, include_note: true)
|
|
150
152
|
regexes.each do |rx|
|
|
151
|
-
|
|
153
|
+
note_matches = include_note && @note.join(' ').match(Regexp.new(rx, Regexp::IGNORECASE))
|
|
154
|
+
return false if @action.match(Regexp.new(rx, Regexp::IGNORECASE)) || note_matches
|
|
152
155
|
end
|
|
153
156
|
true
|
|
154
157
|
end
|
|
155
158
|
|
|
156
|
-
def search_matches_any(regexes)
|
|
159
|
+
def search_matches_any(regexes, include_note: true)
|
|
157
160
|
return true if regexes.empty?
|
|
158
161
|
|
|
159
162
|
regexes.each do |rx|
|
|
160
|
-
|
|
163
|
+
note_matches = include_note && @note.join(' ').match(Regexp.new(rx, Regexp::IGNORECASE))
|
|
164
|
+
return true if @action.match(Regexp.new(rx, Regexp::IGNORECASE)) || note_matches
|
|
161
165
|
end
|
|
162
166
|
false
|
|
163
167
|
end
|
|
164
168
|
|
|
165
|
-
def search_matches_all(regexes)
|
|
169
|
+
def search_matches_all(regexes, include_note: true)
|
|
166
170
|
regexes.each do |rx|
|
|
167
|
-
|
|
171
|
+
note_matches = include_note && @note.join(' ').match(Regexp.new(rx, Regexp::IGNORECASE))
|
|
172
|
+
return false unless @action.match(Regexp.new(rx, Regexp::IGNORECASE)) || note_matches
|
|
168
173
|
end
|
|
169
174
|
true
|
|
170
175
|
end
|
data/lib/na/next_action.rb
CHANGED
|
@@ -139,8 +139,9 @@ module NA
|
|
|
139
139
|
todo.projects
|
|
140
140
|
end
|
|
141
141
|
|
|
142
|
-
def find_actions(target, search, tagged = nil, all: false, done: false, project: nil)
|
|
142
|
+
def find_actions(target, search, tagged = nil, all: false, done: false, project: nil, search_note: true)
|
|
143
143
|
todo = NA::Todo.new({ search: search,
|
|
144
|
+
search_note: search_note,
|
|
144
145
|
require_na: false,
|
|
145
146
|
file_path: target,
|
|
146
147
|
project: project,
|
|
@@ -231,6 +232,7 @@ module NA
|
|
|
231
232
|
|
|
232
233
|
def update_action(target,
|
|
233
234
|
search,
|
|
235
|
+
search_note: true,
|
|
234
236
|
add: nil,
|
|
235
237
|
add_tag: [],
|
|
236
238
|
all: false,
|
|
@@ -327,7 +329,7 @@ module NA
|
|
|
327
329
|
|
|
328
330
|
notify(add.pretty)
|
|
329
331
|
else
|
|
330
|
-
_, actions = find_actions(target, search, tagged, done: done, all: all, project: project)
|
|
332
|
+
_, actions = find_actions(target, search, tagged, done: done, all: all, project: project, search_note: search_note)
|
|
331
333
|
|
|
332
334
|
return if actions.nil?
|
|
333
335
|
|
data/lib/na/string.rb
CHANGED
|
@@ -39,6 +39,8 @@ class ::String
|
|
|
39
39
|
file = File.expand_path(self)
|
|
40
40
|
raise "Missing file #{file}" unless File.exist?(file)
|
|
41
41
|
|
|
42
|
+
NA.notify("#{NA.theme[:error]}#{file} is a directory", exit_code: 2) if File.directory?(file)
|
|
43
|
+
|
|
42
44
|
# IO.read(file).force_encoding('ASCII-8BIT').encode('UTF-8', invalid: :replace, undef: :replace, replace: '?')
|
|
43
45
|
IO.read(file).force_encoding('utf-8')
|
|
44
46
|
end
|
data/lib/na/todo.rb
CHANGED
|
@@ -37,6 +37,7 @@ module NA
|
|
|
37
37
|
regex: false,
|
|
38
38
|
require_na: true,
|
|
39
39
|
search: nil,
|
|
40
|
+
search_note: true,
|
|
40
41
|
tag: nil
|
|
41
42
|
}
|
|
42
43
|
|
|
@@ -93,7 +94,7 @@ module NA
|
|
|
93
94
|
else
|
|
94
95
|
NA.match_working_dir(settings[:query])
|
|
95
96
|
end
|
|
96
|
-
|
|
97
|
+
NA.notify("Files: #{files.join(', ')}", debug:true)
|
|
97
98
|
files.each do |file|
|
|
98
99
|
NA.save_working_dir(File.expand_path(file))
|
|
99
100
|
content = file.read_file
|
|
@@ -124,7 +125,7 @@ module NA
|
|
|
124
125
|
|
|
125
126
|
indent_level = indent
|
|
126
127
|
elsif line.blank?
|
|
127
|
-
in_action = false
|
|
128
|
+
in_action = false # Comment out to allow line breaks in of notes, which isn't TaskPaper-compatible
|
|
128
129
|
elsif line.action?
|
|
129
130
|
in_action = false
|
|
130
131
|
|
|
@@ -137,10 +138,6 @@ module NA
|
|
|
137
138
|
|
|
138
139
|
next if settings[:require_na] && !line.na?
|
|
139
140
|
|
|
140
|
-
has_search = !optional.empty? || !required.empty? || !negated.empty?
|
|
141
|
-
next if has_search && !new_action.search_match?(any: optional,
|
|
142
|
-
all: required,
|
|
143
|
-
none: negated)
|
|
144
141
|
if settings[:project]
|
|
145
142
|
rx = settings[:project].split(%r{[/:]}).join('.*?/')
|
|
146
143
|
next unless parent.join('/') =~ Regexp.new("#{rx}.*?", Regexp::IGNORECASE)
|
|
@@ -161,6 +158,14 @@ module NA
|
|
|
161
158
|
projects = projects.dup
|
|
162
159
|
end
|
|
163
160
|
|
|
161
|
+
actions.delete_if do |new_action|
|
|
162
|
+
has_search = !optional.empty? || !required.empty? || !negated.empty?
|
|
163
|
+
has_search && !new_action.search_match?(any: optional,
|
|
164
|
+
all: required,
|
|
165
|
+
none: negated,
|
|
166
|
+
include_note: settings[:search_note])
|
|
167
|
+
end
|
|
168
|
+
|
|
164
169
|
[files, actions, projects]
|
|
165
170
|
end
|
|
166
171
|
|
data/lib/na/version.rb
CHANGED
data/src/_README.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
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.60<!--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
|
|
data/test.md
CHANGED
|
@@ -3,13 +3,18 @@ comment: 2023-09-03
|
|
|
3
3
|
keywords:
|
|
4
4
|
---
|
|
5
5
|
Other New Project:
|
|
6
|
-
- testing @na
|
|
6
|
+
- testing @na @butter
|
|
7
7
|
Brand New Project:
|
|
8
8
|
- testing @na
|
|
9
|
+
A multi line (multiline) note
|
|
10
|
+
with a line break
|
|
9
11
|
- testing @na
|
|
10
12
|
Project0:
|
|
13
|
+
|
|
11
14
|
- Test1
|
|
15
|
+
|
|
12
16
|
- Test2
|
|
17
|
+
|
|
13
18
|
Project1:
|
|
14
19
|
- Test4
|
|
15
20
|
- Test5
|