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 +4 -4
- data/CHANGELOG.md +17 -0
- data/Gemfile.lock +19 -0
- data/README.md +10 -3
- data/bin/bunch +55 -13
- data/lib/bunch.rb +1 -0
- data/lib/bunch/bunchCLI.rb +109 -18
- data/lib/bunch/url_generator.rb +297 -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: c85d1416d51d972ef7c577b1f143b2b646e9fcd4bb1871253b6ed5f98c5bbb4c
|
4
|
+
data.tar.gz: 5986ff8fdd90521530e7b10c5a151eb0144074fdbed534f869ca03345f8f1988
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
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
|
-
|
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 =
|
19
|
+
opts.banner = "CLI for Bunch.app v#{BunchCLI::VERSION}"
|
15
20
|
|
16
|
-
opts.on('-
|
17
|
-
|
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('-
|
23
|
-
bunch.
|
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('
|
44
|
-
bunch.
|
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
data/lib/bunch/bunchCLI.rb
CHANGED
@@ -1,13 +1,26 @@
|
|
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
|
|
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
|
-
|
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
|
-
|
119
|
-
|
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
|
-
|
126
|
-
|
127
|
-
|
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
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
puts
|
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
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.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:
|
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:
|