bin/hook in hookapp-0.0.7 vs bin/hook in hookapp-2.0.3
- old
+ new
@@ -7,21 +7,34 @@
# Main class for GLI app
class App
extend GLI::App
program_desc 'CLI interface for Hook.app (macOS)'
+ 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.'
+ default_command 'help'
+ autocomplete_commands = true
+ synopsis_format(:terminal)
version Hook::VERSION
subcommand_option_handling :normal
arguments :strict
hooker = nil
desc 'List hooks on a file or url'
+ long_desc %{
+Output a list of all hooks attached to given url(s) or file(s) in the specified format (default "paths").
+
+Run `hook list` with no file/url argument to list all bookmarks.}
+
arg_name 'FILE_OR_URL [FILE_OR_URL...]'
command %i[list ls] do |c|
+ c.desc 'Generate a menu to select hook(s) for opening'
+ c.long_desc 'This option is a shortcut to `hook select` and overrides any other arguments.'
+ c.switch %i[s select]
+
c.desc 'Output only bookmarks with file paths (exclude e.g. emails)'
c.switch %i[f files_only], { negatable: false, default_value: false }
c.desc 'Separate results with NULL separator, only applies with "paths" output for single file argument'
c.switch %i[null], { negatable: false, default_value: false }
@@ -30,22 +43,98 @@
fmt_list = valid_formats.map { |fmt| fmt.sub(/^(.)(.*?)$/, '(\1)\2') }.join(', ')
c.desc "Output format [#{fmt_list}]"
c.flag %i[o output_format], { arg_name: 'format', default_value: 'paths' }
c.action do |_global_options, options, args|
+ if options[:s]
+ return hooker.open_linked(args[0])
+ end
valid_format = hooker.validate_format(options[:o], valid_formats)
- raise 'Invalid output format' unless valid_format
+ exit_now!("Invalid output format: \"#{options[:o]}\"", 6) unless valid_format
result = hooker.linked_bookmarks(args, { files_only: options[:f],
format: valid_format,
null_separator: options[:null] })
puts result
end
end
+ # Shell completion scripts are located in lib/completion/ and named "hook_completion" with
+ # the full shell name as the extension, e.g. "hook_completion.bash".
+ desc 'Shell completion examples'
+ valid_shells = %w[bash zsh fish]
+ long_desc %{
+Output completion script example for the specified shell (#{valid_shells.join(', ')})
+ }
+ arg_name 'SHELL'
+ command %i[scripts] do |c|
+ c.action do |_global_options, _options, args|
+ if args.length > 1
+ exit_now!("Invalid number of arguments, (expected 1)", 5)
+ elsif args.nil? || args.empty?
+ exit_now!("Specify a shell (#{valid_shells.join(', ')})", 0)
+ else
+ if valid_shells.include?(args[0])
+ base_dir = File.expand_path(File.join(File.dirname(__FILE__), '../lib/completion'))
+ completion = File.join(base_dir, "hook_completion.#{args[0]}")
+ script = IO.read(completion)
+ $stdout.puts script
+ else
+ exit_now!("Invalid shell name, must be one of #{valid_shells.join(', ')}", 1)
+ end
+ end
+ end
+ end
+
+
+
+ desc 'Search bookmarks'
+ long_desc %{
+Search bookmark urls and names for a string and output in specified format (default "paths").
+
+Run `hook find` with no search argument to list all bookmarks.}
+ arg_name 'SEARCH_STRING'
+ command %i[find search] do |c|
+ c.desc 'Output only bookmarks with file paths (exclude e.g. emails)'
+ c.switch %i[f files_only], { negatable: false, default_value: false }
+
+ c.desc 'Separate results with NULL separator, only applies with "paths" output for single file argument'
+ c.switch %i[null], { negatable: false, default_value: false }
+
+ valid_formats = %w[hooks paths markdown verbose]
+ fmt_list = valid_formats.map { |fmt| fmt.sub(/^(.)(.*?)$/, '(\1)\2') }.join(', ')
+
+ c.desc "Output format [#{fmt_list}]"
+ c.flag %i[o output_format], { arg_name: 'format', default_value: 'paths' }
+
+ c.desc "Search only bookmark names"
+ c.switch %i[n names_only], { negatable: false, default_value: false }
+
+ c.action do |_global_options, options, args|
+ valid_format = hooker.validate_format(options[:o], valid_formats)
+ exit_now!("Invalid output format: \"#{options[:o]}\"", 6) unless valid_format
+
+ result = hooker.search_bookmarks(args.join(" "), { files_only: options[:f],
+ format: valid_format,
+ null_separator: options[:null],
+ names_only: options[:n] })
+
+ puts result
+ end
+ end
+
desc 'Create bidirectional hooks between two or more files/urls'
+ long_desc %{
+If two files/urls are provided, links will be bi-directional.
+If three or more are provided, `link` defaults to creating bi-directional
+links between each file and the last file in the list. Use `-a` to create
+bi-directional links between every file in the list.
+
+If using `--paste`, the URL/hook link in the clipboard will be used as one argument,
+to be combined with one or more file/url arguments.
+ }
arg_name 'SOURCE [SOURCE...] TARGET'
command %i[link ln] do |c|
c.desc 'Link every listed file or url to every other'
c.switch %i[a all], { negatable: false, default_value: false }
@@ -57,94 +146,122 @@
clipboard = `pbpaste`.strip
clipboard.valid_hook!
args.push(clipboard) if clipboard
end
if args.length < 2
- raise 'At least 2 files must be specified, or one file with --paste'
+ exit_now!('Wrong number of arguments. At least 2 files must be specified, or one file with --paste', 5)
end
if options[:a]
puts hooker.link_all(args)
else
puts hooker.link_files(args)
end
end
end
desc 'Copy Hook URL for file/url to clipboard'
+ long_desc %{
+Creates a bookmark for the specified file or URL and copies its Hook URL to the clipboard.
+
+The copied Hook URL can be used to link to other files (use `hook link --paste FILE/URL),
+or to paste into another app as a link. Use the -m flag to copy a full Markdown link.
+ }
arg_name 'FILE_OR_URL'
command %i[clip cp] do |c|
c.desc 'Copy as Markdown'
c.switch %i[m markdown], { negatable: false, default_value: false }
c.desc 'Copy from application'
c.flag %i[a app], { arg_name: 'APP_NAME' }
c.action do |_global_options, options, args|
- raise 'Wrong number of arguments. Requires a path/url or -a APP_NAME' if args.length != 1 && !options[:a]
+ exit_now!('Wrong number of arguments. Requires a path/url or -a APP_NAME', 5) if args.length != 1 && !options[:a]
if options[:a]
puts hooker.bookmark_from_app(options[:a], { copy: true, markdown: options[:m] })
else
puts hooker.clip_bookmark(args[0], { markdown: options[:m] })
end
end
end
desc 'Get a Hook URL for the frontmost window of an app'
+ long_desc %{
+Specify an application by name (without '.app') to bring that app to the foreground and create a bookmark
+for the active document, note, task, etc., returning a Hook URL.
+
+Use -m to get the response as Markdown, and/or -c to copy the result directly to the clipboard.
+ }
arg_name 'APPLICATION_NAME'
command %i[from] do |c|
c.desc 'Output as Markdown'
c.switch %i[m markdown], { negatable: false, default_value: false }
c.desc 'Copy to clipboard'
c.switch %i[c copy], { negatable: false, default_value: false }
c.action do |_global_options, options, args|
- raise "Wrong number of arguments (1 expected, #{args.length} given)" if args.length != 1
+ exit_now!("Wrong number of arguments (1 expected, #{args.length} given)", 5) if args.length != 1
puts hooker.bookmark_from_app(args[0], { copy: options[:c], markdown: options[:m] })
end
end
desc 'Remove a hook between two files/urls'
+ long_desc %{
+Remove a hook between two files or URLs. If you use --all, all hooks on a given file will be removed.
+
+If --all isn't specified, exactly two arguments (Files/URLs) are required.
+ }
arg_name 'ITEM_1 ITEM_2'
command %i[remove rm] do |c|
c.desc 'Remove ALL links on files, requires confirmation'
- c.switch %i[a all]
+ c.switch %i[a all], { negatable: false, default_value: false }
c.action do |_global_options, options, args|
- result = hooker.delete_hooks(args, { all: options[:r] })
+ result = hooker.delete_hooks(args, { all: options[:a] })
puts result
end
end
desc 'Clone all hooks from one file or url onto another'
+ long_desc %{
+Copy all the files and urls that the first file is hooked to onto another file. Exactly two arguments (SOURCE, TARGET) required.
+ }
arg_name 'SOURCE TARGET'
command %i[clone] do |c|
c.action do |_global_options, _options, args|
- raise "Wrong number of arguments. Two file paths or urls required (#{args.length} given)" if args.length != 2
+ exit_now!("Wrong number of arguments. Two file paths or urls required (#{args.length} given)", 5) if args.length != 2
result = hooker.clone_hooks(args)
puts result
end
end
desc 'Select from hooks on a file/url and open in default application'
+ long_desc %{
+If the target file/URL has hooked items, a menu will be provided. Selecting one or more files
+from this menu will open the item(s) using the default application assigned to the
+filetype by macOS. Allows multiple selections with tab key, and type-ahead fuzzy filtering of results.
+}
arg_name 'FILE_OR_URL'
command %i[select] do |c|
c.action do |_global_options, _options, args|
- raise "Wrong number of arguments. One file path or url required (#{args.length} given)" if args.length != 1
+ exit_now!("Wrong number of arguments. One file path or url required (#{args.length} given)", 5) if args.length != 1
hooker.open_linked(args[0])
end
end
desc 'Open the specified file or url in Hook GUI'
+ long_desc %{
+Opens Hook.app on the specified file/URL for browsing and performing actions. Exactly one argument (File/URL) required.
+ }
arg_name 'FILE_OR_URL'
command %i[open gui] do |c|
c.action do |_global_options, _options, args|
- raise "Wrong number of arguments. One file path or url required (#{args.length} given)" if args.length != 1
+ exit_now!("Wrong number of arguments. One file path or url required (#{args.length} given)", 5) if args.length != 1
hooker.open_gui(args[0])
end
end
@@ -152,10 +269,10 @@
# Pre logic here
# Return true to proceed; false to abort and not call the
# chosen command
# Use skips_pre before a command to skip this block
# on that command only
- hooker = Hooker.new(global)
+ hooker = Hooker.new
true
end
post do |_global, _command, _options, _args|
# Post logic here