hookapp 2.0.5 → 2.0.9

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.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/AUTHORS.md +4 -0
  3. data/CHANGELOG.md +9 -0
  4. data/Gemfile.lock +35 -40
  5. data/LICENSE +21 -0
  6. data/README.md +52 -19
  7. data/Rakefile +7 -3
  8. data/bin/hook +102 -65
  9. data/buildnotes.md +30 -0
  10. data/hook.rdoc +35 -11
  11. data/hookapp.gemspec +1 -0
  12. data/html/App.html +1 -1
  13. data/html/GLI/Commands/Doc.html +1 -1
  14. data/html/GLI/Commands/MarkdownDocumentListener.html +27 -17
  15. data/html/GLI/Commands.html +1 -1
  16. data/html/GLI.html +1 -1
  17. data/html/Hook.html +1 -1
  18. data/html/HookApp.html +106 -44
  19. data/html/Hooker.html +2 -2
  20. data/html/README_rdoc.html +47 -18
  21. data/html/String.html +23 -1
  22. data/html/created.rid +9 -8
  23. data/html/index.html +39 -12
  24. data/html/js/navigation.js.gz +0 -0
  25. data/html/js/search_index.js +1 -1
  26. data/html/js/search_index.js.gz +0 -0
  27. data/html/js/searcher.js.gz +0 -0
  28. data/html/table_of_contents.html +71 -7
  29. data/lib/hook/hookapp.rb +40 -22
  30. data/lib/hook/hooker.rb +1 -0
  31. data/lib/hook/markdown_document_listener.rb +12 -2
  32. data/lib/hook/prompt.rb +113 -0
  33. data/lib/hook/string.rb +4 -0
  34. data/lib/hook/version.rb +1 -1
  35. data/lib/hook.rb +2 -0
  36. data/test/helpers/hook-helpers.rb +76 -0
  37. data/test/hook_clip_test.rb +24 -0
  38. data/test/hook_clone_test.rb +30 -0
  39. data/test/hook_encode_test.rb +30 -0
  40. data/test/hook_link_test.rb +40 -0
  41. data/test/hook_list_test.rb +25 -0
  42. data/test/hook_remove_test.rb +34 -0
  43. data/test/hook_scripts_test.rb +21 -0
  44. metadata +33 -16
  45. data/lib/helpers/fuzzyfilefinder +0 -0
  46. data/test/default_test.rb +0 -14
  47. data/test/hookfiles/01.test +0 -0
  48. data/test/hookfiles/02.test +0 -0
  49. data/test/hookfiles/03.test +0 -0
  50. data/test/hookfiles/04.test +0 -0
  51. data/test/hookfiles/05.test +0 -0
  52. data/test/hookfiles/06.test +0 -0
  53. data/test/hookfiles/07.test +0 -0
  54. data/test/hookfiles/08.test +0 -0
  55. data/test/hookfiles/09.test +0 -0
  56. data/test/hookfiles/10.test +0 -0
  57. data/test/hookfiles/11.test +0 -0
  58. data/test/hookfiles/12.test +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 06acc4dd72c5ca227e0cbf252542ca79e42a31d624b5e78f609cfb019220f3c3
4
- data.tar.gz: 6f2f660014f3486dd80a0fd06c52aa6822844097580780b6addf247ee0ee8cee
3
+ metadata.gz: 5a5b6a517bd76ec8ddfc8ef6ffb98d6690dc56c2d5133bb1ad88635d72aaf55e
4
+ data.tar.gz: ddd95cde21eba658a09a98c04c49a03e98853bc450b257d2f6ad843cdf084f35
5
5
  SHA512:
6
- metadata.gz: 4c3c57b1879c66c9ce671bf3eb7a676e9d543962a50c0647ade2d451f93207c071d34c67a93ccdde8fcf5d19e54a0bb53a056e8cba928e5c6b6cdf69868b69ab
7
- data.tar.gz: 5ba08b7b5ef07d6d0062fc18cfea73957d83146194185de9e1d1cbaf8f5680f230792a919a954099b03e26c023fe204766ece2429acc9fe4de1b0e233418d76a
6
+ metadata.gz: 2ab5784b34f8a8380b37202cd1a674c78083e6ec1748f3320f4292933a7cc20cd20db520daa7fd697dade590fa32d5f7d21224e1ebae4396fe5ec2aaff7f6081
7
+ data.tar.gz: b45ce5ede9b4fa988f660fb5943b0ce1a7ee8e7bfffd9d0d5a45b0a4138c1db812a8f36dffcba02159e20f370e64e2b611e2e968a61fbf2d763ec03295d927d2
data/AUTHORS.md ADDED
@@ -0,0 +1,4 @@
1
+ ## Authors
2
+
3
+ - Brett Terpstra <me@brettterpstra.com>
4
+ - Josh Nichols <joshua.nichols@gmail.com>
data/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ #### 2.0.9
2
+
3
+ - Fix fzf integration across platforms
4
+
5
+ #### 2.0.8
6
+
7
+ - Bug fixes
8
+ - New tests
9
+
1
10
  #### 2.0.3
2
11
 
3
12
  - Incorporate `fzf` for selecting and filtering hooks
data/Gemfile.lock CHANGED
@@ -1,8 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- hookapp (2.0.4)
4
+ hookapp (2.0.9)
5
5
  gli (~> 2.20.1)
6
+ tty-which (~> 0.5, >= 0.5.0)
6
7
 
7
8
  GEM
8
9
  remote: http://rubygems.org/
@@ -17,53 +18,47 @@ GEM
17
18
  builder (3.2.4)
18
19
  childprocess (3.0.0)
19
20
  contracts (0.17)
20
- cucumber (7.0.0)
21
+ cucumber (8.0.0)
21
22
  builder (~> 3.2, >= 3.2.4)
22
- cucumber-core (~> 10.0, >= 10.0.1)
23
- cucumber-create-meta (~> 6.0, >= 6.0.1)
24
- cucumber-cucumber-expressions (~> 12.1, >= 12.1.1)
25
- cucumber-gherkin (~> 20.0, >= 20.0.1)
26
- cucumber-html-formatter (~> 16.0, >= 16.0.1)
27
- cucumber-messages (~> 17.0, >= 17.0.1)
28
- cucumber-wire (~> 6.0, >= 6.0.1)
29
- diff-lcs (~> 1.4, >= 1.4.4)
30
- mime-types (~> 3.3, >= 3.3.1)
31
- multi_test (~> 0.1, >= 0.1.2)
23
+ cucumber-ci-environment (~> 9.0, >= 9.0.4)
24
+ cucumber-core (~> 11.0, >= 11.0.0)
25
+ cucumber-cucumber-expressions (~> 15.1, >= 15.1.1)
26
+ cucumber-gherkin (~> 23.0, >= 23.0.1)
27
+ cucumber-html-formatter (~> 19.1, >= 19.1.0)
28
+ cucumber-messages (~> 18.0, >= 18.0.0)
29
+ diff-lcs (~> 1.5, >= 1.5.0)
30
+ mime-types (~> 3.4, >= 3.4.1)
31
+ multi_test (~> 1.1, >= 1.1.0)
32
32
  sys-uname (~> 1.2, >= 1.2.2)
33
- cucumber-core (10.0.1)
34
- cucumber-gherkin (~> 20.0, >= 20.0.1)
35
- cucumber-messages (~> 17.0, >= 17.0.1)
36
- cucumber-tag-expressions (~> 3.0, >= 3.0.1)
37
- cucumber-create-meta (6.0.1)
38
- cucumber-messages (~> 17.0, >= 17.0.1)
39
- sys-uname (~> 1.2, >= 1.2.2)
40
- cucumber-cucumber-expressions (12.1.3)
41
- cucumber-gherkin (20.0.1)
42
- cucumber-messages (~> 17.0, >= 17.0.1)
43
- cucumber-html-formatter (16.0.1)
44
- cucumber-messages (~> 17.0, >= 17.0.1)
45
- cucumber-messages (17.1.1)
46
- cucumber-tag-expressions (3.0.1)
47
- cucumber-wire (6.1.1)
48
- cucumber-core (~> 10.0, >= 10.0.1)
49
- cucumber-cucumber-expressions (~> 12.1, >= 12.1.2)
50
- cucumber-messages (~> 17.0, >= 17.0.1)
51
- diff-lcs (1.4.4)
52
- ffi (1.15.4)
33
+ cucumber-ci-environment (9.0.4)
34
+ cucumber-core (11.0.0)
35
+ cucumber-gherkin (~> 23.0, >= 23.0.1)
36
+ cucumber-messages (~> 18.0, >= 18.0.0)
37
+ cucumber-tag-expressions (~> 4.1, >= 4.1.0)
38
+ cucumber-cucumber-expressions (15.2.0)
39
+ cucumber-gherkin (23.0.1)
40
+ cucumber-messages (~> 18.0, >= 18.0.0)
41
+ cucumber-html-formatter (19.1.0)
42
+ cucumber-messages (~> 18.0, >= 18.0.0)
43
+ cucumber-messages (18.0.0)
44
+ cucumber-tag-expressions (4.1.0)
45
+ diff-lcs (1.5.0)
46
+ ffi (1.15.5)
53
47
  gli (2.20.1)
54
- mime-types (3.3.1)
48
+ mime-types (3.4.1)
55
49
  mime-types-data (~> 3.2015)
56
- mime-types-data (3.2021.0901)
57
- multi_test (0.1.2)
50
+ mime-types-data (3.2022.0105)
51
+ multi_test (1.1.0)
58
52
  rake (13.0.6)
59
- rdoc (6.3.2)
60
- rspec-expectations (3.10.1)
53
+ rdoc (6.3.3)
54
+ rspec-expectations (3.11.0)
61
55
  diff-lcs (>= 1.2.0, < 2.0)
62
- rspec-support (~> 3.10.0)
63
- rspec-support (3.10.2)
56
+ rspec-support (~> 3.11.0)
57
+ rspec-support (3.11.0)
64
58
  sys-uname (1.2.2)
65
59
  ffi (~> 1.1)
66
- thor (1.1.0)
60
+ thor (1.2.1)
61
+ tty-which (0.5.0)
67
62
 
68
63
  PLATFORMS
69
64
  ruby
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2021 Brett Terpstra
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md CHANGED
@@ -2,9 +2,11 @@
2
2
 
3
3
  CLI interface for Hook.app (macOS)
4
4
 
5
- > Hook.app is a productivity tool for macOS <https://hookproductivity.com/>. This gem includes a `hook` binary that allows interaction with the features of Hook.app.
5
+ > Hook.app is a productivity tool for macOS <https://hookproductivity.com/>.
6
6
 
7
- *v2.0.3*
7
+ This gem includes a `hook` binary that allows interaction with the features of Hook.app.
8
+
9
+ *v2.0.9*
8
10
 
9
11
  ## Installation
10
12
 
@@ -99,13 +101,13 @@ Display the program version
99
101
 
100
102
  ## Commands
101
103
 
102
- ### `$ hook` <mark>`clip|cp`</mark> ` FILE_OR_URL`
104
+ ### `$ hook` <mark>`clip|cp`</mark> `FILE_OR_URL`
103
105
 
104
106
  *Copy Hook URL for file/url to clipboard*
105
107
 
106
108
  > Creates a bookmark for the specified file or URL and copies its Hook URL to the clipboard.
107
109
  >
108
- > The copied Hook URL can be used to link to other files (use `hook link --paste FILE/URL),
110
+ > The copied Hook URL can be used to link to other files (use `hook link --paste FILE/URL`,
109
111
  > or to paste into another app as a link. Use the -m flag to copy a full Markdown link.
110
112
 
111
113
  #### Options
@@ -120,15 +122,17 @@ Copy as Markdown
120
122
 
121
123
  * * * * * *
122
124
 
123
- ### `$ hook` <mark>`clone`</mark> ` SOURCE TARGET`
125
+ ### `$ hook` <mark>`clone`</mark> `SOURCE TARGET`
124
126
 
125
127
  *Clone all hooks from one file or url onto another*
126
128
 
127
- > Copy all the files and urls that the first file is hooked to onto another file. Exactly two arguments (SOURCE, TARGET) required.
129
+ > Copy all the files and urls that the first file is hooked to onto another file.
130
+ >
131
+ > Exactly two arguments (SOURCE, TARGET) required.
128
132
 
129
133
  * * * * * *
130
134
 
131
- ### `$ hook` <mark>`find|search`</mark> ` SEARCH_STRING`
135
+ ### `$ hook` <mark>`find|search`</mark> `[SEARCH_STRING]`
132
136
 
133
137
  *Search bookmarks*
134
138
 
@@ -138,7 +142,7 @@ Copy as Markdown
138
142
 
139
143
  #### Options
140
144
 
141
- ##### `-o` | `--output_format` format
145
+ ##### `-o` | `--output_format` FORMAT
142
146
 
143
147
  Output format [(h)ooks, (p)aths, (m)arkdown, (v)erbose]
144
148
 
@@ -158,7 +162,7 @@ Separate results with NULL separator, only applies with "paths" output for singl
158
162
 
159
163
  * * * * * *
160
164
 
161
- ### `$ hook` <mark>`from`</mark> ` APPLICATION_NAME`
165
+ ### `$ hook` <mark>`from`</mark> `APPLICATION_NAME`
162
166
 
163
167
  *Get a Hook URL for the frontmost window of an app*
164
168
 
@@ -179,7 +183,7 @@ Output as Markdown
179
183
 
180
184
  * * * * * *
181
185
 
182
- ### `$ hook` <mark>`help`</mark> ` command`
186
+ ### `$ hook` <mark>`help`</mark> `command`
183
187
 
184
188
  *Shows a list of commands or help for one command*
185
189
 
@@ -193,7 +197,7 @@ List commands one per line, to assist with shell completion
193
197
 
194
198
  * * * * * *
195
199
 
196
- ### `$ hook` <mark>`link|ln`</mark> ` SOURCE [SOURCE...] TARGET`
200
+ ### `$ hook` <mark>`link|ln`</mark> `SOURCE... TARGET`
197
201
 
198
202
  *Create bidirectional hooks between two or more files/urls*
199
203
 
@@ -217,7 +221,7 @@ Paste URL from clipboard
217
221
 
218
222
  * * * * * *
219
223
 
220
- ### `$ hook` <mark>`list|ls`</mark> ` FILE_OR_URL [FILE_OR_URL...]`
224
+ ### `$ hook` <mark>`list|ls`</mark> `[FILE_OR_URL]...`
221
225
 
222
226
  *List hooks on a file or url*
223
227
 
@@ -227,7 +231,7 @@ Paste URL from clipboard
227
231
 
228
232
  #### Options
229
233
 
230
- ##### `-o` | `--output_format` format
234
+ ##### `-o` | `--output_format` FORMAT
231
235
 
232
236
  Output format [(h)ooks, (p)aths, (m)arkdown, (v)erbose]
233
237
 
@@ -249,15 +253,35 @@ Generate a menu to select hook(s) for opening
249
253
 
250
254
  * * * * * *
251
255
 
252
- ### `$ hook` <mark>`open|gui`</mark> ` FILE_OR_URL`
256
+ ### `$ hook` <mark>`open|gui`</mark> `FILE_OR_URL`
253
257
 
254
258
  *Open the specified file or url in Hook GUI*
255
259
 
256
- > Opens Hook.app on the specified file/URL for browsing and performing actions. Exactly one argument (File/URL) required.
260
+ > Opens Hook.app on the specified file/URL for browsing and performing actions.
261
+ >
262
+ > Exactly one argument (File/URL) required.
263
+
264
+ * * * * * *
265
+
266
+ ### `$ hook` <mark>`percent`</mark> `STRING`
267
+
268
+ *Percent encode/decode a string*
269
+
270
+ > Use encode or decode to apply Hook's url encoding to a string argument. Use '-' to read input from STDIN.
271
+
272
+ #### Commands
273
+
274
+ ##### `$ hook` <mark>`percent decode`</mark> `STRING`
275
+
276
+ *decode a percent-encoded string*
277
+
278
+ ##### `$ hook` <mark>`percent encode`</mark> `STRING`
279
+
280
+ *percent encode a string*
257
281
 
258
282
  * * * * * *
259
283
 
260
- ### `$ hook` <mark>`remove|rm`</mark> ` ITEM_1 ITEM_2`
284
+ ### `$ hook` <mark>`remove|rm`</mark> `FILE_OR_URL...`
261
285
 
262
286
  *Remove a hook between two files/urls*
263
287
 
@@ -271,9 +295,13 @@ Generate a menu to select hook(s) for opening
271
295
 
272
296
  Remove ALL links on files, requires confirmation
273
297
 
298
+ ##### `-f`|`--force`
299
+
300
+
301
+
274
302
  * * * * * *
275
303
 
276
- ### `$ hook` <mark>`scripts`</mark> ` SHELL`
304
+ ### `$ hook` <mark>`scripts`</mark> `SHELL`
277
305
 
278
306
  *Shell completion examples*
279
307
 
@@ -281,7 +309,7 @@ Remove ALL links on files, requires confirmation
281
309
 
282
310
  * * * * * *
283
311
 
284
- ### `$ hook` <mark>`select`</mark> ` FILE_OR_URL`
312
+ ### `$ hook` <mark>`select`</mark> `FILE_OR_URL`
285
313
 
286
314
  *Select from hooks on a file/url and open in default application*
287
315
 
@@ -292,6 +320,11 @@ Remove ALL links on files, requires confirmation
292
320
  * * * * * *
293
321
 
294
322
  #### [Default Command] help
323
+ ## Authors
324
+
325
+ - Brett Terpstra <me@brettterpstra.com>
326
+ - Josh Nichols <joshua.nichols@gmail.com>
327
+
295
328
  ## Credits
296
329
 
297
330
  HookApp embeds [Fuzzy Finder](https://github.com/junegunn/fzf) under the [MIT License](https://github.com/junegunn/fzf/blob/master/LICENSE)
@@ -325,5 +358,5 @@ This software is licensed under the MIT License.
325
358
  THE SOFTWARE.
326
359
 
327
360
 
328
- Documentation generated 2021-09-18 12:29
361
+ Documentation generated 2022-05-26 08:29
329
362
 
data/Rakefile CHANGED
@@ -4,6 +4,7 @@ require 'rubygems/package_task'
4
4
  require 'rdoc/task'
5
5
  require 'cucumber'
6
6
  require 'cucumber/rake/task'
7
+ require 'rake/testtask'
7
8
  Rake::RDocTask.new do |rd|
8
9
  rd.main = "README.rdoc"
9
10
  rd.rdoc_files.include("README.rdoc","lib/**/*.rb","bin/**/*")
@@ -14,6 +15,7 @@ spec = eval(File.read('hookapp.gemspec'))
14
15
 
15
16
  Gem::PackageTask.new(spec) do |pkg|
16
17
  end
18
+
17
19
  CUKE_RESULTS = 'results.html'
18
20
  CLEAN << CUKE_RESULTS
19
21
  desc 'Run features'
@@ -35,10 +37,12 @@ end
35
37
  task :cucumber => :features
36
38
  task 'cucumber:wip' => 'features:wip'
37
39
  task :wip => 'features:wip'
38
- require 'rake/testtask'
40
+
39
41
  Rake::TestTask.new do |t|
40
- t.libs << "test"
42
+ t.libs << ['test', 'test/helpers']
41
43
  t.test_files = FileList['test/*_test.rb']
44
+ t.verbose = ENV['VERBOSE'] =~ /(true|1)/i ? true : false
42
45
  end
43
46
 
44
- task :default => [:test,:features]
47
+ # task :default => [:test,:features]
48
+ task :default => [:test]
data/bin/hook CHANGED
@@ -1,14 +1,17 @@
1
- #!/usr/bin/env ruby
1
+ #!/usr/bin/env ruby -W1
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require 'hook'
5
+ require 'shellwords'
5
6
 
6
7
  # Main class for GLI app
7
8
  class App
8
9
  extend GLI::App
9
10
 
10
11
  program_desc 'CLI interface for Hook.app (macOS)'
11
- program_long_desc 'Hook.app is a productivity tool for macOS <https://hookproductivity.com/>. This gem includes a `hook` binary that allows interaction with the features of Hook.app.'
12
+ program_long_desc 'Hook.app is a productivity tool for macOS <https://hookproductivity.com/>.
13
+
14
+ This gem includes a `hook` binary that allows interaction with the features of Hook.app.'
12
15
  default_command 'help'
13
16
  autocomplete_commands = true
14
17
  synopsis_format(:terminal)
@@ -19,14 +22,13 @@ class App
19
22
  arguments :strict
20
23
 
21
24
  hookapp = nil
25
+ stdin = nil
22
26
 
23
27
  desc 'List hooks on a file or url'
24
- long_desc %{
25
- Output a list of all hooks attached to given url(s) or file(s) in the specified format (default "paths").
26
-
27
- Run `hook list` with no file/url argument to list all bookmarks.}
28
+ long_desc %(Output a list of all hooks attached to given url(s) or file(s) in the specified format (default "paths").
28
29
 
29
- arg_name 'FILE_OR_URL [FILE_OR_URL...]'
30
+ Run `hook list` with no file/url argument to list all bookmarks.)
31
+ arg_name 'FILE_OR_URL', [:optional, :multiple]
30
32
  command %i[list ls] do |c|
31
33
  c.desc 'Generate a menu to select hook(s) for opening'
32
34
  c.long_desc 'This option is a shortcut to `hook select` and overrides any other arguments.'
@@ -41,20 +43,22 @@ Run `hook list` with no file/url argument to list all bookmarks.}
41
43
  valid_formats = %w[hooks paths markdown verbose]
42
44
  fmt_list = valid_formats.map { |fmt| fmt.sub(/^(.)(.*?)$/, '(\1)\2') }.join(', ')
43
45
  c.desc "Output format [#{fmt_list}]"
44
- c.flag %i[o output_format], { arg_name: 'format', default_value: 'paths' }
46
+ c.arg_name 'FORMAT'
47
+ c.flag %i[o output_format], { arg_name: 'FORMAT', default_value: 'paths' }
45
48
 
46
49
  c.action do |_global_options, options, args|
47
50
  if options[:s]
48
- return hookapp.open_linked(args[0])
49
- end
50
- valid_format = hookapp.validate_format(options[:o], valid_formats)
51
- exit_now!("Invalid output format: \"#{options[:o]}\"", 6) unless valid_format
51
+ hookapp.open_linked(args[0])
52
+ else
53
+ valid_format = hookapp.validate_format(options[:o], valid_formats)
54
+ help_now!("Invalid output format: \"#{options[:o]}\"", 6) unless valid_format
52
55
 
53
- result = hookapp.linked_bookmarks(args, { files_only: options[:f],
54
- format: valid_format,
55
- null_separator: options[:null] })
56
+ result = hookapp.linked_bookmarks(args, { files_only: options[:f],
57
+ format: valid_format,
58
+ null_separator: options[:null] })
56
59
 
57
- puts result
60
+ puts result
61
+ end
58
62
  end
59
63
  end
60
64
 
@@ -62,25 +66,21 @@ Run `hook list` with no file/url argument to list all bookmarks.}
62
66
  # the full shell name as the extension, e.g. "hook_completion.bash".
63
67
  desc 'Shell completion examples'
64
68
  valid_shells = %w[bash zsh fish]
65
- long_desc %{
66
- Output completion script example for the specified shell (#{valid_shells.join(', ')})
67
- }
69
+ long_desc %(Output completion script example for the specified shell (#{valid_shells.join(', ')}))
68
70
  arg_name 'SHELL'
69
71
  command %i[scripts] do |c|
70
72
  c.action do |_global_options, _options, args|
71
73
  if args.length > 1
72
- exit_now!("Invalid number of arguments, (expected 1)", 5)
74
+ help_now!('Invalid number of arguments, (expected 1)', 5)
73
75
  elsif args.nil? || args.empty?
74
- exit_now!("Specify a shell (#{valid_shells.join(', ')})", 0)
76
+ help_now!("Specify a shell (#{valid_shells.join(', ')})", 0)
77
+ elsif valid_shells.include?(args[0])
78
+ base_dir = File.expand_path(File.join(File.dirname(__FILE__), '../lib/completion'))
79
+ completion = File.join(base_dir, "hook_completion.#{args[0]}")
80
+ script = IO.read(completion)
81
+ $stdout.puts script
75
82
  else
76
- if valid_shells.include?(args[0])
77
- base_dir = File.expand_path(File.join(File.dirname(__FILE__), '../lib/completion'))
78
- completion = File.join(base_dir, "hook_completion.#{args[0]}")
79
- script = IO.read(completion)
80
- $stdout.puts script
81
- else
82
- exit_now!("Invalid shell name, must be one of #{valid_shells.join(', ')}", 1)
83
- end
83
+ help_now!("Invalid shell name, must be one of #{valid_shells.join(', ')}", 1)
84
84
  end
85
85
  end
86
86
  end
@@ -88,11 +88,10 @@ Output completion script example for the specified shell (#{valid_shells.join(',
88
88
 
89
89
 
90
90
  desc 'Search bookmarks'
91
- long_desc %{
92
- Search bookmark urls and names for a string and output in specified format (default "paths").
91
+ long_desc %(Search bookmark urls and names for a string and output in specified format (default "paths").
93
92
 
94
- Run `hook find` with no search argument to list all bookmarks.}
95
- arg_name 'SEARCH_STRING'
93
+ Run `hook find` with no search argument to list all bookmarks.)
94
+ arg_name 'SEARCH_STRING', :optional
96
95
  command %i[find search] do |c|
97
96
  c.desc 'Output only bookmarks with file paths (exclude e.g. emails)'
98
97
  c.switch %i[f files_only], { negatable: false, default_value: false }
@@ -104,7 +103,7 @@ Run `hook find` with no search argument to list all bookmarks.}
104
103
  fmt_list = valid_formats.map { |fmt| fmt.sub(/^(.)(.*?)$/, '(\1)\2') }.join(', ')
105
104
 
106
105
  c.desc "Output format [#{fmt_list}]"
107
- c.flag %i[o output_format], { arg_name: 'format', default_value: 'paths' }
106
+ c.flag %i[o output_format], { arg_name: 'FORMAT', default_value: 'paths' }
108
107
 
109
108
  c.desc "Search only bookmark names"
110
109
  c.switch %i[n names_only], { negatable: false, default_value: false }
@@ -123,16 +122,15 @@ Run `hook find` with no search argument to list all bookmarks.}
123
122
  end
124
123
 
125
124
  desc 'Create bidirectional hooks between two or more files/urls'
126
- long_desc %{
127
- If two files/urls are provided, links will be bi-directional.
125
+ long_desc 'If two files/urls are provided, links will be bi-directional.
128
126
  If three or more are provided, `link` defaults to creating bi-directional
129
127
  links between each file and the last file in the list. Use `-a` to create
130
128
  bi-directional links between every file in the list.
131
129
 
132
130
  If using `--paste`, the URL/hook link in the clipboard will be used as one argument,
133
131
  to be combined with one or more file/url arguments.
134
- }
135
- arg_name 'SOURCE [SOURCE...] TARGET'
132
+ '
133
+ arg_name 'SOURCE... TARGET'
136
134
  command %i[link ln] do |c|
137
135
  c.desc 'Link every listed file or url to every other'
138
136
  c.switch %i[a all], { negatable: false, default_value: false }
@@ -158,12 +156,10 @@ to be combined with one or more file/url arguments.
158
156
  end
159
157
 
160
158
  desc 'Copy Hook URL for file/url to clipboard'
161
- long_desc %{
162
- Creates a bookmark for the specified file or URL and copies its Hook URL to the clipboard.
159
+ long_desc %{Creates a bookmark for the specified file or URL and copies its Hook URL to the clipboard.
163
160
 
164
- The copied Hook URL can be used to link to other files (use `hook link --paste FILE/URL),
165
- or to paste into another app as a link. Use the -m flag to copy a full Markdown link.
166
- }
161
+ The copied Hook URL can be used to link to other files (use `hook link --paste FILE/URL`,
162
+ or to paste into another app as a link. Use the -m flag to copy a full Markdown link.}
167
163
  arg_name 'FILE_OR_URL'
168
164
  command %i[clip cp] do |c|
169
165
  c.desc 'Copy as Markdown'
@@ -184,12 +180,10 @@ or to paste into another app as a link. Use the -m flag to copy a full Markdown
184
180
  end
185
181
 
186
182
  desc 'Get a Hook URL for the frontmost window of an app'
187
- long_desc %{
188
- Specify an application by name (without '.app') to bring that app to the foreground and create a bookmark
183
+ long_desc %(Specify an application by name (without '.app') to bring that app to the foreground and create a bookmark
189
184
  for the active document, note, task, etc., returning a Hook URL.
190
185
 
191
- Use -m to get the response as Markdown, and/or -c to copy the result directly to the clipboard.
192
- }
186
+ Use -m to get the response as Markdown, and/or -c to copy the result directly to the clipboard.)
193
187
  arg_name 'APPLICATION_NAME'
194
188
  command %i[from] do |c|
195
189
  c.desc 'Output as Markdown'
@@ -206,26 +200,25 @@ Use -m to get the response as Markdown, and/or -c to copy the result directly to
206
200
  end
207
201
 
208
202
  desc 'Remove a hook between two files/urls'
209
- long_desc %{
210
- Remove a hook between two files or URLs. If you use --all, all hooks on a given file will be removed.
203
+ long_desc %(Remove a hook between two files or URLs. If you use --all, all hooks on a given file will be removed.
211
204
 
212
- If --all isn't specified, exactly two arguments (Files/URLs) are required.
213
- }
214
- arg_name 'ITEM_1 ITEM_2'
205
+ If --all isn't specified, exactly two arguments (Files/URLs) are required.)
206
+ arg_name 'FILE_OR_URL', :multiple
215
207
  command %i[remove rm] do |c|
216
208
  c.desc 'Remove ALL links on files, requires confirmation'
217
209
  c.switch %i[a all], { negatable: false, default_value: false }
210
+ c.switch %i[f force], { negatable: false, default_value: false }
218
211
 
219
212
  c.action do |_global_options, options, args|
220
- result = hookapp.delete_hooks(args, { all: options[:a] })
213
+ result = hookapp.delete_hooks(args, { all: options[:all], force: options[:force] })
221
214
  puts result
222
215
  end
223
216
  end
224
217
 
225
218
  desc 'Clone all hooks from one file or url onto another'
226
- long_desc %{
227
- Copy all the files and urls that the first file is hooked to onto another file. Exactly two arguments (SOURCE, TARGET) required.
228
- }
219
+ long_desc 'Copy all the files and urls that the first file is hooked to onto another file.
220
+
221
+ Exactly two arguments (SOURCE, TARGET) required.'
229
222
  arg_name 'SOURCE TARGET'
230
223
  command %i[clone] do |c|
231
224
  c.action do |_global_options, _options, args|
@@ -237,39 +230,83 @@ Copy all the files and urls that the first file is hooked to onto another file.
237
230
  end
238
231
 
239
232
  desc 'Select from hooks on a file/url and open in default application'
240
- long_desc %{
241
- If the target file/URL has hooked items, a menu will be provided. Selecting one or more files
233
+ long_desc %(If the target file/URL has hooked items, a menu will be provided. Selecting one or more files
242
234
  from this menu will open the item(s) using the default application assigned to the
243
- filetype by macOS. Allows multiple selections with tab key, and type-ahead fuzzy filtering of results.
244
- }
235
+ filetype by macOS. Allows multiple selections with tab key, and type-ahead fuzzy filtering of results.)
245
236
  arg_name 'FILE_OR_URL'
246
237
  command %i[select] do |c|
247
238
  c.action do |_global_options, _options, args|
248
- exit_now!("Wrong number of arguments. One file path or url required (#{args.length} given)", 5) if args.length != 1
239
+ help_now!("Wrong number of arguments. One file path or url required (#{args.length} given)", 5) if args.length != 1
249
240
 
250
241
  hookapp.open_linked(args[0])
251
242
  end
252
243
  end
253
244
 
254
245
  desc 'Open the specified file or url in Hook GUI'
255
- long_desc %{
256
- Opens Hook.app on the specified file/URL for browsing and performing actions. Exactly one argument (File/URL) required.
257
- }
246
+ long_desc 'Opens Hook.app on the specified file/URL for browsing and performing actions.
247
+
248
+ Exactly one argument (File/URL) required.'
258
249
  arg_name 'FILE_OR_URL'
259
250
  command %i[open gui] do |c|
260
251
  c.action do |_global_options, _options, args|
261
- exit_now!("Wrong number of arguments. One file path or url required (#{args.length} given)", 5) if args.length != 1
252
+ if args.length != 1
253
+ help_now!("Wrong number of arguments. One file path
254
+ or url required (#{args.length} given)", 5)
255
+ end
262
256
 
263
257
  hookapp.open_gui(args[0])
264
258
  end
265
259
  end
266
260
 
261
+ desc 'Percent encode/decode a string'
262
+ long_desc %(Use encode or decode to apply Hook's url encoding to a string argument. Use '-' to read input from STDIN.)
263
+ arg_name 'STRING'
264
+ command :percent do |c|
265
+ c.desc 'percent encode a string'
266
+ c.arg_name 'STRING'
267
+ c.command :encode do |enc|
268
+ enc.action do |_global_options, _options, args|
269
+ if stdin
270
+ string = stdin
271
+ else
272
+ help_now!('No string provided') unless args.size.positive?
273
+
274
+ string = args.join(' ').strip
275
+ end
276
+
277
+ print hookapp.encode(string)
278
+ end
279
+ end
280
+
281
+ c.desc 'decode a percent-encoded string'
282
+ c.arg_name 'STRING'
283
+ c.command :decode do |dec|
284
+ dec.action do |_global_options, _options, args|
285
+ if stdin
286
+ string = stdin
287
+ else
288
+ help_now!('no string provided') unless args.size.positive?
289
+
290
+ string = args.join(' ').strip
291
+ end
292
+
293
+ print hookapp.decode(string)
294
+ end
295
+ end
296
+
297
+ # c.default_command :encode
298
+ end
299
+
267
300
  pre do |global, _command, _options, _args|
268
301
  # Pre logic here
269
302
  # Return true to proceed; false to abort and not call the
270
303
  # chosen command
271
304
  # Use skips_pre before a command to skip this block
272
305
  # on that command only
306
+ if !STDIN.tty?
307
+ stdin = STDIN.read.strip
308
+ end
309
+
273
310
  hookapp = HookApp.new
274
311
  true
275
312
  end