na 1.2.96 → 1.2.97

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: '039caf8eecb90a37194f6629809951e530c82510989f757e4f0a018cdd4eb5a0'
4
- data.tar.gz: f8faf9b47d8aea7320dcbb4de91b9d446a415c26886e06e898d3370f7c632264
3
+ metadata.gz: 2e863ff02241d9a8c7e8dbf85340d3a7c2b836fe5e7310fc5bc6b0887aed48b6
4
+ data.tar.gz: b5763f97f4f246c576c0e364f7dd85012ff719c83d31538a5b9beae9c88711f3
5
5
  SHA512:
6
- metadata.gz: 26c4763058c114f2d641d2cb7d64be463c21ec48b2df6b41c7380ab810d5af06c37d067ae172f233456044e1993fd72d5da4a835f1bdc8f71ea2e888d9ab8cc9
7
- data.tar.gz: 5a4250a51f3e0753cea79a188293a41ba128af43abb51c6ff82bd10ab74122d98f8fc4ef774e50e2ed6c880f85ab05bc4e4c3c06b5840e3099b8b7bf8be3844a
6
+ metadata.gz: 779dfda39b49c4688eb9d52e3772afc81371d01238e4d37baf6e036d0a7b637f00b98835f3f1c7f19d77ee7265833d7eac7eba6d875791517d00fefe7835f34a
7
+ data.tar.gz: 5ed0dcb700e576b985ed1609345e98899928a6373da41442fc53551fb11a961d3c622672d41cafe712627957b40f3fbd807b186056ad0cabfeb31f1002403a1f
data/.rubocop_todo.yml CHANGED
@@ -1,6 +1,6 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2025-12-03 13:48:16 UTC using RuboCop version 1.81.7.
3
+ # on 2026-02-24 10:37:38 UTC using RuboCop version 1.81.7.
4
4
  # The point is for the user to remove these configuration records
5
5
  # one by one as the offenses are removed from the code base.
6
6
  # Note that changes in the inspected code, or installation of new
@@ -40,7 +40,7 @@ Metrics/BlockNesting:
40
40
  # Offense count: 6
41
41
  # Configuration parameters: CountComments, CountAsOne.
42
42
  Metrics/ClassLength:
43
- Max: 1492
43
+ Max: 1495
44
44
 
45
45
  # Offense count: 41
46
46
  # Configuration parameters: AllowedMethods, AllowedPatterns.
@@ -55,7 +55,7 @@ Metrics/MethodLength:
55
55
  # Offense count: 5
56
56
  # Configuration parameters: CountComments, CountAsOne.
57
57
  Metrics/ModuleLength:
58
- Max: 1494
58
+ Max: 1497
59
59
 
60
60
  # Offense count: 5
61
61
  # Configuration parameters: CountKeywordArgs, MaxOptionalParameters.
data/CHANGELOG.md CHANGED
@@ -1,3 +1,23 @@
1
+ ### 1.2.97
2
+
3
+ 2026-02-24 05:20
4
+
5
+ #### CHANGED
6
+
7
+ - Bump gem version to 1.2.96.
8
+ - Make plugins appear as first-class update actions
9
+ - Tighten csv runtime dependency to ~> 3.2
10
+ - Allow using na update --plugin NAME as only operation
11
+ - Simplify gemspec dependencies and enable MFA
12
+ - Fix crash in `na next` when matching project directories.
13
+ - Keep tags with parentheses when rewriting action text
14
+ - Tag stripping breaking on spaces within tag value
15
+ - Detect terminal width only when stdout is a TTY
16
+ - Filter only-timed output while maintaining tag duration totals
17
+ - Silence test-time stub redefinition warnings
18
+ - Switch gemspec to unified add_dependency style and require MFA
19
+ - Slice handling in TaskPaper @search expressions
20
+
1
21
  ### 1.2.96
2
22
 
3
23
  2025-12-26 02:38
data/Gemfile CHANGED
@@ -12,3 +12,5 @@ group :development do
12
12
  end
13
13
  gem 'chronic'
14
14
  gem 'csv'
15
+
16
+ gem "yard", "~> 0.9.38", group: :development
data/Gemfile.lock CHANGED
@@ -1,9 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- na (1.2.96)
4
+ na (1.2.97)
5
5
  chronic (~> 0.10, >= 0.10.2)
6
- csv (>= 3.2)
6
+ csv (~> 3.2)
7
7
  git (~> 3.0.0)
8
8
  gli (~> 2.21.0)
9
9
  mdless (~> 1.0, >= 1.0.32)
@@ -121,9 +121,10 @@ GEM
121
121
  concurrent-ruby (~> 1.0)
122
122
  unicode-display_width (3.2.0)
123
123
  unicode-emoji (~> 4.1)
124
- unicode-emoji (4.1.0)
124
+ unicode-emoji (4.2.0)
125
125
  uri (1.1.1)
126
126
  wisper (2.0.1)
127
+ yard (0.9.38)
127
128
 
128
129
  PLATFORMS
129
130
  aarch64-linux-gnu
@@ -151,6 +152,7 @@ DEPENDENCIES
151
152
  rubocop-performance (~> 1.21)
152
153
  simplecov (~> 0.22.0)
153
154
  tty-spinner (~> 0.9, >= 0.9.0)
155
+ yard (~> 0.9.38)
154
156
 
155
157
  BUNDLED WITH
156
158
  2.6.6
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.96.
12
+ The current version of `na` is 1.2.97.
13
13
 
14
14
 
15
15
  ### Table of contents
@@ -257,7 +257,7 @@ SYNOPSIS
257
257
  na [global options] command [command options] [arguments...]
258
258
 
259
259
  VERSION
260
- 1.2.96
260
+ 1.2.97
261
261
 
262
262
  GLOBAL OPTIONS
263
263
  -a, --add - Add a next action (deprecated, for backwards compatibility)
@@ -328,7 +328,8 @@ class App
328
328
  options[:edit],
329
329
  options[:started],
330
330
  (options[:end] || options[:finished]),
331
- options[:duration]
331
+ options[:duration],
332
+ !options[:plugin].to_s.empty?
332
333
  ].any?
333
334
  unless actionable
334
335
  # Interactive menu for actions
@@ -344,9 +345,9 @@ class App
344
345
  { key: :archive, label: 'Archive', param: nil },
345
346
  { key: :note, label: 'Add Note', param: 'Note' }
346
347
  ]
347
- # Add "Run Plugin" option if there are enabled plugins with metadata
348
- available_plugins = []
348
+ # Add plugin options directly to the actions menu if there are enabled plugins with metadata
349
349
  begin
350
+ available_plugins = []
350
351
  NA::Plugins.ensure_plugins_home
351
352
  NA::Plugins.list_plugins.each_value do |path|
352
353
  meta = NA::Plugins.parse_plugin_metadata(path)
@@ -354,9 +355,16 @@ class App
354
355
  next unless meta['input'] && meta['output']
355
356
 
356
357
  disp = meta['name'] || File.basename(path, File.extname(path))
357
- available_plugins << { key: :_plugin, label: disp, param: nil, plugin_path: path }
358
+ available_plugins << { label: disp, plugin_path: path }
359
+ end
360
+ available_plugins.each do |plugin|
361
+ actions_menu << {
362
+ key: :_plugin,
363
+ label: "Plugin: #{plugin[:label]}",
364
+ param: nil,
365
+ plugin_path: plugin[:plugin_path]
366
+ }
358
367
  end
359
- actions_menu << { key: :run_plugin, label: 'Run Plugin', param: nil } if available_plugins.any?
360
368
  rescue StandardError
361
369
  # ignore plugin discovery errors in menu
362
370
  end
@@ -382,33 +390,8 @@ class App
382
390
  action_obj = actions_menu.find { |a| a[:label] == selected_action }
383
391
  NA.notify("#{NA.theme[:error]}No action selected, cancelled", exit_code: 1) if action_obj.nil?
384
392
 
385
- # If "Run Plugin" was selected, show plugin selection menu
386
- if action_obj[:key] == :run_plugin
387
- plugin_labels = available_plugins.map { |p| p[:label] }
388
- plugin_selector = nil
389
- if TTY::Which.exist?('fzf')
390
- plugin_selector = 'fzf --prompt="Select plugin> "'
391
- elsif TTY::Which.exist?('gum')
392
- plugin_selector = 'gum choose'
393
- end
394
- selected_plugin = nil
395
- if plugin_selector
396
- require 'open3'
397
- input = plugin_labels.join("\n")
398
- output, = Open3.capture2("echo \"#{input.gsub('"', '\"')}\" | #{plugin_selector}")
399
- selected_plugin = output.strip
400
- else
401
- puts 'Select a plugin:'
402
- plugin_labels.each_with_index { |label, i| puts "#{i + 1}. #{label}" }
403
- idx = ($stdin.gets || '').strip.to_i - 1
404
- selected_plugin = plugin_labels[idx] if idx >= 0 && idx < plugin_labels.size
405
- end
406
- plugin_obj = available_plugins.find { |p| p[:label] == selected_plugin }
407
- NA.notify("#{NA.theme[:error]}No plugin selected, cancelled", exit_code: 1) if plugin_obj.nil?
408
- # Set plugin path directly
409
- options[:plugin] = plugin_obj[:plugin_path]
410
- elsif action_obj[:key] == :_plugin
411
- # Legacy support: if somehow a plugin was selected directly
393
+ if action_obj[:key] == :_plugin
394
+ # Plugin selected directly from the main actions menu
412
395
  options[:plugin] = action_obj[:plugin_path]
413
396
  else
414
397
  # Prompt for parameter if needed
data/lib/na/action.rb CHANGED
@@ -179,9 +179,9 @@ module NA
179
179
  # @param template [Hash] Color template
180
180
  # @param regexes [Array] Regexes to highlight
181
181
  # @param notes [Boolean] Include notes
182
- # @param detect_width [Boolean] Detect terminal width
182
+ # @param detect_width [Boolean] Detect terminal width (defaults to true only when output is a TTY)
183
183
  # @return [String]
184
- def pretty(extension: 'taskpaper', template: {}, regexes: [], notes: false, detect_width: true)
184
+ def pretty(extension: 'taskpaper', template: {}, regexes: [], notes: false, detect_width: $stdout.tty?)
185
185
  NA::Benchmark.measure('Action.pretty') do
186
186
  # Use cached theme instead of loading every time
187
187
  theme = NA.theme
@@ -3,7 +3,7 @@
3
3
  # Next Action methods
4
4
  module NA
5
5
  class << self
6
- attr_accessor :verbose, :extension, :include_ext, :na_tag, :command_line, :command, :globals, :global_file,
6
+ attr_accessor :verbose, :debug, :extension, :include_ext, :na_tag, :command_line, :command, :globals, :global_file,
7
7
  :cwd_is, :cwd, :stdin, :show_cwd_indicator
8
8
 
9
9
  # Select actions across files using existing search pipeline
@@ -84,7 +84,7 @@ module NA
84
84
  # Update action content
85
85
  action.action = text
86
86
  action.note = note.to_s.split("\n")
87
- action.action.gsub!(/(?<=\A| )@\S+(?:\(.*?\))?/, '')
87
+ action.action.gsub!(/(?<=\A| )@[^( \s\n]+(?:\(.*?\))?/, '')
88
88
  unless tags.empty?
89
89
  tag_str = tags.map { |k, v| v.to_s.empty? ? "@#{k}" : "@#{k}(#{v})" }.join(' ')
90
90
  action.action = action.action.strip + (tag_str.empty? ? "" : " #{tag_str}")
@@ -1502,7 +1502,6 @@ module NA
1502
1502
  NA.notify("TP DEBUG expr: #{expr.inspect}", debug: true) if NA.verbose
1503
1503
 
1504
1504
  inner = expr.to_s.strip
1505
- NA.notify("TP DEBUG inner initial: #{inner.inspect}", debug: true) if NA.verbose
1506
1505
  inner = Regexp.last_match(1).strip if inner =~ /\A@search\((.*)\)\s*\z/i
1507
1506
  NA.notify("TP DEBUG inner after @search strip: #{inner.inspect}", debug: true) if NA.verbose
1508
1507
 
@@ -1756,7 +1755,8 @@ module NA
1756
1755
  tags: left_clause[:tags] + right_clause[:tags],
1757
1756
  project: right_clause[:project] || left_clause[:project],
1758
1757
  include_done: right_clause[:include_done].nil? ? left_clause[:include_done] : right_clause[:include_done],
1759
- exclude_projects: left_clause[:exclude_projects] + right_clause[:exclude_projects]
1758
+ exclude_projects: left_clause[:exclude_projects] + right_clause[:exclude_projects],
1759
+ item_paths: Array(left_clause[:item_paths]) + Array(right_clause[:item_paths]), slice: right_clause[:slice] || left_clause[:slice]
1760
1760
  }
1761
1761
  end
1762
1762
  end
data/lib/na/version.rb CHANGED
@@ -5,5 +5,5 @@
5
5
  module Na
6
6
  ##
7
7
  # Current version of the na gem.
8
- VERSION = '1.2.96'
8
+ VERSION = '1.2.97'
9
9
  end
data/na.gemspec CHANGED
@@ -1,7 +1,7 @@
1
1
  # Ensure we require the local version and not one we might have installed already
2
- require './lib/na/version.rb'
2
+ require './lib/na/version'
3
3
 
4
- spec = Gem::Specification.new do |s|
4
+ Gem::Specification.new do |s|
5
5
  s.name = 'na'
6
6
  s.version = Na::VERSION
7
7
  s.author = 'Brett Terpstra'
@@ -15,7 +15,7 @@ spec = Gem::Specification.new do |s|
15
15
  'Add prompt hooks to display your next actions automatically when cd\'ing into a directory.'
16
16
  ].join(' ')
17
17
  s.license = 'MIT'
18
- s.files =`git ls-files -z`.split("\x0").reject { |f| f.strip =~ %r{^((test|spec|features)/|\.git|buildnotes|.*\.taskpaper)} }
18
+ s.files = `git ls-files -z`.split("\x0").reject { |f| f.strip =~ %r{^((test|spec|features)/|\.git|buildnotes|.*\.taskpaper)} }
19
19
  s.require_paths << 'lib'
20
20
  s.extra_rdoc_files = ['README.md', 'na.rdoc']
21
21
  s.rdoc_options << '--title' << 'na' << '--main' << 'README.md' << '--markup' << 'markdown'
@@ -23,16 +23,17 @@ spec = Gem::Specification.new do |s|
23
23
  s.executables << 'na'
24
24
  s.add_development_dependency('minitest', '~> 5.14')
25
25
  s.add_development_dependency('rdoc', '~> 4.3')
26
- s.add_runtime_dependency('chronic', '~> 0.10', '>= 0.10.2')
27
- s.add_runtime_dependency('csv', '>= 3.2')
28
- s.add_runtime_dependency('git', '~> 3.0.0')
29
- s.add_runtime_dependency('gli','~> 2.21.0')
30
- s.add_runtime_dependency('mdless', '~> 1.0', '>= 1.0.32')
31
- s.add_runtime_dependency('ostruct', '~> 0.6', '>= 0.6.1')
32
- s.add_runtime_dependency('tty-reader', '~> 0.9', '>= 0.9.0')
33
- s.add_runtime_dependency('tty-screen', '~> 0.8', '>= 0.8.1')
34
- s.add_runtime_dependency('tty-which', '~> 0.5', '>= 0.5.0')
35
- s.add_development_dependency('tty-spinner', '~> 0.9', '>= 0.9.0')
36
- s.add_development_dependency 'rspec', '~> 3.0'
26
+ s.add_dependency('chronic', '~> 0.10', '>= 0.10.2')
27
+ s.add_dependency('csv', '~> 3.2')
28
+ s.add_dependency('git', '~> 3.0.0')
29
+ s.add_dependency('gli', '~> 2.21.0')
30
+ s.add_dependency('mdless', '~> 1.0', '>= 1.0.32')
31
+ s.add_dependency('ostruct', '~> 0.6', '>= 0.6.1')
32
+ s.add_dependency('tty-reader', '~> 0.9', '>= 0.9.0')
33
+ s.add_dependency('tty-screen', '~> 0.8', '>= 0.8.1')
34
+ s.add_dependency('tty-which', '~> 0.5', '>= 0.5.0')
37
35
  s.add_development_dependency 'bump', '~> 0.6.0'
36
+ s.add_development_dependency 'rspec', '~> 3.0'
37
+ s.add_development_dependency('tty-spinner', '~> 0.9', '>= 0.9.0')
38
+ s.metadata['rubygems_mfa_required'] = 'true'
38
39
  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.95<!--END VER-->.
12
+ The current version of `na` is <!--VER-->1.2.96<!--END VER-->.
13
13
 
14
14
  <!--GITHUB-->
15
15
  ### Table of contents
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.96
4
+ version: 1.2.97
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brett Terpstra
@@ -61,14 +61,14 @@ dependencies:
61
61
  name: csv
62
62
  requirement: !ruby/object:Gem::Requirement
63
63
  requirements:
64
- - - ">="
64
+ - - "~>"
65
65
  - !ruby/object:Gem::Version
66
66
  version: '3.2'
67
67
  type: :runtime
68
68
  prerelease: false
69
69
  version_requirements: !ruby/object:Gem::Requirement
70
70
  requirements:
71
- - - ">="
71
+ - - "~>"
72
72
  - !ruby/object:Gem::Version
73
73
  version: '3.2'
74
74
  - !ruby/object:Gem::Dependency
@@ -200,25 +200,19 @@ dependencies:
200
200
  - !ruby/object:Gem::Version
201
201
  version: 0.5.0
202
202
  - !ruby/object:Gem::Dependency
203
- name: tty-spinner
203
+ name: bump
204
204
  requirement: !ruby/object:Gem::Requirement
205
205
  requirements:
206
206
  - - "~>"
207
207
  - !ruby/object:Gem::Version
208
- version: '0.9'
209
- - - ">="
210
- - !ruby/object:Gem::Version
211
- version: 0.9.0
208
+ version: 0.6.0
212
209
  type: :development
213
210
  prerelease: false
214
211
  version_requirements: !ruby/object:Gem::Requirement
215
212
  requirements:
216
213
  - - "~>"
217
214
  - !ruby/object:Gem::Version
218
- version: '0.9'
219
- - - ">="
220
- - !ruby/object:Gem::Version
221
- version: 0.9.0
215
+ version: 0.6.0
222
216
  - !ruby/object:Gem::Dependency
223
217
  name: rspec
224
218
  requirement: !ruby/object:Gem::Requirement
@@ -234,19 +228,25 @@ dependencies:
234
228
  - !ruby/object:Gem::Version
235
229
  version: '3.0'
236
230
  - !ruby/object:Gem::Dependency
237
- name: bump
231
+ name: tty-spinner
238
232
  requirement: !ruby/object:Gem::Requirement
239
233
  requirements:
240
234
  - - "~>"
241
235
  - !ruby/object:Gem::Version
242
- version: 0.6.0
236
+ version: '0.9'
237
+ - - ">="
238
+ - !ruby/object:Gem::Version
239
+ version: 0.9.0
243
240
  type: :development
244
241
  prerelease: false
245
242
  version_requirements: !ruby/object:Gem::Requirement
246
243
  requirements:
247
244
  - - "~>"
248
245
  - !ruby/object:Gem::Version
249
- version: 0.6.0
246
+ version: '0.9'
247
+ - - ">="
248
+ - !ruby/object:Gem::Version
249
+ version: 0.9.0
250
250
  description: A tool for managing a TaskPaper file of project todos for the current
251
251
  directory. Easily create "next actions" to come back to, add tags and priorities,
252
252
  and notes. Add prompt hooks to display your next actions automatically when cd'ing
@@ -337,7 +337,8 @@ files:
337
337
  homepage: https://brettterpstra.com/projects/na/
338
338
  licenses:
339
339
  - MIT
340
- metadata: {}
340
+ metadata:
341
+ rubygems_mfa_required: 'true'
341
342
  rdoc_options:
342
343
  - "--title"
343
344
  - na
@@ -359,7 +360,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
359
360
  - !ruby/object:Gem::Version
360
361
  version: '0'
361
362
  requirements: []
362
- rubygems_version: 3.6.7
363
+ rubygems_version: 4.0.3
363
364
  specification_version: 4
364
365
  summary: A command line tool for adding and listing project todos
365
366
  test_files: []