na 1.2.37 → 1.2.38
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +22 -0
- data/Gemfile.lock +1 -1
- data/README.md +79 -6
- data/bin/commands/add.rb +11 -13
- data/bin/commands/edit.rb +15 -19
- data/bin/commands/find.rb +11 -6
- data/bin/commands/init.rb +1 -1
- data/bin/commands/next.rb +56 -27
- data/bin/commands/projects.rb +1 -1
- data/bin/commands/saved.rb +3 -4
- data/bin/commands/tagged.rb +7 -7
- data/bin/commands/todos.rb +24 -14
- data/bin/commands/update.rb +24 -27
- data/bin/na +2 -1
- data/lib/na/action.rb +16 -25
- data/lib/na/actions.rb +8 -8
- data/lib/na/colors.rb +23 -1
- data/lib/na/editor.rb +13 -11
- data/lib/na/hash.rb +31 -0
- data/lib/na/next_action.rb +45 -38
- data/lib/na/pager.rb +1 -1
- data/lib/na/prompt.rb +6 -6
- data/lib/na/string.rb +23 -3
- data/lib/na/theme.rb +71 -0
- data/lib/na/todo.rb +2 -2
- data/lib/na/version.rb +1 -1
- data/lib/na.rb +1 -0
- data/src/_README.md +35 -15
- metadata +3 -2
data/lib/na/next_action.rb
CHANGED
@@ -7,6 +7,10 @@ module NA
|
|
7
7
|
|
8
8
|
attr_accessor :verbose, :extension, :na_tag, :command_line, :command, :globals, :global_file, :cwd_is, :cwd, :stdin
|
9
9
|
|
10
|
+
def theme
|
11
|
+
@theme ||= NA::Theme.load_theme
|
12
|
+
end
|
13
|
+
|
10
14
|
##
|
11
15
|
## Output to STDERR
|
12
16
|
##
|
@@ -19,7 +23,7 @@ module NA
|
|
19
23
|
return if debug && !NA.verbose
|
20
24
|
|
21
25
|
if debug
|
22
|
-
$stderr.puts NA::Color.template("{
|
26
|
+
$stderr.puts NA::Color.template("{x}#{NA.theme[:debug]}#{msg}{x}")
|
23
27
|
else
|
24
28
|
$stderr.puts NA::Color.template("{x}#{msg}{x}")
|
25
29
|
end
|
@@ -100,7 +104,7 @@ module NA
|
|
100
104
|
f.puts(content)
|
101
105
|
end
|
102
106
|
save_working_dir(target)
|
103
|
-
notify("{
|
107
|
+
notify("#{NA.theme[:warning]}Created #{NA.theme[:file]}#{target}")
|
104
108
|
end
|
105
109
|
|
106
110
|
##
|
@@ -116,7 +120,7 @@ module NA
|
|
116
120
|
def select_file(files, multiple: false)
|
117
121
|
res = choose_from(files, prompt: multiple ? 'Select files' : 'Select a file', multiple: multiple)
|
118
122
|
|
119
|
-
notify(
|
123
|
+
notify("#{NA.theme[:error]}No file selected, cancelled", exit_code: 1) unless res && res.length.positive?
|
120
124
|
|
121
125
|
res
|
122
126
|
end
|
@@ -143,7 +147,7 @@ module NA
|
|
143
147
|
done: done })
|
144
148
|
|
145
149
|
unless todo.actions.count.positive?
|
146
|
-
NA.notify("{
|
150
|
+
NA.notify("#{NA.theme[:error]}No matching actions found in #{File.basename(target, ".#{NA.extension}").highlight_filename}")
|
147
151
|
return
|
148
152
|
end
|
149
153
|
|
@@ -152,7 +156,7 @@ module NA
|
|
152
156
|
options = todo.actions.map { |action| "#{action.line} % #{action.parent.join('/')} : #{action.action}" }
|
153
157
|
res = choose_from(options, prompt: 'Make a selection: ', multiple: true, sorted: true)
|
154
158
|
|
155
|
-
NA.notify(
|
159
|
+
NA.notify("#{NA.theme[:error]}Cancelled", exit_code: 1) unless res && res.length.positive?
|
156
160
|
|
157
161
|
selected = NA::Actions.new
|
158
162
|
res.each do |result|
|
@@ -247,11 +251,11 @@ module NA
|
|
247
251
|
project = project.sub(/:$/, '')
|
248
252
|
target_proj = projects.select { |pr| pr.project =~ /#{project.gsub(/:/, '.*?:.*?')}/i }.first
|
249
253
|
if target_proj.nil?
|
250
|
-
res = NA.yn(NA::Color.template("{
|
254
|
+
res = NA.yn(NA::Color.template("#{NA.theme[:warning]}Project #{NA.theme[:file]}#{project}#{NA.theme[:warning]} doesn't exist, add it"), default: true)
|
251
255
|
if res
|
252
256
|
target_proj = insert_project(target, project, projects)
|
253
257
|
else
|
254
|
-
NA.notify(
|
258
|
+
NA.notify("#{NA.theme[:error]}Cancelled", exit_code: 1)
|
255
259
|
end
|
256
260
|
end
|
257
261
|
end
|
@@ -270,7 +274,7 @@ module NA
|
|
270
274
|
projects.select { |proj| proj.project =~ /^#{add.parent.join(':')}$/ }.first
|
271
275
|
end
|
272
276
|
|
273
|
-
NA.notify("{
|
277
|
+
NA.notify("#{NA.theme[:error]}Error parsing project #{NA.theme[:filename]}#{target}", exit_code: 1) if target_proj.nil?
|
274
278
|
|
275
279
|
indent = "\t" * target_proj.indent
|
276
280
|
note = note.split("\n") unless note.is_a?(Array)
|
@@ -364,7 +368,11 @@ module NA
|
|
364
368
|
backup_file(target)
|
365
369
|
File.open(target, 'w') { |f| f.puts contents.join("\n") }
|
366
370
|
|
367
|
-
add
|
371
|
+
if add
|
372
|
+
notify("#{NA.theme[:success]}Task added to #{NA.theme[:filename]}#{target}")
|
373
|
+
else
|
374
|
+
notify("#{NA.theme[:success]}Task updated in #{NA.theme[:filename]}#{target}")
|
375
|
+
end
|
368
376
|
end
|
369
377
|
|
370
378
|
##
|
@@ -385,7 +393,6 @@ module NA
|
|
385
393
|
else
|
386
394
|
project = NA.cwd
|
387
395
|
end
|
388
|
-
puts [add_tag, project]
|
389
396
|
end
|
390
397
|
|
391
398
|
action = Action.new(file, project, parent, action, nil, note)
|
@@ -519,12 +526,12 @@ module NA
|
|
519
526
|
##
|
520
527
|
def match_working_dir(search, distance: 1, require_last: true)
|
521
528
|
file = database_path
|
522
|
-
NA.notify(
|
529
|
+
NA.notify("#{NA.theme[:error]}No na database found", exit_code: 1) unless File.exist?(file)
|
523
530
|
|
524
531
|
dirs = file.read_file.split("\n")
|
525
532
|
|
526
533
|
optional = search.filter { |s| !s[:negate] }.map { |t| t[:token] }
|
527
|
-
required = search.filter { |s| s[:required] }.map { |t| t[:token] }
|
534
|
+
required = search.filter { |s| s[:required] && !s[:negate] }.map { |t| t[:token] }
|
528
535
|
negated = search.filter { |s| s[:negate] }.map { |t| t[:token] }
|
529
536
|
|
530
537
|
optional.push('*') if optional.count.zero? && required.count.zero? && negated.count.positive?
|
@@ -533,9 +540,9 @@ module NA
|
|
533
540
|
optional = ['*']
|
534
541
|
end
|
535
542
|
|
536
|
-
NA.notify("
|
537
|
-
NA.notify("
|
538
|
-
NA.notify("
|
543
|
+
NA.notify("Optional directory regex: {x}#{optional.map { |t| t.dir_to_rx(distance: distance) }}", debug: true)
|
544
|
+
NA.notify("Required directory regex: {x}#{required.map { |t| t.dir_to_rx(distance: distance) }}", debug: true)
|
545
|
+
NA.notify("Negated directory regex: {x}#{negated.map { |t| t.dir_to_rx(distance: distance, require_last: false) }}", debug: true)
|
539
546
|
|
540
547
|
if require_last
|
541
548
|
dirs.delete_if { |d| !d.sub(/\.#{NA.extension}$/, '').dir_matches(any: optional, all: required, none: negated) }
|
@@ -546,9 +553,9 @@ module NA
|
|
546
553
|
end
|
547
554
|
end
|
548
555
|
|
549
|
-
dirs = dirs.
|
556
|
+
dirs = dirs.sort_by { |d| File.basename(d) }.uniq
|
550
557
|
if dirs.empty? && require_last
|
551
|
-
NA.notify(
|
558
|
+
NA.notify("#{NA.theme[:warning]}No matches, loosening search", debug: true)
|
552
559
|
match_working_dir(search, distance: 2, require_last: false)
|
553
560
|
else
|
554
561
|
dirs
|
@@ -605,7 +612,7 @@ module NA
|
|
605
612
|
if file
|
606
613
|
restore_modified_file(file)
|
607
614
|
else
|
608
|
-
NA.notify(
|
615
|
+
NA.notify("#{NA.theme[:error]}No matching file found")
|
609
616
|
end
|
610
617
|
end
|
611
618
|
|
@@ -618,9 +625,9 @@ module NA
|
|
618
625
|
bak_file = File.join(File.dirname(file), ".#{File.basename(file)}.bak")
|
619
626
|
if File.exist?(bak_file)
|
620
627
|
FileUtils.mv(bak_file, file)
|
621
|
-
NA.notify("{
|
628
|
+
NA.notify("#{NA.theme[:success]}Backup restored for #{file.highlight_filename}")
|
622
629
|
else
|
623
|
-
NA.notify("{
|
630
|
+
NA.notify("#{NA.theme[:error]}Backup file for #{file.highlight_filename} not found")
|
624
631
|
end
|
625
632
|
end
|
626
633
|
|
@@ -698,13 +705,13 @@ module NA
|
|
698
705
|
else
|
699
706
|
file = database_path
|
700
707
|
content = File.exist?(file) ? file.read_file.strip : ''
|
701
|
-
notify(
|
708
|
+
notify("#{NA.theme[:error]}Database empty", exit_code: 1) if content.empty?
|
702
709
|
|
703
710
|
content.split(/\n/)
|
704
711
|
end
|
705
712
|
|
706
713
|
dirs.map! do |dir|
|
707
|
-
|
714
|
+
dir.highlight_filename
|
708
715
|
end
|
709
716
|
|
710
717
|
puts NA::Color.template(dirs.join("\n"))
|
@@ -717,13 +724,13 @@ module NA
|
|
717
724
|
|
718
725
|
if searches.key?(title)
|
719
726
|
res = yn('Overwrite existing definition?', default: true)
|
720
|
-
notify(
|
727
|
+
notify("#{NA.theme[:error]}Cancelled", exit_code: 0) unless res
|
721
728
|
|
722
729
|
end
|
723
730
|
|
724
731
|
searches[title] = search
|
725
732
|
File.open(file, 'w') { |f| f.puts(YAML.dump(searches)) }
|
726
|
-
NA.notify("{
|
733
|
+
NA.notify("#{NA.theme[:success]}Search #{NA.theme[:filename]}#{title}#{NA.theme[:success]} saved", exit_code: 0)
|
727
734
|
end
|
728
735
|
|
729
736
|
def load_searches
|
@@ -743,37 +750,37 @@ module NA
|
|
743
750
|
end
|
744
751
|
|
745
752
|
def delete_search(strings = nil)
|
746
|
-
NA.notify(
|
753
|
+
NA.notify("#{NA.theme[:error]}Name of search required", exit_code: 1) if strings.nil? || strings.empty?
|
747
754
|
|
748
755
|
file = database_path(file: 'saved_searches.yml')
|
749
|
-
NA.notify(
|
756
|
+
NA.notify("#{NA.theme[:error]}No search definitions file found", exit_code: 1) unless File.exist?(file)
|
750
757
|
|
751
758
|
searches = YAML.safe_load(file.read_file)
|
752
759
|
keys = searches.keys.delete_if { |k| k !~ /(#{strings.join('|')})/ }
|
753
760
|
|
754
|
-
res = yn(NA::Color.template(%({
|
761
|
+
res = yn(NA::Color.template(%(#{NA.theme[:warning]}Remove #{keys.count > 1 ? 'searches' : 'search'} #{NA.theme[:file]}"#{keys.join(', ')}"{x})),
|
755
762
|
default: false)
|
756
763
|
|
757
|
-
NA.notify(
|
764
|
+
NA.notify("#{NA.theme[:error]}Cancelled", exit_code: 1) unless res
|
758
765
|
|
759
766
|
searches.delete_if { |k| keys.include?(k) }
|
760
767
|
|
761
768
|
File.open(file, 'w') { |f| f.puts(YAML.dump(searches)) }
|
762
769
|
|
763
|
-
NA.notify("{
|
770
|
+
NA.notify("#{NA.theme[:warning]}Deleted {bw}#{keys.count}{x}#{NA.theme[:warning]} #{keys.count > 1 ? 'searches' : 'search'}", exit_code: 0)
|
764
771
|
end
|
765
772
|
|
766
773
|
def edit_searches
|
767
774
|
file = database_path(file: 'saved_searches.yml')
|
768
775
|
searches = load_searches
|
769
776
|
|
770
|
-
NA.notify(
|
777
|
+
NA.notify("#{NA.theme[:error]}No search definitions found", exit_code: 1) unless searches.count.positive?
|
771
778
|
|
772
|
-
editor =
|
773
|
-
NA.notify(
|
779
|
+
editor = NA.default_editor
|
780
|
+
NA.notify("#{NA.theme[:error]}No $EDITOR defined", exit_code: 1) unless editor && TTY::Which.exist?(editor)
|
774
781
|
|
775
782
|
system %(#{editor} "#{file}")
|
776
|
-
NA.notify("Opened #{file} in #{editor}", exit_code: 0)
|
783
|
+
NA.notify("#{NA.theme[:success]}Opened #{file} in #{editor}", exit_code: 0)
|
777
784
|
end
|
778
785
|
|
779
786
|
##
|
@@ -786,7 +793,7 @@ module NA
|
|
786
793
|
backup = File.join(File.dirname(target), file)
|
787
794
|
FileUtils.cp(target, backup)
|
788
795
|
save_modified_file(target)
|
789
|
-
NA.notify("{
|
796
|
+
NA.notify("#{NA.theme[:warning]}Backup file created at #{backup.highlight_filename}", debug: true)
|
790
797
|
end
|
791
798
|
|
792
799
|
private
|
@@ -822,15 +829,15 @@ module NA
|
|
822
829
|
'--item.foreground=""'
|
823
830
|
]
|
824
831
|
args.push '--no-limit' if multiple
|
825
|
-
puts NS::Color.template("{
|
832
|
+
puts NS::Color.template("#{NA.theme[:prompt]}#{prompt}{x}")
|
826
833
|
`echo #{Shellwords.escape(options.join("\n"))}|#{TTY::Which.which('gum')} choose #{args.join(' ')}`.strip
|
827
834
|
else
|
828
835
|
reader = TTY::Reader.new
|
829
836
|
puts
|
830
837
|
options.each.with_index do |f, i|
|
831
|
-
puts NA::Color.template(format("{
|
838
|
+
puts NA::Color.template(format("#{NA.theme[:prompt]}%<idx> 2d{xw}) #{NA.theme[:file]}%<action>s{x}\n", idx: i + 1, action: f))
|
832
839
|
end
|
833
|
-
result = reader.read_line(NA::Color.template("{
|
840
|
+
result = reader.read_line(NA::Color.template("#{NA.theme[:prompt]}#{prompt}{x}")).strip
|
834
841
|
result.to_i&.positive? ? options[result.to_i - 1] : nil
|
835
842
|
end
|
836
843
|
|
@@ -871,7 +878,7 @@ module NA
|
|
871
878
|
if TTY::Which.exist?('xdg-open')
|
872
879
|
`xdg-open #{Shellwords.escape(file)}`
|
873
880
|
else
|
874
|
-
notify(
|
881
|
+
notify("#{NA.theme[:error]}Unable to determine executable for `xdg-open`.")
|
875
882
|
end
|
876
883
|
end
|
877
884
|
end
|
data/lib/na/pager.rb
CHANGED
data/lib/na/prompt.rb
CHANGED
@@ -14,7 +14,7 @@ module NA
|
|
14
14
|
when :tag
|
15
15
|
'na tagged $(basename "$PWD")'
|
16
16
|
else
|
17
|
-
NA.notify(
|
17
|
+
NA.notify("#{NA.theme[:error]}When using a global file, a prompt hook requires `--cwd_as [tag|project]`", exit_code: 1)
|
18
18
|
end
|
19
19
|
else
|
20
20
|
'na next'
|
@@ -31,7 +31,7 @@ module NA
|
|
31
31
|
when :tag
|
32
32
|
'na tagged (basename "$PWD")'
|
33
33
|
else
|
34
|
-
NA.notify(
|
34
|
+
NA.notify("#{NA.theme[:error]}When using a global file, a prompt hook requires `--cwd_as [tag|project]`", exit_code: 1)
|
35
35
|
end
|
36
36
|
else
|
37
37
|
'na next'
|
@@ -50,7 +50,7 @@ module NA
|
|
50
50
|
when :tag
|
51
51
|
'na tagged $(basename "$PWD")'
|
52
52
|
else
|
53
|
-
NA.notify(
|
53
|
+
NA.notify("#{NA.theme[:error]}When using a global file, a prompt hook requires `--cwd_as [tag|project]`", exit_code: 1)
|
54
54
|
end
|
55
55
|
else
|
56
56
|
'na next'
|
@@ -83,7 +83,7 @@ module NA
|
|
83
83
|
def show_prompt_hook(shell)
|
84
84
|
file = prompt_file(shell)
|
85
85
|
|
86
|
-
NA.notify("{
|
86
|
+
NA.notify("#{NA.theme[:warning]}# Add this to #{NA.theme[:filename]}#{file}")
|
87
87
|
puts prompt_hook(shell)
|
88
88
|
end
|
89
89
|
|
@@ -91,8 +91,8 @@ module NA
|
|
91
91
|
file = prompt_file(shell)
|
92
92
|
|
93
93
|
File.open(File.expand_path(file), 'a') { |f| f.puts prompt_hook(shell) }
|
94
|
-
NA.notify("{
|
95
|
-
NA.notify("{
|
94
|
+
NA.notify("#{NA.theme[:success]}Added #{NA.theme[:filename]}#{shell}{x}#{NA.theme[:success]} prompt hook to #{NA.theme[:filename]}#{file}#{NA.theme[:success]}.")
|
95
|
+
NA.notify("#{NA.theme[:warning]}You may need to close the current terminal and open a new one to enable the script.")
|
96
96
|
end
|
97
97
|
end
|
98
98
|
end
|
data/lib/na/string.rb
CHANGED
@@ -6,6 +6,15 @@ REGEX_TIME = /^#{REGEX_CLOCK}$/i.freeze
|
|
6
6
|
|
7
7
|
# String helpers
|
8
8
|
class ::String
|
9
|
+
##
|
10
|
+
## Insert a comment character at the start of every line
|
11
|
+
##
|
12
|
+
## @param char [String] The character to insert (default #)
|
13
|
+
##
|
14
|
+
def comment(char = "#")
|
15
|
+
split(/\n/).map { |l| "# #{l}" }.join("\n")
|
16
|
+
end
|
17
|
+
|
9
18
|
##
|
10
19
|
## Tests if object is nil or empty
|
11
20
|
##
|
@@ -75,6 +84,17 @@ class ::String
|
|
75
84
|
self =~ /@#{NA.na_tag}\b/
|
76
85
|
end
|
77
86
|
|
87
|
+
##
|
88
|
+
## Colorize the dirname and filename of a path
|
89
|
+
##
|
90
|
+
## @return Colorized string
|
91
|
+
##
|
92
|
+
def highlight_filename
|
93
|
+
dir = File.dirname(self).shorten_path
|
94
|
+
file = File.basename(self, ".#{NA.extension}")
|
95
|
+
"#{NA.theme[:dirname]}#{dir}/#{NA.theme[:filename]}#{file}{x}"
|
96
|
+
end
|
97
|
+
|
78
98
|
##
|
79
99
|
## Colorize @tags with ANSI escapes
|
80
100
|
##
|
@@ -88,7 +108,7 @@ class ::String
|
|
88
108
|
##
|
89
109
|
## @return [String] string with @tags highlighted
|
90
110
|
##
|
91
|
-
def highlight_tags(color:
|
111
|
+
def highlight_tags(color: NA.theme[:tags], value: NA.theme[:value], parens: NA.theme[:value_parens], last_color: NA.theme[:action])
|
92
112
|
tag_color = NA::Color.template(color)
|
93
113
|
paren_color = NA::Color.template(parens)
|
94
114
|
value_color = NA::Color.template(value)
|
@@ -106,9 +126,9 @@ class ::String
|
|
106
126
|
## @param last_color [String] Color to restore after
|
107
127
|
## highlight
|
108
128
|
##
|
109
|
-
def highlight_search(regexes, color:
|
129
|
+
def highlight_search(regexes, color: NA.theme[:search_highlight], last_color: NA.theme[:action])
|
110
130
|
string = dup
|
111
|
-
color = NA::Color.template(color)
|
131
|
+
color = NA::Color.template(color.dup)
|
112
132
|
regexes.each do |rx|
|
113
133
|
next if rx.nil?
|
114
134
|
|
data/lib/na/theme.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module NA
|
4
|
+
module Theme
|
5
|
+
class << self
|
6
|
+
def template_help
|
7
|
+
<<~EOHELP
|
8
|
+
Use {X} placeholders to apply colors. Available colors are:
|
9
|
+
|
10
|
+
w: white, k: black, g: green, l: blue,
|
11
|
+
y: yellow, c: cyan, m: magenta, r: red,
|
12
|
+
W: bgwhite, K: bgblack, G: bggreen, L: bgblue,
|
13
|
+
Y: bgyellow, C: bgcyan, M: bgmagenta, R: bgred,
|
14
|
+
d: dark, b: bold, u: underline, i: italic, x: reset
|
15
|
+
|
16
|
+
Multiple placeholders can be combined in a single {} pair.
|
17
|
+
|
18
|
+
You can also use {#RGB} and {#RRGGBB} to specify hex colors.
|
19
|
+
Add a b before the # to make the hex a background color ({b#fa0}).
|
20
|
+
|
21
|
+
|
22
|
+
EOHELP
|
23
|
+
end
|
24
|
+
|
25
|
+
def load_theme(template: {})
|
26
|
+
# Default colorization, can be overridden with full or partial template variable
|
27
|
+
default_template = {
|
28
|
+
parent: '{c}',
|
29
|
+
bracket: '{dc}',
|
30
|
+
parent_divider: '{xw}/',
|
31
|
+
action: '{bg}',
|
32
|
+
project: '{xbk}',
|
33
|
+
tags: '{m}',
|
34
|
+
value_parens: '{m}',
|
35
|
+
values: '{c}',
|
36
|
+
search_highlight: '{y}',
|
37
|
+
note: '{dw}',
|
38
|
+
dirname: '{dw}',
|
39
|
+
filename: '{xb}{#eccc87}',
|
40
|
+
prompt: '{m}',
|
41
|
+
success: '{bg}',
|
42
|
+
error: '{b}{#b61d2a}',
|
43
|
+
warning: '{by}',
|
44
|
+
debug: '{dw}',
|
45
|
+
templates: {
|
46
|
+
output: '%filename%parents| %action',
|
47
|
+
default: '%parent%action',
|
48
|
+
single_file: '%parent%action',
|
49
|
+
multi_file: '%filename%parent%action'
|
50
|
+
}
|
51
|
+
}
|
52
|
+
|
53
|
+
# Load custom theme
|
54
|
+
theme_file = NA.database_path(file: 'theme.yaml')
|
55
|
+
theme = if File.exist?(theme_file)
|
56
|
+
YAML.load(IO.read(theme_file)) || {}
|
57
|
+
else
|
58
|
+
{}
|
59
|
+
end
|
60
|
+
theme = default_template.merge(theme)
|
61
|
+
|
62
|
+
File.open(theme_file, 'w') do |f|
|
63
|
+
f.puts template_help.comment
|
64
|
+
f.puts YAML.dump(theme)
|
65
|
+
end
|
66
|
+
|
67
|
+
theme.merge(template)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/lib/na/todo.rb
CHANGED
@@ -51,8 +51,8 @@ module NA
|
|
51
51
|
negated_tag = []
|
52
52
|
projects = []
|
53
53
|
|
54
|
-
NA.notify("
|
55
|
-
NA.notify("
|
54
|
+
NA.notify("Tags: #{settings[:tag]}", debug:true)
|
55
|
+
NA.notify("Search: #{settings[:search]}", debug:true)
|
56
56
|
|
57
57
|
settings[:tag]&.each do |t|
|
58
58
|
unless t[:tag].nil?
|
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.37<!--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(na help)
|
72
|
+
@cli(bundle exec bin/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(na help add)
|
90
|
+
@cli(bundle exec bin/na help add)
|
91
91
|
```
|
92
92
|
|
93
93
|
##### edit
|
94
94
|
|
95
95
|
```
|
96
|
-
@cli(na help edit)
|
96
|
+
@cli(bundle exec bin/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(na help find)
|
106
|
+
@cli(bundle exec bin/na help find)
|
107
107
|
```
|
108
108
|
|
109
109
|
##### init, create
|
110
110
|
|
111
111
|
```
|
112
|
-
@cli(na help init)
|
112
|
+
@cli(bundle exec bin/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(na help next)
|
126
|
+
@cli(bundle exec bin/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(na help projects)
|
134
|
+
@cli(bundle exec bin/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(na help saved)
|
149
|
+
@cli(bundle exec bin/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(na help show)
|
163
|
+
@cli(bundle exec bin/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(na help todos)
|
171
|
+
@cli(bundle exec bin/na help todos)
|
172
172
|
```
|
173
173
|
|
174
174
|
##### update
|
@@ -206,7 +206,7 @@ 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(na help update)
|
209
|
+
@cli(bundle exec bin/na help update)
|
210
210
|
```
|
211
211
|
|
212
212
|
##### changelog
|
@@ -214,7 +214,7 @@ See the help output for a list of all available actions.
|
|
214
214
|
View recent changes with `na changelog` or `na changes`.
|
215
215
|
|
216
216
|
```
|
217
|
-
@cli(na help changelog)
|
217
|
+
@cli(bundle exec bin/na help changelog)
|
218
218
|
```
|
219
219
|
|
220
220
|
##### complete
|
@@ -222,7 +222,7 @@ View recent changes with `na changelog` or `na changes`.
|
|
222
222
|
Mark an action as complete, shortcut for `na update --finish`.
|
223
223
|
|
224
224
|
```
|
225
|
-
@cli(na help complete)
|
225
|
+
@cli(bundle exec bin/na help complete)
|
226
226
|
```
|
227
227
|
|
228
228
|
##### archive
|
@@ -230,7 +230,27 @@ Mark an action as complete, shortcut for `na update --finish`.
|
|
230
230
|
Mark an action as complete and move to archive, shortcut for `na update --archive`.
|
231
231
|
|
232
232
|
```
|
233
|
-
@cli(na help archive)
|
233
|
+
@cli(bundle exec bin/na help archive)
|
234
|
+
```
|
235
|
+
|
236
|
+
##### tag
|
237
|
+
|
238
|
+
Add, remove, or modify tags.
|
239
|
+
|
240
|
+
Use `na tag TAGNAME --[search|tagged] SEARCH_STRING` to add a tag to matching action (use `--all` to apply to all matching actions). If you use `!TAGNAME` it will remove that tag (regardless of value). To change the value of an existing tag (or add it if it doesn't exist), use `~TAGNAME(NEW VALUE)`.
|
241
|
+
|
242
|
+
```
|
243
|
+
@cli(bundle exec bin/na help tag)
|
244
|
+
```
|
245
|
+
|
246
|
+
##### undo
|
247
|
+
|
248
|
+
Undoes the last file change resulting from an add or update command. If no argument is given, it undoes whatever the last change in history was. If an argument is provided, it's used to match against the change history, finding a specific file to restore from backup.
|
249
|
+
|
250
|
+
Only the most recent change can be undone.
|
251
|
+
|
252
|
+
```
|
253
|
+
@cli(bundle exec bin/na help undo)
|
234
254
|
```
|
235
255
|
|
236
256
|
### 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.38
|
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-09-
|
11
|
+
date: 2023-09-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -238,6 +238,7 @@ files:
|
|
238
238
|
- lib/na/project.rb
|
239
239
|
- lib/na/prompt.rb
|
240
240
|
- lib/na/string.rb
|
241
|
+
- lib/na/theme.rb
|
241
242
|
- lib/na/todo.rb
|
242
243
|
- lib/na/version.rb
|
243
244
|
- na.gemspec
|