hookapp 0.0.3 → 2.0.3

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 (78) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/CHANGELOG.md +32 -0
  4. data/Gemfile +1 -1
  5. data/Gemfile.lock +62 -28
  6. data/LICENSE.md +31 -0
  7. data/OVERVIEW.md +80 -0
  8. data/README.md +286 -23
  9. data/Rakefile +1 -1
  10. data/bin/hook +153 -20
  11. data/buildnotes.md +29 -0
  12. data/hook.rdoc +90 -9
  13. data/hookapp.gemspec +9 -8
  14. data/html/App.html +119 -0
  15. data/html/GLI.html +99 -0
  16. data/html/GLI/Commands.html +99 -0
  17. data/html/GLI/Commands/Doc.html +99 -0
  18. data/html/GLI/Commands/MarkdownDocumentListener.html +717 -0
  19. data/html/Hook.html +113 -0
  20. data/html/HookApp.html +1222 -0
  21. data/html/Hooker.html +119 -0
  22. data/html/README_rdoc.html +328 -0
  23. data/html/String.html +427 -0
  24. data/html/created.rid +9 -0
  25. data/html/css/fonts.css +167 -0
  26. data/html/css/rdoc.css +619 -0
  27. data/html/fonts/Lato-Light.ttf +0 -0
  28. data/html/fonts/Lato-LightItalic.ttf +0 -0
  29. data/html/fonts/Lato-Regular.ttf +0 -0
  30. data/html/fonts/Lato-RegularItalic.ttf +0 -0
  31. data/html/fonts/SourceCodePro-Bold.ttf +0 -0
  32. data/html/fonts/SourceCodePro-Regular.ttf +0 -0
  33. data/html/images/add.png +0 -0
  34. data/html/images/arrow_up.png +0 -0
  35. data/html/images/brick.png +0 -0
  36. data/html/images/brick_link.png +0 -0
  37. data/html/images/bug.png +0 -0
  38. data/html/images/bullet_black.png +0 -0
  39. data/html/images/bullet_toggle_minus.png +0 -0
  40. data/html/images/bullet_toggle_plus.png +0 -0
  41. data/html/images/date.png +0 -0
  42. data/html/images/delete.png +0 -0
  43. data/html/images/find.png +0 -0
  44. data/html/images/loadingAnimation.gif +0 -0
  45. data/html/images/macFFBgHack.png +0 -0
  46. data/html/images/package.png +0 -0
  47. data/html/images/page_green.png +0 -0
  48. data/html/images/page_white_text.png +0 -0
  49. data/html/images/page_white_width.png +0 -0
  50. data/html/images/plugin.png +0 -0
  51. data/html/images/ruby.png +0 -0
  52. data/html/images/tag_blue.png +0 -0
  53. data/html/images/tag_green.png +0 -0
  54. data/html/images/transparent.png +0 -0
  55. data/html/images/wrench.png +0 -0
  56. data/html/images/wrench_orange.png +0 -0
  57. data/html/images/zoom.png +0 -0
  58. data/html/index.html +308 -0
  59. data/html/js/darkfish.js +84 -0
  60. data/html/js/navigation.js +105 -0
  61. data/html/js/navigation.js.gz +0 -0
  62. data/html/js/search.js +110 -0
  63. data/html/js/search_index.js +1 -0
  64. data/html/js/search_index.js.gz +0 -0
  65. data/html/js/searcher.js +229 -0
  66. data/html/js/searcher.js.gz +0 -0
  67. data/html/table_of_contents.html +409 -0
  68. data/lib/completion/hook_completion.bash +22 -0
  69. data/lib/completion/hook_completion.fish +31 -0
  70. data/lib/completion/hook_completion.zsh +22 -0
  71. data/lib/helpers/fuzzyfilefinder +0 -0
  72. data/lib/hook.rb +5 -1
  73. data/lib/hook/hookapp.rb +489 -0
  74. data/lib/hook/hooker.rb +1 -308
  75. data/lib/hook/markdown_document_listener.rb +164 -0
  76. data/lib/hook/string.rb +60 -0
  77. data/lib/hook/version.rb +3 -1
  78. metadata +87 -22
@@ -1,313 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # String helpers
4
- class String
5
- def split_hook
6
- elements = split(/\|\|/)
7
- {
8
- name: elements[0],
9
- url: elements[1],
10
- path: elements[2]
11
- }
12
- end
13
-
14
- def split_hooks
15
- split(/\^\^/).map(&:split_hook)
16
- end
17
-
18
- def valid_hook
19
- if File.exist?(self)
20
- File.expand_path(self)
21
- elsif self =~ /\S+:\/\//
22
- self
23
- else
24
- if self =~ /^\[.*?\]\((.*?)\)$/
25
- mdlink = $1
26
- mdlink.valid_hook
27
- else
28
- nil
29
- end
30
- end
31
- end
32
-
33
- def valid_hook!
34
- replace valid_hook
35
- end
36
- end
37
-
38
3
  # Hook.app CLI interface
39
4
  class Hooker
40
- def initialize(global_args)
41
- @global_args = global_args
42
- end
43
-
44
- def validate_format(fmt, options)
45
- valid_format_rx = options.map { |fmt| fmt.sub(/^(.)(.*)$/, '^\1(\2)?$') }
46
- valid_format = false
47
- valid_format_rx.each_with_index do |rx, i|
48
- cmp = Regexp.new(rx, 'i')
49
- next unless fmt =~ cmp
50
- valid_format = options[i]
51
- break
52
- end
53
- return valid_format
54
- end
55
-
56
- def bookmark_for(url)
57
- url.valid_hook!
58
- raise "Invalid target: #{url}" unless url
59
-
60
- mark = `osascript <<'APPLESCRIPT'
61
- tell application "Hook"
62
- set _hook to bookmark from URL "#{url}"
63
- return title of _hook & "||" & address of _hook & "||" & path of _hook
64
- end tell
65
- APPLESCRIPT`.strip
66
- mark.split_hook
67
- end
68
-
69
- def get_hooks(url)
70
- url.valid_hook!
71
- raise "Invalid target: #{url}" unless url
72
-
73
- hooks = `osascript <<'APPLESCRIPT'
74
- tell application "Hook"
75
- set _mark to bookmark from URL "#{url}"
76
- if _mark is {} then return ""
77
- set _hooks to bookmarks hooked to _mark
78
- set _out to {}
79
- repeat with _hook in _hooks
80
- set _out to _out & (title of _hook & "||" & address of _hook & "||" & path of _hook)
81
- end repeat
82
- set {astid, AppleScript's text item delimiters} to {AppleScript's text item delimiters, "^^"}
83
- set _output to _out as string
84
- set AppleScript's text item delimiters to astid
85
- return _output
86
- end tell
87
- APPLESCRIPT`.strip
88
- hooks.split_hooks
89
- end
90
-
91
- def copy_bookmark(url, opts)
92
- mark = bookmark_for(url)
93
- output = if opts[:markdown]
94
- "[#{mark[:name]}](#{mark[:url]})"
95
- else
96
- mark[:url]
97
- end
98
- `/bin/echo -n #{Shellwords.escape(output)} | pbcopy`
99
- %(Copied #{opts[:markdown] ? 'Markdown link' : 'Hook URL'} for '#{mark[:name]}' to clipboard)
100
- end
101
-
102
- def select_hook(marks)
103
- intpad = marks.length.to_s.length + 1
104
- marks.each_with_index do |mark, i|
105
- STDERR.printf "%#{intpad}d) %s\n", i + 1, mark[:name]
106
- end
107
- STDERR.print 'Open which bookmark: '
108
- sel = STDIN.gets.strip.to_i
109
- if sel.positive? && sel <= marks.length
110
- marks[sel - 1]
111
- else
112
- warn 'Invalid selection'
113
- Process.exit 1
114
- end
115
- end
116
-
117
- def open_gui(url)
118
- `osascript <<'APPLESCRIPT'
119
- tell application "Hook"
120
- set _mark to bookmark from URL "#{url.valid_hook}"
121
- invoke on _mark
122
- end tell
123
- APPLESCRIPT`
124
- end
125
-
126
- def open_linked(url)
127
- marks = get_hooks(url)
128
- if marks.empty?
129
- warn "No hooks found for #{url}"
130
- else
131
- res = select_hook(marks)
132
- `open '#{res[:url]}'`
133
- end
134
- end
135
-
136
- def link_files(args)
137
- target = args.pop
138
- target.valid_hook!
139
- raise "Invalid target: #{target}" unless target
140
-
141
- args.each do |file|
142
- file.valid_hook!
143
- raise "Invalid target: #{file}" unless file
144
-
145
- puts "Linking #{file} and #{target}..."
146
- `osascript <<'APPLESCRIPT'
147
- tell application "Hook"
148
- set _mark1 to bookmark from URL "#{file}"
149
- set _mark2 to bookmark from URL "#{target}"
150
- hook together _mark1 and _mark2
151
- return true
152
- end tell
153
- APPLESCRIPT`
154
- end
155
- "Linked #{args.length} files to #{target}"
156
- end
157
-
158
- def clone_hooks(args)
159
- target = args.pop.valid_hook
160
- source = args[0].valid_hook
161
-
162
- if target && source
163
- hooks = get_hooks(source)
164
- hooks.each do |hook|
165
- `osascript <<'APPLESCRIPT'
166
- tell application "Hook"
167
- set _mark1 to bookmark from URL "#{hook[:url]}"
168
- set _mark2 to bookmark from URL "#{target}"
169
- hook together _mark1 and _mark2
170
- return true
171
- end tell
172
- APPLESCRIPT`
173
- end
174
- "Hooks from #{source} cloned to #{target}"
175
- else
176
- raise 'Invalid file specified'
177
- end
178
- end
179
-
180
- def delete_all_hooks(url)
181
- STDERR.print "Are you sure you want to delete ALL hooks from #{url} (y/N)? "
182
- res = STDIN.gets.strip
183
- if res =~ /^y/i
184
- get_hooks(url).each do |hook|
185
- `osascript <<'APPLESCRIPT'
186
- tell application "Hook"
187
- set _mark1 to bookmark from URL "#{hook[:url]}"
188
- set _mark2 to bookmark from URL "#{url}"
189
- remove hook between _mark1 and _mark2
190
- return true
191
- end tell
192
- APPLESCRIPT`
193
- end
194
- "Removed all hooks from #{url}"
195
- end
196
- end
197
-
198
- def delete_hooks(args, opts)
199
- urls = args.map(&:valid_hook).delete_if { |url| !url }
200
- output = []
201
- if opts[:all]
202
- urls.each_with_index do |url, i|
203
- raise "Invalid target: #{args[i]}" unless url
204
-
205
- output.push(delete_all_hooks(url))
206
- end
207
- return output.join("\n")
208
- end
209
-
210
- if urls.length == 2
211
- source = urls[0]
212
- target = urls[1]
213
- `osascript <<'APPLESCRIPT'
214
- tell application "Hook"
215
- set _mark1 to bookmark from URL "#{source}"
216
- set _mark2 to bookmark from URL "#{target}"
217
- remove hook between _mark1 and _mark2
218
- return true
219
- end tell
220
- APPLESCRIPT`
221
- return "Hook removed between #{source} and #{target}"
222
- else
223
- raise "Invalid number of URLs or files specified"
224
-
225
- end
226
- end
227
-
228
- def link_all(args)
229
- args.each do |file|
230
- source = file.valid_hook
231
- link_to = args.dup.map(&:valid_url).reject { |url|
232
- url == source
233
- }
234
- link_to.each do |url|
235
- `osascript <<'APPLESCRIPT'
236
- tell application "Hook"
237
- set _mark1 to bookmark from URL "#{source}"
238
- set _mark2 to bookmark from URL "#{url}"
239
- hook together _mark1 and _mark2
240
- return true
241
- end tell
242
- APPLESCRIPT`
243
- end
244
- end
245
- "Linked #{args.length} files to each other"
246
- end
247
-
248
- def linked_bookmarks(args, opts)
249
- result = []
250
-
251
- separator = args.length == 1 && opts[:format] == 'paths' && opts[:null_separator] ? "\0" : "\n"
252
-
253
- args.each do |url|
254
- source_mark = bookmark_for(url)
255
- filename = source_mark[:name]
256
-
257
- case opts[:format]
258
- when /^m/
259
- filename = "[#{source_mark[:name]}](#{source_mark[:url]})"
260
- filename += " <file://#{CGI.escape(source_mark[:path])}>" if source_mark[:path]
261
- when /^p/
262
- filename = "File: #{source_mark[:name]}"
263
- filename += " (#{source_mark[:path]})" if source_mark[:path]
264
- when /^h/
265
- filename = "File: #{source_mark[:name]}"
266
- filename += " (#{source_mark[:url]})" if source_mark[:url]
267
- else
268
- filename = "Bookmarks attached to #{source_mark[:path] || source_mark[:url]}"
269
- end
270
-
271
- hooks_arr = get_hooks(url)
272
-
273
- if !hooks_arr.empty?
274
- hooks_arr.reject! { |h| h[:path].nil? || h[:path] == '' } if opts[:files_only]
275
-
276
- output = []
277
-
278
- case opts[:format]
279
- when /^m/
280
- hooks_arr.each do |h|
281
- output.push("- [#{h[:name]}](#{h[:url]})")
282
- end
283
- when /^p/
284
- hooks_arr.each do |h|
285
- output.push(h[:path].nil? ? h[:url] : h[:path])
286
- end
287
- when /^h/
288
- hooks_arr.each do |h|
289
- output.push(h[:url])
290
- end
291
- else
292
- hooks_arr.each do |h|
293
- output.push("Title: #{h[:name]}\nPath: #{h[:path]}\nAddress: #{h[:url]}\n---------------------")
294
- end
295
- end
296
- else
297
- output = ['No bookmarks']
298
- end
299
- result.push({ file: filename, links: output.join(separator) })
300
- end
301
-
302
- if result.length > 1 || opts[:format] == 'verbose'
303
- result.map! do |res|
304
- "#{res[:file]}\n\n#{res[:links]}\n"
305
- end
306
- else
307
- result.map! do |res|
308
- res[:links]
309
- end
310
- end
311
- result.join(separator)
312
- end
5
+ include HookApp
313
6
  end
@@ -0,0 +1,164 @@
1
+ require 'stringio'
2
+ require 'time'
3
+ require 'fileutils'
4
+
5
+ module GLI
6
+ module Commands
7
+ # DocumentListener class for GLI documentation generator
8
+ class MarkdownDocumentListener
9
+ def initialize(_global_options, _options, _arguments, app)
10
+ @exe = app.exe_name
11
+ if File.exist?('README.md') # Back up existing README
12
+ FileUtils.mv('README.md', 'README.bak')
13
+ $stderr.puts "Backing up existing README.md to README.bak"
14
+ end
15
+ @io = File.new('README.md', 'w')
16
+ @nest = '#'
17
+ @arg_name_formatter = GLI::Commands::HelpModules::ArgNameFormatter.new
18
+ end
19
+
20
+ def beginning
21
+ end
22
+
23
+ # Called when processing has completed
24
+ def ending
25
+ if File.exist?('CREDITS.md')
26
+ @io.puts IO.read('CREDITS.md')
27
+ @io.puts
28
+ end
29
+ if File.exist?('LICENSE.md')
30
+ @io.puts IO.read('LICENSE.md')
31
+ @io.puts
32
+ end
33
+ @io.puts
34
+ @io.puts "Documentation generated #{Time.now.strftime('%Y-%m-%d %H:%M')}"
35
+ @io.puts
36
+ @io.close
37
+ end
38
+
39
+ # Gives you the program description
40
+ def program_desc(desc)
41
+ @io.puts "# #{@exe} CLI"
42
+ @io.puts
43
+ @io.puts desc
44
+ @io.puts
45
+ end
46
+
47
+ def program_long_desc(desc)
48
+ @io.puts "> #{desc}"
49
+ @io.puts
50
+ end
51
+
52
+ # Gives you the program version
53
+ def version(version)
54
+ @io.puts "*v#{version}*"
55
+ @io.puts
56
+ # Hacking in the overview file
57
+ if File.exist?('OVERVIEW.md')
58
+ @io.puts IO.read('OVERVIEW.md')
59
+ @io.puts
60
+ end
61
+ end
62
+
63
+ def options
64
+ if @nest.size == 1
65
+ @io.puts "## Global Options"
66
+ else
67
+ @io.puts header("Options", 1)
68
+ end
69
+ @io.puts
70
+ end
71
+
72
+ # Gives you a flag in the current context
73
+ def flag(name, aliases, desc, long_desc, default_value, arg_name, must_match, _type)
74
+ invocations = ([name] + Array(aliases)).map { |_| "`" + add_dashes(_) + "`" }.join(' | ')
75
+ usage = "#{invocations} #{arg_name || 'arg'}"
76
+ @io.puts header(usage, 2)
77
+ @io.puts
78
+ @io.puts String(desc).strip
79
+ @io.puts "\n*Default Value:* `#{default_value || 'None'}`\n" unless default_value.nil?
80
+ @io.puts "\n*Must Match:* `#{must_match.to_s}`\n" unless must_match.nil?
81
+ cmd_desc = String(long_desc).strip
82
+ @io.puts "> #{cmd_desc}\n" unless cmd_desc.length == 0
83
+ @io.puts
84
+ end
85
+
86
+ # Gives you a switch in the current context
87
+ def switch(name, aliases, desc, long_desc, negatable)
88
+ if negatable
89
+ name = "[no-]#{name}" if name.to_s.length > 1
90
+ aliases = aliases.map { |_| _.to_s.length > 1 ? "[no-]#{_}" : _ }
91
+ end
92
+ invocations = ([name] + aliases).map { |_| "`" + add_dashes(_) + "`" }.join('|')
93
+ @io.puts header("#{invocations}", 2)
94
+ @io.puts
95
+ @io.puts String(desc).strip
96
+ cmd_desc = String(long_desc).strip
97
+ @io.puts "\n> #{cmd_desc}\n" unless cmd_desc.length == 0
98
+ @io.puts
99
+ end
100
+
101
+ def end_options
102
+ end
103
+
104
+ def commands
105
+ @io.puts header("Commands", 1)
106
+ @io.puts
107
+ increment_nest
108
+ end
109
+
110
+ # Gives you a command in the current context and creates a new context of this command
111
+ def command(name, aliases, desc, long_desc, arg_name, arg_options)
112
+ arg_name_fmt = @arg_name_formatter.format(arg_name, arg_options, [])
113
+ @io.puts header("`$ #{@exe}` <mark>`#{([name] + aliases).join('|')}`</mark> `#{arg_name_fmt}`", 1)
114
+ @io.puts
115
+ @io.puts "*#{String(desc).strip}*"
116
+ @io.puts
117
+ cmd_desc = String(long_desc).strip.split("\n").map { |_| "> #{_}" }.join("\n")
118
+ @io.puts "#{cmd_desc}\n\n" unless cmd_desc.length == 0
119
+ increment_nest
120
+ end
121
+
122
+ # Ends a command, and "pops" you back up one context
123
+ def end_command(_name)
124
+ decrement_nest
125
+ @io.puts "* * * * * *\n\n" unless @nest.size > 2
126
+ end
127
+
128
+ # Gives you the name of the current command in the current context
129
+ def default_command(name)
130
+ @io.puts "#### [Default Command] #{name}" unless name.nil?
131
+ end
132
+
133
+ def end_commands
134
+ decrement_nest
135
+ end
136
+
137
+ private
138
+
139
+ def add_dashes(name)
140
+ name = "-#{name}"
141
+ name = "-#{name}" if name.length > 2
142
+ name
143
+ end
144
+
145
+ def header(content, increment)
146
+ if @nest.size + increment > 6
147
+ "**#{content}**"
148
+ else
149
+ "#{@nest}#{'#'*increment} #{content}"
150
+ end
151
+ end
152
+
153
+ def increment_nest(increment=1)
154
+ @nest = "#{@nest}#{'#'*increment}"
155
+ end
156
+
157
+ def decrement_nest(increment=1)
158
+ @nest.gsub!(/#{'#'*increment}$/, '')
159
+ end
160
+ end
161
+ end
162
+ end
163
+
164
+ GLI::Commands::Doc::FORMATS['markdown'] = GLI::Commands::MarkdownDocumentListener