na 1.2.6 → 1.2.8
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 +26 -0
- data/Gemfile.lock +1 -1
- data/README.md +14 -8
- data/bin/na +7 -11
- data/lib/na/next_action.rb +75 -77
- data/lib/na/project.rb +6 -4
- data/lib/na/version.rb +1 -1
- data/src/README.md +12 -6
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a5d95b5e069cbe51ad597f9af95744a84590e9513d28dd53c5710c477c59e19e
|
4
|
+
data.tar.gz: bbaefe5d4151348443260a940f143e83d5514967886caa8d4a0e5848f01860a1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9747348a856378659ab51925aace1eb7f0e056003e6f3a06bc53cb23c3f954f3b2cbd60b4c598db4e2e537052be665eda10871718f2aa517b19d9ef28a2ab82a
|
7
|
+
data.tar.gz: 7d2dff9e215a1e05a70aa31a0abb10d98d8a2937936192c74a6f952c195e292b8f24bffd5968a0d2190b7f0548ffaaeb699c10066781566f68950ca62a0314d7
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,29 @@
|
|
1
|
+
### 1.2.8
|
2
|
+
|
3
|
+
2022-10-28 11:52
|
4
|
+
|
5
|
+
#### IMPROVED
|
6
|
+
|
7
|
+
- Empty lines in notes end a task in the parser
|
8
|
+
- Moving a task to the end of a project respects line breaks
|
9
|
+
|
10
|
+
#### FIXED
|
11
|
+
|
12
|
+
- Moving action within same project to end not parsing correctly
|
13
|
+
|
14
|
+
### 1.2.7
|
15
|
+
|
16
|
+
2022-10-28 07:29
|
17
|
+
|
18
|
+
#### IMPROVED
|
19
|
+
|
20
|
+
- Code refactoring
|
21
|
+
|
22
|
+
#### FIXED
|
23
|
+
|
24
|
+
- All_req error
|
25
|
+
- Adding entries to project names containing hyphen
|
26
|
+
|
1
27
|
### 1.2.6
|
2
28
|
|
3
29
|
2022-10-26 10:50
|
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.2.
|
12
|
+
The current version of `na` is 1.2.8
|
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.
|
@@ -31,9 +31,13 @@ If you don't have Ruby/RubyGems, you can install them pretty easily with Homebre
|
|
31
31
|
|
32
32
|
|
33
33
|
|
34
|
+
### Optional Dependencies
|
35
|
+
|
36
|
+
If you have [gum][] installed, na will use it for command line input when adding tasks and notes. If you have [fzf][] installed, it will be used for menus, falling back to gum if available.
|
37
|
+
|
34
38
|
### Features
|
35
39
|
|
36
|
-
You can list next actions in files in the current directory by typing `na`. By default, `na` looks for `*.taskpaper` files and extracts items tagged `@na` and not `@done`.
|
40
|
+
You can list next actions in files in the current directory by typing `na`. By default, `na` looks for `*.taskpaper` files and extracts items tagged `@na` and not `@done`. This can be modified to work with a single global file, and all of these options can be changed in the configuration.
|
37
41
|
|
38
42
|
#### Easy matching
|
39
43
|
|
@@ -73,11 +77,11 @@ SYNOPSIS
|
|
73
77
|
na [global options] command [command options] [arguments...]
|
74
78
|
|
75
79
|
VERSION
|
76
|
-
1.2.
|
80
|
+
1.2.8
|
77
81
|
|
78
82
|
GLOBAL OPTIONS
|
79
83
|
-a, --[no-]add - Add a next action (deprecated, for backwards compatibility)
|
80
|
-
--add_at=POSITION - Add all new/moved entries at [s]tart or [e]nd of target project (default:
|
84
|
+
--add_at=POSITION - Add all new/moved entries at [s]tart or [e]nd of target project (default: start)
|
81
85
|
--cwd_as=TYPE - Use current working directory as [p]roject, [t]ag, or [n]one (default: none)
|
82
86
|
-d, --depth=DEPTH - Recurse to depth (default: 3)
|
83
87
|
--[no-]debug - Display verbose output
|
@@ -479,6 +483,9 @@ EXAMPLES
|
|
479
483
|
|
480
484
|
Global options such as todo extension and default next action tag can be stored permanently by using the `na initconfig` command. Run na with the global options you'd like to set, and add `initconfig` at the end of the command. A file will be written to `~/.na.rc`. You can edit this manually, or just update it using the `initconfig --force` command to overwrite it with new settings.
|
481
485
|
|
486
|
+
> You can see all available global options by running `na help`.
|
487
|
+
|
488
|
+
|
482
489
|
Example: `na --ext md --na_tag next initconfig --force`
|
483
490
|
|
484
491
|
When this command is run, it doesn't include options for subcommands, but inserts placeholders for them. If you want to permanently set an option for a subcommand, you'll need to edit `~/.na.rc`. For example, if you wanted the `next` command to always recurse 2 levels deep, you could edit it to look like this:
|
@@ -509,12 +516,14 @@ When using a global file, you can additionally include `--cwd_as TYPE` to determ
|
|
509
516
|
|
510
517
|
#### Add tasks at the end of a project
|
511
518
|
|
512
|
-
By default, tasks are added at the top of the target project (Inbox, etc.). If you prefer new tasks to go at the
|
519
|
+
By default, tasks are added at the top of the target project (Inbox, etc.). If you prefer new tasks to go at the end of the project by default, include `--add_at end` as a global option when running `initconfig`.
|
513
520
|
|
514
521
|
### Prompt Hooks
|
515
522
|
|
516
523
|
You can add a prompt command to your shell to have na automatically list your next actions when you `cd` into a directory. To install a prompt command for your current shell, just run `na prompt install`. It works with Zsh, Bash, and Fish. If you'd rather make the changes to your startup file yourself, run `na prompt show` to get the hook and instructions printed out for copying.
|
517
524
|
|
525
|
+
If you're using a single global file, you'll need `--cwd_as` to be `tag` or `project` for a prompt command to work. na will detect which system you're using and provide a prompt command that lists actions based on the current directory using either project or tag.
|
526
|
+
|
518
527
|
> You can also get output for shells other than the one you're currently using by adding "bash", "zsh", or "fish" to the show or install command.
|
519
528
|
|
520
529
|
|
@@ -523,9 +532,6 @@ You can add a prompt command to your shell to have na automatically list your ne
|
|
523
532
|
|
524
533
|
After installing a hook, you'll need to close your terminal and start a new session to initialize the new commands.
|
525
534
|
|
526
|
-
### Misc
|
527
|
-
|
528
|
-
If you have [gum][] installed, na will use it for command line input when adding tasks and notes. If you have [fzf][] installed, it will be used for menus, falling back to gum if available.
|
529
535
|
|
530
536
|
[fzf]: https://github.com/junegunn/fzf
|
531
537
|
[gum]: https://github.com/charmbracelet/gum
|
data/bin/na
CHANGED
@@ -232,6 +232,7 @@ class App
|
|
232
232
|
end
|
233
233
|
elsif options[:todo]
|
234
234
|
todo = []
|
235
|
+
all_req = options[:todo] !~ /[+!\-]/
|
235
236
|
options[:todo].split(/ *, */).each do |a|
|
236
237
|
m = a.match(/^(?<req>[+\-!])?(?<tok>.*?)$/)
|
237
238
|
todo.push({
|
@@ -249,13 +250,10 @@ class App
|
|
249
250
|
unless File.exist?(target)
|
250
251
|
|
251
252
|
res = NA.yn(NA::Color.template("{by}Specified file not found, create #{todo}"), default: true)
|
252
|
-
|
253
|
-
basename = File.basename(target, ".#{NA.extension}")
|
254
|
-
NA.create_todo(target, basename)
|
255
|
-
else
|
256
|
-
NA.notify('{r}Cancelled{x}', exit_code: 1)
|
253
|
+
NA.notify('{r}Cancelled{x}', exit_code: 1) unless res
|
257
254
|
|
258
|
-
|
255
|
+
basename = File.basename(target, ".#{NA.extension}")
|
256
|
+
NA.create_todo(target, basename)
|
259
257
|
end
|
260
258
|
|
261
259
|
end
|
@@ -271,10 +269,8 @@ class App
|
|
271
269
|
end
|
272
270
|
end
|
273
271
|
target = files.count > 1 ? NA.select_file(files) : files[0]
|
274
|
-
unless files.count.positive? && File.exist?(target)
|
275
|
-
NA.notify('{r}Cancelled{x}', exit_code: 1)
|
272
|
+
NA.notify('{r}Cancelled{x}', exit_code: 1) unless files.count.positive? && File.exist?(target)
|
276
273
|
|
277
|
-
end
|
278
274
|
end
|
279
275
|
|
280
276
|
action = if args.count.positive?
|
@@ -1009,7 +1005,7 @@ class App
|
|
1009
1005
|
global[:cwd_as] =~ /^p/ ? :project : :tag
|
1010
1006
|
end
|
1011
1007
|
NA.weed_cache_file
|
1012
|
-
NA.notify("{dw}{ globals: #{NA.globals}, command_line: #{NA.command_line},
|
1008
|
+
NA.notify("{dw}{ globals: #{NA.globals}, command_line: #{NA.command_line}, command: #{NA.command}}", debug: true)
|
1013
1009
|
true
|
1014
1010
|
end
|
1015
1011
|
|
@@ -1057,6 +1053,6 @@ ARGV.each do |arg|
|
|
1057
1053
|
in_globals = false
|
1058
1054
|
end
|
1059
1055
|
end
|
1060
|
-
|
1056
|
+
NA.command = NA.command_line[0]
|
1061
1057
|
|
1062
1058
|
exit App.run(ARGV)
|
data/lib/na/next_action.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
# Next Action methods
|
4
4
|
module NA
|
5
5
|
class << self
|
6
|
-
attr_accessor :verbose, :extension, :na_tag, :command_line, :globals, :global_file, :cwd_is, :cwd, :stdin
|
6
|
+
attr_accessor :verbose, :extension, :na_tag, :command_line, :command, :globals, :global_file, :cwd_is, :cwd, :stdin
|
7
7
|
|
8
8
|
##
|
9
9
|
## Output to STDERR
|
@@ -116,36 +116,20 @@ module NA
|
|
116
116
|
## @param files [Array] The files
|
117
117
|
## @param multiple [Boolean] allow multiple selections
|
118
118
|
##
|
119
|
+
## @return [String, Array] array if multiple
|
119
120
|
def select_file(files, multiple: false)
|
120
|
-
|
121
|
-
res = choose_from(files, prompt: 'Use which file?', multiple: multiple)
|
122
|
-
unless res
|
123
|
-
notify('{r}No file selected, cancelled', exit_code: 1)
|
124
|
-
end
|
121
|
+
res = choose_from(files, prompt: multiple ? 'Select files' : 'Select a file', multiple: multiple)
|
125
122
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
'--cursor.foreground="151"',
|
130
|
-
'--item.foreground=""'
|
131
|
-
]
|
132
|
-
args.push('--no-limit') if multiple
|
133
|
-
res = `echo #{Shellwords.escape(files.join("\n"))}|#{TTY::Which.which('gum')} choose #{args.join(' ')}`
|
134
|
-
multiple ? res.split("\n") : res.strip
|
135
|
-
else
|
136
|
-
reader = TTY::Reader.new
|
137
|
-
puts
|
138
|
-
files.each.with_index do |f, i|
|
139
|
-
puts NA::Color.template(format("{bw}%<idx> 2d{xw}) {y}%<file>s{x}\n", idx: i + 1, file: f))
|
140
|
-
end
|
141
|
-
res = reader.read_line(NA::Color.template('{bw}Use which file? {x}')).strip.to_i
|
142
|
-
files[res - 1]
|
143
|
-
end
|
123
|
+
notify('{r}No file selected, cancelled', exit_code: 1) unless res && res.length.positive?
|
124
|
+
|
125
|
+
res
|
144
126
|
end
|
145
127
|
|
146
128
|
def shift_index_after(projects, idx, length = 1)
|
147
129
|
projects.map do |proj|
|
148
|
-
proj.line = proj.line
|
130
|
+
proj.line = proj.line - length if proj.line > idx
|
131
|
+
proj.last_line = proj.last_line - length if proj.last_line > idx
|
132
|
+
|
149
133
|
proj
|
150
134
|
end
|
151
135
|
end
|
@@ -166,33 +150,12 @@ module NA
|
|
166
150
|
return [projects, actions] if actions.count == 1 || all
|
167
151
|
|
168
152
|
options = actions.map { |action| "#{action.line} % #{action.parent.join('/')} : #{action.action}" }
|
169
|
-
res =
|
170
|
-
choose_from(options, prompt: 'Make a selection: ', multiple: true, sorted: true)
|
171
|
-
elsif TTY::Which.exist?('gum')
|
172
|
-
args = [
|
173
|
-
'--cursor.foreground="151"',
|
174
|
-
'--item.foreground=""',
|
175
|
-
'--no-limit'
|
176
|
-
]
|
177
|
-
`echo #{Shellwords.escape(options.join("\n"))}|#{TTY::Which.which('gum')} choose #{args.join(' ')}`.strip
|
178
|
-
else
|
179
|
-
reader = TTY::Reader.new
|
180
|
-
puts
|
181
|
-
options.each.with_index do |f, i|
|
182
|
-
puts NA::Color.template(format("{bw}%<idx> 2d{xw}) {y}%<action>s{x}\n", idx: i + 1, action: f))
|
183
|
-
end
|
184
|
-
result = reader.read_line(NA::Color.template('{bw}Use which file? {x}')).strip
|
185
|
-
if result && result.to_i.positive?
|
186
|
-
options[result.to_i - 1]
|
187
|
-
else
|
188
|
-
nil
|
189
|
-
end
|
190
|
-
end
|
153
|
+
res = choose_from(options, prompt: 'Make a selection: ', multiple: true, sorted: true)
|
191
154
|
|
192
155
|
NA.notify('{r}Cancelled', exit_code: 1) unless res && res.length.positive?
|
193
156
|
|
194
157
|
selected = []
|
195
|
-
res.
|
158
|
+
res.each do |result|
|
196
159
|
idx = result.match(/^(\d+)(?= % )/)[1]
|
197
160
|
action = actions.select { |a| a.line == idx.to_i }.first
|
198
161
|
selected.push(action)
|
@@ -235,7 +198,7 @@ module NA
|
|
235
198
|
content = "#{input.join("\n")}\n#{content}"
|
236
199
|
end
|
237
200
|
|
238
|
-
new_project = NA::Project.new(path.map(&:cap_first).join(':'), indent - 1, input.count - 1)
|
201
|
+
new_project = NA::Project.new(path.map(&:cap_first).join(':'), indent - 1, input.count - 1, input.count - 1)
|
239
202
|
else
|
240
203
|
line = final_match.line + 1
|
241
204
|
indent = final_match.indent + 1
|
@@ -245,7 +208,7 @@ module NA
|
|
245
208
|
indent += 1
|
246
209
|
end
|
247
210
|
content = content.split("\n").insert(line, input.join("\n")).join("\n")
|
248
|
-
new_project = NA::Project.new(path.map(&:cap_first).join(':'), indent - 1, line + input.count - 1)
|
211
|
+
new_project = NA::Project.new(path.map(&:cap_first).join(':'), indent - 1, line + input.count - 1, line + input.count - 1)
|
249
212
|
end
|
250
213
|
|
251
214
|
File.open(target, 'w') do |f|
|
@@ -327,6 +290,7 @@ module NA
|
|
327
290
|
projects.select { |proj| proj.project =~ /^#{action.parent.join(':')}$/ }.first
|
328
291
|
end
|
329
292
|
|
293
|
+
|
330
294
|
indent = "\t" * target_proj.indent
|
331
295
|
note = note.split("\n") unless note.is_a?(Array)
|
332
296
|
note = if note.empty?
|
@@ -345,19 +309,18 @@ module NA
|
|
345
309
|
break
|
346
310
|
end
|
347
311
|
end
|
348
|
-
|
349
312
|
target_line = if this_idx == projects.length - 1
|
350
313
|
contents.count
|
351
314
|
else
|
352
|
-
projects[this_idx
|
315
|
+
projects[this_idx].last_line + 1
|
353
316
|
end
|
354
317
|
else
|
355
|
-
target_line = target_proj.line
|
318
|
+
target_line = target_proj.line + 1
|
356
319
|
end
|
357
320
|
|
358
321
|
contents.insert(target_line, "#{indent}\t- #{action.action}#{note}")
|
359
322
|
else
|
360
|
-
|
323
|
+
_, actions = find_actions(target, search, tagged, done: done, all: all)
|
361
324
|
|
362
325
|
return if actions.nil?
|
363
326
|
|
@@ -367,6 +330,8 @@ module NA
|
|
367
330
|
|
368
331
|
projects = shift_index_after(projects, action.line, action.note.count + 1)
|
369
332
|
|
333
|
+
target_proj = projects.select { |proj| proj.project =~ /^#{target_proj.project}$/ }.first
|
334
|
+
|
370
335
|
action = process_action(action, priority: priority, finish: finish, add_tag: add_tag, remove_tag: remove_tag)
|
371
336
|
|
372
337
|
target_proj = if target_proj
|
@@ -385,14 +350,21 @@ module NA
|
|
385
350
|
note = note.empty? ? '' : "\n#{indent}\t\t#{note.join("\n#{indent}\t\t").strip}"
|
386
351
|
|
387
352
|
if append
|
388
|
-
this_idx =
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
353
|
+
this_idx = 0
|
354
|
+
projects.each_with_index do |proj, idx|
|
355
|
+
if proj.line == target_proj.line
|
356
|
+
this_idx = idx
|
357
|
+
break
|
358
|
+
end
|
393
359
|
end
|
360
|
+
|
361
|
+
target_line = if this_idx == projects.length - 1
|
362
|
+
contents.count
|
363
|
+
else
|
364
|
+
projects[this_idx].last_line + 1
|
365
|
+
end
|
394
366
|
else
|
395
|
-
target_line = target_proj.line
|
367
|
+
target_line = target_proj.line + 1
|
396
368
|
end
|
397
369
|
|
398
370
|
contents.insert(target_line, "#{indent}\t- #{action.action}#{note}")
|
@@ -535,9 +507,10 @@ module NA
|
|
535
507
|
content = file.read_file
|
536
508
|
indent_level = 0
|
537
509
|
parent = []
|
510
|
+
last_line = 0
|
538
511
|
in_action = false
|
539
512
|
content.split("\n").each.with_index do |line, idx|
|
540
|
-
if line =~ /^([ \t]*)([
|
513
|
+
if line =~ /^([ \t]*)([^\-][^@()]+?): *(@\S+ *)*$/
|
541
514
|
in_action = false
|
542
515
|
proj = Regexp.last_match(2)
|
543
516
|
indent = line.indent_level
|
@@ -551,20 +524,23 @@ module NA
|
|
551
524
|
parent.push(proj)
|
552
525
|
end
|
553
526
|
|
554
|
-
projects.push(NA::Project.new(parent.join(':'), indent, idx
|
527
|
+
projects.push(NA::Project.new(parent.join(':'), indent, idx, idx))
|
555
528
|
|
556
529
|
indent_level = indent
|
530
|
+
elsif line.strip =~ /^$/
|
531
|
+
in_action = false
|
557
532
|
elsif line =~ /^[ \t]*- /
|
558
533
|
in_action = false
|
559
|
-
# search_for_done = false
|
560
|
-
# optional_tag.each { |t| search_for_done = true if t[:tag] =~ /done/ }
|
561
|
-
next if line =~ /@done/ && !done
|
562
|
-
|
563
|
-
next if require_na && line !~ /@#{NA.na_tag}\b/
|
564
534
|
|
565
535
|
action = line.sub(/^[ \t]*- /, '')
|
566
536
|
new_action = NA::Action.new(file, File.basename(file, ".#{NA.extension}"), parent.dup, action, idx)
|
567
537
|
|
538
|
+
projects[-1].last_line = idx if projects.count.positive?
|
539
|
+
|
540
|
+
next if line =~ /@done/ && !done
|
541
|
+
|
542
|
+
next if require_na && line !~ /@#{NA.na_tag}\b/
|
543
|
+
|
568
544
|
has_search = !optional.empty? || !required.empty? || !negated.empty?
|
569
545
|
|
570
546
|
next if has_search && !new_action.search_match?(any: optional,
|
@@ -583,10 +559,12 @@ module NA
|
|
583
559
|
|
584
560
|
actions.push(new_action)
|
585
561
|
in_action = true
|
586
|
-
|
587
|
-
actions[-1].note.push(line.strip) if actions.count.positive?
|
562
|
+
elsif in_action
|
563
|
+
actions[-1].note.push(line.strip) if actions.count.positive?
|
564
|
+
projects[-1].last_line = idx if projects.count.positive?
|
588
565
|
end
|
589
566
|
end
|
567
|
+
projects = projects.dup
|
590
568
|
end
|
591
569
|
|
592
570
|
[files, actions, projects]
|
@@ -822,21 +800,41 @@ module NA
|
|
822
800
|
## @param sorted [Boolean] If true, sort selections alphanumerically
|
823
801
|
## @param fzf_args [Array] Additional fzf arguments
|
824
802
|
##
|
803
|
+
## @return [String, Array] array if multiple is true
|
825
804
|
def choose_from(options, prompt: 'Make a selection: ', multiple: false, sorted: true, fzf_args: [])
|
826
805
|
return nil unless $stdout.isatty
|
827
806
|
|
828
|
-
default_args = [%(--prompt="#{prompt}"), "--height=#{options.count + 2}", '--info=inline']
|
829
|
-
default_args << '--multi' if multiple
|
830
|
-
default_args << '--bind ctrl-a:select-all'
|
831
|
-
header = "esc: cancel,#{multiple ? ' tab: multi-select, ctrl-a: select all,' : ''} return: confirm"
|
832
|
-
default_args << %(--header="#{header}")
|
833
|
-
default_args.concat(fzf_args)
|
834
807
|
options.sort! if sorted
|
835
808
|
|
836
|
-
res =
|
809
|
+
res = if TTY::Which.exist?('fzf')
|
810
|
+
default_args = [%(--prompt="#{prompt}"), "--height=#{options.count + 2}", '--info=inline']
|
811
|
+
default_args << '--multi' if multiple
|
812
|
+
default_args << '--bind ctrl-a:select-all' if multiple
|
813
|
+
header = "esc: cancel,#{multiple ? ' tab: multi-select, ctrl-a: select all,' : ''} return: confirm"
|
814
|
+
default_args << %(--header="#{header}")
|
815
|
+
default_args.concat(fzf_args)
|
816
|
+
`echo #{Shellwords.escape(options.join("\n"))}|#{TTY::Which.which('fzf')} #{default_args.join(' ')}`.strip
|
817
|
+
elsif TTY::Which.exist?('gum')
|
818
|
+
args = [
|
819
|
+
'--cursor.foreground="151"',
|
820
|
+
'--item.foreground=""'
|
821
|
+
]
|
822
|
+
args.push '--no-limit' if multiple
|
823
|
+
puts NS::Color.template("{bw}#{prompt}{x}")
|
824
|
+
`echo #{Shellwords.escape(options.join("\n"))}|#{TTY::Which.which('gum')} choose #{args.join(' ')}`.strip
|
825
|
+
else
|
826
|
+
reader = TTY::Reader.new
|
827
|
+
puts
|
828
|
+
options.each.with_index do |f, i|
|
829
|
+
puts NA::Color.template(format("{bw}%<idx> 2d{xw}) {y}%<action>s{x}\n", idx: i + 1, action: f))
|
830
|
+
end
|
831
|
+
result = reader.read_line(NA::Color.template("{bw}#{prompt}{x}")).strip
|
832
|
+
result.to_i&.positive? ? options[result.to_i - 1] : nil
|
833
|
+
end
|
834
|
+
|
837
835
|
return false if res.strip.size.zero?
|
838
836
|
|
839
|
-
res
|
837
|
+
multiple ? res.split(/\n/) : res
|
840
838
|
end
|
841
839
|
|
842
840
|
def parse_search(tag, negate)
|
data/lib/na/project.rb
CHANGED
@@ -2,24 +2,26 @@
|
|
2
2
|
|
3
3
|
module NA
|
4
4
|
class Project < Hash
|
5
|
-
attr_accessor :project, :indent, :line
|
5
|
+
attr_accessor :project, :indent, :line, :last_line
|
6
6
|
|
7
|
-
def initialize(project, indent = 0, line = 0)
|
7
|
+
def initialize(project, indent = 0, line = 0, last_line = 0)
|
8
8
|
super()
|
9
9
|
@project = project
|
10
10
|
@indent = indent
|
11
11
|
@line = line
|
12
|
+
@last_line = last_line
|
12
13
|
end
|
13
14
|
|
14
15
|
def to_s
|
15
|
-
{ project: @project, indent: @indent, line: @line }.to_s
|
16
|
+
{ project: @project, indent: @indent, line: @line, last_line: @last_line }.to_s
|
16
17
|
end
|
17
18
|
|
18
19
|
def inspect
|
19
20
|
[
|
20
21
|
"@project: #{@project}",
|
21
22
|
"@indent: #{@indent}",
|
22
|
-
"@line: #{@line}"
|
23
|
+
"@line: #{@line}",
|
24
|
+
"@last_line: #{@last_line}"
|
23
25
|
].join(" ")
|
24
26
|
end
|
25
27
|
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.2.
|
12
|
+
The current version of `na` is <!--VER-->1.2.7<!--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
|
|
@@ -30,9 +30,13 @@ If you don't have Ruby/RubyGems, you can install them pretty easily with Homebre
|
|
30
30
|
|
31
31
|
<!--JEKYLL> You can find the na source code (MIT license) on [GitHub][].-->
|
32
32
|
|
33
|
+
### Optional Dependencies
|
34
|
+
|
35
|
+
If you have [gum][] installed, na will use it for command line input when adding tasks and notes. If you have [fzf][] installed, it will be used for menus, falling back to gum if available.
|
36
|
+
|
33
37
|
### Features
|
34
38
|
|
35
|
-
You can list next actions in files in the current directory by typing `na`. By default, `na` looks for `*.taskpaper` files and extracts items tagged `@na` and not `@done`.
|
39
|
+
You can list next actions in files in the current directory by typing `na`. By default, `na` looks for `*.taskpaper` files and extracts items tagged `@na` and not `@done`. This can be modified to work with a single global file, and all of these options can be changed in the configuration.
|
36
40
|
|
37
41
|
#### Easy matching
|
38
42
|
|
@@ -209,6 +213,9 @@ See the help output for a list of all available actions.
|
|
209
213
|
|
210
214
|
Global options such as todo extension and default next action tag can be stored permanently by using the `na initconfig` command. Run na with the global options you'd like to set, and add `initconfig` at the end of the command. A file will be written to `~/.na.rc`. You can edit this manually, or just update it using the `initconfig --force` command to overwrite it with new settings.
|
211
215
|
|
216
|
+
> You can see all available global options by running `na help`.
|
217
|
+
<!--JEKYLL{:.tip}-->
|
218
|
+
|
212
219
|
Example: `na --ext md --na_tag next initconfig --force`
|
213
220
|
|
214
221
|
When this command is run, it doesn't include options for subcommands, but inserts placeholders for them. If you want to permanently set an option for a subcommand, you'll need to edit `~/.na.rc`. For example, if you wanted the `next` command to always recurse 2 levels deep, you could edit it to look like this:
|
@@ -239,12 +246,14 @@ When using a global file, you can additionally include `--cwd_as TYPE` to determ
|
|
239
246
|
|
240
247
|
#### Add tasks at the end of a project
|
241
248
|
|
242
|
-
By default, tasks are added at the top of the target project (Inbox, etc.). If you prefer new tasks to go at the
|
249
|
+
By default, tasks are added at the top of the target project (Inbox, etc.). If you prefer new tasks to go at the end of the project by default, include `--add_at end` as a global option when running `initconfig`.
|
243
250
|
|
244
251
|
### Prompt Hooks
|
245
252
|
|
246
253
|
You can add a prompt command to your shell to have na automatically list your next actions when you `cd` into a directory. To install a prompt command for your current shell, just run `na prompt install`. It works with Zsh, Bash, and Fish. If you'd rather make the changes to your startup file yourself, run `na prompt show` to get the hook and instructions printed out for copying.
|
247
254
|
|
255
|
+
If you're using a single global file, you'll need `--cwd_as` to be `tag` or `project` for a prompt command to work. na will detect which system you're using and provide a prompt command that lists actions based on the current directory using either project or tag.
|
256
|
+
|
248
257
|
> You can also get output for shells other than the one you're currently using by adding "bash", "zsh", or "fish" to the show or install command.
|
249
258
|
<!--JEKYLL{:.tip}-->
|
250
259
|
|
@@ -253,9 +262,6 @@ You can add a prompt command to your shell to have na automatically list your ne
|
|
253
262
|
|
254
263
|
After installing a hook, you'll need to close your terminal and start a new session to initialize the new commands.
|
255
264
|
|
256
|
-
### Misc
|
257
|
-
|
258
|
-
If you have [gum][] installed, na will use it for command line input when adding tasks and notes. If you have [fzf][] installed, it will be used for menus, falling back to gum if available.
|
259
265
|
|
260
266
|
[fzf]: https://github.com/junegunn/fzf
|
261
267
|
[gum]: https://github.com/charmbracelet/gum
|
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.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brett Terpstra
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-10-
|
11
|
+
date: 2022-10-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|