na 1.1.19 → 1.1.21

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: 3a57cbddd075c808316dbf206b6ff65d4d0caf307c4c27524faf94f6e86517d3
4
- data.tar.gz: 2e0ff764b2a777eb5089c228f7979c131c7669557f033f657241052cd3345b53
3
+ metadata.gz: '0430897c007446c9ad1a1e3463ddc3d8e192a43e8d60a46a9669745086ea45f3'
4
+ data.tar.gz: e33799f49bbaf623d188c64f549e71dcea41b317b95b3b5d0f72f8a378a3f9fd
5
5
  SHA512:
6
- metadata.gz: 4516162349290992f0a156161e3f3b1e7831ad383c38d9061ff44d267b862037e5cfb04796ac1143c4bdd1b60fa77b6c9576ee265add84abc19a5958d30dd8a6
7
- data.tar.gz: 91c86e3ea2c36fd66cbbc7211c9ebab460af7a9ba14668bb1f55a7a14d7e8b5aaf2ff8b7795672ee7c3856a3ae47b0783a40033c427b2df69ff2c0c6c60697e4
6
+ metadata.gz: d8c9a03b08abf20cb826e452ad75478b0f58dc0309ce51bee29e3b31b6c37de8e99cdd22926aef1ffe10183b151b54b6047196ce5c8987c32b0fa013942d5673
7
+ data.tar.gz: 7bb18376e8b53aa2c283206058c48dce786576d3a50d6e9567a0958011cab7f2f7203fecf0142cc49f3d5abc49a0342a4a3c20ff19318f79ac2d26ca00af206b
data/.travis.yml ADDED
@@ -0,0 +1,11 @@
1
+ ---
2
+ language: ruby
3
+ sudo: required
4
+ dist: trusty
5
+ cache: bundler
6
+ rvm:
7
+ - ruby-3.0.1
8
+ install:
9
+ - gem install bundler --version '2.2.29'
10
+ - bundle install
11
+ script: "bundle exec rake test"
data/CHANGELOG.md CHANGED
@@ -1,3 +1,25 @@
1
+ ### 1.1.21
2
+
3
+ 2022-10-07 04:26
4
+
5
+ #### NEW
6
+
7
+ - `na todos` will list (and optionally search) known todo files from history
8
+
9
+ #### IMPROVED
10
+
11
+ - Fuzzier matching of todo file history
12
+ - Help output fixes
13
+ - Code documentation
14
+
15
+ ### 1.1.20
16
+
17
+ 2022-10-07 03:16
18
+
19
+ #### IMPROVED
20
+
21
+ - Date comparisons that don't specify a time are automatically adjusted to "noon" to allow direct comparison of days
22
+
1
23
  ### 1.1.19
2
24
 
3
25
  2022-10-07 03:06
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- na (1.1.19)
4
+ na (1.1.21)
5
5
  chronic (~> 0.10, >= 0.10.2)
6
6
  gli (~> 2.21.0)
7
7
  tty-reader (~> 0.9, >= 0.9.0)
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.1.19
12
+ The current version of `na` is 1.1.21
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.
@@ -59,7 +59,7 @@ SYNOPSIS
59
59
  na [global options] command [command options] [arguments...]
60
60
 
61
61
  VERSION
62
- 1.1.19
62
+ 1.1.21
63
63
 
64
64
  GLOBAL OPTIONS
65
65
  -a, --[no-]add - Add a next action (deprecated, for backwards compatibility)
@@ -83,6 +83,7 @@ COMMANDS
83
83
  next, show - Show next actions
84
84
  prompt - Show or install prompt hooks for the current shell
85
85
  tagged - Find actions matching a tag
86
+ todos - Show list of known todo files
86
87
  ```
87
88
 
88
89
  #### Commands
@@ -102,7 +103,7 @@ SYNOPSIS
102
103
  na [global options] add [command options] ACTION
103
104
 
104
105
  DESCRIPTION
105
- Provides an easy way to store todos while you work. Add quick reminders and (if you set up Prompt Hooks) they'll automatically display next time you enter the directory. If multiple todo files are found in the current directory, a menu will allow you to pick to which file the action gets added.
106
+ Provides an easy way to store todos while you work. Add quick reminders and (if you set up Prompt Hooks) they'll automatically display next time you enter the directory. If multiple todo files are found in the current directory, a menu will allow you to pick to which file the action gets added.
106
107
 
107
108
  COMMAND OPTIONS
108
109
  -d, --depth=DEPTH - Search for files X directories deep (default: 1)
@@ -206,7 +207,7 @@ EXAMPLES
206
207
 
207
208
  ##### next, show
208
209
 
209
- Examples:
210
+ Examples:
210
211
 
211
212
  - `na show` (list all next actions in the current directory)
212
213
  - `na show -d 3` (list all next actions in the current directory and look for additional files 3 levels deep from there)
@@ -218,7 +219,10 @@ NAME
218
219
 
219
220
  SYNOPSIS
220
221
 
221
- na [global options] next [command options] OPTIONAL_QUERY
222
+ na [global options] next [command options] [QUERY]
223
+
224
+ DESCRIPTION
225
+ Next actions are actions which contain the next action tag (default @na), do not contain @done, and are not in the Archive project.
222
226
 
223
227
  COMMAND OPTIONS
224
228
  -d, --depth=DEPTH - Recurse to depth (default: 2)
@@ -245,38 +249,30 @@ Separate multiple tags with spaces or commas. By default tags are combined with
245
249
 
246
250
  ```
247
251
  NAME
248
- tagged - Find actions matching a tag
252
+ next - Show next actions
249
253
 
250
254
  SYNOPSIS
251
255
 
252
- na [global options] tagged [command options] TAG [VALUE]
256
+ na [global options] next [command options] [QUERY]
253
257
 
254
258
  DESCRIPTION
255
- Finds actions with tags matching the arguments. An action is shown if it contains all of the tags listed. Add a + before a tag to make it required and others optional. You can specify values using TAG=VALUE pairs. Use <, >, and = for numeric comparisons, and *=, ^=, and $= for text comparisons. Date comparisons use natural language (`na tagged "due<=today"`) and are detected automatically.
259
+ Next actions are actions which contain the next action tag (default @na), do not contain @done, and are not in the Archive project.
256
260
 
257
261
  COMMAND OPTIONS
258
- -d, --depth=DEPTH - Recurse to depth (default: 1)
259
- --in=TODO_PATH - Show actions from a specific todo file in history (default: none)
260
- -o, --or - Combine tags with OR, displaying actions matching ANY of the tags
262
+ -d, --depth=DEPTH - Recurse to depth (default: 2)
261
263
  --proj, --project=PROJECT[/SUBPROJECT] - Show actions from a specific project (default: none)
262
- -v, --invert - Show actions not matching tags
264
+ -t, --tag=TAG - Alternate tag to search for (default: none)
263
265
 
264
266
  EXAMPLES
265
267
 
266
- # Show all actions tagged @maybe
267
- na tagged maybe
268
-
269
- # Show all actions tagged @feature AND @idea, recurse 3 levels
270
- na tagged -d 3 "feature, idea"
271
-
272
- # Show all actions tagged @feature OR @idea
273
- na tagged --or "feature, idea"
268
+ # display the next actions from any todo files in the current directory
269
+ na next
274
270
 
275
- # Show actions with @priority(4) or @priority(5)
276
- na tagged "priority>=4"
271
+ # display the next actions from the current directory, traversing 3 levels deep
272
+ na next -d 3
277
273
 
278
- # Show actions with a due date coming up in the next 2 days
279
- na tagged "due<in 2 days"
274
+ # display next actions for a project you visited in the past
275
+ na next marked
280
276
  ```
281
277
 
282
278
  ### Configuration
data/bin/na CHANGED
@@ -54,7 +54,9 @@ class App
54
54
  switch %i[debug]
55
55
 
56
56
  desc 'Show next actions'
57
- arg_name 'OPTIONAL_QUERY'
57
+ long_desc "Next actions are actions which contain the next action tag (default @na),
58
+ do not contain @done, and are not in the Archive project."
59
+ arg_name 'QUERY', optional: true
58
60
  command %i[next show] do |c|
59
61
  c.example 'na next', desc: 'display the next actions from any todo files in the current directory'
60
62
  c.example 'na next -d 3', desc: 'display the next actions from the current directory, traversing 3 levels deep'
@@ -114,11 +116,12 @@ class App
114
116
  end
115
117
 
116
118
  desc 'Add a new next action'
117
- long_desc 'Provides an easy way to store todos while you work. Add quick reminders and (if you set up Prompt Hooks)
118
- they\'ll automatically display next time you enter the directory.
119
+ long_desc 'Provides an easy way to store todos while you work. Add quick
120
+ reminders and (if you set up Prompt Hooks) they\'ll automatically display
121
+ next time you enter the directory.
119
122
 
120
- If multiple todo files are found in the current directory, a menu will allow you to pick to which
121
- file the action gets added.'
123
+ If multiple todo files are found in the current directory, a menu will
124
+ allow you to pick to which file the action gets added.'
122
125
  arg_name 'ACTION'
123
126
  command :add do |c|
124
127
  c.example 'na add "A cool feature I thought of @idea"', desc: 'Add a new action to the Inbox, including a tag'
@@ -314,12 +317,12 @@ class App
314
317
 
315
318
  desc 'Find actions matching a tag'
316
319
  long_desc 'Finds actions with tags matching the arguments. An action is shown if it
317
- contains all of the tags listed. Add a + before a tag to make it required
318
- and others optional. You can specify values using TAG=VALUE pairs.
319
- Use <, >, and = for numeric comparisons, and *=, ^=, and $= for text comparisons.
320
- Date comparisons use natural language (`na tagged "due<=today"`) and
321
- are detected automatically.'
322
- arg_name 'TAG [VALUE]'
320
+ contains all of the tags listed. Add a + before a tag to make it required
321
+ and others optional. You can specify values using TAG=VALUE pairs.
322
+ Use <, >, and = for numeric comparisons, and *=, ^=, and $= for text comparisons.
323
+ Date comparisons use natural language (`na tagged "due<=today"`) and
324
+ are detected automatically.'
325
+ arg_name 'TAG[=VALUE]'
323
326
  command %i[tagged] do |c|
324
327
  c.example 'na tagged maybe', desc: 'Show all actions tagged @maybe'
325
328
  c.example 'na tagged -d 3 "feature, idea"', desc: 'Show all actions tagged @feature AND @idea, recurse 3 levels'
@@ -388,7 +391,7 @@ class App
388
391
  end
389
392
 
390
393
  desc 'Create a new todo file in the current directory'
391
- arg_name '[PROJECT]'
394
+ arg_name 'PROJECT', optional: true
392
395
  command %i[init create] do |c|
393
396
  c.example 'na init', desc: 'Generate a new todo file, prompting for project name'
394
397
  c.example 'na init warpspeed', desc: 'Generate a new todo for a project called warpspeed'
@@ -456,13 +459,35 @@ class App
456
459
  end
457
460
  end
458
461
 
462
+ desc 'Show list of known todo files'
463
+ long_desc 'Arguments will be interpreted as a query against which the
464
+ list of todos will be fuzzy matched. Separate directories with
465
+ /, :, or a space, e.g. `na todos code/marked`'
466
+ arg_name 'QUERY', optional: true
467
+ command %i[todos] do |c|
468
+ c.action do |_global_options, _options, args|
469
+ if args.count.positive?
470
+ tokens = []
471
+ args.each do |arg|
472
+ m = arg.match(/^(?<req>\+)?(?<tok>.*?)$/)
473
+ tokens.push({
474
+ token: m['tok'],
475
+ required: !m['req'].nil?
476
+ })
477
+ end
478
+ end
479
+
480
+ NA.list_todos(query: tokens)
481
+ end
482
+ end
483
+
459
484
  desc 'Show or install prompt hooks for the current shell'
460
485
  long_desc 'Installing the prompt hook allows you to automatically
461
486
  list next actions when you cd into a directory'
462
487
  command %i[prompt] do |c|
463
488
  c.desc 'Output the prompt hook for the current shell to STDOUT. Pass an argument to
464
489
  specify a shell (zsh, bash, fish)'
465
- c.arg_name '[SHELL]'
490
+ c.arg_name 'SHELL', optional: true
466
491
  c.command %i[show] do |s|
467
492
  s.action do |_global_options, _options, args|
468
493
  shell = if args.count.positive?
@@ -483,7 +508,7 @@ class App
483
508
  end
484
509
 
485
510
  c.desc 'Install the hook for the current shell to the appropriate startup file.'
486
- c.arg_name '[SHELL]'
511
+ c.arg_name 'SHELL', optional: true
487
512
  c.command %i[install] do |s|
488
513
  s.action do |_global_options, _options, args|
489
514
  shell = if args.count.positive?
data/lib/na/action.rb CHANGED
@@ -137,14 +137,14 @@ module NA
137
137
  return false if tag_val.nil?
138
138
 
139
139
  begin
140
- if val =~ /^today$/i
141
- val = 'today at 12am'
142
- tag_val = tag_val.sub(/\d\d:\d\d/, '00:00')
143
- end
144
-
145
140
  tag_date = Time.parse(tag_val)
146
141
  date = Chronic.parse(val)
147
142
 
143
+ unless val =~ /(\d:\d|a[mp]|now)/i
144
+ tag_date = Time.parse(tag_date.strftime('%Y-%m-%d 12:00'))
145
+ date = Time.parse(date.strftime('%Y-%m-%d 12:00'))
146
+ end
147
+
148
148
  puts "Comparing #{tag_date} #{tag[:comp]} #{date}" if NA.verbose
149
149
 
150
150
  case tag[:comp]
@@ -5,13 +5,27 @@ module NA
5
5
  class << self
6
6
  attr_accessor :verbose, :extension, :na_tag
7
7
 
8
- def notify(msg, exit_code: false)
8
+ ##
9
+ ## Output to STDERR
10
+ ##
11
+ ## @param msg [String] The message
12
+ ## @param exit_code [Number] The exit code, no exit if false
13
+ ##
14
+ def notify(msg, exit_code: false, debug: false)
15
+ return if debug && !@verbose
16
+
9
17
  $stderr.puts NA::Color.template("{x}#{msg}{x}")
10
18
  if exit_code && exit_code.is_a?(Number)
11
19
  Process.exit exit_code
12
20
  end
13
21
  end
14
22
 
23
+ ##
24
+ ## Create a new todo file
25
+ ##
26
+ ## @param target [String] The target path
27
+ ## @param basename [String] The project base name
28
+ ##
15
29
  def create_todo(target, basename)
16
30
  File.open(target, 'w') do |f|
17
31
  content = <<~ENDCONTENT
@@ -32,12 +46,24 @@ module NA
32
46
  notify("{y}Created {bw}#{target}")
33
47
  end
34
48
 
49
+ ##
50
+ ## Use the *nix `find` command to locate files matching NA.extension
51
+ ##
52
+ ## @param depth [Number] The depth at which to search
53
+ ##
35
54
  def find_files(depth: 1)
36
55
  files = `find . -name "*.#{NA.extension}" -maxdepth #{depth}`.strip.split("\n")
37
56
  files.each { |f| save_working_dir(File.expand_path(f)) }
38
57
  files
39
58
  end
40
59
 
60
+ ##
61
+ ## Select from multiple files
62
+ ##
63
+ ## @note If `gum` or `fzf` are available, they'll be used (in that order)
64
+ ##
65
+ ## @param files [Array] The files
66
+ ##
41
67
  def select_file(files)
42
68
  if TTY::Which.exist?('gum')
43
69
  args = [
@@ -63,12 +89,22 @@ module NA
63
89
  end
64
90
  end
65
91
 
92
+ ##
93
+ ## Add an action to a todo file
94
+ ##
95
+ ## @param file [String] The target file
96
+ ## @param project [String] The project name
97
+ ## @param action [String] The action
98
+ ## @param note [String] The note
99
+ ##
66
100
  def add_action(file, project, action, note = nil)
67
101
  content = IO.read(file)
102
+ # Insert the target project at the top if it doesn't exist
68
103
  unless content =~ /^[ \t]*#{project}:/i
69
104
  content = "#{project.cap_first}:\n#{content}"
70
105
  end
71
106
 
107
+ # Insert the action at the top of the target project
72
108
  content.sub!(/^([ \t]*)#{project}:(.*?)$/i) do
73
109
  m = Regexp.last_match
74
110
  note = note.nil? ? '' : "\n#{m[1]}\t\t#{note.join('').strip}"
@@ -80,6 +116,14 @@ module NA
80
116
  notify("{by}Task added to {bw}#{file}")
81
117
  end
82
118
 
119
+ ##
120
+ ## Pretty print a list of actions
121
+ ##
122
+ ## @param actions [Array] The actions
123
+ ## @param depth [Number] The depth
124
+ ## @param files [Array] The files actions originally came from
125
+ ## @param regexes [Array] The regexes used to gather actions
126
+ ##
83
127
  def output_actions(actions, depth, files: nil, regexes: [])
84
128
  return if files.nil?
85
129
 
@@ -99,11 +143,23 @@ module NA
99
143
  '%parent%action'
100
144
  end
101
145
 
102
- files.map { |f| notify("{dw}#{f}") } if files && @verbose
146
+ files.map { |f| notify("{dw}#{f}", debug: true) } if files
103
147
 
104
148
  puts(actions.map { |action| action.pretty(template: { output: template }, regexes: regexes) })
105
149
  end
106
150
 
151
+ ##
152
+ ## Read a todo file and create a list of actions
153
+ ##
154
+ ## @param depth [Number] The directory depth to search for files
155
+ ## @param query [Hash] The project query
156
+ ## @param tag [Hash] Tags to search for
157
+ ## @param search [String] A search string
158
+ ## @param negate [Boolean] Invert results
159
+ ## @param regex [Boolean] Interpret as regular expression
160
+ ## @param project [String] The project
161
+ ## @param require_na [Boolean] Require @na tag
162
+ ##
107
163
  def parse_actions(depth: 1, query: nil, tag: nil, search: nil, negate: false, regex: false, project: nil, require_na: true)
108
164
  actions = []
109
165
  required = []
@@ -220,6 +276,9 @@ module NA
220
276
  end
221
277
  end
222
278
 
279
+ ##
280
+ ## Remove entries from cache database that no longer exist
281
+ ##
223
282
  def weed_cache_file
224
283
  db_dir = File.expand_path('~/.local/share/na')
225
284
  db_file = 'tdlist.txt'
@@ -231,6 +290,24 @@ module NA
231
290
  end
232
291
  end
233
292
 
293
+ def list_todos(query: [])
294
+ if query
295
+ dirs = match_working_dir(query)
296
+ else
297
+ file = database_path
298
+ content = File.exist?(file) ? IO.read(file).strip : ''
299
+ notify('{br}Database empty', exit_code: 1) if content.empty?
300
+
301
+ dirs = content.split(/\n/)
302
+ end
303
+
304
+ dirs.map! do |dir|
305
+ "{xg}#{dir.sub(/^#{ENV['HOME']}/, '~').sub(%r{/([^/]+)\.#{NA.extension}$}, '/{xbw}\1{x}')}"
306
+ end
307
+
308
+ puts NA::Color.template(dirs.join("\n"))
309
+ end
310
+
234
311
  private
235
312
 
236
313
  ##
@@ -302,29 +379,26 @@ module NA
302
379
  ## between characters
303
380
  ##
304
381
  def match_working_dir(search, distance: 1)
305
- optional = []
306
- required = []
307
-
308
- search&.each do |t|
309
- # Make "search" into "s.{0,1}e.{0,1}a.{0,1}r.{0,1}c.{0,1}h"
310
- new_rx = t[:token].to_s.split('').join(".{0,#{distance}}")
311
-
312
- optional.push(new_rx)
313
- required.push(new_rx) if t[:required]
314
- end
382
+ search = search.map { |t| t[:token] }.join('/')
383
+ optional = [search]
384
+ required = [search]
315
385
 
316
- match_dir(optional, required)
317
- end
318
-
319
- def match_dir(optional, required)
320
386
  file = database_path
321
387
  notify('{r}No na database found', exit_code: 1) unless File.exist?(file)
322
388
 
323
389
  dirs = IO.read(file).split("\n")
390
+
391
+ NA.notify("{bw}Directory regex: {x}#{required.map(&:dir_to_rx)}", debug: true)
392
+
324
393
  dirs.delete_if { |d| !d.dir_matches(any: optional, all: required) }
325
394
  dirs.sort.uniq
326
395
  end
327
396
 
397
+ ##
398
+ ## Save a todo file path to the database
399
+ ##
400
+ ## @param todo_file The todo file path
401
+ ##
328
402
  def save_working_dir(todo_file)
329
403
  file = database_path
330
404
  content = File.exist?(file) ? IO.read(file) : ''
@@ -334,6 +408,12 @@ module NA
334
408
  File.open(file, 'w') { |f| f.puts dirs.join("\n") }
335
409
  end
336
410
 
411
+ ##
412
+ ## macOS open command
413
+ ##
414
+ ## @param file The file
415
+ ## @param app The application
416
+ ##
337
417
  def darwin_open(file, app: nil)
338
418
  if app
339
419
  `open -a "#{app}" #{Shellwords.escape(file)}`
@@ -342,10 +422,20 @@ module NA
342
422
  end
343
423
  end
344
424
 
425
+ ##
426
+ ## Windows open command
427
+ ##
428
+ ## @param file The file
429
+ ##
345
430
  def win_open(file)
346
431
  `start #{Shellwords.escape(file)}`
347
432
  end
348
433
 
434
+ ##
435
+ ## Linux open command
436
+ ##
437
+ ## @param file The file
438
+ ##
349
439
  def linux_open(file)
350
440
  if TTY::Which.exist?('xdg-open')
351
441
  `xdg-open #{Shellwords.escape(file)}`
data/lib/na/string.rb CHANGED
@@ -55,8 +55,8 @@ class ::String
55
55
  scan(/\e\[[\d;]+m/).join('').gsub(/\e\[0m/, '')
56
56
  end
57
57
 
58
- def dir_to_rx
59
- "#{split(%r{[/:]}).join('.*?/.*?')}[^/]+$"
58
+ def dir_to_rx(distance: 2)
59
+ "#{split(%r{[/:]}).map { |comp| comp.split('').join(".{0,#{distance}}") }.join('.*?/.*?')}[^/]+$"
60
60
  end
61
61
 
62
62
  def dir_matches(any: [], all: [])
data/lib/na/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Na
2
- VERSION = '1.1.19'
2
+ VERSION = '1.1.21'
3
3
  end
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.1.18<!--END VER-->.
12
+ The current version of `na` is <!--VER-->1.1.20<!--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
 
@@ -90,7 +90,7 @@ Unless `--exact` is specified, search is tokenized and combined with AND, so `na
90
90
 
91
91
  ##### next, show
92
92
 
93
- Examples:
93
+ Examples:
94
94
 
95
95
  - `na show` (list all next actions in the current directory)
96
96
  - `na show -d 3` (list all next actions in the current directory and look for additional files 3 levels deep from there)
@@ -107,7 +107,7 @@ Example: `na tagged feature +maybe`.
107
107
  Separate multiple tags with spaces or commas. By default tags are combined with AND, so actions matching all of the tags listed will be displayed. Use `+` to make a tag required and `!` to negate a tag (only display if the action does _not_ contain the tag). When `+` and/or `!` are used, undecorated tokens become optional matches. Use `-v` to invert the search and display all actions that _don't_ match.
108
108
 
109
109
  ```
110
- @cli(bundle exec bin/na help tagged)
110
+ @cli(bundle exec bin/na help show)
111
111
  ```
112
112
 
113
113
  ### Configuration
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.1.19
4
+ version: 1.1.21
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brett Terpstra
@@ -178,6 +178,7 @@ extra_rdoc_files:
178
178
  - README.md
179
179
  - na.rdoc
180
180
  files:
181
+ - ".travis.yml"
181
182
  - CHANGELOG.md
182
183
  - Gemfile
183
184
  - Gemfile.lock