hookapp 0.0.7 → 2.0.7

Sign up to get free protection for your applications and to get access to all the features.
data/bin/hook CHANGED
@@ -1,25 +1,40 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'gli'
5
4
  require 'hook'
5
+ require 'shellwords'
6
6
 
7
7
  # Main class for GLI app
8
8
  class App
9
9
  extend GLI::App
10
10
 
11
11
  program_desc 'CLI interface for Hook.app (macOS)'
12
+ program_long_desc 'Hook.app is a productivity tool for macOS <https://hookproductivity.com/>.
13
+ This gem includes a `hook` binary that allows interaction with the features of Hook.app.'
14
+ default_command 'help'
15
+ autocomplete_commands = true
16
+ synopsis_format(:terminal)
12
17
 
13
18
  version Hook::VERSION
14
19
 
15
20
  subcommand_option_handling :normal
16
21
  arguments :strict
17
22
 
18
- hooker = nil
23
+ hookapp = nil
24
+ stdin = nil
19
25
 
20
26
  desc 'List hooks on a file or url'
27
+ long_desc %{
28
+ Output a list of all hooks attached to given url(s) or file(s) in the specified format (default "paths").
29
+
30
+ Run `hook list` with no file/url argument to list all bookmarks.}
31
+
21
32
  arg_name 'FILE_OR_URL [FILE_OR_URL...]'
22
33
  command %i[list ls] do |c|
34
+ c.desc 'Generate a menu to select hook(s) for opening'
35
+ c.long_desc 'This option is a shortcut to `hook select` and overrides any other arguments.'
36
+ c.switch %i[s select]
37
+
23
38
  c.desc 'Output only bookmarks with file paths (exclude e.g. emails)'
24
39
  c.switch %i[f files_only], { negatable: false, default_value: false }
25
40
 
@@ -32,10 +47,13 @@ class App
32
47
  c.flag %i[o output_format], { arg_name: 'format', default_value: 'paths' }
33
48
 
34
49
  c.action do |_global_options, options, args|
35
- valid_format = hooker.validate_format(options[:o], valid_formats)
36
- raise 'Invalid output format' unless valid_format
50
+ if options[:s]
51
+ return hookapp.open_linked(args[0])
52
+ end
53
+ valid_format = hookapp.validate_format(options[:o], valid_formats)
54
+ exit_now!("Invalid output format: \"#{options[:o]}\"", 6) unless valid_format
37
55
 
38
- result = hooker.linked_bookmarks(args, { files_only: options[:f],
56
+ result = hookapp.linked_bookmarks(args, { files_only: options[:f],
39
57
  format: valid_format,
40
58
  null_separator: options[:null] })
41
59
 
@@ -43,7 +61,80 @@ class App
43
61
  end
44
62
  end
45
63
 
64
+ # Shell completion scripts are located in lib/completion/ and named "hook_completion" with
65
+ # the full shell name as the extension, e.g. "hook_completion.bash".
66
+ desc 'Shell completion examples'
67
+ valid_shells = %w[bash zsh fish]
68
+ long_desc %{
69
+ Output completion script example for the specified shell (#{valid_shells.join(', ')})
70
+ }
71
+ arg_name 'SHELL'
72
+ command %i[scripts] do |c|
73
+ c.action do |_global_options, _options, args|
74
+ if args.length > 1
75
+ exit_now!("Invalid number of arguments, (expected 1)", 5)
76
+ elsif args.nil? || args.empty?
77
+ exit_now!("Specify a shell (#{valid_shells.join(', ')})", 0)
78
+ else
79
+ if valid_shells.include?(args[0])
80
+ base_dir = File.expand_path(File.join(File.dirname(__FILE__), '../lib/completion'))
81
+ completion = File.join(base_dir, "hook_completion.#{args[0]}")
82
+ script = IO.read(completion)
83
+ $stdout.puts script
84
+ else
85
+ exit_now!("Invalid shell name, must be one of #{valid_shells.join(', ')}", 1)
86
+ end
87
+ end
88
+ end
89
+ end
90
+
91
+
92
+
93
+ desc 'Search bookmarks'
94
+ long_desc %{
95
+ Search bookmark urls and names for a string and output in specified format (default "paths").
96
+
97
+ Run `hook find` with no search argument to list all bookmarks.}
98
+ arg_name 'SEARCH_STRING'
99
+ command %i[find search] do |c|
100
+ c.desc 'Output only bookmarks with file paths (exclude e.g. emails)'
101
+ c.switch %i[f files_only], { negatable: false, default_value: false }
102
+
103
+ c.desc 'Separate results with NULL separator, only applies with "paths" output for single file argument'
104
+ c.switch %i[null], { negatable: false, default_value: false }
105
+
106
+ valid_formats = %w[hooks paths markdown verbose]
107
+ fmt_list = valid_formats.map { |fmt| fmt.sub(/^(.)(.*?)$/, '(\1)\2') }.join(', ')
108
+
109
+ c.desc "Output format [#{fmt_list}]"
110
+ c.flag %i[o output_format], { arg_name: 'format', default_value: 'paths' }
111
+
112
+ c.desc "Search only bookmark names"
113
+ c.switch %i[n names_only], { negatable: false, default_value: false }
114
+
115
+ c.action do |_global_options, options, args|
116
+ valid_format = hookapp.validate_format(options[:o], valid_formats)
117
+ exit_now!("Invalid output format: \"#{options[:o]}\"", 6) unless valid_format
118
+
119
+ result = hookapp.search_bookmarks(args.join(" "), { files_only: options[:f],
120
+ format: valid_format,
121
+ null_separator: options[:null],
122
+ names_only: options[:n] })
123
+
124
+ puts result
125
+ end
126
+ end
127
+
46
128
  desc 'Create bidirectional hooks between two or more files/urls'
129
+ long_desc %{
130
+ If two files/urls are provided, links will be bi-directional.
131
+ If three or more are provided, `link` defaults to creating bi-directional
132
+ links between each file and the last file in the list. Use `-a` to create
133
+ bi-directional links between every file in the list.
134
+
135
+ If using `--paste`, the URL/hook link in the clipboard will be used as one argument,
136
+ to be combined with one or more file/url arguments.
137
+ }
47
138
  arg_name 'SOURCE [SOURCE...] TARGET'
48
139
  command %i[link ln] do |c|
49
140
  c.desc 'Link every listed file or url to every other'
@@ -59,17 +150,23 @@ class App
59
150
  args.push(clipboard) if clipboard
60
151
  end
61
152
  if args.length < 2
62
- raise 'At least 2 files must be specified, or one file with --paste'
153
+ exit_now!('Wrong number of arguments. At least 2 files must be specified, or one file with --paste', 5)
63
154
  end
64
155
  if options[:a]
65
- puts hooker.link_all(args)
156
+ puts hookapp.link_all(args)
66
157
  else
67
- puts hooker.link_files(args)
158
+ puts hookapp.link_files(args)
68
159
  end
69
160
  end
70
161
  end
71
162
 
72
163
  desc 'Copy Hook URL for file/url to clipboard'
164
+ long_desc %{
165
+ Creates a bookmark for the specified file or URL and copies its Hook URL to the clipboard.
166
+
167
+ The copied Hook URL can be used to link to other files (use `hook link --paste FILE/URL),
168
+ or to paste into another app as a link. Use the -m flag to copy a full Markdown link.
169
+ }
73
170
  arg_name 'FILE_OR_URL'
74
171
  command %i[clip cp] do |c|
75
172
  c.desc 'Copy as Markdown'
@@ -79,17 +176,23 @@ class App
79
176
  c.flag %i[a app], { arg_name: 'APP_NAME' }
80
177
 
81
178
  c.action do |_global_options, options, args|
82
- raise 'Wrong number of arguments. Requires a path/url or -a APP_NAME' if args.length != 1 && !options[:a]
179
+ exit_now!('Wrong number of arguments. Requires a path/url or -a APP_NAME', 5) if args.length != 1 && !options[:a]
83
180
 
84
181
  if options[:a]
85
- puts hooker.bookmark_from_app(options[:a], { copy: true, markdown: options[:m] })
182
+ puts hookapp.bookmark_from_app(options[:a], { copy: true, markdown: options[:m] })
86
183
  else
87
- puts hooker.clip_bookmark(args[0], { markdown: options[:m] })
184
+ puts hookapp.clip_bookmark(args[0], { markdown: options[:m] })
88
185
  end
89
186
  end
90
187
  end
91
188
 
92
189
  desc 'Get a Hook URL for the frontmost window of an app'
190
+ long_desc %{
191
+ Specify an application by name (without '.app') to bring that app to the foreground and create a bookmark
192
+ for the active document, note, task, etc., returning a Hook URL.
193
+
194
+ Use -m to get the response as Markdown, and/or -c to copy the result directly to the clipboard.
195
+ }
93
196
  arg_name 'APPLICATION_NAME'
94
197
  command %i[from] do |c|
95
198
  c.desc 'Output as Markdown'
@@ -99,62 +202,122 @@ class App
99
202
  c.switch %i[c copy], { negatable: false, default_value: false }
100
203
 
101
204
  c.action do |_global_options, options, args|
102
- raise "Wrong number of arguments (1 expected, #{args.length} given)" if args.length != 1
205
+ exit_now!("Wrong number of arguments (1 expected, #{args.length} given)", 5) if args.length != 1
103
206
 
104
- puts hooker.bookmark_from_app(args[0], { copy: options[:c], markdown: options[:m] })
207
+ puts hookapp.bookmark_from_app(args[0], { copy: options[:c], markdown: options[:m] })
105
208
  end
106
209
  end
107
210
 
108
211
  desc 'Remove a hook between two files/urls'
212
+ long_desc %{
213
+ Remove a hook between two files or URLs. If you use --all, all hooks on a given file will be removed.
214
+
215
+ If --all isn't specified, exactly two arguments (Files/URLs) are required.
216
+ }
109
217
  arg_name 'ITEM_1 ITEM_2'
110
218
  command %i[remove rm] do |c|
111
219
  c.desc 'Remove ALL links on files, requires confirmation'
112
- c.switch %i[a all]
220
+ c.switch %i[a all], { negatable: false, default_value: false }
221
+ c.switch %i[f force], { negatable: false, default_value: false }
113
222
 
114
223
  c.action do |_global_options, options, args|
115
- result = hooker.delete_hooks(args, { all: options[:r] })
224
+ result = hookapp.delete_hooks(args, { all: options[:all], force: options[:force] })
116
225
  puts result
117
226
  end
118
227
  end
119
228
 
120
229
  desc 'Clone all hooks from one file or url onto another'
230
+ long_desc %{
231
+ Copy all the files and urls that the first file is hooked to onto another file. Exactly two arguments (SOURCE, TARGET) required.
232
+ }
121
233
  arg_name 'SOURCE TARGET'
122
234
  command %i[clone] do |c|
123
235
  c.action do |_global_options, _options, args|
124
- raise "Wrong number of arguments. Two file paths or urls required (#{args.length} given)" if args.length != 2
236
+ exit_now!("Wrong number of arguments. Two file paths or urls required (#{args.length} given)", 5) if args.length != 2
125
237
 
126
- result = hooker.clone_hooks(args)
238
+ result = hookapp.clone_hooks(args)
127
239
  puts result
128
240
  end
129
241
  end
130
242
 
131
243
  desc 'Select from hooks on a file/url and open in default application'
244
+ long_desc %{
245
+ If the target file/URL has hooked items, a menu will be provided. Selecting one or more files
246
+ from this menu will open the item(s) using the default application assigned to the
247
+ filetype by macOS. Allows multiple selections with tab key, and type-ahead fuzzy filtering of results.
248
+ }
132
249
  arg_name 'FILE_OR_URL'
133
250
  command %i[select] do |c|
134
251
  c.action do |_global_options, _options, args|
135
- raise "Wrong number of arguments. One file path or url required (#{args.length} given)" if args.length != 1
252
+ exit_now!("Wrong number of arguments. One file path or url required (#{args.length} given)", 5) if args.length != 1
136
253
 
137
- hooker.open_linked(args[0])
254
+ hookapp.open_linked(args[0])
138
255
  end
139
256
  end
140
257
 
141
258
  desc 'Open the specified file or url in Hook GUI'
259
+ long_desc %{
260
+ Opens Hook.app on the specified file/URL for browsing and performing actions. Exactly one argument (File/URL) required.
261
+ }
142
262
  arg_name 'FILE_OR_URL'
143
263
  command %i[open gui] do |c|
144
264
  c.action do |_global_options, _options, args|
145
- raise "Wrong number of arguments. One file path or url required (#{args.length} given)" if args.length != 1
265
+ exit_now!("Wrong number of arguments. One file path or url required (#{args.length} given)", 5) if args.length != 1
146
266
 
147
- hooker.open_gui(args[0])
267
+ hookapp.open_gui(args[0])
148
268
  end
149
269
  end
150
270
 
271
+ desc 'Percent encode/decode a string'
272
+ long_desc %{Use encode or decode to apply Hook's url encoding to a string argument. Use '-' to read input from STDIN.}
273
+ arg_name 'STRING'
274
+ command :percent do |c|
275
+ c.desc 'percent encode a string'
276
+ c.arg_name 'STRING'
277
+ c.command :encode do |enc|
278
+ enc.action do |_global_options, _options, args|
279
+ if stdin
280
+ string = stdin
281
+ else
282
+ exit_now!('no string provided') unless args.size.positive?
283
+
284
+ string = args.join(' ').strip
285
+ end
286
+
287
+ print hookapp.encode(string)
288
+ end
289
+ end
290
+
291
+ c.desc 'decode a percent-encoded string'
292
+ c.arg_name 'STRING'
293
+ c.command :decode do |dec|
294
+ dec.action do |_global_options, _options, args|
295
+ if stdin
296
+ string = stdin
297
+ else
298
+ exit_now! ('no string provided') unless args.size.positive?
299
+
300
+ string = args.join(' ').strip
301
+ end
302
+
303
+ print hookapp.decode(string)
304
+ end
305
+ end
306
+
307
+ # c.default_command :encode
308
+ end
309
+
151
310
  pre do |global, _command, _options, _args|
152
311
  # Pre logic here
153
312
  # Return true to proceed; false to abort and not call the
154
313
  # chosen command
155
314
  # Use skips_pre before a command to skip this block
156
315
  # on that command only
157
- hooker = Hooker.new(global)
316
+ if !STDIN.tty?
317
+ stdin = STDIN.read.strip
318
+ end
319
+
320
+ hookapp = HookApp.new
158
321
  true
159
322
  end
160
323
 
data/buildnotes.md ADDED
@@ -0,0 +1,59 @@
1
+ # hookapp
2
+
3
+ Hook.app CLI
4
+
5
+ ## Editing
6
+
7
+ Main executable is located in `bin/hook`. All commands are defined here.
8
+
9
+ Helpers and main classes are in `lib/`.
10
+
11
+ @run(subl -p hookapp.sublime-project)
12
+
13
+ ## Building the Gem
14
+
15
+ @run(rake clobber rdoc package)
16
+
17
+ ## Deploy
18
+
19
+ 1. Bump version
20
+ 2. Commit and push to GitHub
21
+ 3. See Updating the Docs
22
+ 4. Package the gem (See Building the Gem)
23
+ 5. Push the gem with `gem push pkg/hookapp-[VERSION].gem`
24
+
25
+ ## Updating the Docs
26
+
27
+ Update the docs with `bundle exec bin/hook _doc --format=markdown` and `bundle exec bin/hook _doc --format=rdoc`, then run `rake rerdoc`
28
+
29
+ @run(bundle exec bin/hook _doc --format=rdoc && bundle exec bin/hook _doc --format=markdown && rake rerdoc)
30
+
31
+ ## Test
32
+
33
+ Run all tests using `rake test`.
34
+
35
+ Run verbose using `rake test TESTOPT="-v"`
36
+
37
+ Run a single test using `rake test TEST=test/TEST_FILE.rb`
38
+
39
+ This howzit task accepts an optional argument pointing to a specific test (just the test part of the filename, e.g. archive runs `test/doing_archive_test.rb`).
40
+
41
+ `howzit -r test -- archive` (or `bld test archive` with the Fish function)
42
+
43
+ ```run
44
+ #!/bin/bash
45
+ if [[ -n $1 ]]; then
46
+ rake test TESTOPT="-v" TEST=test/hook_$1_test.rb
47
+ if [[ $? != 0 ]]; then
48
+ echo "Available tests"
49
+ echo -e "\033[1;32;40m"
50
+ FILES="test/hook_*_test.rb"
51
+ for file in $FILES; do
52
+ echo $(basename $file ".rb") | sed -E 's/hook_(.*)_test/- \1/'
53
+ done
54
+ echo -e "\033[0m"
55
+ fi
56
+ else
57
+ rake test TESTOPT="-v"
58
+ fi
59
+ ```
data/hook.rdoc CHANGED
@@ -1,6 +1,9 @@
1
1
  == hook - CLI interface for Hook.app (macOS)
2
2
 
3
- v0.0.5
3
+ Hook.app is a productivity tool for macOS <https://hookproductivity.com/>.
4
+ This gem includes a `hook` binary that allows interaction with the features of Hook.app.
5
+
6
+ v2.0.7
4
7
 
5
8
  === Global Options
6
9
  === --help
@@ -17,7 +20,10 @@ Display the program version
17
20
  ==== Command: <tt>clip|cp FILE_OR_URL</tt>
18
21
  Copy Hook URL for file/url to clipboard
19
22
 
23
+ Creates a bookmark for the specified file or URL and copies its Hook URL to the clipboard.
20
24
 
25
+ The copied Hook URL can be used to link to other files (use `hook link --paste FILE/URL),
26
+ or to paste into another app as a link. Use the -m flag to copy a full Markdown link.
21
27
  ===== Options
22
28
  ===== -a|--app APP_NAME
23
29
 
@@ -34,11 +40,43 @@ Copy as Markdown
34
40
  ==== Command: <tt>clone SOURCE TARGET</tt>
35
41
  Clone all hooks from one file or url onto another
36
42
 
43
+ Copy all the files and urls that the first file is hooked to onto another file. Exactly two arguments (SOURCE, TARGET) required.
44
+ ==== Command: <tt>find|search SEARCH_STRING</tt>
45
+ Search bookmarks
46
+
47
+ Search bookmark urls and names for a string and output in specified format (default "paths").
48
+
49
+ Run `hook find` with no search argument to list all bookmarks.
50
+ ===== Options
51
+ ===== -o|--output_format format
52
+
53
+ Output format [(h)ooks, (p)aths, (m)arkdown, (v)erbose]
54
+
55
+ [Default Value] paths
56
+
57
+
58
+ ===== -f|--files_only
59
+ Output only bookmarks with file paths (exclude e.g. emails)
60
+
61
+
62
+
63
+ ===== -n|--names_only
64
+ Search only bookmark names
65
+
66
+
67
+
68
+ ===== --null
69
+ Separate results with NULL separator, only applies with "paths" output for single file argument
70
+
71
+
37
72
 
38
73
  ==== Command: <tt>from APPLICATION_NAME</tt>
39
74
  Get a Hook URL for the frontmost window of an app
40
75
 
76
+ Specify an application by name (without '.app') to bring that app to the foreground and create a bookmark
77
+ for the active document, note, task, etc., returning a Hook URL.
41
78
 
79
+ Use -m to get the response as Markdown, and/or -c to copy the result directly to the clipboard.
42
80
  ===== Options
43
81
  ===== -c|--copy
44
82
  Copy to clipboard
@@ -63,7 +101,13 @@ List commands one per line, to assist with shell completion
63
101
  ==== Command: <tt>link|ln SOURCE [SOURCE...] TARGET</tt>
64
102
  Create bidirectional hooks between two or more files/urls
65
103
 
104
+ If two files/urls are provided, links will be bi-directional.
105
+ If three or more are provided, `link` defaults to creating bi-directional
106
+ links between each file and the last file in the list. Use `-a` to create
107
+ bi-directional links between every file in the list.
66
108
 
109
+ If using `--paste`, the URL/hook link in the clipboard will be used as one argument,
110
+ to be combined with one or more file/url arguments.
67
111
  ===== Options
68
112
  ===== -a|--all
69
113
  Link every listed file or url to every other
@@ -78,7 +122,9 @@ Paste URL from clipboard
78
122
  ==== Command: <tt>list|ls FILE_OR_URL [FILE_OR_URL...]</tt>
79
123
  List hooks on a file or url
80
124
 
125
+ Output a list of all hooks attached to given url(s) or file(s) in the specified format (default "paths").
81
126
 
127
+ Run `hook list` with no file/url argument to list all bookmarks.
82
128
  ===== Options
83
129
  ===== -o|--output_format format
84
130
 
@@ -97,21 +143,53 @@ Separate results with NULL separator, only applies with "paths" output for singl
97
143
 
98
144
 
99
145
 
146
+ ===== -s|--[no-]select
147
+ Generate a menu to select hook(s) for opening
148
+
149
+ This option is a shortcut to `hook select` and overrides any other arguments.
150
+
100
151
  ==== Command: <tt>open|gui FILE_OR_URL</tt>
101
152
  Open the specified file or url in Hook GUI
102
153
 
154
+ Opens Hook.app on the specified file/URL for browsing and performing actions. Exactly one argument (File/URL) required.
155
+ ==== Command: <tt>percent STRING</tt>
156
+ Percent encode/decode a string
157
+
158
+ Use encode or decode to apply Hook's url encoding to a string argument. Use '-' to read input from STDIN.
159
+ ===== Commands
160
+ ====== Command: <tt>decode STRING</tt>
161
+ decode a percent-encoded string
162
+
163
+
164
+ ====== Command: <tt>encode STRING</tt>
165
+ percent encode a string
166
+
103
167
 
104
168
  ==== Command: <tt>remove|rm ITEM_1 ITEM_2</tt>
105
169
  Remove a hook between two files/urls
106
170
 
171
+ Remove a hook between two files or URLs. If you use --all, all hooks on a given file will be removed.
107
172
 
173
+ If --all isn't specified, exactly two arguments (Files/URLs) are required.
108
174
  ===== Options
109
- ===== -a|--[no-]all
175
+ ===== -a|--all
110
176
  Remove ALL links on files, requires confirmation
111
177
 
112
178
 
113
179
 
180
+ ===== -f|--force
181
+
182
+
183
+
184
+
185
+ ==== Command: <tt>scripts SHELL</tt>
186
+ Shell completion examples
187
+
188
+ Output completion script example for the specified shell (bash, zsh, fish)
114
189
  ==== Command: <tt>select FILE_OR_URL</tt>
115
190
  Select from hooks on a file/url and open in default application
116
191
 
117
-
192
+ If the target file/URL has hooked items, a menu will be provided. Selecting one or more files
193
+ from this menu will open the item(s) using the default application assigned to the
194
+ filetype by macOS. Allows multiple selections with tab key, and type-ahead fuzzy filtering of results.
195
+ [Default Command] help
data/hookapp.gemspec CHANGED
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Ensure we require the local version and not one we might have installed already
2
4
  require File.join([File.dirname(__FILE__), 'lib', 'hook', 'version.rb'])
3
- spec = Gem::Specification.new do |s|
5
+ Gem::Specification.new do |s|
4
6
  s.name = 'hookapp'
5
7
  s.version = Hook::VERSION
6
8
  s.author = 'Brett Terpstra'
@@ -8,15 +10,14 @@ spec = Gem::Specification.new do |s|
8
10
  s.homepage = 'https://brettterpstra.com'
9
11
  s.platform = Gem::Platform::RUBY
10
12
  s.summary = 'A CLI for Hook.app (macOS)'
11
- s.files = `git ls-files`.split("
12
- ")
13
+ s.files = `git ls-files`.split("\n")
13
14
  s.require_paths << 'lib'
14
- s.extra_rdoc_files = ['README.rdoc','hook.rdoc']
15
+ s.extra_rdoc_files = ['README.rdoc', 'hook.rdoc']
15
16
  s.rdoc_options << '--title' << 'hook' << '--main' << 'README.rdoc' << '-ri'
16
17
  s.bindir = 'bin'
17
18
  s.executables << 'hook'
18
- s.add_development_dependency('rake','~> 13.0.1')
19
- s.add_development_dependency('rdoc','~> 6.1.2')
20
- s.add_development_dependency('aruba','~> 0.14.14')
21
- s.add_runtime_dependency('gli','2.19.0')
19
+ s.add_development_dependency('aruba', '~> 0.14.14')
20
+ s.add_development_dependency('rake', '~> 13.0.1')
21
+ s.add_development_dependency('rdoc', '~> 6.3.2')
22
+ s.add_runtime_dependency('gli', '~> 2.20.1')
22
23
  end
@@ -0,0 +1,22 @@
1
+ # Source this script from ~/.bash_profile
2
+ _hook_targets()
3
+ {
4
+ local cmds cur ff
5
+ if (($COMP_CWORD == 1))
6
+ then
7
+ cur="${COMP_WORDS[1]}"
8
+ cmds="$(hook help -c)"
9
+ COMPREPLY=($(compgen -W "$cmds" -- "$cur"))
10
+ COMPREPLY=( "${COMPREPLY[@]/%/ }" )
11
+ else
12
+ # get all matching files and directories
13
+ COMPREPLY=($(compgen -f -- "${COMP_WORDS[$COMP_CWORD]}"))
14
+
15
+ for ((ff=0; ff<${#COMPREPLY[@]}; ff++)); do
16
+ [[ -d ${COMPREPLY[$ff]} ]] && COMPREPLY[$ff]+='/'
17
+ [[ -f ${COMPREPLY[$ff]} ]] && COMPREPLY[$ff]+=' '
18
+ done
19
+ fi
20
+ }
21
+
22
+ complete -o bashdefault -o default -o nospace -F _hook_targets hook
@@ -0,0 +1,31 @@
1
+ # Save this script in ~/.config/fish/completions/hook.fish
2
+ function __fish_hook_needs_command
3
+ # Figure out if the current invocation already has a command.
4
+
5
+ set -l opts h-help v-version
6
+ set cmd (commandline -opc)
7
+ set -e cmd[1]
8
+ argparse -s $opts -- $cmd 2>/dev/null
9
+ or return 0
10
+ # These flags function as commands, effectively.
11
+ if set -q argv[1]
12
+ # Also print the command, so this can be used to figure out what it is.
13
+ echo $argv[1]
14
+ return 1
15
+ end
16
+ return 0
17
+ end
18
+
19
+ function __fish_hook_using_command
20
+ set -l cmd (__fish_hook_needs_command)
21
+ test -z "$cmd"
22
+ and return 1
23
+ contains -- $cmd $argv
24
+ and return 0
25
+ end
26
+
27
+ function __fish_hook_subcommands
28
+ hook help -c
29
+ end
30
+
31
+ complete -xc hook -n '__fish_hook_needs_command' -a '(__fish_hook_subcommands)'
@@ -0,0 +1,22 @@
1
+ # Source this script from ~/.zshrc
2
+ _hook_targets()
3
+ {
4
+ local cmds cur ff
5
+ if (($COMP_CWORD == 1))
6
+ then
7
+ cur="${COMP_WORDS[1]}"
8
+ cmds="$(hook help -c)"
9
+ COMPREPLY=($(compgen -W "$cmds" -- "$cur"))
10
+ COMPREPLY=( "${COMPREPLY[@]/%/ }" )
11
+ else
12
+ # get all matching files and directories
13
+ COMPREPLY=($(compgen -f -- "${COMP_WORDS[$COMP_CWORD]}"))
14
+
15
+ for ((ff=0; ff<${#COMPREPLY[@]}; ff++)); do
16
+ [[ -d ${COMPREPLY[$ff]} ]] && COMPREPLY[$ff]+='/'
17
+ [[ -f ${COMPREPLY[$ff]} ]] && COMPREPLY[$ff]+=' '
18
+ done
19
+ fi
20
+ }
21
+
22
+ complete -o bashdefault -o default -o nospace -F _hook_targets hook
Binary file