na 1.2.45 → 1.2.47

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 999328238e283419f4e31a30244177baed7a0aca57b5c112dc29434d68c039f0
4
- data.tar.gz: 6d0182ffc278c67ed1d44701d0e7fb7ec68de947ad592fefa2e4494bf8ca09d4
3
+ metadata.gz: ed76ea2928d227d65651ad179f0950c2505611c540673f96494feae0ce621ca1
4
+ data.tar.gz: da06581a2771d1675ef1e69229803de2a677b6e30b5a4e2531e8497677cfe40a
5
5
  SHA512:
6
- metadata.gz: a0e0db55f26d7a136c179ebd1a391e3822cee860e72b22bc227d2d5321fd8ec659619ed33f3cfb93e8ca25d3da7d072b12ceea9717c8f4bd499dd9ab2dd814a2
7
- data.tar.gz: 3bf8afbfd84a9b19699c0bdfa443c3e0b46f4557188e5a3d19b9cf99123e0fff3a3baa943b31f1c084435e4e37ea7f59c90a3dfaa1825cdea93d5d88f83fc2c5
6
+ metadata.gz: 63e8b9f8fdd3ad3c394dbe022030ab334f3826dbba22d7a0d6971ab02a7d47db243cc308517825a84589bae8ea4333d9aceb393640dd4f13d4d6e67f7a5fa0ef
7
+ data.tar.gz: 4145b57e31f6f876c965b540adf187584e91acb8f2438b9eef8fced56c2938a2c7dd004f7c65a5a5b9040bfd2fc55675e1fc18a579c1318d17f7efe3a80a70b5
data/.travis.yml CHANGED
@@ -4,7 +4,7 @@ sudo: required
4
4
  dist: trusty
5
5
  cache: bundler
6
6
  rvm:
7
- - ruby-3.0.0
7
+ - ruby-3.1.0
8
8
  install:
9
9
  - gem install bundler --version '2.2.29'
10
10
  - bundle install
data/CHANGELOG.md CHANGED
@@ -1,3 +1,29 @@
1
+ ### 1.2.47
2
+
3
+ 2023-09-07 10:47
4
+
5
+ #### NEW
6
+
7
+ - `na update --search OLD_TEXT --replace NEW_TEXT` (added --replace)
8
+
9
+ #### IMPROVED
10
+
11
+ - When not showing notes, add an asterisk in the template note
12
+ - When showing notes, indent to the beginning of the action
13
+
14
+ ### 1.2.46
15
+
16
+ 2023-09-06 21:25
17
+
18
+ #### IMPROVED
19
+
20
+ - Add `--project` to archive and update
21
+ - Add `--project` flag to complete
22
+
23
+ #### FIXED
24
+
25
+ - Error when creating new project in todo file
26
+
1
27
  ### 1.2.45
2
28
 
3
29
  2023-09-06 19:19
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- na (1.2.45)
4
+ na (1.2.47)
5
5
  chronic (~> 0.10, >= 0.10.2)
6
6
  gli (~> 2.21.0)
7
7
  mdless (~> 1.0, >= 1.0.32)
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.45
12
+ The current version of `na` is 1.2.47
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.45
80
+ 1.2.47
81
81
 
82
82
  GLOBAL OPTIONS
83
83
  -a, --add - Add a next action (deprecated, for backwards compatibility)
@@ -487,26 +487,29 @@ DESCRIPTION
487
487
  Provides an easy way to complete, prioritize, and tag existing actions. If multiple todo files are found in the current directory, a menu will allow you to pick which file to act on.
488
488
 
489
489
  COMMAND OPTIONS
490
- -a, --archive - Add a @done tag to action and move to Archive
491
- --all - Act on all matches immediately (no menu)
492
- --at=POSITION - When moving task, add at [s]tart or [e]nd of target project (default: none)
493
- -d, --depth=DEPTH - Search for files X directories deep (default: 1)
494
- --delete - Delete an action
495
- --[no-]done - Include @done actions
496
- -e, --regex - Interpret search pattern as regular expression
497
- --edit - Open action in editor (vim). Natural language dates will be parsed and converted in date-based tags.
498
- -f, --finish - Add a @done tag to action
499
- --file=PATH - Specify the file to search for the task (default: none)
500
- --in, --todo=TODO_FILE - Use a known todo file, partial matches allowed (default: none)
501
- -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.
502
- -o, --overwrite - Overwrite note instead of appending
503
- -p, --priority=PRIO - Add/change a priority level 1-5 (default: 0)
504
- -r, --remove=TAG - Remove a tag from the action, use multiple times or combine multiple tags with a comma, wildcards (* and ?) allowed (may be used more than once, default: none)
505
- --restore - Remove @done tag from action
506
- -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)
507
- --tagged=TAG - Match actions containing tag. Allows value comparisons (may be used more than once, default: none)
508
- --to, --project, --proj=PROJECT - Move action to specific project (default: none)
509
- -x, --exact - Match pattern exactly
490
+ -a, --archive - Add a @done tag to action and move to Archive
491
+ --all - Act on all matches immediately (no menu)
492
+ --at=POSITION - When moving task, add at [s]tart or [e]nd of target project (default: none)
493
+ -d, --depth=DEPTH - Search for files X directories deep (default: 1)
494
+ --delete - Delete an action
495
+ --[no-]done - Include @done actions
496
+ -e, --regex - Interpret search pattern as regular expression
497
+ --edit - Open action in editor (vim). Natural language dates will be parsed and converted in date-based tags.
498
+ -f, --finish - Add a @done tag to action
499
+ --file=PATH - Specify the file to search for the task (default: none)
500
+ --in, --todo=TODO_FILE - Use a known todo file, partial matches allowed (default: none)
501
+ -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.
502
+ -o, --overwrite - Overwrite note instead of appending
503
+ -p, --priority=PRIO - Add/change a priority level 1-5 (default: 0)
504
+ --proj, --project=PROJECT[/SUBPROJECT] - Affect actions from a specific project (default: none)
505
+ -r, --remove=TAG - Remove a tag from the action, use multiple times or combine multiple tags with a comma, wildcards (* and ?) allowed (may be used more than once, default: none)
506
+ --replace=TEXT - Use with --find to find and replace with new text. Enables --exact when used (default: none)
507
+ --restore - Remove @done tag from action
508
+ --search, --find, --grep=QUERY - Filter results using search terms (may be used more than once, default: none)
509
+ -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)
510
+ --tagged=TAG - Match actions containing tag. Allows value comparisons (may be used more than once, default: none)
511
+ --to, --move=PROJECT - Move action to specific project (default: none)
512
+ -x, --exact - Match pattern exactly
510
513
 
511
514
  EXAMPLES
512
515
 
@@ -546,17 +549,19 @@ SYNOPSIS
546
549
  na [global options] complete [command options] ACTION
547
550
 
548
551
  COMMAND OPTIONS
549
- -a, --archive - Add a @done tag to action and move to Archive
550
- --all - Act on all matches immediately (no menu)
551
- -d, --depth=DEPTH - Search for files X directories deep (default: 1)
552
- -e, --regex - Interpret search pattern as regular expression
553
- --file=PATH - Specify the file to search for the task (default: none)
554
- --in, --todo=TODO_FILE - Use a known todo file, partial matches allowed (default: none)
555
- -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.
556
- -o, --overwrite - Overwrite note instead of appending
557
- --tagged=TAG - Match actions containing tag. Allows value comparisons (may be used more than once, default: none)
558
- --to, --project, --proj=PROJECT - Move action to specific project (default: none)
559
- -x, --exact - Match pattern exactly
552
+ -a, --archive - Add a @done tag to action and move to Archive
553
+ --all - Act on all matches immediately (no menu)
554
+ -d, --depth=DEPTH - Search for files X directories deep (default: 1)
555
+ -e, --regex - Interpret search pattern as regular expression
556
+ --file=PATH - Specify the file to search for the task (default: none)
557
+ --in, --todo=TODO_FILE - Use a known todo file, partial matches allowed (default: none)
558
+ -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.
559
+ -o, --overwrite - Overwrite note instead of appending
560
+ --proj, --project=PROJECT[/SUBPROJECT] - Affect actions from a specific project (default: none)
561
+ --search, --find, --grep=QUERY - Filter results using search terms (may be used more than once, default: none)
562
+ --tagged=TAG - Match actions containing tag. Allows value comparisons (may be used more than once, default: none)
563
+ --to, --move=PROJECT - Move action to specific project (default: none)
564
+ -x, --exact - Match pattern exactly
560
565
 
561
566
  EXAMPLES
562
567
 
@@ -580,15 +585,18 @@ SYNOPSIS
580
585
  na [global options] archive [command options] ACTION
581
586
 
582
587
  COMMAND OPTIONS
583
- --all - Act on all matches immediately (no menu)
584
- -d, --depth=DEPTH - Search for files X directories deep (default: 1)
585
- --done - Archive all done tasks
586
- -e, --regex - Interpret search pattern as regular expression
587
- --file=PATH - Specify the file to search for the task (default: none)
588
- -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.
589
- -o, --overwrite - Overwrite note instead of appending
590
- --tagged=TAG - Match actions containing tag. Allows value comparisons (may be used more than once, default: none)
591
- -x, --exact - Match pattern exactly
588
+ --all - Act on all matches immediately (no menu)
589
+ -d, --depth=DEPTH - Search for files X directories deep (default: 1)
590
+ --done - Archive all done tasks
591
+ -e, --regex - Interpret search pattern as regular expression
592
+ --file=PATH - Specify the file to search for the task (default: none)
593
+ --in, --todo=TODO_FILE - Use a known todo file, partial matches allowed (default: none)
594
+ -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.
595
+ -o, --overwrite - Overwrite note instead of appending
596
+ --proj, --project=PROJECT[/SUBPROJECT] - Affect actions from a specific project (default: none)
597
+ --search, --find, --grep=QUERY - Filter results using search terms (may be used more than once, default: none)
598
+ --tagged=TAG - Match actions containing tag. Allows value comparisons (may be used more than once, default: none)
599
+ -x, --exact - Match pattern exactly
592
600
 
593
601
  EXAMPLE
594
602
 
@@ -30,24 +30,41 @@ class App
30
30
  c.arg_name 'TAG'
31
31
  c.flag %i[tagged], multiple: true
32
32
 
33
+ c.desc 'Affect actions from a specific project'
34
+ c.arg_name 'PROJECT[/SUBPROJECT]'
35
+ c.flag %i[proj project]
36
+
33
37
  c.desc 'Act on all matches immediately (no menu)'
34
38
  c.switch %i[all], negatable: false
35
39
 
40
+ c.desc 'Filter results using search terms'
41
+ c.arg_name 'QUERY'
42
+ c.flag %i[search find grep], multiple: true
43
+
36
44
  c.desc 'Interpret search pattern as regular expression'
37
45
  c.switch %i[e regex], negatable: false
38
46
 
39
47
  c.desc 'Match pattern exactly'
40
48
  c.switch %i[x exact], negatable: false
41
49
 
50
+ c.desc 'Use a known todo file, partial matches allowed'
51
+ c.arg_name 'TODO_FILE'
52
+ c.flag %i[in todo]
53
+
42
54
  c.action do |global, options, args|
55
+ args.concat(options[:search])
56
+
43
57
  if options[:done]
44
- options[:tagged] = ['done']
58
+ options[:tagged] << 'done'
45
59
  options[:all] = true
60
+ else
61
+ options[:tagged] << '-done'
46
62
  end
47
63
 
48
64
  options[:done] = true
65
+ options['done'] = true
49
66
  options[:finish] = true
50
- options[:project] = 'Archive'
67
+ options[:move] = 'Archive'
51
68
  options[:archive] = true
52
69
  options[:a] = true
53
70
 
@@ -22,7 +22,11 @@ class App
22
22
 
23
23
  c.desc 'Move action to specific project'
24
24
  c.arg_name 'PROJECT'
25
- c.flag %i[to project proj]
25
+ c.flag %i[to move]
26
+
27
+ c.desc 'Affect actions from a specific project'
28
+ c.arg_name 'PROJECT[/SUBPROJECT]'
29
+ c.flag %i[proj project]
26
30
 
27
31
  c.desc 'Specify the file to search for the task'
28
32
  c.arg_name 'PATH'
@@ -36,6 +40,10 @@ class App
36
40
  c.arg_name 'DEPTH'
37
41
  c.flag %i[d depth], must_match: /^[1-9]$/, type: :integer, default_value: 1
38
42
 
43
+ c.desc 'Filter results using search terms'
44
+ c.arg_name 'QUERY'
45
+ c.flag %i[search find grep], multiple: true
46
+
39
47
  c.desc 'Match actions containing tag. Allows value comparisons'
40
48
  c.arg_name 'TAG'
41
49
  c.flag %i[tagged], multiple: true
@@ -50,9 +58,12 @@ class App
50
58
  c.switch %i[x exact], negatable: false
51
59
 
52
60
  c.action do |global, options, args|
61
+ args.concat(options[:search])
62
+
53
63
  options[:finish] = true
54
64
  options[:f] = true
55
- options[:project] = 'Archive' if options[:archive] && !options[:project]
65
+ options[:to] = 'Archive' if options[:archive] && !options[:to]
66
+ options[:move] = 'Archive' if options[:archive] && !options[:move]
56
67
 
57
68
  cmd = commands[:update]
58
69
  action = cmd.send(:get_action, nil)
@@ -33,7 +33,11 @@ class App
33
33
 
34
34
  c.desc 'Move action to specific project'
35
35
  c.arg_name 'PROJECT'
36
- c.flag %i[to project proj]
36
+ c.flag %i[to move]
37
+
38
+ c.desc 'Affect actions from a specific project'
39
+ c.arg_name 'PROJECT[/SUBPROJECT]'
40
+ c.flag %i[proj project]
37
41
 
38
42
  c.desc 'Use a known todo file, partial matches allowed'
39
43
  c.arg_name 'TODO_FILE'
@@ -51,6 +55,10 @@ class App
51
55
  c.arg_name 'TAG'
52
56
  c.flag %i[r remove], multiple: true
53
57
 
58
+ c.desc 'Use with --find to find and replace with new text. Enables --exact when used'
59
+ c.arg_name 'TEXT'
60
+ c.flag %i[replace]
61
+
54
62
  c.desc 'Add a @done tag to action'
55
63
  c.switch %i[f finish], negatable: false
56
64
 
@@ -75,6 +83,10 @@ class App
75
83
  c.arg_name 'DEPTH'
76
84
  c.flag %i[d depth], must_match: /^[1-9]$/, type: :integer, default_value: 1
77
85
 
86
+ c.desc 'Filter results using search terms'
87
+ c.arg_name 'QUERY'
88
+ c.flag %i[search find grep], multiple: true
89
+
78
90
  c.desc 'Match actions containing tag. Allows value comparisons'
79
91
  c.arg_name 'TAG'
80
92
  c.flag %i[tagged], multiple: true
@@ -90,6 +102,9 @@ class App
90
102
 
91
103
  c.action do |global_options, options, args|
92
104
  reader = TTY::Reader.new
105
+
106
+ args.concat(options[:search])
107
+
93
108
  append = options[:at] ? options[:at] =~ /^[ae]/i : global_options[:add_at] =~ /^[ae]/i
94
109
 
95
110
  if options[:restore] || (!options[:remove].nil? && options[:remove].include?('done'))
@@ -97,10 +112,12 @@ class App
97
112
  options[:tagged] << '+done'
98
113
  elsif !options[:remove].nil? && !options[:remove].empty?
99
114
  options[:tagged].concat(options[:remove])
100
- elsif options[:finish]
115
+ elsif options[:finish] && !options[:done]
101
116
  options[:tagged] << '-done'
102
117
  end
103
118
 
119
+ options[:exact] = true unless options[:replace].nil?
120
+
104
121
  action = if args.count.positive?
105
122
  args.join(' ').strip
106
123
  else
@@ -168,8 +185,8 @@ class App
168
185
  note = stdin_note.empty? ? [] : stdin_note
169
186
  note.concat(line_note) unless line_note.nil? || line_note.empty?
170
187
 
171
- target_proj = if options[:project]
172
- options[:project]
188
+ target_proj = if options[:move]
189
+ options[:move]
173
190
  elsif NA.cwd_is == :project
174
191
  NA.cwd
175
192
  end
@@ -204,7 +221,7 @@ class App
204
221
  files = NA.find_files_matching({
205
222
  depth: options[:depth],
206
223
  done: options[:done],
207
- project: target_proj,
224
+ project: options[:project],
208
225
  regex: options[:regex],
209
226
  require_na: false,
210
227
  search: tokens,
@@ -219,7 +236,7 @@ class App
219
236
 
220
237
  if options[:archive]
221
238
  options[:finish] = true
222
- options[:project] = 'Archive'
239
+ options[:move] = 'Archive'
223
240
  end
224
241
 
225
242
  NA.notify("#{NA.theme[:error]}No search terms provided", exit_code: 1) if tokens.nil? && options[:tagged].empty?
@@ -233,11 +250,13 @@ class App
233
250
  done: options[:done],
234
251
  edit: options[:edit],
235
252
  finish: options[:finish],
253
+ move: target_proj,
236
254
  note: note,
237
255
  overwrite: options[:overwrite],
238
256
  priority: priority,
239
- project: target_proj,
257
+ project: options[:project],
240
258
  remove_tag: remove_tags,
259
+ replace: options[:replace],
241
260
  tagged: tags)
242
261
  end
243
262
  end
data/lib/na/action.rb CHANGED
@@ -59,6 +59,7 @@ module NA
59
59
  @project: #{@project}
60
60
  @parent: #{@parent.join('>')}
61
61
  @action: #{@action}
62
+ @tags: #{@tags}
62
63
  @note: #{@note}
63
64
  EOINSPECT
64
65
  end
@@ -94,14 +95,8 @@ module NA
94
95
  file_tpl = "#{template[:file]}#{file} {x}"
95
96
  filename = NA::Color.template(file_tpl)
96
97
 
97
- # Add notes if needed
98
- note = if notes && @note.count.positive?
99
- NA::Color.template("\n#{@note.map { |l| " #{template[:note]}• #{l}{x}" }.join("\n")}")
100
- else
101
- ''
102
- end
103
-
104
98
  # colorize the action and highlight tags
99
+ @action.gsub!(/\{(.*?)\}/, '\\{\1\\}')
105
100
  action = NA::Color.template("#{template[:action]}#{@action.sub(/ @#{NA.na_tag}\b/, '')}{x}")
106
101
  action = action.highlight_tags(color: template[:tags],
107
102
  parens: template[:value_parens],
@@ -110,9 +105,27 @@ module NA
110
105
 
111
106
  if detect_width
112
107
  width = TTY::Screen.columns
113
- prefix = NA::Color.uncolor(pretty(template: { templates: { output: template[:templates][:output].sub(/%action/, '') } }, detect_width: false))
108
+ prefix = NA::Color.uncolor(pretty(template: { templates: { output: template[:templates][:output].sub(/%action/, '').sub(/%note/, '') } }, detect_width: false))
114
109
  indent = prefix.length
110
+
111
+ # Add notes if needed
112
+ note = if notes && @note.count.positive?
113
+ NA::Color.template(@note.wrap(width, indent, template[:note]))
114
+ elsif !notes && @note.count.positive?
115
+ action += "#{template[:note]}*"
116
+ else
117
+ ''
118
+ end
119
+
115
120
  action = action.wrap(width, indent)
121
+ else
122
+ note = if notes && @note.count.positive?
123
+ NA::Color.template("\n#{@note.map { |l| " #{template[:note]}• #{l.wrap(width, indent)}{x}" }.join("\n")}")
124
+ elsif !notes && @note.count.positive?
125
+ action += "#{template[:note]}*"
126
+ else
127
+ ''
128
+ end
116
129
  end
117
130
 
118
131
  # Replace variables in template string and output colorized
@@ -184,7 +197,6 @@ module NA
184
197
  return false if keys.empty?
185
198
 
186
199
  key = keys[0]
187
-
188
200
  return true if tag[:comp].nil?
189
201
 
190
202
  tag_val = @tags[key]
data/lib/na/actions.rb CHANGED
@@ -79,7 +79,7 @@ module NA
79
79
 
80
80
  files.map { |f| NA.notify(f, debug: true) } if files
81
81
 
82
- output = map { |action| action.pretty(template: { output: template }, regexes: regexes, notes: notes) }
82
+ output = map { |action| action.pretty(template: { templates: { output: template } }, regexes: regexes, notes: notes) }
83
83
  NA::Pager.page(output.join("\n"))
84
84
  end
85
85
  end
data/lib/na/array.rb CHANGED
@@ -10,4 +10,11 @@ class ::Array
10
10
  def remove_bad
11
11
  compact.map { |x| x.is_a?(String) ? x.strip : x }.select(&:good?)
12
12
  end
13
+
14
+ def wrap(width, indent, color)
15
+ map! do |l|
16
+ "#{color}#{' ' * indent }• #{l.wrap(width, indent)}{x}"
17
+ end
18
+ "\n#{join("\n")}"
19
+ end
13
20
  end
@@ -139,10 +139,11 @@ module NA
139
139
  todo.projects
140
140
  end
141
141
 
142
- def find_actions(target, search, tagged = nil, all: false, done: false)
142
+ def find_actions(target, search, tagged = nil, all: false, done: false, project: nil)
143
143
  todo = NA::Todo.new({ search: search,
144
144
  require_na: false,
145
145
  file_path: target,
146
+ project: project,
146
147
  tag: tagged,
147
148
  done: done })
148
149
 
@@ -241,20 +242,23 @@ module NA
241
242
  overwrite: false,
242
243
  priority: 0,
243
244
  project: nil,
245
+ move: nil,
244
246
  remove_tag: [],
247
+ replace: nil,
245
248
  tagged: nil)
246
249
 
247
250
  projects = find_projects(target)
248
251
 
249
252
  target_proj = nil
250
253
 
251
- if project
252
- project = project.sub(/:$/, '')
253
- target_proj = projects.select { |pr| pr.project =~ /#{project.gsub(/:/, '.*?:.*?')}/i }.first
254
+ if move
255
+ move = move.sub(/:$/, '')
256
+ target_proj = projects.select { |pr| pr.project =~ /#{move.gsub(/:/, '.*?:.*?')}/i }.first
254
257
  if target_proj.nil?
255
- res = NA.yn(NA::Color.template("#{NA.theme[:warning]}Project #{NA.theme[:file]}#{project}#{NA.theme[:warning]} doesn't exist, add it"), default: true)
258
+ res = NA.yn(NA::Color.template("#{NA.theme[:warning]}Project #{NA.theme[:file]}#{move}#{NA.theme[:warning]} doesn't exist, add it"), default: true)
256
259
  if res
257
- target_proj = insert_project(target, project, projects)
260
+ target_proj = insert_project(target, move, projects)
261
+ projects << target_proj
258
262
  else
259
263
  NA.notify("#{NA.theme[:error]}Cancelled", exit_code: 1)
260
264
  end
@@ -308,7 +312,7 @@ module NA
308
312
 
309
313
  notify(add.pretty)
310
314
  else
311
- _, actions = find_actions(target, search, tagged, done: done, all: all)
315
+ _, actions = find_actions(target, search, tagged, done: done, all: all, project: project)
312
316
 
313
317
  return if actions.nil?
314
318
 
@@ -325,6 +329,9 @@ module NA
325
329
  action.note = new_note
326
330
  end
327
331
 
332
+ # If replace is defined, use search to search and replace text in action
333
+ action.action.sub!(Regexp.new(Regexp.escape(search), Regexp::IGNORECASE), replace) if replace
334
+
328
335
  action.process(priority: priority, finish: finish, add_tag: add_tag, remove_tag: remove_tag)
329
336
 
330
337
  target_proj = if target_proj
@@ -489,23 +496,22 @@ module NA
489
496
  tag: nil
490
497
  }
491
498
  opts = defaults.merge(options)
492
-
493
499
  files = find_files(depth: options[:depth])
494
-
495
500
  files.delete_if do |file|
496
- todo = NA::Todo.new({
497
- depth: options[:depth],
498
- done: options[:done],
499
- file_path: file,
500
- negate: options[:negate],
501
- project: options[:project],
502
- query: options[:query],
503
- regex: options[:regex],
504
- require_na: options[:require_na],
505
- search: options[:search],
506
- tag: options[:tag]
507
- })
508
- todo.actions.length.zero?
501
+ cmd_options = {
502
+ depth: options[:depth],
503
+ done: options[:done],
504
+ file_path: file,
505
+ negate: options[:negate],
506
+ project: options[:project],
507
+ query: options[:query],
508
+ regex: options[:regex],
509
+ require_na: options[:require_na],
510
+ search: options[:search],
511
+ tag: options[:tag]
512
+ }
513
+ todo = NA::Todo.new(cmd_options)
514
+ todo.actions.empty?
509
515
  end
510
516
 
511
517
  files
data/lib/na/todo.rb CHANGED
@@ -61,7 +61,7 @@ module NA
61
61
  required_tag.push(t) if t[:required] && t[:negate]
62
62
  negated_tag.push(t) unless t[:negate]
63
63
  else
64
- optional_tag.push(t) unless t[:negate]
64
+ optional_tag.push(t) unless t[:negate] || t[:required]
65
65
  required_tag.push(t) if t[:required] && !t[:negate]
66
66
  negated_tag.push(t) if t[:negate]
67
67
  end
@@ -133,11 +133,9 @@ module NA
133
133
  next if settings[:require_na] && !line.na?
134
134
 
135
135
  has_search = !optional.empty? || !required.empty? || !negated.empty?
136
-
137
136
  next if has_search && !new_action.search_match?(any: optional,
138
137
  all: required,
139
138
  none: negated)
140
-
141
139
  if settings[:project]
142
140
  rx = settings[:project].split(%r{[/:]}).join('.*?/')
143
141
  next unless parent.join('/') =~ Regexp.new("#{rx}.*?", Regexp::IGNORECASE)
data/lib/na/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Na
2
- VERSION = '1.2.45'
2
+ VERSION = '1.2.47'
3
3
  end
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.44<!--END VER-->.
12
+ The current version of `na` is <!--VER-->1.2.46<!--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
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: na
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.45
4
+ version: 1.2.47
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brett Terpstra
@@ -246,7 +246,6 @@ files:
246
246
  - na.rdoc
247
247
  - scripts/fixreadme.rb
248
248
  - src/_README.md
249
- - test2.txt
250
249
  homepage: https://brettterpstra.com/projects/na/
251
250
  licenses:
252
251
  - MIT
data/test2.txt DELETED
@@ -1,7 +0,0 @@
1
- ---
2
- comment: 2023
3
- keywords:
4
- ---
5
-
6
- Inbox:
7
- - Test @na