na 1.1.13 → 1.1.14
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 +13 -0
- data/Gemfile.lock +1 -1
- data/README.md +7 -3
- data/bin/na +5 -3
- data/lib/na/action.rb +2 -2
- data/lib/na/next_action.rb +11 -7
- data/lib/na/string.rb +48 -22
- data/lib/na/version.rb +1 -1
- data/src/README.md +7 -3
- 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: 2324b729bcc5e20eab3e063427fa5c6480274ea844fe72117e7f25c7e9801764
|
4
|
+
data.tar.gz: 68d00ee26f320e14afd0e6a72a072b2cf30c82beaaf7818962b90e7fa0884914
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b6b7fd0066ba41b9fa184ab3231cb8d7b68e68526bc380f21f2b12048de1c4a4eae24d2da8e47abe95c2389536e90ee32fa35ebdf786570745b8153c72d65e4a
|
7
|
+
data.tar.gz: 320264ba4f636f8a68804f7767bd09a4c2105adf684b603514d933003f06f72e2cebb978476a659c2a7ee716fbdaadf7f9fd507c3985ec2dc870162da2751414
|
data/CHANGELOG.md
CHANGED
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.14
|
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.
|
@@ -37,7 +37,7 @@ You can list next actions in files in the current directory by typing `na`. By d
|
|
37
37
|
|
38
38
|
#### Easy matching
|
39
39
|
|
40
|
-
`na` features intelligent project matching. Every time it locates a todo file, it adds the project to the database. Once a project is recorded, you can list its actions by using any portion of the parent directories or file names. If your project is in `~/Sites/dev/markedapp`, you could quickly list its next actions by typing `na next dev
|
40
|
+
`na` features intelligent project matching. Every time it locates a todo file, it adds the project to the database. Once a project is recorded, you can list its actions by using any portion of the parent directories or file names. If your project is in `~/Sites/dev/markedapp`, you could quickly list its next actions by typing `na next dev/mark`. Creat paths by separating with / or :, separate multiple queries with spaces. na will always look for the shortest match for a path.
|
41
41
|
|
42
42
|
#### Recursion
|
43
43
|
|
@@ -152,6 +152,8 @@ EXAMPLES
|
|
152
152
|
|
153
153
|
Example: `na find cool feature idea`
|
154
154
|
|
155
|
+
Unless `--exact` is specified, search is tokenized and combined with OR, so `na find cool feature idea` translates to `cool OR feature OR idea`, matching any string that contains any of the words. To make a token required, add a `+` before it (e.g. `cool +feature idea` is `(cool OR idea) AND feature`). Wildcards allowed (`*` and `?`), use `--regex` to interpret the search as a regular expression. Use `-v` to invert the results (display non-matching actions only).
|
156
|
+
|
155
157
|
```
|
156
158
|
NAME
|
157
159
|
find - Find actions matching a search pattern
|
@@ -229,7 +231,9 @@ EXAMPLES
|
|
229
231
|
|
230
232
|
##### tagged
|
231
233
|
|
232
|
-
Example: `na tagged feature +maybe
|
234
|
+
Example: `na tagged feature +maybe`.
|
235
|
+
|
236
|
+
Separate multiple tags with spaces or commas. By default tags are combined with OR, so actions matching any of the tags listed will be displayed. Use `+` to make a tag required and `!` to negate a tag (only display if the action does _not_ contain the tag). Use `-v` to invert the search and display all actions that _don't_ match.
|
233
237
|
|
234
238
|
```
|
235
239
|
NAME
|
data/bin/na
CHANGED
@@ -269,7 +269,7 @@ class App
|
|
269
269
|
tokens = Regexp.new(args.join(' '), Regexp::IGNORECASE)
|
270
270
|
else
|
271
271
|
tokens = []
|
272
|
-
args.each do |arg|
|
272
|
+
args.join(' ').split(/ /).each do |arg|
|
273
273
|
m = arg.match(/^(?<req>[+\-!])?(?<tok>.*?)$/)
|
274
274
|
tokens.push({
|
275
275
|
token: m['tok'],
|
@@ -285,7 +285,8 @@ class App
|
|
285
285
|
regex: options[:regex],
|
286
286
|
project: options[:project],
|
287
287
|
require_na: false)
|
288
|
-
|
288
|
+
regexes = tokens.delete_if { |token| token[:negate] }.map { |token| token[:token] }
|
289
|
+
NA.output_actions(actions, depth, files: files, regexes: regexes)
|
289
290
|
end
|
290
291
|
end
|
291
292
|
|
@@ -336,7 +337,8 @@ class App
|
|
336
337
|
negate: options[:invert],
|
337
338
|
project: options[:project],
|
338
339
|
require_na: false)
|
339
|
-
|
340
|
+
regexes = tags.delete_if { |token| token[:negate] }.map { |token| token[:token] }
|
341
|
+
NA.output_actions(actions, depth, files: files, regexes: regexes)
|
340
342
|
end
|
341
343
|
end
|
342
344
|
|
data/lib/na/action.rb
CHANGED
@@ -27,7 +27,7 @@ module NA
|
|
27
27
|
EOINSPECT
|
28
28
|
end
|
29
29
|
|
30
|
-
def pretty(extension: 'taskpaper', template: {})
|
30
|
+
def pretty(extension: 'taskpaper', template: {}, regexes: [])
|
31
31
|
default_template = {
|
32
32
|
file: '{xbk}',
|
33
33
|
parent: '{c}',
|
@@ -67,7 +67,7 @@ module NA
|
|
67
67
|
NA::Color.template(template[:output].gsub(/%filename/, filename)
|
68
68
|
.gsub(/%project/, project)
|
69
69
|
.gsub(/%parents?/, parents)
|
70
|
-
.gsub(/%action/, action))
|
70
|
+
.gsub(/%action/, action.highlight_search(regexes)))
|
71
71
|
end
|
72
72
|
|
73
73
|
def tags_match?(any: [], all: [], none: [])
|
data/lib/na/next_action.rb
CHANGED
@@ -80,8 +80,10 @@ module NA
|
|
80
80
|
notify("{by}Task added to {bw}#{file}")
|
81
81
|
end
|
82
82
|
|
83
|
-
def output_actions(actions, depth, files: nil)
|
84
|
-
|
83
|
+
def output_actions(actions, depth, files: nil, regexes: [])
|
84
|
+
return if files.nil?
|
85
|
+
|
86
|
+
template = if files.count.positive?
|
85
87
|
if files.count == 1
|
86
88
|
'%parent%action'
|
87
89
|
else
|
@@ -96,11 +98,10 @@ module NA
|
|
96
98
|
else
|
97
99
|
'%parent%action'
|
98
100
|
end
|
99
|
-
if files && @verbose
|
100
|
-
files.map { |f| notify("{dw}#{f}") }
|
101
|
-
end
|
102
101
|
|
103
|
-
|
102
|
+
files.map { |f| notify("{dw}#{f}") } if files && @verbose
|
103
|
+
|
104
|
+
puts(actions.map { |action| action.pretty(template: { output: template }, regexes: regexes) })
|
104
105
|
end
|
105
106
|
|
106
107
|
def parse_actions(depth: 1, query: nil, tag: nil, search: nil, negate: false, regex: false, project: nil, require_na: true)
|
@@ -136,7 +137,10 @@ module NA
|
|
136
137
|
end
|
137
138
|
else
|
138
139
|
search.each do |t|
|
139
|
-
|
140
|
+
opt, req, neg = parse_search(t, negate)
|
141
|
+
optional.concat(opt)
|
142
|
+
required.concat(req)
|
143
|
+
negated.concat(neg)
|
140
144
|
end
|
141
145
|
end
|
142
146
|
end
|
data/lib/na/string.rb
CHANGED
@@ -5,9 +5,7 @@ class ::String
|
|
5
5
|
prefix = match(/(^[ \t]+)/)
|
6
6
|
return 0 if prefix.nil?
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
tabs
|
8
|
+
prefix[1].gsub(/ /, "\t").scan(/\t/).count
|
11
9
|
end
|
12
10
|
|
13
11
|
##
|
@@ -21,21 +19,65 @@ class ::String
|
|
21
19
|
tag_color = NA::Color.template(color)
|
22
20
|
paren_color = NA::Color.template(parens)
|
23
21
|
value_color = NA::Color.template(value)
|
24
|
-
gsub(/(\s|m)(@[^ ("']+)(?:(\()(.*?)(\)))?/,
|
22
|
+
gsub(/(\s|m)(@[^ ("']+)(?:(\()(.*?)(\)))?/,
|
23
|
+
"\\1#{tag_color}\\2#{paren_color}\\3#{value_color}\\4#{paren_color}\\5#{last_color}")
|
24
|
+
end
|
25
|
+
|
26
|
+
def highlight_search(regexes, color: '{y}')
|
27
|
+
string = dup
|
28
|
+
color = NA::Color.template(color)
|
29
|
+
regexes.each do |rx|
|
30
|
+
next if rx.nil?
|
31
|
+
|
32
|
+
string.gsub!(/(#{rx.wildcard_to_rx})/i, "#{color}\\1#{NA::Color.template('{xg}')}")
|
33
|
+
end
|
34
|
+
string
|
35
|
+
end
|
36
|
+
|
37
|
+
# Returns the last escape sequence from a string.
|
38
|
+
#
|
39
|
+
# Actually returns all escape codes, with the assumption
|
40
|
+
# that the result of inserting them will generate the
|
41
|
+
# same color as was set at the end of the string.
|
42
|
+
# Because you can send modifiers like dark and bold
|
43
|
+
# separate from color codes, only using the last code
|
44
|
+
# may not render the same style.
|
45
|
+
#
|
46
|
+
# @return [String] All escape codes in string
|
47
|
+
#
|
48
|
+
def last_color
|
49
|
+
scan(/\e\[[\d;]+m/).join('').gsub(/\e\[0m/, '')
|
25
50
|
end
|
26
51
|
|
27
52
|
def dir_to_rx
|
28
|
-
split(%r{[/:]}).join('.*?/.*?')
|
53
|
+
"#{split(%r{[/:]}).join('.*?/.*?')}[^/]+$"
|
29
54
|
end
|
30
55
|
|
31
56
|
def dir_matches(any: [], all: [])
|
32
|
-
matches_any(any.map
|
57
|
+
matches_any(any.map(&:dir_to_rx)) && matches_all(all.map(&:dir_to_rx))
|
33
58
|
end
|
34
59
|
|
35
60
|
def matches(any: [], all: [], none: [])
|
36
61
|
matches_any(any) && matches_all(all) && matches_none(none)
|
37
62
|
end
|
38
63
|
|
64
|
+
def wildcard_to_rx
|
65
|
+
gsub(/\./, '\\.').gsub(/\*/, '.*?').gsub(/\?/, '.')
|
66
|
+
end
|
67
|
+
|
68
|
+
def cap_first!
|
69
|
+
replace cap_first
|
70
|
+
end
|
71
|
+
|
72
|
+
def cap_first
|
73
|
+
sub(/^([a-z])(.*)$/) do
|
74
|
+
m = Regexp.last_match
|
75
|
+
m[1].upcase << m[2]
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
39
81
|
def matches_none(regexes)
|
40
82
|
regexes.each do |rx|
|
41
83
|
return false if match(Regexp.new(rx, Regexp::IGNORECASE))
|
@@ -44,7 +86,6 @@ class ::String
|
|
44
86
|
end
|
45
87
|
|
46
88
|
def matches_any(regexes)
|
47
|
-
string = dup
|
48
89
|
regexes.each do |rx|
|
49
90
|
return true if match(Regexp.new(rx, Regexp::IGNORECASE))
|
50
91
|
end
|
@@ -57,19 +98,4 @@ class ::String
|
|
57
98
|
end
|
58
99
|
true
|
59
100
|
end
|
60
|
-
|
61
|
-
def wildcard_to_rx
|
62
|
-
gsub(/\./, '\\.').gsub(/\*/, '.*?').gsub(/\?/, '.')
|
63
|
-
end
|
64
|
-
|
65
|
-
def cap_first!
|
66
|
-
replace cap_first
|
67
|
-
end
|
68
|
-
|
69
|
-
def cap_first
|
70
|
-
sub(/^([a-z])(.*)$/) do
|
71
|
-
m = Regexp.last_match
|
72
|
-
m[1].upcase << m[2]
|
73
|
-
end
|
74
|
-
end
|
75
101
|
end
|
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.13<!--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
|
|
@@ -36,7 +36,7 @@ You can list next actions in files in the current directory by typing `na`. By d
|
|
36
36
|
|
37
37
|
#### Easy matching
|
38
38
|
|
39
|
-
`na` features intelligent project matching. Every time it locates a todo file, it adds the project to the database. Once a project is recorded, you can list its actions by using any portion of the parent directories or file names. If your project is in `~/Sites/dev/markedapp`, you could quickly list its next actions by typing `na next dev
|
39
|
+
`na` features intelligent project matching. Every time it locates a todo file, it adds the project to the database. Once a project is recorded, you can list its actions by using any portion of the parent directories or file names. If your project is in `~/Sites/dev/markedapp`, you could quickly list its next actions by typing `na next dev/mark`. Creat paths by separating with / or :, separate multiple queries with spaces. na will always look for the shortest match for a path.
|
40
40
|
|
41
41
|
#### Recursion
|
42
42
|
|
@@ -151,6 +151,8 @@ EXAMPLES
|
|
151
151
|
|
152
152
|
Example: `na find cool feature idea`
|
153
153
|
|
154
|
+
Unless `--exact` is specified, search is tokenized and combined with OR, so `na find cool feature idea` translates to `cool OR feature OR idea`, matching any string that contains any of the words. To make a token required, add a `+` before it (e.g. `cool +feature idea` is `(cool OR idea) AND feature`). Wildcards allowed (`*` and `?`), use `--regex` to interpret the search as a regular expression. Use `-v` to invert the results (display non-matching actions only).
|
155
|
+
|
154
156
|
```
|
155
157
|
NAME
|
156
158
|
find - Find actions matching a search pattern
|
@@ -228,7 +230,9 @@ EXAMPLES
|
|
228
230
|
|
229
231
|
##### tagged
|
230
232
|
|
231
|
-
Example: `na tagged feature +maybe
|
233
|
+
Example: `na tagged feature +maybe`.
|
234
|
+
|
235
|
+
Separate multiple tags with spaces or commas. By default tags are combined with OR, so actions matching any of the tags listed will be displayed. Use `+` to make a tag required and `!` to negate a tag (only display if the action does _not_ contain the tag). Use `-v` to invert the search and display all actions that _don't_ match.
|
232
236
|
|
233
237
|
```
|
234
238
|
NAME
|