na 1.0.4 → 1.0.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f9da419b49e24864d0adfc81fa3834c8920d482de91597124b3640b14d5fb0e6
4
- data.tar.gz: ed6cb25a6889ff354baef255e7abeeb6a8ff13aee6907f84af5078c4aaee9954
3
+ metadata.gz: ac0a37d801443c68aaee6eee3b6c4a31461a61d4221c7a073beb0f176d7d7424
4
+ data.tar.gz: d04d6bd01a3104f6858e9a797af728486b80a8482b6644a09940a6272ae2ec4b
5
5
  SHA512:
6
- metadata.gz: 6e4c30403c700644291354a66cc542eb98545c429a843119083b2251535df823fce89f8b218e4fb8a778e6f07dac8b5d562a09df0c75569383798b5659489082
7
- data.tar.gz: 59bee0616ecfa10cf204028776538cd0ec4cb268a5a903a3f16558a84b464824cd09c848098b5767c48e8c8e7d53273fd79773487857a5c18b0e7ee6e84461b9
6
+ metadata.gz: 7ec40b0dd9ff9f154cc22e5d1cb2df700fae82e9c8118110d72b0ea3aeed46a0bd7543955e8b491f99816a9c5dea8ede5866534c362abbb771a3fefbe8d346d9
7
+ data.tar.gz: c66d44910edfe4200655b6775665ead7836b47dd7b8b20385da29ee21ce6ba38d5fef0f99b2da009385d9962204cf491d3ee928b2c255bd5d2ce278d8a4c15fa
data/CHANGELOG.md CHANGED
@@ -1,3 +1,19 @@
1
+ ### 1.0.6
2
+
3
+ 2022-09-28 04:22
4
+
5
+ #### NEW
6
+
7
+ - `na prompt [show|install]` command to help with adding prompt hooks to your shell
8
+
9
+ ### 1.0.5
10
+
11
+ 2022-09-28 01:53
12
+
13
+ #### FIXED
14
+
15
+ - A note containing a colon would be recognized as a project line
16
+
1
17
  ### 1.0.4
2
18
 
3
19
  2022-09-28 01:18
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.5)
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.3.
12
+ The current version of `na` is 1.0.5.
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'
@@ -94,11 +94,9 @@ class App
94
94
  tag = options[:tag] == global_options[: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
 
@@ -148,7 +146,7 @@ class App
148
146
  action = "#{action.gsub(/@priority\(\d+\)/, '')} @priority(#{options[:priority]})"
149
147
  end
150
148
 
151
- na_tag = global_options[:na_tag]
149
+ na_tag = NA.na_tag
152
150
  na_tag = options[:tag] unless options[:tag].nil?
153
151
 
154
152
  action = "#{action.gsub(/@#{na_tag}/, '')} @#{na_tag}"
@@ -167,7 +165,7 @@ class App
167
165
  print NA::Color.template('{by}Specified file not found, create it? {w}(y/{g}N{w}){x} ')
168
166
  res = reader.read_char
169
167
  if res =~ /y/i
170
- basename = File.basename(target, ".#{global_options[:ext]}")
168
+ basename = File.basename(target, ".#{NA.extension}")
171
169
  NA.create_todo(target, basename)
172
170
  else
173
171
  puts NA::Color.template('{r}Cancelled{x}')
@@ -175,15 +173,15 @@ class App
175
173
  end
176
174
  end
177
175
  else
178
- files = NA.find_files(depth: 1, extension: global_options[:ext])
176
+ files = NA.find_files(depth: 1)
179
177
  if files.count == 0
180
178
  print NA::Color.template('{by}No todo file found, create one? {w}(y/{g}N{w}){x} ')
181
179
  res = reader.read_char
182
180
  if res =~ /y/i
183
181
  basename = File.expand_path('.').split('/').last
184
- target = "#{basename}.#{global_options[:ext]}"
182
+ target = "#{basename}.#{NA.extension}"
185
183
  NA.create_todo(target, basename)
186
- files = NA.find_files(depth: 1, extension: global_options[:ext])
184
+ files = NA.find_files(depth: 1)
187
185
  end
188
186
  end
189
187
  target = files.count > 1 ? NA.select_file(files) : files[0]
@@ -236,10 +234,8 @@ class App
236
234
  end
237
235
 
238
236
  files, actions = NA.parse_actions(depth: depth,
239
- extension: global_options[:ext],
240
- na_tag: global_options[:na_tag],
241
237
  search: tokens)
242
- NA.output_actions(actions, depth, global_options[:ext], files: files)
238
+ NA.output_actions(actions, depth, files: files)
243
239
  end
244
240
  end
245
241
 
@@ -278,10 +274,8 @@ class App
278
274
  end
279
275
 
280
276
  files, actions = NA.parse_actions(depth: depth,
281
- extension: global_options[:ext],
282
- na_tag: global_options[:na_tag],
283
277
  tag: tags)
284
- NA.output_actions(actions, depth, global_options[:ext], files: files)
278
+ NA.output_actions(actions, depth, files: files)
285
279
  end
286
280
  end
287
281
 
@@ -300,7 +294,7 @@ class App
300
294
  project = reader.read_line(NA::Color.template('{y}Project name {bw}> {x}'), value: project).strip
301
295
  end
302
296
 
303
- target = "#{project}.#{global_options[:ext]}"
297
+ target = "#{project}.#{NA.extension}"
304
298
 
305
299
  if File.exist?(target)
306
300
  print NA::Color.template("{r}File {bw}#{target}{r} already exists, overwrite it? {br}y{w}/{bg}N{x} ")
@@ -339,7 +333,7 @@ class App
339
333
  else
340
334
  options[:depth].nil? ? global_options[:depth].to_i : options[:depth].to_i
341
335
  end
342
- files = NA.find_files(depth: depth, extension: global_options[:ext])
336
+ files = NA.find_files(depth: depth)
343
337
  file = if files.count > 1
344
338
  NA.select_file(files)
345
339
  else
@@ -354,8 +348,59 @@ class App
354
348
  end
355
349
  end
356
350
 
351
+ desc 'Show or install prompt hooks for the current shell'
352
+ long_desc 'Installing the prompt hook allows you to automatically
353
+ list next actions when you cd into a directory'
354
+ command %i[prompt] do |c|
355
+ c.desc 'Output the prompt hook for the current shell to STDOUT. Pass an argument to specify a shell (zsh, bash, fish)'
356
+ c.arg_name '[SHELL]'
357
+ c.command %i[show] do |s|
358
+ s.action do |global_options, options, args|
359
+ if args.count.positive?
360
+ shell = args[0]
361
+ else
362
+ shell = File.basename(ENV['SHELL'])
363
+ end
364
+
365
+ case shell
366
+ when /^f/i
367
+ NA::Prompt.show_prompt_hook(:fish)
368
+ when /^z/i
369
+ NA::Prompt.show_prompt_hook(:zsh)
370
+ when /^b/i
371
+ NA::Prompt.show_prompt_hook(:bash)
372
+ end
373
+ end
374
+ end
375
+
376
+ c.desc 'Install the hook for the current shell to the appropriate startup file.'
377
+ c.arg_name '[SHELL]'
378
+ c.command %i[install] do |s|
379
+ s.action do |global_options, options, args|
380
+ if args.count.positive?
381
+ shell = args[0]
382
+ else
383
+ shell = File.basename(ENV['SHELL'])
384
+ end
385
+
386
+ case shell
387
+ when /^f/i
388
+ NA::Prompt.install_prompt_hook(:fish)
389
+ when /^z/i
390
+ NA::Prompt.install_prompt_hook(:zsh)
391
+ when /^b/i
392
+ NA::Prompt.install_prompt_hook(:bash)
393
+ end
394
+ end
395
+ end
396
+ end
397
+
398
+
399
+
357
400
  pre do |global, command, options, args|
358
- NA.verbose = global[:verbose]
401
+ NA.verbose = global[:debug]
402
+ NA.extension = global[:ext]
403
+ NA.na_tag = global[:na_tag]
359
404
  true
360
405
  end
361
406
 
@@ -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,11 @@ 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
+ `find . -name "*.#{NA.extension}" -maxdepth #{depth}`.strip.split("\n")
30
30
  end
31
31
 
32
32
  def select_file(files)
@@ -39,7 +39,7 @@ module NA
39
39
  elsif TTY::Which.exist?('fzf')
40
40
  res = choose_from(files, prompt: 'Use which file?')
41
41
  unless res
42
- puts 'No file selected, cancelled'
42
+ $stderr.puts 'No file selected, cancelled'
43
43
  Process.exit 1
44
44
  end
45
45
 
@@ -69,17 +69,17 @@ module NA
69
69
 
70
70
  File.open(file, 'w') { |f| f.puts content }
71
71
 
72
- puts NA::Color.template("{by}Task added to {bw}#{file}{x}")
72
+ $stderr.puts NA::Color.template("{by}Task added to {bw}#{file}{x}")
73
73
  end
74
74
 
75
- def output_actions(actions, depth, extension, files: nil)
75
+ def output_actions(actions, depth, files: nil)
76
76
  template = if files&.count.positive?
77
77
  if files.count == 1
78
78
  '%parent%action'
79
79
  else
80
80
  '%filename%parent%action'
81
81
  end
82
- elsif NA.find_files(depth: depth, extension: extension).count > 1
82
+ elsif NA.find_files(depth: depth).count > 1
83
83
  if depth > 1
84
84
  '%filename%parent%action'
85
85
  else
@@ -89,13 +89,13 @@ module NA
89
89
  '%parent%action'
90
90
  end
91
91
  if files && @verbose
92
- puts files.map { |f| NA::Color.template("{dw}#{f}{x}") }
92
+ $stderr.puts files.map { |f| NA::Color.template("{dw}#{f}{x}") }
93
93
  end
94
94
 
95
95
  puts actions.map { |action| action.pretty(template: { output: template }) }
96
96
  end
97
97
 
98
- def parse_actions(depth: 1, extension: 'taskpaper', na_tag: 'na', query: nil, tag: nil, search: nil)
98
+ def parse_actions(depth: 1, query: nil, tag: nil, search: nil)
99
99
  actions = []
100
100
  required = []
101
101
  optional = []
@@ -122,10 +122,10 @@ module NA
122
122
  end
123
123
  end
124
124
 
125
- na_tag = "@#{na_tag.sub(/^@/, '')}"
125
+ na_tag = "@#{NA.na_tag.sub(/^@/, '')}"
126
126
 
127
127
  if query.nil?
128
- files = find_files(depth: depth, extension: extension)
128
+ files = find_files(depth: depth)
129
129
  else
130
130
  files = match_working_dir(query)
131
131
  end
@@ -137,7 +137,7 @@ module NA
137
137
  parent = []
138
138
  content.split("\n").each do |line|
139
139
  new_action = nil
140
- if line =~ /([ \t]*)([^\-]+.*?):/
140
+ if line =~ /([ \t]*)([^\-]+.*?): *(@\S+ *)*$/
141
141
  proj = Regexp.last_match(2)
142
142
  indent = line.indent_level
143
143
 
@@ -156,8 +156,8 @@ module NA
156
156
 
157
157
  end
158
158
 
159
- action = line.sub(/^[ \t]*- /, '').sub(/ #{na_tag}/, '')
160
- new_action = NA::Action.new(file, File.basename(file, ".#{extension}"), parent.dup, action)
159
+ action = line.sub(/^[ \t]*- /, '').sub(/ #{NA.na_tag}/, '')
160
+ new_action = NA::Action.new(file, File.basename(file, ".#{NA.extension}"), parent.dup, action)
161
161
  actions.push(new_action)
162
162
  end
163
163
  end
@@ -220,7 +220,7 @@ module NA
220
220
  dirs.delete_if { |d| !d.matches(any: optional, all: required) }
221
221
  dirs.sort.uniq
222
222
  else
223
- puts NA::Color.template('{r}No na database found{x}')
223
+ $stderr.puts NA::Color.template('{r}No na database found{x}')
224
224
  Process.exit 1
225
225
  end
226
226
  end
@@ -269,7 +269,7 @@ module NA
269
269
  if 'xdg-open'.available?
270
270
  `xdg-open #{Shellwords.escape(file)}`
271
271
  else
272
- puts NA::Color.template('{r}Unable to determine executable for `open`.{x}')
272
+ $stderr.puts NA::Color.template('{r}Unable to determine executable for `open`.{x}')
273
273
  end
274
274
  end
275
275
  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 }
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
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
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.4'
2
+ VERSION = '1.0.6'
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.3<!--END VER-->.
12
+ The current version of `na` is <!--VER-->1.0.5<!--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.4
4
+ version: 1.0.6
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