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