na 1.1.13 → 1.1.14
Sign up to get free protection for your applications and to get access to all the features.
- 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
|