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 +4 -4
- data/CHANGELOG.md +15 -0
- data/Gemfile.lock +1 -1
- data/README.md +8 -8
- data/bin/na +38 -22
- data/lib/na/next_action.rb +6 -6
- data/lib/na/string.rb +52 -8
- data/lib/na/version.rb +1 -1
- data/src/README.md +4 -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: 584d55c84c26fddeb65bf537b4743b5cac4308f39d796d336d95c900fc966deb
|
4
|
+
data.tar.gz: 73ea4289a1e43ce0b67f66f803a0db07359fe3f077358328a58c172c06daa107
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
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.
|
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.
|
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
|
213
|
-
- `na
|
214
|
-
- `na
|
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
|
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
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
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
|
-
|
297
|
-
|
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
|
-
|
378
|
-
|
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
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
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
|
|
data/lib/na/next_action.rb
CHANGED
@@ -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
|
-
|
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
|
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
|
46
|
-
# that the result of inserting them
|
47
|
-
# same color as was set at
|
48
|
-
# Because you can send
|
49
|
-
#
|
50
|
-
#
|
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
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.
|
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
|
96
|
-
- `na
|
97
|
-
- `na
|
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)
|