na 1.0.5 → 1.0.7

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 92a40acdde96bfe4a27a093edf4e0f909b23b1c300d6be4f742323ac4e9233be
4
- data.tar.gz: bfddb6edfe9cddf7a631819bd980708fd816d2853b3146f348c2095b1ca7aee2
3
+ metadata.gz: 9aab87ece3f35afbe5280d6c1b777c9d8dece4916f796eedb3dfebdbbeb5032e
4
+ data.tar.gz: 46b7eef3d84ede3a69f9497e4d0bb4fcc772fd159fbffe23f9749f3172bc2cdf
5
5
  SHA512:
6
- metadata.gz: 77fd24c44ea1b7dba5fb2feb8d36e625972b7662c3032d96ffb7af28843cc08ad16f911fb58778b7cfc831b329859effb04134168517eb596f1da4e9d62cc001
7
- data.tar.gz: 212c87e2f59706bd6ed9b5e4cec2ecbd629e9b344a7538f653d8b278dd0f9e62aeb2ceada2d2ed8ef12421fc8c54396ec6e2462b77fe28f90d90946a6aed3967
6
+ metadata.gz: 05bda9033431ce005ad32fb9cd1c711642504972ffa73131d1c989b90dd4b50089b53d9e6746df4555d87e9b65d8b3c2c3707023dd8a8287f8596f4583a727f5
7
+ data.tar.gz: d474663a84ca7ef0287f05c3c2ed6fa63b0fb3d6482337b33343bbfa71a7a7d1c4fe542f91d9c75797c48a4f073079b85a96ef6704d2056b193b7f891596cbf9
data/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ ### 1.0.7
2
+
3
+ 2022-09-28 04:38
4
+
5
+ ### 1.0.6
6
+
7
+ 2022-09-28 04:22
8
+
9
+ #### NEW
10
+
11
+ - `na prompt [show|install]` command to help with adding prompt hooks to your shell
12
+
1
13
  ### 1.0.5
2
14
 
3
15
  2022-09-28 01:53
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- na (1.0.4)
4
+ na (1.0.6)
5
5
  gli (~> 2.21.0)
6
6
  tty-reader (~> 0.9, >= 0.9.0)
7
7
  tty-screen (~> 0.8, >= 0.8.1)
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.0.4.
12
+ The current version of `na` is 1.0.6.
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
 
@@ -293,7 +293,6 @@ Fish (in ~/.config/fish/conf.d/*.fish):
293
293
 
294
294
  ```fish
295
295
  function __should_na --on-variable PWD
296
- # function __should_na --on-event fish_prompt
297
296
  test -s (basename $PWD)".taskpaper" && na
298
297
  end
299
298
  ```
data/bin/na CHANGED
@@ -48,7 +48,7 @@ class App
48
48
  flag %i[d depth], type: :integer, must_match: /^\d+$/
49
49
 
50
50
  desc 'Display verbose output'
51
- switch %i[verbose]
51
+ switch %i[debug]
52
52
 
53
53
  desc 'Show next actions'
54
54
  arg_name 'OPTIONAL_QUERY'
@@ -91,14 +91,12 @@ class App
91
91
  end
92
92
  end
93
93
 
94
- tag = options[:tag] == global_options[:na_tag] ? nil : options[:tag]
94
+ tag = options[:tag] == NA.na_tag ? nil : options[:tag]
95
95
  files, actions = NA.parse_actions(depth: depth,
96
96
  query: tokens,
97
- extension: global_options[:ext],
98
- na_tag: global_options[:na_tag],
99
97
  tag: tag)
100
98
 
101
- NA.output_actions(actions, depth, global_options[:ext], files: files)
99
+ NA.output_actions(actions, depth, files: files)
102
100
  end
103
101
  end
104
102
 
@@ -124,6 +122,9 @@ class App
124
122
  c.arg_name 'TAG'
125
123
  c.flag %i[t tag]
126
124
 
125
+ c.desc 'Don\'t add next action tag to new entry'
126
+ c.switch %i[x]
127
+
127
128
  c.desc 'Specify the file to which the task should be added'
128
129
  c.arg_name 'PATH'
129
130
  c.flag %i[f file]
@@ -148,10 +149,15 @@ class App
148
149
  action = "#{action.gsub(/@priority\(\d+\)/, '')} @priority(#{options[:priority]})"
149
150
  end
150
151
 
151
- na_tag = global_options[:na_tag]
152
- na_tag = options[:tag] unless options[:tag].nil?
152
+ na_tag = NA.na_tag
153
+ if options[:x]
154
+ na_tag = ''
155
+ else
156
+ na_tag = options[:tag] unless options[:tag].nil?
157
+ na_tag = " @#{na_tag}"
158
+ end
153
159
 
154
- action = "#{action.gsub(/@#{na_tag}/, '')} @#{na_tag}"
160
+ action = "#{action.gsub(/#{na_tag}/, '')}#{na_tag}"
155
161
 
156
162
  note = if options[:note]
157
163
  if TTY::Which.exist?('gum')
@@ -167,7 +173,7 @@ class App
167
173
  print NA::Color.template('{by}Specified file not found, create it? {w}(y/{g}N{w}){x} ')
168
174
  res = reader.read_char
169
175
  if res =~ /y/i
170
- basename = File.basename(target, ".#{global_options[:ext]}")
176
+ basename = File.basename(target, ".#{NA.extension}")
171
177
  NA.create_todo(target, basename)
172
178
  else
173
179
  puts NA::Color.template('{r}Cancelled{x}')
@@ -175,15 +181,15 @@ class App
175
181
  end
176
182
  end
177
183
  else
178
- files = NA.find_files(depth: 1, extension: global_options[:ext])
184
+ files = NA.find_files(depth: 1)
179
185
  if files.count == 0
180
186
  print NA::Color.template('{by}No todo file found, create one? {w}(y/{g}N{w}){x} ')
181
187
  res = reader.read_char
182
188
  if res =~ /y/i
183
189
  basename = File.expand_path('.').split('/').last
184
- target = "#{basename}.#{global_options[:ext]}"
190
+ target = "#{basename}.#{NA.extension}"
185
191
  NA.create_todo(target, basename)
186
- files = NA.find_files(depth: 1, extension: global_options[:ext])
192
+ files = NA.find_files(depth: 1)
187
193
  end
188
194
  end
189
195
  target = files.count > 1 ? NA.select_file(files) : files[0]
@@ -193,7 +199,6 @@ class App
193
199
  end
194
200
  end
195
201
 
196
- NA.save_working_dir(File.expand_path(target))
197
202
  NA.add_action(target, action, note)
198
203
  end
199
204
  end
@@ -236,10 +241,8 @@ class App
236
241
  end
237
242
 
238
243
  files, actions = NA.parse_actions(depth: depth,
239
- extension: global_options[:ext],
240
- na_tag: global_options[:na_tag],
241
244
  search: tokens)
242
- NA.output_actions(actions, depth, global_options[:ext], files: files)
245
+ NA.output_actions(actions, depth, files: files)
243
246
  end
244
247
  end
245
248
 
@@ -278,10 +281,8 @@ class App
278
281
  end
279
282
 
280
283
  files, actions = NA.parse_actions(depth: depth,
281
- extension: global_options[:ext],
282
- na_tag: global_options[:na_tag],
283
284
  tag: tags)
284
- NA.output_actions(actions, depth, global_options[:ext], files: files)
285
+ NA.output_actions(actions, depth, files: files)
285
286
  end
286
287
  end
287
288
 
@@ -300,7 +301,7 @@ class App
300
301
  project = reader.read_line(NA::Color.template('{y}Project name {bw}> {x}'), value: project).strip
301
302
  end
302
303
 
303
- target = "#{project}.#{global_options[:ext]}"
304
+ target = "#{project}.#{NA.extension}"
304
305
 
305
306
  if File.exist?(target)
306
307
  print NA::Color.template("{r}File {bw}#{target}{r} already exists, overwrite it? {br}y{w}/{bg}N{x} ")
@@ -339,7 +340,7 @@ class App
339
340
  else
340
341
  options[:depth].nil? ? global_options[:depth].to_i : options[:depth].to_i
341
342
  end
342
- files = NA.find_files(depth: depth, extension: global_options[:ext])
343
+ files = NA.find_files(depth: depth)
343
344
  file = if files.count > 1
344
345
  NA.select_file(files)
345
346
  else
@@ -354,8 +355,59 @@ class App
354
355
  end
355
356
  end
356
357
 
358
+ desc 'Show or install prompt hooks for the current shell'
359
+ long_desc 'Installing the prompt hook allows you to automatically
360
+ list next actions when you cd into a directory'
361
+ command %i[prompt] do |c|
362
+ c.desc 'Output the prompt hook for the current shell to STDOUT. Pass an argument to specify a shell (zsh, bash, fish)'
363
+ c.arg_name '[SHELL]'
364
+ c.command %i[show] do |s|
365
+ s.action do |global_options, options, args|
366
+ if args.count.positive?
367
+ shell = args[0]
368
+ else
369
+ shell = File.basename(ENV['SHELL'])
370
+ end
371
+
372
+ case shell
373
+ when /^f/i
374
+ NA::Prompt.show_prompt_hook(:fish)
375
+ when /^z/i
376
+ NA::Prompt.show_prompt_hook(:zsh)
377
+ when /^b/i
378
+ NA::Prompt.show_prompt_hook(:bash)
379
+ end
380
+ end
381
+ end
382
+
383
+ c.desc 'Install the hook for the current shell to the appropriate startup file.'
384
+ c.arg_name '[SHELL]'
385
+ c.command %i[install] do |s|
386
+ s.action do |global_options, options, args|
387
+ if args.count.positive?
388
+ shell = args[0]
389
+ else
390
+ shell = File.basename(ENV['SHELL'])
391
+ end
392
+
393
+ case shell
394
+ when /^f/i
395
+ NA::Prompt.install_prompt_hook(:fish)
396
+ when /^z/i
397
+ NA::Prompt.install_prompt_hook(:zsh)
398
+ when /^b/i
399
+ NA::Prompt.install_prompt_hook(:bash)
400
+ end
401
+ end
402
+ end
403
+ end
404
+
405
+
406
+
357
407
  pre do |global, command, options, args|
358
- NA.verbose = global[:verbose]
408
+ NA.verbose = global[:debug]
409
+ NA.extension = global[:ext]
410
+ NA.na_tag = global[:na_tag]
359
411
  true
360
412
  end
361
413
 
@@ -3,7 +3,7 @@
3
3
  # Next Action methods
4
4
  module NA
5
5
  class << self
6
- attr_accessor :verbose
6
+ attr_accessor :verbose, :extension, :na_tag
7
7
 
8
8
  def create_todo(target, basename)
9
9
  File.open(target, 'w') do |f|
@@ -22,11 +22,13 @@ module NA
22
22
  ENDCONTENT
23
23
  f.puts(content)
24
24
  end
25
- puts NA::Color.template("{y}Created {bw}#{target}{x}")
25
+ $stderr.puts NA::Color.template("{y}Created {bw}#{target}{x}")
26
26
  end
27
27
 
28
- def find_files(depth: 1, extension: 'taskpaper')
29
- `find . -name "*.#{extension}" -maxdepth #{depth}`.strip.split("\n")
28
+ def find_files(depth: 1)
29
+ files = `find . -name "*.#{NA.extension}" -maxdepth #{depth}`.strip.split("\n")
30
+ files.each { |f| save_working_dir(File.expand_path(f)) }
31
+ files
30
32
  end
31
33
 
32
34
  def select_file(files)
@@ -39,7 +41,7 @@ module NA
39
41
  elsif TTY::Which.exist?('fzf')
40
42
  res = choose_from(files, prompt: 'Use which file?')
41
43
  unless res
42
- puts 'No file selected, cancelled'
44
+ $stderr.puts 'No file selected, cancelled'
43
45
  Process.exit 1
44
46
  end
45
47
 
@@ -69,17 +71,17 @@ module NA
69
71
 
70
72
  File.open(file, 'w') { |f| f.puts content }
71
73
 
72
- puts NA::Color.template("{by}Task added to {bw}#{file}{x}")
74
+ $stderr.puts NA::Color.template("{by}Task added to {bw}#{file}{x}")
73
75
  end
74
76
 
75
- def output_actions(actions, depth, extension, files: nil)
77
+ def output_actions(actions, depth, files: nil)
76
78
  template = if files&.count.positive?
77
79
  if files.count == 1
78
80
  '%parent%action'
79
81
  else
80
82
  '%filename%parent%action'
81
83
  end
82
- elsif NA.find_files(depth: depth, extension: extension).count > 1
84
+ elsif NA.find_files(depth: depth).count > 1
83
85
  if depth > 1
84
86
  '%filename%parent%action'
85
87
  else
@@ -89,13 +91,13 @@ module NA
89
91
  '%parent%action'
90
92
  end
91
93
  if files && @verbose
92
- puts files.map { |f| NA::Color.template("{dw}#{f}{x}") }
94
+ $stderr.puts files.map { |f| NA::Color.template("{dw}#{f}{x}") }
93
95
  end
94
96
 
95
97
  puts actions.map { |action| action.pretty(template: { output: template }) }
96
98
  end
97
99
 
98
- def parse_actions(depth: 1, extension: 'taskpaper', na_tag: 'na', query: nil, tag: nil, search: nil)
100
+ def parse_actions(depth: 1, query: nil, tag: nil, search: nil)
99
101
  actions = []
100
102
  required = []
101
103
  optional = []
@@ -122,10 +124,10 @@ module NA
122
124
  end
123
125
  end
124
126
 
125
- na_tag = "@#{na_tag.sub(/^@/, '')}"
127
+ na_tag = "@#{NA.na_tag.sub(/^@/, '')}"
126
128
 
127
129
  if query.nil?
128
- files = find_files(depth: depth, extension: extension)
130
+ files = find_files(depth: depth)
129
131
  else
130
132
  files = match_working_dir(query)
131
133
  end
@@ -151,13 +153,15 @@ module NA
151
153
  indent_level = indent
152
154
  end
153
155
  elsif line =~ /^[ \t]*- / && line !~ / @done/
156
+ next unless line =~ /@#{NA.na_tag}\b/
157
+
154
158
  unless optional.empty? && required.empty?
155
159
  next unless line.matches(any: optional, all: required)
156
160
 
157
161
  end
158
162
 
159
- action = line.sub(/^[ \t]*- /, '').sub(/ #{na_tag}/, '')
160
- new_action = NA::Action.new(file, File.basename(file, ".#{extension}"), parent.dup, action)
163
+ action = line.sub(/^[ \t]*- /, '').sub(/ @#{NA.na_tag}\b/, '')
164
+ new_action = NA::Action.new(file, File.basename(file, ".#{NA.extension}"), parent.dup, action)
161
165
  actions.push(new_action)
162
166
  end
163
167
  end
@@ -220,7 +224,7 @@ module NA
220
224
  dirs.delete_if { |d| !d.matches(any: optional, all: required) }
221
225
  dirs.sort.uniq
222
226
  else
223
- puts NA::Color.template('{r}No na database found{x}')
227
+ $stderr.puts NA::Color.template('{r}No na database found{x}')
224
228
  Process.exit 1
225
229
  end
226
230
  end
@@ -269,7 +273,7 @@ module NA
269
273
  if 'xdg-open'.available?
270
274
  `xdg-open #{Shellwords.escape(file)}`
271
275
  else
272
- puts NA::Color.template('{r}Unable to determine executable for `open`.{x}')
276
+ $stderr.puts NA::Color.template('{r}Unable to determine executable for `open`.{x}')
273
277
  end
274
278
  end
275
279
  end
data/lib/na/prompt.rb ADDED
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NA
4
+ # Prompt Hooks
5
+ module Prompt
6
+ class << self
7
+ def prompt_hook(shell)
8
+ case shell
9
+ when :zsh
10
+ <<~EOHOOK
11
+ # zsh prompt hook for na
12
+ chpwd() { na next }
13
+ EOHOOK
14
+ when :fish
15
+ <<~EOHOOK
16
+ # Fish Prompt Command
17
+ function __should_na --on-variable PWD
18
+ test -s (basename $PWD)".#{NA.extension}" && na next
19
+ end
20
+ EOHOOK
21
+ when :bash
22
+ <<~EOHOOK
23
+ # Bash PROMPT_COMMAND for na
24
+ last_command_was_cd() {
25
+ [[ $(history 1|sed -e "s/^[ ]*[0-9]*[ ]*//") =~ ^((cd|z|j|jump|g|f|pushd|popd|exit)([ ]|$)) ]] && na next
26
+ }
27
+ if [[ -z "$PROMPT_COMMAND" ]]; then
28
+ PROMPT_COMMAND="eval 'last_command_was_cd'"
29
+ else
30
+ echo $PROMPT_COMMAND | grep -v -q "last_command_was_cd" && PROMPT_COMMAND="$PROMPT_COMMAND;"'eval "last_command_was_cd"'
31
+ fi
32
+ EOHOOK
33
+ end
34
+ end
35
+
36
+ def prompt_file(shell)
37
+ files = {
38
+ zsh: '~/.zshrc',
39
+ fish: '~/.config/fish/conf.d/na.fish',
40
+ bash: '~/.bash_profile'
41
+ }
42
+
43
+ files[shell]
44
+ end
45
+
46
+ def show_prompt_hook(shell)
47
+ file = prompt_file(shell)
48
+
49
+ $stderr.puts NA::Color.template("{bw}# Add this to {y}#{file}{x}")
50
+ puts prompt_hook(shell)
51
+ end
52
+
53
+ def install_prompt_hook(shell)
54
+ file = prompt_file(shell)
55
+
56
+ File.open(File.expand_path(file), 'a') { |f| f.puts prompt_hook(shell) }
57
+ $stderr.puts NA::Color.template("{y}Added {bw}#{shell}{xy} prompt hook to {bw}#{file}{x}")
58
+ end
59
+ end
60
+ end
61
+ end
data/lib/na/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Na
2
- VERSION = '1.0.5'
2
+ VERSION = '1.0.7'
3
3
  end
data/lib/na.rb CHANGED
@@ -11,3 +11,4 @@ require 'na/colors.rb'
11
11
  require 'na/string.rb'
12
12
  require 'na/action.rb'
13
13
  require 'na/next_action.rb'
14
+ require 'na/prompt.rb'
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.0.4<!--END VER-->.
12
+ The current version of `na` is <!--VER-->1.0.6<!--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
 
@@ -293,7 +293,6 @@ Fish (in ~/.config/fish/conf.d/*.fish):
293
293
 
294
294
  ```fish
295
295
  function __should_na --on-variable PWD
296
- # function __should_na --on-event fish_prompt
297
296
  test -s (basename $PWD)".taskpaper" && na
298
297
  end
299
298
  ```
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: na
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.5
4
+ version: 1.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brett Terpstra
@@ -170,6 +170,7 @@ files:
170
170
  - lib/na/action.rb
171
171
  - lib/na/colors.rb
172
172
  - lib/na/next_action.rb
173
+ - lib/na/prompt.rb
173
174
  - lib/na/string.rb
174
175
  - lib/na/version.rb
175
176
  - na.gemspec