bunchcli 1.0.0 → 1.1.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '064668e5dae28ec08fe4a939dc270e9b1880116f68f8ad39fc3c2252cd7609fa'
4
- data.tar.gz: be7be6b0cf5404ae193aec36d50b4efa4b6672b03be4e875f60cd89fcf3a07b9
3
+ metadata.gz: c85d1416d51d972ef7c577b1f143b2b646e9fcd4bb1871253b6ed5f98c5bbb4c
4
+ data.tar.gz: 5986ff8fdd90521530e7b10c5a151eb0144074fdbed534f869ca03345f8f1988
5
5
  SHA512:
6
- metadata.gz: 59abf612ddfe2eff6f5b54bf7952e08f67cad5bc7c2ec06ca9eb6d15aa097798c6bfaf6686292041fba6dd4fd34e3dc013ef3ffdff60c271a85b0fa99b64b144
7
- data.tar.gz: e888ed65aef4791420808cc5220f275c9e3c9c618ba931d273f4b118f3ffdcecb978b641e298ba0d18024758977ba3e883095daca71859af25e381291f903ce9
6
+ metadata.gz: d93fa5c16bc0e49dd24ead5c7d33ba786024e115b71c290142afc520118fc99a601de1bb0b35205aa102317a1a9af430f16d379ff803816ebe92c4fef4ad72af
7
+ data.tar.gz: 24bb5364188045b58253836044a9980ff1e99adb716841c5af206b08074467eb154a7e29484ad7f311528037eb61463711be43dcdcc7a9d873727670d802a057
data/CHANGELOG.md CHANGED
@@ -1,3 +1,20 @@
1
+ ### 1.1.4
2
+
3
+ - Add `--show-config-key KEY` query for specific keys (dir, toggle, method)
4
+
5
+ ### 1.1.3
6
+
7
+ - Add --prefs option
8
+
9
+ ### 1.1.2
10
+
11
+ - Allow app name in x-success if bundle id can't be found
12
+
13
+ ### 1.1
14
+
15
+ - Add interactive URL builder
16
+ - Snippet handling
17
+
1
18
  ### 1.0
2
19
 
3
20
  - Initial release
data/Gemfile.lock ADDED
@@ -0,0 +1,19 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ bunchcli (1.1.3)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ rake (12.3.3)
10
+
11
+ PLATFORMS
12
+ x86_64-darwin-19
13
+
14
+ DEPENDENCIES
15
+ bunchcli!
16
+ rake (~> 12.0)
17
+
18
+ BUNDLED WITH
19
+ 2.2.4
data/README.md CHANGED
@@ -10,14 +10,21 @@ A CLI for [Bunch.app](https://brettterpstra.com/projects/bunch).
10
10
 
11
11
  $ bunch -h
12
12
  CLI for Bunch.app
13
- -h, --help Display this screen
14
- -f, --force-refresh Force refresh cached preferences
15
13
  -l, --list List available Bunches
14
+ -s, --show BUNCH Show contents of Bunch
16
15
  -o, --open Open Bunch ignoring "Toggle Bunches" preference
17
16
  -c, --close Close Bunch ignoring "Toggle Bunches" preference
18
17
  -t, --toggle Toggle Bunch ignoring "Toggle Bunches" preference
19
- -s, --show BUNCH Show contents of Bunch
18
+ --snippet Load as snippet
19
+ --fragment=FRAGMENT Run a specific section
20
+ --vars=VARS Variables to pass to a snippet, comma-separated
21
+ --pref Set a preference. Run without argument to list available preferences.
22
+ -u, --url Output URL instead of opening
23
+ -i, --interactive Interactively generate a Bunch url
20
24
  --show-config Display configuration values
25
+ -f, --force-refresh Force refresh cached preferences
26
+ -h, --help Display this screen
27
+ -v, --version Display Bunch version
21
28
 
22
29
  Usage: `bunch [options] BUNCH_NAME|PATH_TO_FILE`
23
30
 
data/bin/bunch CHANGED
@@ -6,25 +6,25 @@ require 'bunch'
6
6
  def help
7
7
  puts "\nUsage: #{File.basename(__FILE__)} [options] BUNCH_NAME|PATH_TO_FILE"
8
8
  puts "\nBunch names are case insensitive and will execute first match"
9
+ puts "Use 'bunch -h' to display options"
10
+ end
11
+
12
+ def version
13
+ puts "Bunch CLI v#{BunchCLI::VERSION}"
9
14
  end
10
15
 
11
16
  bunch = Bunch.new
12
17
 
13
18
  optparse = OptionParser.new do |opts|
14
- opts.banner = 'CLI for Bunch.app'
19
+ opts.banner = "CLI for Bunch.app v#{BunchCLI::VERSION}"
15
20
 
16
- opts.on('-h', '--help', 'Display this screen') do |_opt|
17
- puts opts
18
- help
21
+ opts.on('-l', '--list', 'List available Bunches') do |_opt|
22
+ bunch.list_bunches
19
23
  Process.exit 0
20
24
  end
21
25
 
22
- opts.on('-f', '--force-refresh', 'Force refresh cached preferences') do |opt|
23
- bunch.update_cache
24
- end
25
-
26
- opts.on('-l', '--list', 'List available Bunches') do |_opt|
27
- bunch.list_bunches
26
+ opts.on('-s', '--show BUNCH', 'Show contents of Bunch') do |opt|
27
+ bunch.show(opt)
28
28
  Process.exit 0
29
29
  end
30
30
 
@@ -40,15 +40,55 @@ optparse = OptionParser.new do |opts|
40
40
  bunch.url_method = 'toggle'
41
41
  end
42
42
 
43
- opts.on('-s', '--show BUNCH', 'Show contents of Bunch') do |opt|
44
- bunch.show(opt)
43
+ opts.on('--snippet', 'Load as snippet') do |opt|
44
+ bunch.url_method = 'snippet'
45
+ end
46
+
47
+ opts.on('--fragment=FRAGMENT', 'Run a specific section') do |opt|
48
+ bunch.fragment = opt
49
+ end
50
+
51
+ opts.on('--vars=VARS', 'Variables to pass to a snippet, comma-separated') do |opt|
52
+ bunch.variables = opt
53
+ end
54
+
55
+ opts.on('--pref', 'Set a preference. Run without argument to list available preferences.') do |opt|
56
+ bunch.url_method = 'setPref'
57
+ end
58
+
59
+ opts.on('-u', '--url', 'Output URL instead of opening') do |_opt|
60
+ bunch.show_url = true
61
+ end
62
+
63
+ opts.on('-i','--interactive', 'Interactively generate a Bunch url') do |opt|
64
+ BunchURLGenerator.new.generate
45
65
  Process.exit 0
46
66
  end
47
67
 
48
- opts.on('--show-config', 'Display configuration values') do |opt|
68
+ opts.on('--show-config', 'Display all configuration values') do |opt|
49
69
  bunch.show_config
50
70
  Process.exit 0
51
71
  end
72
+
73
+ opts.on('--show-config-key KEY', 'Display a config value [dir, toggle, method]') do |opt|
74
+ bunch.show_config(opt)
75
+ Process.exit 0
76
+ end
77
+
78
+ opts.on('-f', '--force-refresh', 'Force refresh cached preferences') do |opt|
79
+ bunch.update_cache
80
+ end
81
+
82
+ opts.on('-h', '--help', 'Display this screen') do |_opt|
83
+ puts opts
84
+ help
85
+ Process.exit 0
86
+ end
87
+
88
+ opts.on('-v', '--version', 'Display Bunch version') do |_opt|
89
+ version
90
+ Process.exit 0
91
+ end
52
92
  end
53
93
 
54
94
  optparse.parse!
@@ -57,6 +97,8 @@ unless ARGV.length > 0
57
97
  if STDIN.stat.size > 0
58
98
  bunch.url_method = 'raw'
59
99
  bunch.open(CGI.escape(STDIN.read))
100
+ elsif bunch.url_method == 'setPref'
101
+ bunch.list_preferences
60
102
  else
61
103
  puts "CLI for Bunches.app"
62
104
  help
data/lib/bunch.rb CHANGED
@@ -4,4 +4,5 @@ CACHE_FILE = "~/.bunch_cli_cache"
4
4
  require "bunch/version"
5
5
  require 'yaml'
6
6
  require 'cgi'
7
+ require 'bunch/url_generator'
7
8
  require 'bunch/bunchCLI'
@@ -1,13 +1,26 @@
1
1
  class Bunch
2
- attr_writer :url_method
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
 
16
+ def launch_if_needed
17
+ pid = `ps ax | grep 'MacOS/Bunch'|grep -v grep`.strip
18
+ if pid == ""
19
+ `open -a Bunch`
20
+ sleep 2
21
+ end
22
+ end
23
+
11
24
  def update_cache
12
25
  @bunch_dir = nil
13
26
  @url_method = nil
@@ -41,6 +54,18 @@ class Bunch
41
54
  @bunches = settings['bunches'] || generate_bunch_list
42
55
  end
43
56
 
57
+ def variable_query
58
+ vars = @variables.split(/,/).map { |v| v.strip }
59
+ query = []
60
+ vars.each { |v|
61
+ parts = v.split(/=/).map { |v| v.strip }
62
+ k = parts[0]
63
+ v = parts[1]
64
+ query << "#{k}=#{CGI.escape(v)}"
65
+ }
66
+ query
67
+ end
68
+
44
69
  # items.push({title: 0})
45
70
  def generate_bunch_list
46
71
  items = []
@@ -69,12 +94,17 @@ class Bunch
69
94
  end
70
95
 
71
96
  def url(bunch)
97
+ params = "&x-success=#{@success}" if @success
72
98
  if url_method == 'file'
73
- %(x-bunch://raw?file=#{bunch})
99
+ %(x-bunch://raw?file=#{bunch}#{params})
74
100
  elsif url_method == 'raw'
75
- %(x-bunch://raw?txt=#{bunch})
101
+ %(x-bunch://raw?txt=#{bunch}#{params})
102
+ elsif url_method == 'snippet'
103
+ %(x-bunch://snippet?file=#{bunch}#{params})
104
+ elsif url_method == 'setPref'
105
+ %(x-bunch://setPref?#{bunch})
76
106
  else
77
- %(x-bunch://#{url_method}?bunch=#{bunch[:title]})
107
+ %(x-bunch://#{url_method}?bunch=#{bunch[:title]}#{params})
78
108
  end
79
109
  end
80
110
 
@@ -104,31 +134,83 @@ class Bunch
104
134
  (url_method.gsub(/e$/, '') + 'ing').capitalize
105
135
  end
106
136
 
137
+ def list_preferences
138
+ prefs =<<EOF
139
+ toggleBunches=[0,1] Allow Bunches to be both opened and closed
140
+ configDir=[path] Absolute path to Bunches folder
141
+ singleBunchMode=[0,1] Close open Bunch when opening new one
142
+ preserveOpenBunches=[0,1] Restore Open Bunches on Launch
143
+ debugLevel=[0-4] Set the logging level for the Bunch Log
144
+ EOF
145
+ puts prefs
146
+ end
147
+
148
+
107
149
  def open(str)
150
+ launch_if_needed
108
151
  # get front app
109
152
  front_app = %x{osascript -e 'tell application "System Events" to return name of first application process whose frontmost is true'}.strip
153
+ bid = bundle_id(front_app)
154
+ @success = bid if (bid)
155
+
110
156
  if @url_method == 'raw'
111
157
  warn 'Running raw string'
112
- `open '#{url(str)}'`
158
+ if @show_url
159
+ $stdout.puts url(str)
160
+ else
161
+ `open '#{url(str)}'`
162
+ end
163
+ elsif @url_method == 'snippet'
164
+ _url = url(str)
165
+ params = []
166
+ params << "fragment=#{CGI.escape(@fragment)}" if @fragment
167
+ params.concat(variable_query) if @variables
168
+ _url += '&' + params.join('&')
169
+ if @show_url
170
+ $stdout.puts _url
171
+ else
172
+ warn "Opening snippet"
173
+ `open '#{_url}'`
174
+ end
175
+ elsif @url_method == 'setPref'
176
+ if str =~ /^(\w+)=([^= ]+)$/
177
+ _url = url(str)
178
+ if @show_url
179
+ $stdout.puts _url
180
+ else
181
+ warn "Setting preference #{str}"
182
+ `open '#{_url}'`
183
+ end
184
+ else
185
+ warn "Invalid key=value pair"
186
+ Process.exit 1
187
+ end
113
188
  else
114
189
  bunch = find_bunch(str)
115
190
  unless bunch
116
191
  if File.exists?(str)
117
192
  @url_method = 'file'
118
- warn "Opening file"
119
- `open '#{url(str)}'`
193
+ if @show_url
194
+ $stdout.puts url(str)
195
+ else
196
+ warn "Opening file"
197
+ `open '#{url(str)}'`
198
+ end
120
199
  else
121
200
  warn 'No matching Bunch found'
122
201
  Process.exit 1
123
202
  end
124
203
  else
125
- warn "#{human_action} #{bunch[:title]}"
126
-
127
- `open "#{url(bunch)}"`
204
+ if @show_url
205
+ $stdout.puts url(str)
206
+ else
207
+ warn "#{human_action} #{bunch[:title]}"
208
+ `open '#{url(bunch)}'`
209
+ end
128
210
  end
129
211
  end
130
212
  # attempt to restore front app
131
- %x{osascript -e 'delay 2' -e 'tell application "#{front_app}" to activate'}
213
+ # %x{osascript -e 'delay 2' -e 'tell application "#{front_app}" to activate'}
132
214
  end
133
215
 
134
216
  def show(str)
@@ -137,12 +219,21 @@ class Bunch
137
219
  puts output
138
220
  end
139
221
 
140
- def show_config
141
- puts "Bunches Folder: #{bunch_dir}"
142
- puts "Default URL Method: #{url_method}"
143
- puts "Cached Bunches"
144
- bunches.each {|b|
145
- puts " - #{b[:title]}"
146
- }
222
+ def show_config(key=nil)
223
+ case key
224
+ when /(folder|dir)/
225
+ puts bunch_dir
226
+ when /toggle/
227
+ puts url_method == 'toggle' ? 'true' : 'false'
228
+ when /method/
229
+ puts url_method
230
+ else
231
+ puts "Bunches Folder: #{bunch_dir}"
232
+ puts "Default URL Method: #{url_method}"
233
+ puts "Cached Bunches"
234
+ bunches.each {|b|
235
+ puts " - #{b[:title]}"
236
+ }
237
+ end
147
238
  end
148
239
  end
@@ -0,0 +1,297 @@
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
+ foundapp = apps.split(/\n/).select! { |line| line.chomp =~ /#{shortname}\.app$/i }[0]
21
+
22
+ if foundapp
23
+ bid = `mdls -name kMDItemCFBundleIdentifier -r "#{foundapp}"`.chomp
24
+ else
25
+ # warn "Could not locate bundle id for #{shortname}, using provided app name"
26
+ bid = app
27
+ end
28
+ bid
29
+ end
30
+ end
31
+
32
+ # CLI Prompt utilities
33
+ module Prompt
34
+ def choose_number(query = '->', max)
35
+ stty_save = `stty -g`.chomp
36
+ sel = nil
37
+ begin
38
+ while !sel =~ /^\d+$/ || sel.to_i <= 0 || sel.to_i > max
39
+ sel = Readline.readline("#{query}", true)
40
+ return nil if sel =~ /^\s*$/
41
+ end
42
+ rescue Interrupt
43
+ system('stty', stty_save) # Restore
44
+ exit
45
+ end
46
+ sel ? sel.to_i : nil
47
+ end
48
+
49
+ def get_line(query = '->')
50
+ stty_save = `stty -g`.chomp
51
+ begin
52
+ line = Readline.readline("#{query}: ", true)
53
+ rescue Interrupt
54
+ system('stty', stty_save) # Restore
55
+ exit
56
+ end
57
+ line.chomp
58
+ end
59
+
60
+ def get_text(query = 'Enter text, ^d to end')
61
+ stty_save = `stty -g`.chomp
62
+ lines = []
63
+ puts query
64
+ begin
65
+ while (line = Readline.readline)
66
+ lines << line
67
+ end
68
+ rescue Interrupt
69
+ system('stty', stty_save) # Restore
70
+ exit
71
+ end
72
+ lines.join("\n").chomp
73
+ end
74
+
75
+ def url_encode_text
76
+ text = get_text
77
+ puts
78
+ CGI.escape(text)
79
+ end
80
+ end
81
+
82
+ # Single menu item
83
+ class MenuItem
84
+ attr_accessor :id, :title, :value
85
+
86
+ def initialize(id, title, value)
87
+ @id = id
88
+ @title = title
89
+ @value = value
90
+ end
91
+ end
92
+
93
+ # Collection of menu items
94
+ class Menu
95
+ include Prompt
96
+ attr_accessor :items
97
+
98
+ def initialize(items)
99
+ @items = items
100
+ end
101
+
102
+ def choose(query = 'Select an item')
103
+ throw 'No items initialized' if @items.nil?
104
+ STDERR.puts
105
+ STDERR.puts "┌#{("─" * 74)}┐"
106
+ intpad = Math::log10(@items.length).to_i + 1
107
+ @items.each_with_index do |item, idx|
108
+ idxstr = "%#{intpad}d" % (idx + 1)
109
+ line = "#{idxstr}: #{item.title}"
110
+ pad = 74 - line.length
111
+ STDERR.puts "│#{line}#{" " * pad}│"
112
+ end
113
+ STDERR.puts "└┤ #{query} ├#{"─" * (70 - query.length)}┘"
114
+ sel = choose_number("> ", @items.length)
115
+ sel ? @items[sel.to_i - 1] : nil
116
+ end
117
+ end
118
+
119
+ class Snippet
120
+ attr_accessor :fragments, :contents
121
+
122
+ def initialize(file)
123
+ if File.exist?(File.expand_path(file))
124
+ @contents = IO.read(File.expand_path(file))
125
+ @fragments = fragments
126
+ else
127
+ throw ('Tried to initialize snippet with invalid file')
128
+ end
129
+ end
130
+
131
+ def fragments
132
+ rx = /(?i-m)(?:[-#]+)\[([\s\S]*?)\][-# ]*\n([\s\S]*?)(?=\n(?:-+\[|#+\[|$))/
133
+ matches = @contents.scan(rx)
134
+ fragments = {}
135
+ matches.each do |m|
136
+ key = m[0]
137
+ value = m[1]
138
+
139
+ fragments[key] = value
140
+ end
141
+ fragments
142
+ end
143
+
144
+ def choose_fragment
145
+ unless @fragments.empty?
146
+ items = []
147
+ @fragments.each { |k, v| items << MenuItem.new(k, k, v) }
148
+ menu = Menu.new(items)
149
+ return menu.choose('Select fragment')
150
+ end
151
+ nil
152
+ end
153
+ end
154
+
155
+ # File search functions
156
+ class BunchFinder
157
+ include Prompt
158
+ attr_accessor :config_dir
159
+
160
+ def initialize
161
+ config_dir = `defaults read com.brettterpstra.bunch configDir`.strip
162
+ config_dir = File.expand_path(config_dir)
163
+ if File.directory?(config_dir)
164
+ @config_dir = config_dir
165
+ else
166
+ throw 'Unable to retrieve Bunches Folder'
167
+ end
168
+ end
169
+
170
+ def files_to_items(dir, pattern)
171
+ Dir.chdir(dir)
172
+ items = []
173
+ Dir.glob(pattern) do |f|
174
+ if f.text?
175
+ filename = File.basename(f)
176
+ items << MenuItem.new(filename, filename, filename)
177
+ end
178
+ end
179
+ items
180
+ end
181
+
182
+ def choose_bunch
183
+ items = files_to_items(@config_dir, '*.bunch')
184
+ items.map! do |item|
185
+ item.title = File.basename(item.title, '.bunch')
186
+ item.value = File.basename(item.title, '.bunch')
187
+ item
188
+ end
189
+ menu = Menu.new(items)
190
+ menu.choose('Select a Bunch')
191
+ end
192
+
193
+ def choose_snippet
194
+ items = files_to_items(@config_dir, '*')
195
+ menu = Menu.new(items)
196
+ menu.choose('Select a Snippet')
197
+ end
198
+
199
+ def expand_path(file)
200
+ File.join(@config_dir, file)
201
+ end
202
+
203
+ def contents(snippet)
204
+ IO.read(File.join(@config_dir, snippet))
205
+ end
206
+
207
+ def variables(content)
208
+ matches = content.scan(/\$\{(\S+)(:.*?)?\}/)
209
+ variables = []
210
+ matches.each { |m| variables << m[0].sub(/:\S+$/, '') }
211
+ variables.uniq
212
+ end
213
+
214
+ def fill_variables(text)
215
+ vars = variables(text)
216
+ output = []
217
+ unless vars.empty?
218
+ puts 'Enter values for variables'
219
+ vars.each do |var|
220
+ res = get_line(var)
221
+ output << [var, CGI.escape(res)] unless res.empty?
222
+ end
223
+ end
224
+ output
225
+ end
226
+ end
227
+
228
+ class BunchURLGenerator
229
+ include Prompt
230
+ include Util
231
+
232
+ def generate
233
+ menu_items = [
234
+ MenuItem.new('open', 'Open a Bunch', 'open'),
235
+ MenuItem.new('close', 'Close a Bunch', 'close'),
236
+ MenuItem.new('toggle', 'Toggle a Bunch', 'toggle'),
237
+ MenuItem.new('snippet', 'Load a Snippet', 'snippet'),
238
+ MenuItem.new('raw', 'Load raw text', 'raw')
239
+ ]
240
+
241
+ menu = Menu.new(menu_items)
242
+ finder = BunchFinder.new
243
+
244
+ selection = menu.choose
245
+ Process.exit 0 unless selection
246
+ url = "x-bunch://#{selection.value}"
247
+ parameters = []
248
+ case selection.id
249
+ when /(open|close|toggle)/
250
+ parameters << ['bunch', CGI.escape(finder.choose_bunch.value)]
251
+ when /snippet/
252
+ filename = finder.choose_snippet.value
253
+ parameters << ['file', filename]
254
+ filename = finder.expand_path(filename)
255
+ snippet = Snippet.new(filename)
256
+ fragment = snippet.choose_fragment
257
+ if fragment
258
+ parameters << ['fragment', CGI.escape(fragment.title)]
259
+ contents = fragment.value
260
+ else
261
+ contents = snippet.contents
262
+ end
263
+ variables = finder.fill_variables(contents)
264
+ parameters.concat(variables) if variables.length
265
+ when /raw/
266
+ parameters << ['text', menu.url_encode_text]
267
+ else
268
+ Process.exit 0
269
+ end
270
+
271
+ menu.items = [
272
+ MenuItem.new('app', 'Application', 'find_bid'),
273
+ MenuItem.new('url', 'URL', 'get_line(')
274
+ ]
275
+
276
+ selection = menu.choose('Add success action? (Enter to skip)')
277
+
278
+ if selection
279
+ case selection.id
280
+ when /app/
281
+ app = get_line('Application name')
282
+ value = bundle_id(app)
283
+ when /url/
284
+ value = get_line('URL')
285
+ end
286
+
287
+ parameters << ['x-success', value] if value
288
+
289
+ delay = get_line('Delay for success action')
290
+ parameters << ['x-delay', delay.to_s] if delay =~ /^\d+$/
291
+ end
292
+
293
+ query_string = parameters.map { |param| "#{param[0]}=#{param[1]}" }.join('&')
294
+
295
+ puts url + '?' + query_string
296
+ end
297
+ end
data/lib/bunch/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module BunchCLI
2
- VERSION = "1.0.0"
2
+ VERSION = "1.1.4"
3
3
  end
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.0.0
4
+ version: 1.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brett Terpstra
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-12-19 00:00:00.000000000 Z
11
+ date: 2021-02-03 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: