na 1.2.35 → 1.2.37
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 +28 -0
- data/Gemfile.lock +1 -1
- data/README.md +79 -2
- data/bin/commands/complete.rb +4 -0
- data/bin/commands/edit.rb +6 -5
- data/bin/commands/find.rb +27 -19
- data/bin/commands/next.rb +22 -18
- data/bin/commands/prompt.rb +2 -0
- data/bin/commands/tagged.rb +32 -25
- data/bin/commands/todos.rb +3 -3
- data/bin/commands/undo.rb +22 -0
- data/bin/commands/update.rb +12 -2
- data/lib/na/action.rb +27 -1
- data/lib/na/actions.rb +87 -0
- data/lib/na/editor.rb +123 -0
- data/lib/na/next_action.rb +203 -471
- data/lib/na/todo.rb +183 -0
- data/lib/na/version.rb +1 -1
- data/lib/na.rb +3 -0
- data/src/_README.md +36 -12
- metadata +6 -2
data/lib/na/todo.rb
ADDED
@@ -0,0 +1,183 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module NA
|
4
|
+
class Todo
|
5
|
+
attr_accessor :actions, :projects, :files
|
6
|
+
|
7
|
+
def initialize(options = {})
|
8
|
+
@files, @actions, @projects = parse(options)
|
9
|
+
end
|
10
|
+
|
11
|
+
##
|
12
|
+
## Read a todo file and create a list of actions
|
13
|
+
##
|
14
|
+
## @param options The options
|
15
|
+
##
|
16
|
+
## @option depth [Number] The directory depth to
|
17
|
+
## search for files
|
18
|
+
## @option done [Boolean] include @done actions
|
19
|
+
## @option query [Hash] The todo file query
|
20
|
+
## @option tag [Array] Tags to search for
|
21
|
+
## @option search [String] A search string
|
22
|
+
## @option negate [Boolean] Invert results
|
23
|
+
## @option regex [Boolean] Interpret as regular
|
24
|
+
## expression
|
25
|
+
## @option project [String] The project
|
26
|
+
## @option require_na [Boolean] Require @na tag
|
27
|
+
## @option file_path [String] file path to parse
|
28
|
+
##
|
29
|
+
def parse(options)
|
30
|
+
defaults = {
|
31
|
+
depth: 1,
|
32
|
+
done: false,
|
33
|
+
file_path: nil,
|
34
|
+
negate: false,
|
35
|
+
project: nil,
|
36
|
+
query: nil,
|
37
|
+
regex: false,
|
38
|
+
require_na: true,
|
39
|
+
search: nil,
|
40
|
+
tag: nil
|
41
|
+
}
|
42
|
+
|
43
|
+
settings = defaults.merge(options)
|
44
|
+
|
45
|
+
actions = NA::Actions.new
|
46
|
+
required = []
|
47
|
+
optional = []
|
48
|
+
negated = []
|
49
|
+
required_tag = []
|
50
|
+
optional_tag = []
|
51
|
+
negated_tag = []
|
52
|
+
projects = []
|
53
|
+
|
54
|
+
NA.notify("{dw}Tags: #{settings[:tag]}", debug:true)
|
55
|
+
NA.notify("{dw}Search: #{settings[:search]}", debug:true)
|
56
|
+
|
57
|
+
settings[:tag]&.each do |t|
|
58
|
+
unless t[:tag].nil?
|
59
|
+
if settings[:negate]
|
60
|
+
optional_tag.push(t) if t[:negate]
|
61
|
+
required_tag.push(t) if t[:required] && t[:negate]
|
62
|
+
negated_tag.push(t) unless t[:negate]
|
63
|
+
else
|
64
|
+
optional_tag.push(t) unless t[:negate]
|
65
|
+
required_tag.push(t) if t[:required] && !t[:negate]
|
66
|
+
negated_tag.push(t) if t[:negate]
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
unless settings[:search].nil? || settings[:search].empty?
|
72
|
+
if settings[:regex] || settings[:search].is_a?(String)
|
73
|
+
if settings[:negate]
|
74
|
+
negated.push(settings[:search])
|
75
|
+
else
|
76
|
+
optional.push(settings[:search])
|
77
|
+
required.push(settings[:search])
|
78
|
+
end
|
79
|
+
else
|
80
|
+
settings[:search].each do |t|
|
81
|
+
opt, req, neg = parse_search(t, settings[:negate])
|
82
|
+
optional.concat(opt)
|
83
|
+
required.concat(req)
|
84
|
+
negated.concat(neg)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
files = if !settings[:file_path].nil?
|
90
|
+
[settings[:file_path]]
|
91
|
+
elsif settings[:query].nil?
|
92
|
+
NA.find_files(depth: settings[:depth])
|
93
|
+
else
|
94
|
+
NA.match_working_dir(settings[:query])
|
95
|
+
end
|
96
|
+
|
97
|
+
files.each do |file|
|
98
|
+
NA.save_working_dir(File.expand_path(file))
|
99
|
+
content = file.read_file
|
100
|
+
indent_level = 0
|
101
|
+
parent = []
|
102
|
+
in_action = false
|
103
|
+
content.split(/\n/).each.with_index do |line, idx|
|
104
|
+
if line.project?
|
105
|
+
in_action = false
|
106
|
+
proj = line.project
|
107
|
+
indent = line.indent_level
|
108
|
+
|
109
|
+
if indent.zero? # top level project
|
110
|
+
parent = [proj]
|
111
|
+
elsif indent <= indent_level # if indent level is same or less, split parent before indent level and append
|
112
|
+
parent.slice!(indent, parent.count - indent)
|
113
|
+
parent.push(proj)
|
114
|
+
else # if indent level is greater, append project to parent
|
115
|
+
parent.push(proj)
|
116
|
+
end
|
117
|
+
|
118
|
+
projects.push(NA::Project.new(parent.join(':'), indent, idx, idx))
|
119
|
+
|
120
|
+
indent_level = indent
|
121
|
+
elsif line.blank?
|
122
|
+
in_action = false
|
123
|
+
elsif line.action?
|
124
|
+
in_action = false
|
125
|
+
|
126
|
+
action = line.action
|
127
|
+
new_action = NA::Action.new(file, File.basename(file, ".#{NA.extension}"), parent.dup, action, idx)
|
128
|
+
|
129
|
+
projects[-1].last_line = idx if projects.count.positive?
|
130
|
+
|
131
|
+
next if line.done? && !settings[:done]
|
132
|
+
|
133
|
+
next if settings[:require_na] && !line.na?
|
134
|
+
|
135
|
+
has_search = !optional.empty? || !required.empty? || !negated.empty?
|
136
|
+
|
137
|
+
next if has_search && !new_action.search_match?(any: optional,
|
138
|
+
all: required,
|
139
|
+
none: negated)
|
140
|
+
|
141
|
+
if settings[:project]
|
142
|
+
rx = settings[:project].split(%r{[/:]}).join('.*?/')
|
143
|
+
next unless parent.join('/') =~ Regexp.new("#{rx}.*?", Regexp::IGNORECASE)
|
144
|
+
end
|
145
|
+
|
146
|
+
has_tag = !optional_tag.empty? || !required_tag.empty? || !negated_tag.empty?
|
147
|
+
next if has_tag && !new_action.tags_match?(any: optional_tag,
|
148
|
+
all: required_tag,
|
149
|
+
none: negated_tag)
|
150
|
+
|
151
|
+
actions.push(new_action)
|
152
|
+
in_action = true
|
153
|
+
elsif in_action
|
154
|
+
actions[-1].note.push(line.strip) if actions.count.positive?
|
155
|
+
projects[-1].last_line = idx if projects.count.positive?
|
156
|
+
end
|
157
|
+
end
|
158
|
+
projects = projects.dup
|
159
|
+
end
|
160
|
+
|
161
|
+
[files, actions, projects]
|
162
|
+
end
|
163
|
+
|
164
|
+
def parse_search(tag, negate)
|
165
|
+
required = []
|
166
|
+
optional = []
|
167
|
+
negated = []
|
168
|
+
new_rx = tag[:token].to_s.wildcard_to_rx
|
169
|
+
|
170
|
+
if negate
|
171
|
+
optional.push(new_rx) if tag[:negate]
|
172
|
+
required.push(new_rx) if tag[:required] && tag[:negate]
|
173
|
+
negated.push(new_rx) unless tag[:negate]
|
174
|
+
else
|
175
|
+
optional.push(new_rx) unless tag[:negate]
|
176
|
+
required.push(new_rx) if tag[:required] && !tag[:negate]
|
177
|
+
negated.push(new_rx) if tag[:negate]
|
178
|
+
end
|
179
|
+
|
180
|
+
[optional, required, negated]
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
data/lib/na/version.rb
CHANGED
data/lib/na.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.2.
|
12
|
+
The current version of `na` is <!--VER-->1.2.35<!--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
|
|
@@ -69,7 +69,7 @@ You can mark todos as complete, delete them, add and remove tags, change priorit
|
|
69
69
|
### Usage
|
70
70
|
|
71
71
|
```
|
72
|
-
@cli(
|
72
|
+
@cli(na help)
|
73
73
|
```
|
74
74
|
|
75
75
|
#### Commands
|
@@ -87,13 +87,13 @@ Use the `--note` switch to add a note. If STDIN (piped) input is present when th
|
|
87
87
|
Notes are not displayed by the `next/tagged/find` commands unless `--notes` is specified.
|
88
88
|
|
89
89
|
```
|
90
|
-
@cli(
|
90
|
+
@cli(na help add)
|
91
91
|
```
|
92
92
|
|
93
93
|
##### edit
|
94
94
|
|
95
95
|
```
|
96
|
-
@cli(
|
96
|
+
@cli(na help edit)
|
97
97
|
```
|
98
98
|
|
99
99
|
##### find
|
@@ -103,13 +103,13 @@ Example: `na find cool feature idea`
|
|
103
103
|
Unless `--exact` is specified, search is tokenized and combined with AND, so `na find cool feature idea` translates to `cool AND feature AND idea`, matching any string that contains all of the words. To make a token required and others optional, 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).
|
104
104
|
|
105
105
|
```
|
106
|
-
@cli(
|
106
|
+
@cli(na help find)
|
107
107
|
```
|
108
108
|
|
109
109
|
##### init, create
|
110
110
|
|
111
111
|
```
|
112
|
-
@cli(
|
112
|
+
@cli(na help init)
|
113
113
|
```
|
114
114
|
|
115
115
|
##### next, show
|
@@ -123,7 +123,7 @@ Examples:
|
|
123
123
|
To see all next actions across all known todos, use `na next "*"`. You can combine multiple arguments to see actions across multiple todos, e.g. `na next marked nvultra`.
|
124
124
|
|
125
125
|
```
|
126
|
-
@cli(
|
126
|
+
@cli(na help next)
|
127
127
|
```
|
128
128
|
|
129
129
|
##### projects
|
@@ -131,7 +131,7 @@ To see all next actions across all known todos, use `na next "*"`. You can combi
|
|
131
131
|
List all projects in a file. If arguments are provided, they're used to match a todo file from history, otherwise the todo file(s) in the current directory will be used.
|
132
132
|
|
133
133
|
```
|
134
|
-
@cli(
|
134
|
+
@cli(na help projects)
|
135
135
|
```
|
136
136
|
|
137
137
|
##### saved
|
@@ -146,7 +146,7 @@ Run `na saved` without an argument to list your saved searches.
|
|
146
146
|
<!--JEKYLL{:.tip}-->
|
147
147
|
|
148
148
|
```
|
149
|
-
@cli(
|
149
|
+
@cli(na help saved)
|
150
150
|
```
|
151
151
|
|
152
152
|
##### tagged
|
@@ -160,7 +160,7 @@ You can also perform value comparisons on tags. A value in a TaskPaper tag is ad
|
|
160
160
|
To perform a string comparison, you can use `*=` (contains), `^=` (starts with), `$=` (ends with), or `=` (matches). E.g. `na tagged "note*=video"`.
|
161
161
|
|
162
162
|
```
|
163
|
-
@cli(
|
163
|
+
@cli(na help show)
|
164
164
|
```
|
165
165
|
|
166
166
|
##### todos
|
@@ -168,7 +168,7 @@ To perform a string comparison, you can use `*=` (contains), `^=` (starts with),
|
|
168
168
|
List all known todo files from history.
|
169
169
|
|
170
170
|
```
|
171
|
-
@cli(
|
171
|
+
@cli(na help todos)
|
172
172
|
```
|
173
173
|
|
174
174
|
##### update
|
@@ -206,7 +206,31 @@ Notes are not displayed by the `next/tagged/find` commands unless `--notes` is s
|
|
206
206
|
See the help output for a list of all available actions.
|
207
207
|
|
208
208
|
```
|
209
|
-
@cli(
|
209
|
+
@cli(na help update)
|
210
|
+
```
|
211
|
+
|
212
|
+
##### changelog
|
213
|
+
|
214
|
+
View recent changes with `na changelog` or `na changes`.
|
215
|
+
|
216
|
+
```
|
217
|
+
@cli(na help changelog)
|
218
|
+
```
|
219
|
+
|
220
|
+
##### complete
|
221
|
+
|
222
|
+
Mark an action as complete, shortcut for `na update --finish`.
|
223
|
+
|
224
|
+
```
|
225
|
+
@cli(na help complete)
|
226
|
+
```
|
227
|
+
|
228
|
+
##### archive
|
229
|
+
|
230
|
+
Mark an action as complete and move to archive, shortcut for `na update --archive`.
|
231
|
+
|
232
|
+
```
|
233
|
+
@cli(na help archive)
|
210
234
|
```
|
211
235
|
|
212
236
|
### Configuration
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: na
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.37
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brett Terpstra
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-09-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -222,12 +222,15 @@ files:
|
|
222
222
|
- bin/commands/saved.rb
|
223
223
|
- bin/commands/tagged.rb
|
224
224
|
- bin/commands/todos.rb
|
225
|
+
- bin/commands/undo.rb
|
225
226
|
- bin/commands/update.rb
|
226
227
|
- bin/na
|
227
228
|
- lib/na.rb
|
228
229
|
- lib/na/action.rb
|
230
|
+
- lib/na/actions.rb
|
229
231
|
- lib/na/array.rb
|
230
232
|
- lib/na/colors.rb
|
233
|
+
- lib/na/editor.rb
|
231
234
|
- lib/na/hash.rb
|
232
235
|
- lib/na/help_monkey_patch.rb
|
233
236
|
- lib/na/next_action.rb
|
@@ -235,6 +238,7 @@ files:
|
|
235
238
|
- lib/na/project.rb
|
236
239
|
- lib/na/prompt.rb
|
237
240
|
- lib/na/string.rb
|
241
|
+
- lib/na/todo.rb
|
238
242
|
- lib/na/version.rb
|
239
243
|
- na.gemspec
|
240
244
|
- na.rdoc
|