na 1.1.21 → 1.1.22

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '0430897c007446c9ad1a1e3463ddc3d8e192a43e8d60a46a9669745086ea45f3'
4
- data.tar.gz: e33799f49bbaf623d188c64f549e71dcea41b317b95b3b5d0f72f8a378a3f9fd
3
+ metadata.gz: 584d55c84c26fddeb65bf537b4743b5cac4308f39d796d336d95c900fc966deb
4
+ data.tar.gz: 73ea4289a1e43ce0b67f66f803a0db07359fe3f077358328a58c172c06daa107
5
5
  SHA512:
6
- metadata.gz: d8c9a03b08abf20cb826e452ad75478b0f58dc0309ce51bee29e3b31b6c37de8e99cdd22926aef1ffe10183b151b54b6047196ce5c8987c32b0fa013942d5673
7
- data.tar.gz: 7bb18376e8b53aa2c283206058c48dce786576d3a50d6e9567a0958011cab7f2f7203fecf0142cc49f3d5abc49a0342a4a3c20ff19318f79ac2d26ca00af206b
6
+ metadata.gz: 89945d2a8df1c1ea11360da4258c09f9b5c8ad38f41ca5ef98a68b99c33b41fb0b718919cc680eb356903f284cef8dd4271acea94af7f8c4adca031d445a6a26
7
+ data.tar.gz: 7c3f8c30bf5a4c69270641aadfb036303c42ee8678a09c2e8b5faad7883aff0ac0139caf465f9d37b84cf170ed4ee072ad20d4872b8c760b97d0e2ca1f3b6e2e
data/CHANGELOG.md CHANGED
@@ -1,3 +1,18 @@
1
+ ### 1.1.22
2
+
3
+ 2022-10-07 05:58
4
+
5
+ #### IMPROVED
6
+
7
+ - Help output and code documentation
8
+ - Allow wildcards (* and ?) when matching todo history
9
+ - Allow multiple todo queries separated by comma
10
+
11
+ #### FIXED
12
+
13
+ - Remove file extension when matching todo history
14
+ - Todo history query failed on exact match
15
+
1
16
  ### 1.1.21
2
17
 
3
18
  2022-10-07 04:26
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- na (1.1.21)
4
+ na (1.1.22)
5
5
  chronic (~> 0.10, >= 0.10.2)
6
6
  gli (~> 2.21.0)
7
7
  tty-reader (~> 0.9, >= 0.9.0)
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.1.21
12
+ The current version of `na` is 1.1.22
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.
@@ -59,7 +59,7 @@ SYNOPSIS
59
59
  na [global options] command [command options] [arguments...]
60
60
 
61
61
  VERSION
62
- 1.1.21
62
+ 1.1.22
63
63
 
64
64
  GLOBAL OPTIONS
65
65
  -a, --[no-]add - Add a next action (deprecated, for backwards compatibility)
@@ -171,7 +171,7 @@ DESCRIPTION
171
171
  COMMAND OPTIONS
172
172
  -d, --depth=DEPTH - Recurse to depth (default: none)
173
173
  -e, --regex - Interpret search pattern as regular expression
174
- --in=TODO_PATH - Show actions from a specific todo file in history (default: none)
174
+ --in=TODO_PATH - Show actions from a specific todo file in history. May use wildcards (* and ?) (default: none)
175
175
  -o, --or - Combine search tokens with OR, displaying actions matching ANY of the terms
176
176
  --proj, --project=PROJECT[/SUBPROJECT] - Show actions from a specific project (default: none)
177
177
  -v, --invert - Show actions not matching search pattern
@@ -209,9 +209,9 @@ EXAMPLES
209
209
 
210
210
  Examples:
211
211
 
212
- - `na show` (list all next actions in the current directory)
213
- - `na show -d 3` (list all next actions in the current directory and look for additional files 3 levels deep from there)
214
- - `na show marked2` (show next actions from another directory you've previously used na on)
212
+ - `na next` (list all next actions in the current directory)
213
+ - `na next -d 3` (list all next actions in the current directory and look for additional files 3 levels deep from there)
214
+ - `na next marked2` (show next actions from another directory you've previously used na on)
215
215
 
216
216
  ```
217
217
  NAME
@@ -222,7 +222,7 @@ SYNOPSIS
222
222
  na [global options] next [command options] [QUERY]
223
223
 
224
224
  DESCRIPTION
225
- Next actions are actions which contain the next action tag (default @na), do not contain @done, and are not in the Archive project.
225
+ Next actions are actions which contain the next action tag (default @na), do not contain @done, and are not in the Archive project. Arguments will target a todo file from history, whether it's in the current directory or not. Todo file queries can include path components separated by / or :, and may use wildcards (`*` to match any text, `?` to match a single character). Multiple queries allowed (separate arguments or separated by comma).
226
226
 
227
227
  COMMAND OPTIONS
228
228
  -d, --depth=DEPTH - Recurse to depth (default: 2)
@@ -256,7 +256,7 @@ SYNOPSIS
256
256
  na [global options] next [command options] [QUERY]
257
257
 
258
258
  DESCRIPTION
259
- Next actions are actions which contain the next action tag (default @na), do not contain @done, and are not in the Archive project.
259
+ Next actions are actions which contain the next action tag (default @na), do not contain @done, and are not in the Archive project. Arguments will target a todo file from history, whether it's in the current directory or not. Todo file queries can include path components separated by / or :, and may use wildcards (`*` to match any text, `?` to match a single character). Multiple queries allowed (separate arguments or separated by comma).
260
260
 
261
261
  COMMAND OPTIONS
262
262
  -d, --depth=DEPTH - Recurse to depth (default: 2)
data/bin/na CHANGED
@@ -54,8 +54,12 @@ class App
54
54
  switch %i[debug]
55
55
 
56
56
  desc 'Show next actions'
57
- long_desc "Next actions are actions which contain the next action tag (default @na),
58
- do not contain @done, and are not in the Archive project."
57
+ long_desc 'Next actions are actions which contain the next action tag (default @na),
58
+ do not contain @done, and are not in the Archive project.
59
+
60
+ Arguments will target a todo file from history, whether it\'s in the current
61
+ directory or not. Todo file queries can include path components separated by /
62
+ or :, and may use wildcards (`*` to match any text, `?` to match a single character). Multiple queries allowed (separate arguments or separated by comma).'
59
63
  arg_name 'QUERY', optional: true
60
64
  command %i[next show] do |c|
61
65
  c.example 'na next', desc: 'display the next actions from any todo files in the current directory'
@@ -93,11 +97,13 @@ class App
93
97
  if args.count.positive?
94
98
  tokens = []
95
99
  args.each do |arg|
96
- m = arg.match(/^(?<req>\+)?(?<tok>.*?)$/)
97
- tokens.push({
98
- token: m['tok'],
99
- required: !m['req'].nil?
100
- })
100
+ arg.split(/ *, */).each do |a|
101
+ m = a.match(/^(?<req>\+)?(?<tok>.*?)$/)
102
+ tokens.push({
103
+ token: m['tok'],
104
+ required: !m['req'].nil?
105
+ })
106
+ end
101
107
  end
102
108
  end
103
109
 
@@ -251,7 +257,7 @@ class App
251
257
  c.arg_name 'DEPTH'
252
258
  c.flag %i[d depth], type: :integer, must_match: /^\d+$/
253
259
 
254
- c.desc 'Show actions from a specific todo file in history'
260
+ c.desc 'Show actions from a specific todo file in history. May use wildcards (* and ?)'
255
261
  c.arg_name 'TODO_PATH'
256
262
  c.flag %i[in]
257
263
 
@@ -292,10 +298,14 @@ class App
292
298
 
293
299
  todo = nil
294
300
  if options[:in]
295
- todo = [{
296
- token: options[:in],
297
- required: true
298
- }]
301
+ todo = []
302
+ options[:in].split(/ *, */).each do |a|
303
+ m = a.match(/^(?<req>\+)?(?<tok>.*?)$/)
304
+ todo.push({
305
+ token: m['tok'],
306
+ required: !m['req'].nil?
307
+ })
308
+ end
299
309
  end
300
310
 
301
311
  files, actions = NA.parse_actions(depth: depth,
@@ -335,7 +345,7 @@ class App
335
345
  c.default_value 1
336
346
  c.flag %i[d depth], type: :integer, must_match: /^\d+$/
337
347
 
338
- c.desc 'Show actions from a specific todo file in history'
348
+ c.desc 'Show actions from a specific todo file in history. May use wildcards (* and ?)'
339
349
  c.arg_name 'TODO_PATH'
340
350
  c.flag %i[in]
341
351
 
@@ -373,10 +383,14 @@ class App
373
383
 
374
384
  todo = nil
375
385
  if options[:in]
376
- todo = [{
377
- token: options[:in],
378
- required: true
379
- }]
386
+ todo = []
387
+ options[:in].split(/ *, */).each do |a|
388
+ m = a.match(/^(?<req>\+)?(?<tok>.*?)$/)
389
+ todo.push({
390
+ token: m['tok'],
391
+ required: !m['req'].nil?
392
+ })
393
+ end
380
394
  end
381
395
 
382
396
  files, actions = NA.parse_actions(depth: depth,
@@ -469,11 +483,13 @@ class App
469
483
  if args.count.positive?
470
484
  tokens = []
471
485
  args.each do |arg|
472
- m = arg.match(/^(?<req>\+)?(?<tok>.*?)$/)
473
- tokens.push({
474
- token: m['tok'],
475
- required: !m['req'].nil?
476
- })
486
+ arg.split(/ *, */).each do |a|
487
+ m = a.match(/^(?<req>\+)?(?<tok>.*?)$/)
488
+ tokens.push({
489
+ token: m['tok'],
490
+ required: !m['req'].nil?
491
+ })
492
+ end
477
493
  end
478
494
  end
479
495
 
@@ -379,18 +379,18 @@ module NA
379
379
  ## between characters
380
380
  ##
381
381
  def match_working_dir(search, distance: 1)
382
- search = search.map { |t| t[:token] }.join('/')
383
- optional = [search]
384
- required = [search]
385
-
386
382
  file = database_path
387
383
  notify('{r}No na database found', exit_code: 1) unless File.exist?(file)
388
384
 
389
385
  dirs = IO.read(file).split("\n")
390
386
 
391
- NA.notify("{bw}Directory regex: {x}#{required.map(&:dir_to_rx)}", debug: true)
387
+ optional = search.map { |t| t[:token] }
388
+ required = search.filter { |s| s[:required] }.map { |t| t[:token] }
389
+
390
+ NA.notify("{bw}Optional directory regex: {x}#{optional.map(&:dir_to_rx)}", debug: true)
391
+ NA.notify("{bw}Required directory regex: {x}#{required.map(&:dir_to_rx)}", debug: true)
392
392
 
393
- dirs.delete_if { |d| !d.dir_matches(any: optional, all: required) }
393
+ dirs.delete_if { |d| !d.sub(/\.#{NA.extension}$/, '').dir_matches(any: optional, all: required) }
394
394
  dirs.sort.uniq
395
395
  end
396
396
 
data/lib/na/string.rb CHANGED
@@ -1,6 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # String helpers
3
4
  class ::String
5
+ ##
6
+ ## Determine indentation level of line
7
+ ##
8
+ ## @return [Number] number of indents detected
9
+ ##
4
10
  def indent_level
5
11
  prefix = match(/(^[ \t]+)/)
6
12
  return 0 if prefix.nil?
@@ -11,7 +17,13 @@ class ::String
11
17
  ##
12
18
  ## Colorize @tags with ANSI escapes
13
19
  ##
14
- ## @param color [String] color (see #Color)
20
+ ## @param color [String] color (see #Color)
21
+ ## @param value [String] The value color
22
+ ## template
23
+ ## @param parens [String] The parens color
24
+ ## template
25
+ ## @param last_color [String] Color to restore after
26
+ ## tag highlight
15
27
  ##
16
28
  ## @return [String] string with @tags highlighted
17
29
  ##
@@ -23,6 +35,16 @@ class ::String
23
35
  "\\1#{tag_color}\\2#{paren_color}\\3#{value_color}\\4#{paren_color}\\5#{last_color}")
24
36
  end
25
37
 
38
+ ##
39
+ ## Highlight search results
40
+ ##
41
+ ## @param regexes [Array] The regexes for the
42
+ ## search
43
+ ## @param color [String] The highlight color
44
+ ## template
45
+ ## @param last_color [String] Color to restore after
46
+ ## highlight
47
+ ##
26
48
  def highlight_search(regexes, color: '{y}', last_color: '{xg}')
27
49
  string = dup
28
50
  color = NA::Color.template(color)
@@ -42,12 +64,13 @@ class ::String
42
64
 
43
65
  # Returns the last escape sequence from a string.
44
66
  #
45
- # Actually returns all escape codes, with the assumption
46
- # that the result of inserting them will generate the
47
- # same color as was set at the end of the string.
48
- # Because you can send modifiers like dark and bold
49
- # separate from color codes, only using the last code
50
- # may not render the same style.
67
+ # @note Actually returns all escape codes, with the
68
+ # assumption that the result of inserting them
69
+ # will generate the same color as was set at
70
+ # the end of the string. Because you can send
71
+ # modifiers like dark and bold separate from
72
+ # color codes, only using the last code may
73
+ # not render the same style.
51
74
  #
52
75
  # @return [String] All escape codes in string
53
76
  #
@@ -55,8 +78,18 @@ class ::String
55
78
  scan(/\e\[[\d;]+m/).join('').gsub(/\e\[0m/, '')
56
79
  end
57
80
 
81
+ ##
82
+ ## Convert a directory path to a regular expression
83
+ ##
84
+ ## @note Splits at / or :, adds variable distance
85
+ ## between characters, joins segments with
86
+ ## slashes and requires that last segment
87
+ ## match last segment of target path
88
+ ##
89
+ ## @param distance The distance
90
+ ##
58
91
  def dir_to_rx(distance: 2)
59
- "#{split(%r{[/:]}).map { |comp| comp.split('').join(".{0,#{distance}}") }.join('.*?/.*?')}[^/]+$"
92
+ "#{split(%r{[/:]}).map { |comp| comp.split('').join(".{0,#{distance}}").gsub(/\*/, '[^ ]*?') }.join('.*?/.*?')}[^/]*?$"
60
93
  end
61
94
 
62
95
  def dir_matches(any: [], all: [])
@@ -67,6 +100,11 @@ class ::String
67
100
  matches_any(any) && matches_all(all) && matches_none(none)
68
101
  end
69
102
 
103
+ ##
104
+ ## Convert wildcard characters to regular expressions
105
+ ##
106
+ ## @return [String] Regex string
107
+ ##
70
108
  def wildcard_to_rx
71
109
  gsub(/\./, '\\.').gsub(/\*/, '[^ ]*?').gsub(/\?/, '.')
72
110
  end
@@ -75,6 +113,12 @@ class ::String
75
113
  replace cap_first
76
114
  end
77
115
 
116
+ ##
117
+ ## Capitalize first character, leaving other
118
+ ## capitalization in place
119
+ ##
120
+ ## @return [String] capitalized string
121
+ ##
78
122
  def cap_first
79
123
  sub(/^([a-z])(.*)$/) do
80
124
  m = Regexp.last_match
data/lib/na/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Na
2
- VERSION = '1.1.21'
2
+ VERSION = '1.1.22'
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.1.20<!--END VER-->.
12
+ The current version of `na` is <!--VER-->1.1.21<!--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
 
@@ -92,9 +92,9 @@ Unless `--exact` is specified, search is tokenized and combined with AND, so `na
92
92
 
93
93
  Examples:
94
94
 
95
- - `na show` (list all next actions in the current directory)
96
- - `na show -d 3` (list all next actions in the current directory and look for additional files 3 levels deep from there)
97
- - `na show marked2` (show next actions from another directory you've previously used na on)
95
+ - `na next` (list all next actions in the current directory)
96
+ - `na next -d 3` (list all next actions in the current directory and look for additional files 3 levels deep from there)
97
+ - `na next marked2` (show next actions from another directory you've previously used na on)
98
98
 
99
99
  ```
100
100
  @cli(bundle exec bin/na help next)
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.1.21
4
+ version: 1.1.22
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brett Terpstra