bunchcli 1.0.0 → 1.1.0
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.
- checksums.yaml +4 -4
- data/Gemfile.lock +19 -0
- data/bin/bunch +32 -11
- data/lib/bunch.rb +1 -0
- data/lib/bunch/bunchCLI.rb +57 -11
- data/lib/bunch/url_generator.rb +296 -0
- data/lib/bunch/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 010c20799d4e9e35409737ee3dfd5e3a755096ff212eb9a02787dfcee16dc5e2
|
|
4
|
+
data.tar.gz: daccb516131e6816f4ea5cd153e14df691e3089600e77114e1755cf502efe131
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b9f94711eadea1d3cf6cd3ebef2244663cc793b1dc3bd121ac2bb1409431c24215d03b172db13d76966143529c99578bfce000bebbba89dbbf16410d1653ab93
|
|
7
|
+
data.tar.gz: 2923722c6988c146be4eaa19b20b732413eb95fad52c890a0bd47165e50a61e576042d4934d376a6f5ed992723f5d843ee645b3eaa7eb10cdb677628f996ce99
|
data/Gemfile.lock
ADDED
data/bin/bunch
CHANGED
|
@@ -13,18 +13,13 @@ bunch = Bunch.new
|
|
|
13
13
|
optparse = OptionParser.new do |opts|
|
|
14
14
|
opts.banner = 'CLI for Bunch.app'
|
|
15
15
|
|
|
16
|
-
opts.on('-
|
|
17
|
-
|
|
18
|
-
help
|
|
16
|
+
opts.on('-l', '--list', 'List available Bunches') do |_opt|
|
|
17
|
+
bunch.list_bunches
|
|
19
18
|
Process.exit 0
|
|
20
19
|
end
|
|
21
20
|
|
|
22
|
-
opts.on('-
|
|
23
|
-
bunch.
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
opts.on('-l', '--list', 'List available Bunches') do |_opt|
|
|
27
|
-
bunch.list_bunches
|
|
21
|
+
opts.on('-s', '--show BUNCH', 'Show contents of Bunch') do |opt|
|
|
22
|
+
bunch.show(opt)
|
|
28
23
|
Process.exit 0
|
|
29
24
|
end
|
|
30
25
|
|
|
@@ -40,8 +35,24 @@ optparse = OptionParser.new do |opts|
|
|
|
40
35
|
bunch.url_method = 'toggle'
|
|
41
36
|
end
|
|
42
37
|
|
|
43
|
-
opts.on('
|
|
44
|
-
bunch.
|
|
38
|
+
opts.on('--snippet', 'Load as snippet') do |opt|
|
|
39
|
+
bunch.url_method = 'snippet'
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
opts.on('--fragment=FRAGMENT', 'Run a specific section') do |opt|
|
|
43
|
+
bunch.fragment = opt
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
opts.on('--vars=VARS', 'Variables to pass to a snippet, comma-separated') do |opt|
|
|
47
|
+
bunch.variables = opt
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
opts.on('-u', '--url', 'Output URL instead of opening') do |_opt|
|
|
51
|
+
bunch.show_url = true
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
opts.on('-i','--interactive', 'Interactively generate a Bunch url') do |opt|
|
|
55
|
+
BunchURLGenerator.new.generate
|
|
45
56
|
Process.exit 0
|
|
46
57
|
end
|
|
47
58
|
|
|
@@ -49,6 +60,16 @@ optparse = OptionParser.new do |opts|
|
|
|
49
60
|
bunch.show_config
|
|
50
61
|
Process.exit 0
|
|
51
62
|
end
|
|
63
|
+
|
|
64
|
+
opts.on('-f', '--force-refresh', 'Force refresh cached preferences') do |opt|
|
|
65
|
+
bunch.update_cache
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
opts.on('-h', '--help', 'Display this screen') do |_opt|
|
|
69
|
+
puts opts
|
|
70
|
+
help
|
|
71
|
+
Process.exit 0
|
|
72
|
+
end
|
|
52
73
|
end
|
|
53
74
|
|
|
54
75
|
optparse.parse!
|
data/lib/bunch.rb
CHANGED
data/lib/bunch/bunchCLI.rb
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
class Bunch
|
|
2
|
-
|
|
2
|
+
include Util
|
|
3
|
+
attr_writer :url_method, :fragment, :variables, :show_url
|
|
3
4
|
|
|
4
5
|
def initialize
|
|
5
6
|
@bunch_dir = nil
|
|
6
7
|
@url_method = nil
|
|
7
8
|
@bunches = nil
|
|
9
|
+
@fragment = nil
|
|
10
|
+
@variables = nil
|
|
11
|
+
@success = nil
|
|
12
|
+
@show_url = false
|
|
8
13
|
get_cache
|
|
9
14
|
end
|
|
10
15
|
|
|
@@ -41,6 +46,18 @@ class Bunch
|
|
|
41
46
|
@bunches = settings['bunches'] || generate_bunch_list
|
|
42
47
|
end
|
|
43
48
|
|
|
49
|
+
def variable_query
|
|
50
|
+
vars = @variables.split(/,/).map { |v| v.strip }
|
|
51
|
+
query = []
|
|
52
|
+
vars.each { |v|
|
|
53
|
+
parts = v.split(/=/).map { |v| v.strip }
|
|
54
|
+
k = parts[0]
|
|
55
|
+
v = parts[1]
|
|
56
|
+
query << "#{k}=#{CGI.escape(v)}"
|
|
57
|
+
}
|
|
58
|
+
query
|
|
59
|
+
end
|
|
60
|
+
|
|
44
61
|
# items.push({title: 0})
|
|
45
62
|
def generate_bunch_list
|
|
46
63
|
items = []
|
|
@@ -69,12 +86,15 @@ class Bunch
|
|
|
69
86
|
end
|
|
70
87
|
|
|
71
88
|
def url(bunch)
|
|
89
|
+
params = "&x-success=#{@success}" if @success
|
|
72
90
|
if url_method == 'file'
|
|
73
|
-
%(x-bunch://raw?file=#{bunch})
|
|
91
|
+
%(x-bunch://raw?file=#{bunch}#{params})
|
|
74
92
|
elsif url_method == 'raw'
|
|
75
|
-
%(x-bunch://raw?txt=#{bunch})
|
|
93
|
+
%(x-bunch://raw?txt=#{bunch}#{params})
|
|
94
|
+
elsif url_method == 'snippet'
|
|
95
|
+
%(x-bunch://snippet?file=#{bunch}#{params})
|
|
76
96
|
else
|
|
77
|
-
%(x-bunch://#{url_method}?bunch=#{bunch[:title]})
|
|
97
|
+
%(x-bunch://#{url_method}?bunch=#{bunch[:title]}#{params})
|
|
78
98
|
end
|
|
79
99
|
end
|
|
80
100
|
|
|
@@ -107,28 +127,54 @@ class Bunch
|
|
|
107
127
|
def open(str)
|
|
108
128
|
# get front app
|
|
109
129
|
front_app = %x{osascript -e 'tell application "System Events" to return name of first application process whose frontmost is true'}.strip
|
|
130
|
+
bid = bundle_id(front_app)
|
|
131
|
+
@success = bid if (bid)
|
|
132
|
+
|
|
110
133
|
if @url_method == 'raw'
|
|
111
134
|
warn 'Running raw string'
|
|
112
|
-
|
|
135
|
+
if @show_url
|
|
136
|
+
$stdout.puts url(str)
|
|
137
|
+
else
|
|
138
|
+
`open '#{url(str)}'`
|
|
139
|
+
end
|
|
140
|
+
elsif @url_method == 'snippet'
|
|
141
|
+
_url = url(str)
|
|
142
|
+
params = []
|
|
143
|
+
params << "fragment=#{CGI.escape(@fragment)}" if @fragment
|
|
144
|
+
params.concat(variable_query) if @variables
|
|
145
|
+
_url += '&' + params.join('&')
|
|
146
|
+
if @show_url
|
|
147
|
+
$stdout.puts _url
|
|
148
|
+
else
|
|
149
|
+
warn "Opening snippet"
|
|
150
|
+
`open '#{_url}'`
|
|
151
|
+
end
|
|
113
152
|
else
|
|
114
153
|
bunch = find_bunch(str)
|
|
115
154
|
unless bunch
|
|
116
155
|
if File.exists?(str)
|
|
117
156
|
@url_method = 'file'
|
|
118
|
-
|
|
119
|
-
|
|
157
|
+
if @show_url
|
|
158
|
+
$stdout.puts url(str)
|
|
159
|
+
else
|
|
160
|
+
warn "Opening file"
|
|
161
|
+
`open '#{url(str)}'`
|
|
162
|
+
end
|
|
120
163
|
else
|
|
121
164
|
warn 'No matching Bunch found'
|
|
122
165
|
Process.exit 1
|
|
123
166
|
end
|
|
124
167
|
else
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
168
|
+
if @show_url
|
|
169
|
+
$stdout.puts url(str)
|
|
170
|
+
else
|
|
171
|
+
warn "#{human_action} #{bunch[:title]}"
|
|
172
|
+
`open '#{url(bunch)}'`
|
|
173
|
+
end
|
|
128
174
|
end
|
|
129
175
|
end
|
|
130
176
|
# attempt to restore front app
|
|
131
|
-
%x{osascript -e 'delay 2' -e 'tell application "#{front_app}" to activate'}
|
|
177
|
+
# %x{osascript -e 'delay 2' -e 'tell application "#{front_app}" to activate'}
|
|
132
178
|
end
|
|
133
179
|
|
|
134
180
|
def show(str)
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'readline'
|
|
4
|
+
require 'cgi'
|
|
5
|
+
|
|
6
|
+
# String additions
|
|
7
|
+
class String
|
|
8
|
+
def text?
|
|
9
|
+
res = `file "#{self}"`
|
|
10
|
+
res =~ /text/
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# misc utils
|
|
15
|
+
module Util
|
|
16
|
+
def bundle_id(app)
|
|
17
|
+
shortname = app.sub(/\.app$/, '')
|
|
18
|
+
apps = `mdfind -onlyin /Applications -onlyin /Applications/Setapp -onlyin /Applications/Utilities -onlyin ~/Applications -onlyin /Developer/Applications 'kMDItemKind==Application'`
|
|
19
|
+
|
|
20
|
+
app = apps.split(/\n/).select! { |line| line.chomp =~ /#{shortname}\.app$/ }[0]
|
|
21
|
+
|
|
22
|
+
if app
|
|
23
|
+
bid = `mdls -name kMDItemCFBundleIdentifier -r "#{app}"`.chomp
|
|
24
|
+
else
|
|
25
|
+
warn "Could not locate bundle id for #{shortname}"
|
|
26
|
+
end
|
|
27
|
+
bid
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# CLI Prompt utilities
|
|
32
|
+
module Prompt
|
|
33
|
+
def choose_number(query = '->', max)
|
|
34
|
+
stty_save = `stty -g`.chomp
|
|
35
|
+
sel = nil
|
|
36
|
+
begin
|
|
37
|
+
while !sel =~ /^\d+$/ || sel.to_i <= 0 || sel.to_i > max
|
|
38
|
+
sel = Readline.readline("#{query}", true)
|
|
39
|
+
return nil if sel =~ /^\s*$/
|
|
40
|
+
end
|
|
41
|
+
rescue Interrupt
|
|
42
|
+
system('stty', stty_save) # Restore
|
|
43
|
+
exit
|
|
44
|
+
end
|
|
45
|
+
sel ? sel.to_i : nil
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def get_line(query = '->')
|
|
49
|
+
stty_save = `stty -g`.chomp
|
|
50
|
+
begin
|
|
51
|
+
line = Readline.readline("#{query}: ", true)
|
|
52
|
+
rescue Interrupt
|
|
53
|
+
system('stty', stty_save) # Restore
|
|
54
|
+
exit
|
|
55
|
+
end
|
|
56
|
+
line.chomp
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def get_text(query = 'Enter text, ^d to end')
|
|
60
|
+
stty_save = `stty -g`.chomp
|
|
61
|
+
lines = []
|
|
62
|
+
puts query
|
|
63
|
+
begin
|
|
64
|
+
while (line = Readline.readline)
|
|
65
|
+
lines << line
|
|
66
|
+
end
|
|
67
|
+
rescue Interrupt
|
|
68
|
+
system('stty', stty_save) # Restore
|
|
69
|
+
exit
|
|
70
|
+
end
|
|
71
|
+
lines.join("\n").chomp
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def url_encode_text
|
|
75
|
+
text = get_text
|
|
76
|
+
puts
|
|
77
|
+
CGI.escape(text)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Single menu item
|
|
82
|
+
class MenuItem
|
|
83
|
+
attr_accessor :id, :title, :value
|
|
84
|
+
|
|
85
|
+
def initialize(id, title, value)
|
|
86
|
+
@id = id
|
|
87
|
+
@title = title
|
|
88
|
+
@value = value
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Collection of menu items
|
|
93
|
+
class Menu
|
|
94
|
+
include Prompt
|
|
95
|
+
attr_accessor :items
|
|
96
|
+
|
|
97
|
+
def initialize(items)
|
|
98
|
+
@items = items
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def choose(query = 'Select an item')
|
|
102
|
+
throw 'No items initialized' if @items.nil?
|
|
103
|
+
STDERR.puts
|
|
104
|
+
STDERR.puts "┌#{("─" * 74)}┐"
|
|
105
|
+
intpad = Math::log10(@items.length).to_i + 1
|
|
106
|
+
@items.each_with_index do |item, idx|
|
|
107
|
+
idxstr = "%#{intpad}d" % (idx + 1)
|
|
108
|
+
line = "#{idxstr}: #{item.title}"
|
|
109
|
+
pad = 74 - line.length
|
|
110
|
+
STDERR.puts "│#{line}#{" " * pad}│"
|
|
111
|
+
end
|
|
112
|
+
STDERR.puts "└┤ #{query} ├#{"─" * (70 - query.length)}┘"
|
|
113
|
+
sel = choose_number("> ", @items.length)
|
|
114
|
+
sel ? @items[sel.to_i - 1] : nil
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
class Snippet
|
|
119
|
+
attr_accessor :fragments, :contents
|
|
120
|
+
|
|
121
|
+
def initialize(file)
|
|
122
|
+
if File.exist?(File.expand_path(file))
|
|
123
|
+
@contents = IO.read(File.expand_path(file))
|
|
124
|
+
@fragments = fragments
|
|
125
|
+
else
|
|
126
|
+
throw ('Tried to initialize snippet with invalid file')
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def fragments
|
|
131
|
+
rx = /(?i-m)(?:[-#]+)\[([\s\S]*?)\][-# ]*\n([\s\S]*?)(?=\n(?:-+\[|#+\[|$))/
|
|
132
|
+
matches = @contents.scan(rx)
|
|
133
|
+
fragments = {}
|
|
134
|
+
matches.each do |m|
|
|
135
|
+
key = m[0]
|
|
136
|
+
value = m[1]
|
|
137
|
+
|
|
138
|
+
fragments[key] = value
|
|
139
|
+
end
|
|
140
|
+
fragments
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def choose_fragment
|
|
144
|
+
unless @fragments.empty?
|
|
145
|
+
items = []
|
|
146
|
+
@fragments.each { |k, v| items << MenuItem.new(k, k, v) }
|
|
147
|
+
menu = Menu.new(items)
|
|
148
|
+
return menu.choose('Select fragment')
|
|
149
|
+
end
|
|
150
|
+
nil
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# File search functions
|
|
155
|
+
class BunchFinder
|
|
156
|
+
include Prompt
|
|
157
|
+
attr_accessor :config_dir
|
|
158
|
+
|
|
159
|
+
def initialize
|
|
160
|
+
config_dir = `defaults read com.brettterpstra.bunch configDir`.strip
|
|
161
|
+
config_dir = File.expand_path(config_dir)
|
|
162
|
+
if File.directory?(config_dir)
|
|
163
|
+
@config_dir = config_dir
|
|
164
|
+
else
|
|
165
|
+
throw 'Unable to retrieve Bunches Folder'
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def files_to_items(dir, pattern)
|
|
170
|
+
Dir.chdir(dir)
|
|
171
|
+
items = []
|
|
172
|
+
Dir.glob(pattern) do |f|
|
|
173
|
+
if f.text?
|
|
174
|
+
filename = File.basename(f)
|
|
175
|
+
items << MenuItem.new(filename, filename, filename)
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
items
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def choose_bunch
|
|
182
|
+
items = files_to_items(@config_dir, '*.bunch')
|
|
183
|
+
items.map! do |item|
|
|
184
|
+
item.title = File.basename(item.title, '.bunch')
|
|
185
|
+
item.value = File.basename(item.title, '.bunch')
|
|
186
|
+
item
|
|
187
|
+
end
|
|
188
|
+
menu = Menu.new(items)
|
|
189
|
+
menu.choose('Select a Bunch')
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def choose_snippet
|
|
193
|
+
items = files_to_items(@config_dir, '*')
|
|
194
|
+
menu = Menu.new(items)
|
|
195
|
+
menu.choose('Select a Snippet')
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def expand_path(file)
|
|
199
|
+
File.join(@config_dir, file)
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
def contents(snippet)
|
|
203
|
+
IO.read(File.join(@config_dir, snippet))
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
def variables(content)
|
|
207
|
+
matches = content.scan(/\$\{(\S+)(:.*?)?\}/)
|
|
208
|
+
variables = []
|
|
209
|
+
matches.each { |m| variables << m[0].sub(/:\S+$/, '') }
|
|
210
|
+
variables.uniq
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def fill_variables(text)
|
|
214
|
+
vars = variables(text)
|
|
215
|
+
output = []
|
|
216
|
+
unless vars.empty?
|
|
217
|
+
puts 'Enter values for variables'
|
|
218
|
+
vars.each do |var|
|
|
219
|
+
res = get_line(var)
|
|
220
|
+
output << [var, CGI.escape(res)] unless res.empty?
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
output
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
class BunchURLGenerator
|
|
228
|
+
include Prompt
|
|
229
|
+
include Util
|
|
230
|
+
|
|
231
|
+
def generate
|
|
232
|
+
menu_items = [
|
|
233
|
+
MenuItem.new('open', 'Open a Bunch', 'open'),
|
|
234
|
+
MenuItem.new('close', 'Close a Bunch', 'close'),
|
|
235
|
+
MenuItem.new('toggle', 'Toggle a Bunch', 'toggle'),
|
|
236
|
+
MenuItem.new('snippet', 'Load a Snippet', 'snippet'),
|
|
237
|
+
MenuItem.new('raw', 'Load raw text', 'raw')
|
|
238
|
+
]
|
|
239
|
+
|
|
240
|
+
menu = Menu.new(menu_items)
|
|
241
|
+
finder = BunchFinder.new
|
|
242
|
+
|
|
243
|
+
selection = menu.choose
|
|
244
|
+
Process.exit 0 unless selection
|
|
245
|
+
url = "x-bunch://#{selection.value}"
|
|
246
|
+
parameters = []
|
|
247
|
+
case selection.id
|
|
248
|
+
when /(open|close|toggle)/
|
|
249
|
+
parameters << ['bunch', CGI.escape(finder.choose_bunch.value)]
|
|
250
|
+
when /snippet/
|
|
251
|
+
filename = finder.choose_snippet.value
|
|
252
|
+
parameters << ['file', filename]
|
|
253
|
+
filename = finder.expand_path(filename)
|
|
254
|
+
snippet = Snippet.new(filename)
|
|
255
|
+
fragment = snippet.choose_fragment
|
|
256
|
+
if fragment
|
|
257
|
+
parameters << ['fragment', CGI.escape(fragment.title)]
|
|
258
|
+
contents = fragment.value
|
|
259
|
+
else
|
|
260
|
+
contents = snippet.contents
|
|
261
|
+
end
|
|
262
|
+
variables = finder.fill_variables(contents)
|
|
263
|
+
parameters.concat(variables) if variables.length
|
|
264
|
+
when /raw/
|
|
265
|
+
parameters << ['text', menu.url_encode_text]
|
|
266
|
+
else
|
|
267
|
+
Process.exit 0
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
menu.items = [
|
|
271
|
+
MenuItem.new('app', 'Application', 'find_bid'),
|
|
272
|
+
MenuItem.new('url', 'URL', 'get_line(')
|
|
273
|
+
]
|
|
274
|
+
|
|
275
|
+
selection = menu.choose('Add success action? (Enter to skip)')
|
|
276
|
+
|
|
277
|
+
if selection
|
|
278
|
+
case selection.id
|
|
279
|
+
when /app/
|
|
280
|
+
app = get_line('Application name')
|
|
281
|
+
value = bundle_id(app)
|
|
282
|
+
when /url/
|
|
283
|
+
value = get_line('URL')
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
parameters << ['x-success', value] if value
|
|
287
|
+
|
|
288
|
+
delay = get_line('Delay for success action')
|
|
289
|
+
parameters << ['x-delay', delay.to_s] if delay =~ /^\d+$/
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
query_string = parameters.map { |param| "#{param[0]}=#{param[1]}" }.join('&')
|
|
293
|
+
|
|
294
|
+
puts url + '?' + query_string
|
|
295
|
+
end
|
|
296
|
+
end
|
data/lib/bunch/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: bunchcli
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Brett Terpstra
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2021-01-24 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description:
|
|
14
14
|
email:
|
|
@@ -21,6 +21,7 @@ files:
|
|
|
21
21
|
- ".gitignore"
|
|
22
22
|
- CHANGELOG.md
|
|
23
23
|
- Gemfile
|
|
24
|
+
- Gemfile.lock
|
|
24
25
|
- LICENSE.txt
|
|
25
26
|
- README.md
|
|
26
27
|
- Rakefile
|
|
@@ -28,6 +29,7 @@ files:
|
|
|
28
29
|
- bunchcli.gemspec
|
|
29
30
|
- lib/bunch.rb
|
|
30
31
|
- lib/bunch/bunchCLI.rb
|
|
32
|
+
- lib/bunch/url_generator.rb
|
|
31
33
|
- lib/bunch/version.rb
|
|
32
34
|
homepage: https://brettterpstra.com/projects/bunch
|
|
33
35
|
licenses:
|