hiiro 0.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 +7 -0
- data/.config/.keep +0 -0
- data/CLAUDE.md +101 -0
- data/LICENSE +21 -0
- data/README.md +276 -0
- data/Rakefile +3 -0
- data/bin/h +415 -0
- data/bin/h-buffer +46 -0
- data/bin/h-pane +63 -0
- data/bin/h-plugin +51 -0
- data/bin/h-session +43 -0
- data/bin/h-video +522 -0
- data/bin/h-window +59 -0
- data/docs/README.md +41 -0
- data/docs/h-buffer.md +52 -0
- data/docs/h-pane.md +71 -0
- data/docs/h-plugin.md +58 -0
- data/docs/h-session.md +63 -0
- data/docs/h-video.md +172 -0
- data/docs/h-window.md +77 -0
- data/exe/hiiro +13 -0
- data/hiiro.gemspec +30 -0
- data/lib/hiiro/version.rb +3 -0
- data/lib/hiiro.rb +389 -0
- data/plugins/notify.rb +30 -0
- data/plugins/pins.rb +113 -0
- data/plugins/project.rb +75 -0
- data/plugins/task.rb +679 -0
- data/plugins/tmux.rb +29 -0
- data/script/compare +14 -0
- data/script/install +16 -0
- metadata +92 -0
data/lib/hiiro.rb
ADDED
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
require "fileutils"
|
|
2
|
+
require "yaml"
|
|
3
|
+
|
|
4
|
+
require_relative "hiiro/version"
|
|
5
|
+
|
|
6
|
+
class Hiiro
|
|
7
|
+
def self.init(*args, plugins: [], logging: false, **values, &block)
|
|
8
|
+
args = ARGV if args.empty?
|
|
9
|
+
|
|
10
|
+
new($0, *args, logging: logging, **values).tap do |hiiro|
|
|
11
|
+
hiiro.load_plugins(*plugins)
|
|
12
|
+
|
|
13
|
+
hiiro.add_subcmd(:edit, **values) { |*args|
|
|
14
|
+
system(ENV['EDITOR'] || 'nvim', hiiro.bin)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
block.call(hiiro) if block
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def self.load_env
|
|
22
|
+
Config.plugin_files.each do |plugin_file|
|
|
23
|
+
require plugin_file
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
attr_reader :bin, :bin_name, :all_args
|
|
28
|
+
attr_reader :subcmd, :args
|
|
29
|
+
attr_reader :loaded_plugins
|
|
30
|
+
attr_reader :logging
|
|
31
|
+
attr_reader :global_values
|
|
32
|
+
|
|
33
|
+
def initialize(bin, *args, logging: false, **values)
|
|
34
|
+
@bin = bin
|
|
35
|
+
@bin_name = File.basename(bin)
|
|
36
|
+
@all_args = args
|
|
37
|
+
@subcmd, *@args = args # normally i would never do this
|
|
38
|
+
@loaded_plugins = []
|
|
39
|
+
@logging = logging
|
|
40
|
+
@global_values = values
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def run
|
|
44
|
+
result = runner.run(*args)
|
|
45
|
+
|
|
46
|
+
handle_result(result)
|
|
47
|
+
|
|
48
|
+
exit 1
|
|
49
|
+
rescue => e
|
|
50
|
+
puts "ERROR: #{e.message}"
|
|
51
|
+
puts e.backtrace
|
|
52
|
+
exit 1
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def handle_result(result)
|
|
56
|
+
exit 0 if result.nil? || result
|
|
57
|
+
|
|
58
|
+
exit 1
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def runnable?
|
|
62
|
+
runner
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def runner
|
|
66
|
+
runners.runner || runners.default_subcommand
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def runners
|
|
70
|
+
@runners ||= Runners.new(self)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def add_default(**values, &handler)
|
|
74
|
+
runners.add_subcommand(:DEFAULT, handler, **global_values, **values)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def add_subcommand(name, **values, &handler)
|
|
78
|
+
runners.add_subcommand(name, handler, **global_values, **values)
|
|
79
|
+
end
|
|
80
|
+
alias add_subcmd add_subcommand
|
|
81
|
+
|
|
82
|
+
def full_name
|
|
83
|
+
runner&.full_name || [bin_name, subcmd].join(?-)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def subcommand_names
|
|
87
|
+
runners.subcommand_names
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def pins = @pins ||= Pin.new(self)
|
|
91
|
+
|
|
92
|
+
def load_plugins(*plugins)
|
|
93
|
+
plugins.flatten.each { |plugin| load_plugin(plugin) }
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def load_plugin(plugin_const)
|
|
97
|
+
return if @loaded_plugins.include?(plugin_const)
|
|
98
|
+
|
|
99
|
+
plugin_const.load(self)
|
|
100
|
+
@loaded_plugins.push(plugin_const)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def help
|
|
104
|
+
ambiguous = runners.ambiguous_matches
|
|
105
|
+
|
|
106
|
+
if ambiguous.any?
|
|
107
|
+
puts "Ambiguous subcommand #{subcmd.inspect}!"
|
|
108
|
+
puts ""
|
|
109
|
+
puts "Did you mean one of these?"
|
|
110
|
+
list_runners(ambiguous)
|
|
111
|
+
else
|
|
112
|
+
subcmd_msg = "Subcommand required!"
|
|
113
|
+
subcmd_msg = "Subcommand #{subcmd.inspect} not found!" if subcmd
|
|
114
|
+
|
|
115
|
+
puts subcmd_msg
|
|
116
|
+
puts ""
|
|
117
|
+
puts "Possible subcommands:"
|
|
118
|
+
list_runners(runners.all_runners)
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def list_runners(list)
|
|
123
|
+
max_name = list.map { |r| r.subcommand_name.length }.max || 0
|
|
124
|
+
max_type = list.map { |r| r.type.to_s.length }.max || 0
|
|
125
|
+
max_params = list.map { |r| r.params_string.to_s.length }.max || 0
|
|
126
|
+
|
|
127
|
+
list.each do |r|
|
|
128
|
+
name = r.subcommand_name.ljust(max_name)
|
|
129
|
+
type = "(#{r.type})".ljust(max_type + 2)
|
|
130
|
+
params = r.params_string
|
|
131
|
+
params_col = params ? params.ljust(max_params) : ''.ljust(max_params)
|
|
132
|
+
location = r.location
|
|
133
|
+
puts " #{name} #{params_col} #{type} #{location}"
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def log(message)
|
|
138
|
+
return unless logging
|
|
139
|
+
|
|
140
|
+
puts "[Hiiro: #{bin_name} #{(runner&.subcommand_name || subcmd).inspect}]: #{message}"
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def parsed_args
|
|
144
|
+
i = Args.new(*args)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def get_value(name)
|
|
148
|
+
runner&.values&.[](name)
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
class Config
|
|
152
|
+
class << self
|
|
153
|
+
def plugin_files
|
|
154
|
+
Dir.glob(File.join(plugin_dir, '*'))
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def plugin_dir
|
|
158
|
+
config_dir('plugins')
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def config_dir(subdir=nil)
|
|
162
|
+
File.join(Dir.home, '.config/hiiro', *[subdir].compact).tap do |config_path|
|
|
163
|
+
FileUtils.mkdir_p(config_path) unless Dir.exist?(config_path)
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
class Runners
|
|
170
|
+
attr_reader :hiiro, :bin_name, :subcmd, :subcommands
|
|
171
|
+
|
|
172
|
+
def initialize(hiiro)
|
|
173
|
+
@hiiro = hiiro
|
|
174
|
+
@bin_name = hiiro.bin_name
|
|
175
|
+
@subcmd = hiiro.subcmd
|
|
176
|
+
@subcommands = {}
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def runner
|
|
180
|
+
return default_subcommand if subcmd.to_s == ''
|
|
181
|
+
|
|
182
|
+
exact_runner || unambiguous_runner
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def default_subcommand
|
|
186
|
+
Subcommand.new(bin_name, :default, lambda { hiiro.help; false })
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def subcommand_names
|
|
190
|
+
all_runners.map(&:subcommand_name)
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def all_runners
|
|
194
|
+
[*all_bins, *subcommands.values]
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
def paths
|
|
198
|
+
@paths ||= ENV['PATH'].split(?:).uniq
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def all_bins
|
|
202
|
+
pattern = format('{%s}/%s-*', paths.join(?,), bin_name)
|
|
203
|
+
|
|
204
|
+
Dir.glob(pattern).map { |path| Bin.new(bin_name, path) }
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def add_subcommand(name, handler, **values)
|
|
208
|
+
@subcommands[name] = Subcommand.new(bin_name, name, handler, values)
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def exact_runner
|
|
212
|
+
all_runners.find { |r| r.exact_match?(subcmd) }
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def unambiguous_runner
|
|
216
|
+
return nil if subcmd.nil?
|
|
217
|
+
|
|
218
|
+
matches = matching_runners
|
|
219
|
+
return matches.first if matches.count == 1
|
|
220
|
+
|
|
221
|
+
nil
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
def ambiguous_matches
|
|
225
|
+
return [] if subcmd.nil?
|
|
226
|
+
|
|
227
|
+
matches = matching_runners
|
|
228
|
+
return matches if matches.count > 1
|
|
229
|
+
|
|
230
|
+
[]
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
def matching_runners
|
|
234
|
+
remove_child_runners(all_matching_runners)
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
def all_matching_runners
|
|
238
|
+
all_runners.select { |r| r.match?(subcmd) }
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def remove_child_runners(list)
|
|
242
|
+
list.reject do |r|
|
|
243
|
+
list.any? { |other| r != other && r.full_name.start_with?(other.full_name + ?-) }
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
class Bin
|
|
248
|
+
attr_reader :bin_name, :path, :name
|
|
249
|
+
alias full_name name
|
|
250
|
+
|
|
251
|
+
def initialize(bin_name, path)
|
|
252
|
+
@bin_name = bin_name
|
|
253
|
+
@path = path
|
|
254
|
+
@name = File.basename(path)
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
def run(*args)
|
|
258
|
+
system(path, *args)
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
def exact_match?(subcmd)
|
|
262
|
+
subcommand_name == subcmd.to_s
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
def match?(subcmd)
|
|
266
|
+
subcommand_name.start_with?(subcmd.to_s)
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
def subcommand_name
|
|
270
|
+
name.sub("#{bin_name}-", '')
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
def values
|
|
274
|
+
{}
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
def type
|
|
278
|
+
:bin
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
def location
|
|
282
|
+
path
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
def params_string
|
|
286
|
+
nil
|
|
287
|
+
end
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
class Subcommand
|
|
291
|
+
attr_reader :bin_name, :name, :handler, :values
|
|
292
|
+
alias subcommand_name name
|
|
293
|
+
|
|
294
|
+
def initialize(bin_name, name, handler, values={})
|
|
295
|
+
@bin_name = bin_name
|
|
296
|
+
@name = name.to_s
|
|
297
|
+
@handler = handler
|
|
298
|
+
@values = values || {}
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
def run(*args)
|
|
302
|
+
handler.call(*args)
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
def exact_match?(subcmd)
|
|
306
|
+
name == subcmd.to_s
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
def match?(subcmd)
|
|
310
|
+
name.start_with?(subcmd.to_s)
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
def full_name
|
|
314
|
+
[bin_name, name].join(?-)
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
def type
|
|
318
|
+
:subcommand
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
def location
|
|
322
|
+
handler.source_location&.join(':')
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
def params_string
|
|
326
|
+
return nil unless handler.respond_to?(:parameters)
|
|
327
|
+
|
|
328
|
+
params = handler.parameters
|
|
329
|
+
return nil if params.empty?
|
|
330
|
+
return nil if params == [[:rest]] || params == [[:rest, :args]]
|
|
331
|
+
|
|
332
|
+
params.map { |type, name|
|
|
333
|
+
case type
|
|
334
|
+
when :req then "<#{name}>"
|
|
335
|
+
when :opt then "[#{name}]"
|
|
336
|
+
when :rest then "[*#{name}]" if name
|
|
337
|
+
when :keyreq then "<#{name}:>"
|
|
338
|
+
when :key then "[#{name}:]"
|
|
339
|
+
when :keyrest then "[**#{name}]" if name
|
|
340
|
+
when :block then "[&#{name}]" if name
|
|
341
|
+
end
|
|
342
|
+
}.compact.join(' ')
|
|
343
|
+
end
|
|
344
|
+
end
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
class Args
|
|
348
|
+
attr_reader :raw_args
|
|
349
|
+
|
|
350
|
+
def initialize(*raw_args)
|
|
351
|
+
@raw_args = raw_args
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
def flags
|
|
355
|
+
@flags ||= proc {
|
|
356
|
+
raw_args.select { |arg|
|
|
357
|
+
arg.match?(/^-[^-]/)
|
|
358
|
+
}.flat_map { |arg|
|
|
359
|
+
arg.sub(/^-/, '').chars
|
|
360
|
+
}
|
|
361
|
+
}.call
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
def flag?(flag)
|
|
365
|
+
flags.include?(flag)
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
def flag_value(flag)
|
|
369
|
+
found_flag = false
|
|
370
|
+
raw_args.each do |arg|
|
|
371
|
+
if found_flag
|
|
372
|
+
return arg
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
if arg.match?(/^-\w*#{flag}/)
|
|
376
|
+
found_flag = true
|
|
377
|
+
end
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
nil
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
def values
|
|
384
|
+
raw_args.reject do |arg|
|
|
385
|
+
arg.match?(/^-/)
|
|
386
|
+
end
|
|
387
|
+
end
|
|
388
|
+
end
|
|
389
|
+
end
|
data/plugins/notify.rb
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
module Notify
|
|
4
|
+
def self.load(hiiro)
|
|
5
|
+
hiiro.log "Plugin loaded: #{name}"
|
|
6
|
+
|
|
7
|
+
hiiro.load_plugin(Tmux)
|
|
8
|
+
attach_methods(hiiro)
|
|
9
|
+
add_subcommands(hiiro)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def self.add_subcommands(hiiro)
|
|
13
|
+
hiiro.add_subcmd(:notify) do |message, link=nil, title=nil, command=nil|
|
|
14
|
+
hiiro.notify(message, title:, link:, command:)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.attach_methods(hiiro)
|
|
19
|
+
hiiro.instance_eval do
|
|
20
|
+
def notify(message, title: nil, link: nil, command: nil)
|
|
21
|
+
args = ['terminal-notifier', '-message', message]
|
|
22
|
+
args += ['-title', title] if title
|
|
23
|
+
args += ['-open', link] if link
|
|
24
|
+
args += ['-execute', command] if command
|
|
25
|
+
|
|
26
|
+
system(*args) if system('which', 'terminal-notifier')
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
data/plugins/pins.rb
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
module Pins
|
|
4
|
+
def self.load(hiiro)
|
|
5
|
+
hiiro.log "Plugin loaded: #{name}"
|
|
6
|
+
|
|
7
|
+
attach_methods(hiiro)
|
|
8
|
+
add_subcommands(hiiro)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def self.add_subcommands(hiiro)
|
|
12
|
+
hiiro.add_subcmd(:pin) do |*args|
|
|
13
|
+
pins = hiiro.pins
|
|
14
|
+
|
|
15
|
+
case args
|
|
16
|
+
in [] then pins.pins.each {|k,v| puts "#{k} => #{v.inspect}" }
|
|
17
|
+
in ['all'] then pins.pins.each {|k,v| puts "#{k} => #{v.inspect}" }
|
|
18
|
+
in ['get', name] then puts pins.get(name)
|
|
19
|
+
in [name] then puts pins.get(name)
|
|
20
|
+
in ['rm', name] then puts pins.remove_and_save(name)
|
|
21
|
+
in ['remove', name] then puts pins.remove_and_save(name)
|
|
22
|
+
in ['set', name, value] then pins.set_and_save(name, value)
|
|
23
|
+
in [name, value] then pins.set_and_save(name, value)
|
|
24
|
+
in [name, *values] then pins.set_and_save(name, values.join(' '))
|
|
25
|
+
else
|
|
26
|
+
puts "No matching pin subcommand for #{args.inspect}"
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def self.attach_methods(hiiro)
|
|
32
|
+
hiiro.instance_eval do
|
|
33
|
+
def pins
|
|
34
|
+
@pins ||= Pin.new(self)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
class Pin
|
|
40
|
+
attr_reader :hiiro
|
|
41
|
+
|
|
42
|
+
def initialize(hiiro) = @hiiro = hiiro
|
|
43
|
+
|
|
44
|
+
def get(name)
|
|
45
|
+
pins[find(name)]
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def set(name, value)
|
|
49
|
+
pins[name.to_s] = value
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def set_and_save(name, value)
|
|
53
|
+
set(name, value)
|
|
54
|
+
save_pins
|
|
55
|
+
value
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def find(partial)
|
|
59
|
+
pins.keys.map(&:to_s).find do |pin_name|
|
|
60
|
+
pin_name.start_with?(partial)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def find_all(partial)
|
|
65
|
+
pins.keys.map(&:to_s).select do |pin_name|
|
|
66
|
+
pin_name.start_with?(partial)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def remove(name)
|
|
71
|
+
all_matches = find_all(name)
|
|
72
|
+
|
|
73
|
+
if all_matches.count > 1
|
|
74
|
+
puts "Unable to remove pin. Multiple matches: #{all_matches.inspect}"
|
|
75
|
+
return
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
pin_name = all_matches.first
|
|
79
|
+
|
|
80
|
+
pins.delete(pin_name.to_s)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def remove_and_save(name)
|
|
84
|
+
remove(name)
|
|
85
|
+
save_pins
|
|
86
|
+
pins
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def pin_filename = hiiro.bin_name
|
|
90
|
+
def pin_dir = Hiiro::Config.config_dir('pins').tap {|dir| FileUtils.mkdir_p(dir) }
|
|
91
|
+
def pin_file = File.join(pin_dir, pin_filename)
|
|
92
|
+
def pins
|
|
93
|
+
return @pins if @pins
|
|
94
|
+
|
|
95
|
+
unless File.exist?(pin_file)
|
|
96
|
+
File.write(pin_file, YAML.dump({}, stringify_names: true))
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
@pins = YAML.safe_load_file(pin_file)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def save_pins(pins = nil)
|
|
103
|
+
pins = pins || @pins || {}
|
|
104
|
+
|
|
105
|
+
File.write(pin_file, YAML.dump(pins, stringify_names: true))
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def pins!
|
|
109
|
+
@pins = nil
|
|
110
|
+
pins
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
data/plugins/project.rb
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
module Project
|
|
4
|
+
def self.load(hiiro)
|
|
5
|
+
hiiro.log "Plugin loaded: #{name}"
|
|
6
|
+
|
|
7
|
+
hiiro.load_plugin(Tmux)
|
|
8
|
+
attach_methods(hiiro)
|
|
9
|
+
add_subcommands(hiiro)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def self.add_subcommands(hiiro)
|
|
13
|
+
hiiro.add_subcmd(:project) do |project_name|
|
|
14
|
+
re = /#{project_name}/i
|
|
15
|
+
|
|
16
|
+
conf_matches = hiiro.projects_from_config.select{|k,v| k.match?(re) }
|
|
17
|
+
dir_matches = hiiro.project_dirs.select{|proj, path| proj.match?(re) }
|
|
18
|
+
|
|
19
|
+
puts(conf_matches:,dir_matches:)
|
|
20
|
+
matches = dir_matches.merge(conf_matches)
|
|
21
|
+
if matches.count > 1
|
|
22
|
+
matches = matches.select{|name, path| name == project_name }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
puts matches_two: matches
|
|
26
|
+
case matches.count
|
|
27
|
+
when 0
|
|
28
|
+
name = 'proj'
|
|
29
|
+
path = File.join(Dir.home, 'proj')
|
|
30
|
+
|
|
31
|
+
unless Dir.exist?(path)
|
|
32
|
+
puts "Error: #{path.inspect} does not exist"
|
|
33
|
+
exit 1
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
puts "changing dir: #{path}"
|
|
37
|
+
Dir.chdir(path)
|
|
38
|
+
|
|
39
|
+
hiiro.start_tmux_session(name)
|
|
40
|
+
when 1
|
|
41
|
+
name, path = matches.first
|
|
42
|
+
|
|
43
|
+
puts "changing dir: #{path}"
|
|
44
|
+
Dir.chdir(path)
|
|
45
|
+
|
|
46
|
+
hiiro.start_tmux_session(name)
|
|
47
|
+
when (2..)
|
|
48
|
+
puts "ERROR: Multiple matches found"
|
|
49
|
+
puts
|
|
50
|
+
puts "Matches:"
|
|
51
|
+
matches.each { |name, path|
|
|
52
|
+
puts format(" %s: %s", name, path)
|
|
53
|
+
}
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def self.attach_methods(hiiro)
|
|
59
|
+
hiiro.instance_eval do
|
|
60
|
+
def project_dirs
|
|
61
|
+
Dir.glob(File.join(Dir.home, 'proj', '*/')).map { |path|
|
|
62
|
+
[File.basename(path), path]
|
|
63
|
+
}.to_h
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def projects_from_config
|
|
67
|
+
projects_file = File.join(Dir.home, '.config/hiiro', 'projects.yml')
|
|
68
|
+
|
|
69
|
+
return {} unless File.exist?(projects_file)
|
|
70
|
+
|
|
71
|
+
YAML.safe_load_file(projects_file)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|