markdown_exec 1.3.3.4 → 1.3.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -0
- data/CHANGELOG.md +16 -109
- data/Gemfile.lock +1 -1
- data/Rakefile +26 -596
- data/bin/tab_completion.sh +7 -7
- data/lib/block_label.rb +82 -0
- data/lib/env_opts.rb +6 -6
- data/lib/environment_opt_parse.rb +3 -3
- data/lib/fcb.rb +133 -0
- data/lib/filter.rb +181 -0
- data/lib/markdown_block_manager.rb +195 -0
- data/lib/markdown_exec/version.rb +1 -1
- data/lib/markdown_exec.rb +78 -482
- data/lib/mdoc.rb +194 -0
- data/lib/menu.src.yml +448 -0
- data/lib/menu.yml +35 -9
- data/lib/menu_options.rb +0 -0
- data/lib/menu_options.yml +0 -0
- data/lib/object_present.rb +8 -8
- data/lib/option_value.rb +88 -0
- data/lib/regexp.rb +110 -0
- data/lib/saved_assets.rb +59 -0
- data/lib/saved_files_matcher.rb +61 -0
- metadata +14 -2
data/lib/markdown_exec.rb
CHANGED
@@ -12,10 +12,17 @@ require 'shellwords'
|
|
12
12
|
require 'tty-prompt'
|
13
13
|
require 'yaml'
|
14
14
|
|
15
|
+
require_relative 'block_label'
|
15
16
|
require_relative 'cached_nested_file_reader'
|
16
17
|
require_relative 'cli'
|
17
18
|
require_relative 'colorize'
|
18
19
|
require_relative 'env'
|
20
|
+
require_relative 'fcb'
|
21
|
+
require_relative 'filter'
|
22
|
+
require_relative 'mdoc'
|
23
|
+
require_relative 'option_value'
|
24
|
+
require_relative 'saved_assets'
|
25
|
+
require_relative 'saved_files_matcher'
|
19
26
|
require_relative 'shared'
|
20
27
|
require_relative 'tap'
|
21
28
|
require_relative 'markdown_exec/version'
|
@@ -90,14 +97,14 @@ public
|
|
90
97
|
|
91
98
|
# :reek:UtilityFunction
|
92
99
|
def list_recent_output(saved_stdout_folder, saved_stdout_glob, list_count)
|
93
|
-
|
94
|
-
|
100
|
+
SavedFilesMatcher.most_recent_list(saved_stdout_folder,
|
101
|
+
saved_stdout_glob, list_count)
|
95
102
|
end
|
96
103
|
|
97
104
|
# :reek:UtilityFunction
|
98
105
|
def list_recent_scripts(saved_script_folder, saved_script_glob, list_count)
|
99
|
-
|
100
|
-
|
106
|
+
SavedFilesMatcher.most_recent_list(saved_script_folder,
|
107
|
+
saved_script_glob, list_count)
|
101
108
|
end
|
102
109
|
|
103
110
|
# convert regex match groups to a hash with symbol keys
|
@@ -111,428 +118,9 @@ end
|
|
111
118
|
#
|
112
119
|
module MarkdownExec
|
113
120
|
# :reek:IrresponsibleModule
|
114
|
-
class Error < StandardError; end
|
115
|
-
|
116
|
-
# fenced code block
|
117
|
-
#
|
118
|
-
class FCB
|
119
|
-
def initialize(options = {})
|
120
|
-
@attrs = {
|
121
|
-
body: nil,
|
122
|
-
call: nil,
|
123
|
-
headings: [],
|
124
|
-
name: nil,
|
125
|
-
reqs: [],
|
126
|
-
shell: '',
|
127
|
-
title: '',
|
128
|
-
random: Random.new.rand,
|
129
|
-
text: nil # displayable in menu
|
130
|
-
}.merge options
|
131
|
-
end
|
132
|
-
|
133
|
-
def to_h
|
134
|
-
@attrs
|
135
|
-
end
|
136
|
-
|
137
|
-
def to_yaml
|
138
|
-
@attrs.to_yaml
|
139
|
-
end
|
140
|
-
|
141
|
-
private
|
142
|
-
|
143
|
-
# :reek:ManualDispatch
|
144
|
-
def method_missing(method, *args, &block)
|
145
|
-
method_name = method.to_s
|
146
|
-
|
147
|
-
if @attrs.respond_to?(method_name)
|
148
|
-
@attrs.send(method_name, *args, &block)
|
149
|
-
elsif method_name[-1] == '='
|
150
|
-
@attrs[method_name.chop.to_sym] = args[0]
|
151
|
-
else
|
152
|
-
@attrs[method_name.to_sym]
|
153
|
-
end
|
154
|
-
rescue StandardError => err
|
155
|
-
warn(error = "ERROR ** FCB.method_missing(method: #{method_name}," \
|
156
|
-
" *args: #{args.inspect}, &block)")
|
157
|
-
warn err.inspect
|
158
|
-
warn(caller[0..4])
|
159
|
-
raise StandardError, error
|
160
|
-
end
|
161
|
-
|
162
|
-
# option names are available as methods
|
163
|
-
#
|
164
|
-
def respond_to_missing?(_method_name, _include_private = false)
|
165
|
-
true # recognize all hash methods, rest are treated as hash keys
|
166
|
-
end
|
167
|
-
end
|
168
|
-
|
169
|
-
# select fcb per options
|
170
|
-
#
|
171
|
-
# :reek:UtilityFunction
|
172
|
-
class Filter
|
173
|
-
# def self.fcb_title_parse(opts, fcb_title)
|
174
|
-
# fcb_title.match(Regexp.new(opts[:fenced_start_ex_match])).named_captures.sym_keys
|
175
|
-
# end
|
176
|
-
|
177
|
-
def self.fcb_select?(options, fcb)
|
178
|
-
# options.tap_yaml 'options'
|
179
|
-
# fcb.tap_inspect 'fcb'
|
180
|
-
name = fcb.fetch(:name, '').tap_inspect 'name'
|
181
|
-
shell = fcb.fetch(:shell, '').tap_inspect 'shell'
|
182
|
-
|
183
|
-
## include hidden blocks for later use
|
184
|
-
#
|
185
|
-
name_default = true
|
186
|
-
name_exclude = nil
|
187
|
-
name_select = nil
|
188
|
-
shell_default = true
|
189
|
-
shell_exclude = nil
|
190
|
-
shell_select = nil
|
191
|
-
hidden_name = nil
|
192
|
-
|
193
|
-
if name.present? && options[:block_name]
|
194
|
-
if name =~ /#{options[:block_name]}/
|
195
|
-
'=~ block_name'.tap_puts
|
196
|
-
name_select = true
|
197
|
-
name_exclude = false
|
198
|
-
else
|
199
|
-
'!~ block_name'.tap_puts
|
200
|
-
name_exclude = true
|
201
|
-
name_select = false
|
202
|
-
end
|
203
|
-
end
|
204
|
-
|
205
|
-
if name.present? && name_select.nil? && options[:select_by_name_regex].present?
|
206
|
-
'+select_by_name_regex'.tap_puts
|
207
|
-
name_select = (!!(name =~ /#{options[:select_by_name_regex]}/)).tap_inspect 'name_select'
|
208
|
-
end
|
209
|
-
|
210
|
-
if shell.present? && options[:select_by_shell_regex].present?
|
211
|
-
'+select_by_shell_regex'.tap_puts
|
212
|
-
shell_select = (!!(shell =~ /#{options[:select_by_shell_regex]}/)).tap_inspect 'shell_select'
|
213
|
-
end
|
214
|
-
|
215
|
-
if name.present? && name_exclude.nil? && options[:exclude_by_name_regex].present?
|
216
|
-
'-exclude_by_name_regex'.tap_puts
|
217
|
-
name_exclude = (!!(name =~ /#{options[:exclude_by_name_regex]}/)).tap_inspect 'name_exclude'
|
218
|
-
end
|
219
|
-
|
220
|
-
if shell.present? && options[:exclude_by_shell_regex].present?
|
221
|
-
'-exclude_by_shell_regex'.tap_puts
|
222
|
-
shell_exclude = (!!(shell =~ /#{options[:exclude_by_shell_regex]}/)).tap_inspect 'shell_exclude'
|
223
|
-
end
|
224
|
-
|
225
|
-
if name.present? && options[:hide_blocks_by_name] &&
|
226
|
-
options[:block_name_hidden_match].present?
|
227
|
-
'+block_name_hidden_match'.tap_puts
|
228
|
-
hidden_name = (!!(name =~ /#{options[:block_name_hidden_match]}/)).tap_inspect 'hidden_name'
|
229
|
-
end
|
230
|
-
|
231
|
-
if shell.present? && options[:hide_blocks_by_shell] &&
|
232
|
-
options[:block_shell_hidden_match].present?
|
233
|
-
'-hide_blocks_by_shell'.tap_puts
|
234
|
-
(!!(shell =~ /#{options[:block_shell_hidden_match]}/)).tap_inspect 'hidden_shell'
|
235
|
-
end
|
236
|
-
|
237
|
-
if options[:bash_only]
|
238
|
-
'-bash_only'.tap_puts
|
239
|
-
shell_default = (shell == 'bash').tap_inspect 'shell_default'
|
240
|
-
end
|
241
|
-
|
242
|
-
## name matching does not filter hidden blocks
|
243
|
-
#
|
244
|
-
case
|
245
|
-
when options[:no_chrome] && fcb.fetch(:chrome, false)
|
246
|
-
'-no_chrome'.tap_puts
|
247
|
-
false
|
248
|
-
when options[:exclude_expect_blocks] && shell == 'expect'
|
249
|
-
'-exclude_expect_blocks'.tap_puts
|
250
|
-
false
|
251
|
-
when hidden_name == true
|
252
|
-
true
|
253
|
-
when name_exclude == true, shell_exclude == true,
|
254
|
-
name_select == false, shell_select == false
|
255
|
-
false
|
256
|
-
when name_select == true, shell_select == true
|
257
|
-
true
|
258
|
-
when name_default == false, shell_default == false
|
259
|
-
false
|
260
|
-
else
|
261
|
-
true
|
262
|
-
end.tap_inspect
|
263
|
-
# binding.pry
|
264
|
-
rescue StandardError => err
|
265
|
-
warn("ERROR ** Filter::fcb_select?(); #{err.inspect}")
|
266
|
-
raise err
|
267
|
-
end
|
268
|
-
end # class Filter
|
269
|
-
|
270
|
-
## an imported markdown document
|
271
|
-
#
|
272
|
-
class MDoc
|
273
|
-
attr_reader :table
|
274
|
-
|
275
|
-
# convert block name to fcb_parse
|
276
|
-
#
|
277
|
-
def initialize(table)
|
278
|
-
@table = table
|
279
|
-
end
|
280
|
-
|
281
|
-
def collect_recursively_required_code(name)
|
282
|
-
get_required_blocks(name)
|
283
|
-
.map do |fcb|
|
284
|
-
body = fcb[:body].join("\n")
|
285
|
-
|
286
|
-
if fcb[:cann]
|
287
|
-
xcall = fcb[:cann][1..-2]
|
288
|
-
mstdin = xcall.match(/<(?<type>\$)?(?<name>[A-Za-z_\-.\w]+)/)
|
289
|
-
mstdout = xcall.match(/>(?<type>\$)?(?<name>[A-Za-z_\-.\w]+)/)
|
290
|
-
|
291
|
-
yqcmd = if mstdin[:type]
|
292
|
-
"echo \"$#{mstdin[:name]}\" | yq '#{body}'"
|
293
|
-
else
|
294
|
-
"yq e '#{body}' '#{mstdin[:name]}'"
|
295
|
-
end
|
296
|
-
if mstdout[:type]
|
297
|
-
"export #{mstdout[:name]}=$(#{yqcmd})"
|
298
|
-
else
|
299
|
-
"#{yqcmd} > '#{mstdout[:name]}'"
|
300
|
-
end
|
301
|
-
elsif fcb[:stdout]
|
302
|
-
stdout = fcb[:stdout]
|
303
|
-
body = fcb[:body].join("\n")
|
304
|
-
if stdout[:type]
|
305
|
-
%(export #{stdout[:name]}=$(cat <<"EOF"\n#{body}\nEOF\n))
|
306
|
-
else
|
307
|
-
"cat > '#{stdout[:name]}' <<\"EOF\"\n" \
|
308
|
-
"#{body}\n" \
|
309
|
-
"EOF\n"
|
310
|
-
end
|
311
|
-
else
|
312
|
-
fcb[:body]
|
313
|
-
end
|
314
|
-
end.flatten(1)
|
315
|
-
end
|
316
|
-
|
317
|
-
def get_block_by_name(name, default = {})
|
318
|
-
@table.select { |fcb| fcb.fetch(:name, '') == name }.fetch(0, default)
|
319
|
-
end
|
320
|
-
|
321
|
-
def get_required_blocks(name)
|
322
|
-
name_block = get_block_by_name(name)
|
323
|
-
raise "Named code block `#{name}` not found." if name_block.nil? || name_block.keys.empty?
|
324
|
-
|
325
|
-
all = [name_block.fetch(:name, '')] + recursively_required(name_block[:reqs])
|
326
|
-
|
327
|
-
# in order of appearance in document
|
328
|
-
# insert function blocks
|
329
|
-
@table.select { |fcb| all.include? fcb.fetch(:name, '') }
|
330
|
-
.map do |fcb|
|
331
|
-
if (call = fcb[:call])
|
332
|
-
[get_block_by_name("[#{call.match(/^%\((\S+) |\)/)[1]}]")
|
333
|
-
.merge({ cann: call })]
|
334
|
-
else
|
335
|
-
[]
|
336
|
-
end + [fcb]
|
337
|
-
end.flatten(1)
|
338
|
-
end
|
339
|
-
|
340
|
-
# :reek:UtilityFunction
|
341
|
-
def hide_menu_block_per_options(opts, block)
|
342
|
-
(opts[:hide_blocks_by_name] &&
|
343
|
-
block[:name]&.match(Regexp.new(opts[:block_name_hidden_match])) &&
|
344
|
-
(block[:name]&.present? || block[:label]&.present?)
|
345
|
-
).tap_inspect
|
346
|
-
end
|
347
|
-
|
348
|
-
# def blocks_for_menu(opts)
|
349
|
-
# if opts[:hide_blocks_by_name]
|
350
|
-
# @table.reject { |block| hide_menu_block_per_options opts, block }
|
351
|
-
# else
|
352
|
-
# @table
|
353
|
-
# end
|
354
|
-
# end
|
355
|
-
|
356
|
-
def fcbs_per_options(opts = {})
|
357
|
-
options = opts.merge(block_name_hidden_match: nil)
|
358
|
-
selrows = @table.select do |fcb_title_groups|
|
359
|
-
Filter.fcb_select? options, fcb_title_groups
|
360
|
-
end
|
361
|
-
# binding.pry
|
362
|
-
### hide rows correctly
|
363
|
-
|
364
|
-
if opts[:hide_blocks_by_name]
|
365
|
-
selrows.reject { |block| hide_menu_block_per_options opts, block }
|
366
|
-
else
|
367
|
-
selrows
|
368
|
-
end.map do |block|
|
369
|
-
# block[:name] = block[:text] if block[:name].nil?
|
370
|
-
block
|
371
|
-
end
|
372
|
-
end
|
373
|
-
|
374
|
-
def recursively_required(reqs)
|
375
|
-
return [] unless reqs
|
376
|
-
|
377
|
-
rem = reqs
|
378
|
-
memo = []
|
379
|
-
while rem.count.positive?
|
380
|
-
rem = rem.map do |req|
|
381
|
-
next if memo.include? req
|
382
|
-
|
383
|
-
memo += [req]
|
384
|
-
get_block_by_name(req).fetch(:reqs, [])
|
385
|
-
end
|
386
|
-
.compact
|
387
|
-
.flatten(1)
|
388
|
-
end
|
389
|
-
memo
|
390
|
-
end
|
391
|
-
end # class MDoc
|
392
|
-
|
393
|
-
# format option defaults and values
|
394
|
-
#
|
395
|
-
# :reek:TooManyInstanceVariables
|
396
|
-
class BlockLabel
|
397
|
-
def initialize(filename:, headings:, menu_blocks_with_docname:,
|
398
|
-
menu_blocks_with_headings:, title:, body:, text:)
|
399
|
-
@filename = filename
|
400
|
-
@headings = headings
|
401
|
-
@menu_blocks_with_docname = menu_blocks_with_docname
|
402
|
-
@menu_blocks_with_headings = menu_blocks_with_headings
|
403
|
-
# @title = title.present? ? title : body
|
404
|
-
@title = title
|
405
|
-
@body = body
|
406
|
-
@text = text
|
407
|
-
rescue StandardError => err
|
408
|
-
warn(error = "ERROR ** BlockLabel.initialize(); #{err.inspect}")
|
409
|
-
binding.pry if $tap_enable
|
410
|
-
raise ArgumentError, error
|
411
|
-
end
|
412
|
-
|
413
|
-
# join title, headings, filename
|
414
|
-
#
|
415
|
-
def make
|
416
|
-
label = @title
|
417
|
-
label = @body unless label.present?
|
418
|
-
label = @text unless label.present?
|
419
|
-
label.tap_inspect
|
420
|
-
([label] +
|
421
|
-
(if @menu_blocks_with_headings
|
422
|
-
[@headings.compact.join(' # ')]
|
423
|
-
else
|
424
|
-
[]
|
425
|
-
end) +
|
426
|
-
(
|
427
|
-
if @menu_blocks_with_docname
|
428
|
-
[@filename]
|
429
|
-
else
|
430
|
-
[]
|
431
|
-
end
|
432
|
-
)).join(' ')
|
433
|
-
rescue StandardError => err
|
434
|
-
warn(error = "ERROR ** BlockLabel.make(); #{err.inspect}")
|
435
|
-
binding.pry if $tap_enable
|
436
|
-
raise ArgumentError, error
|
437
|
-
end
|
438
|
-
end # class BlockLabel
|
439
|
-
|
440
121
|
FNR11 = '/'
|
441
122
|
FNR12 = ',~'
|
442
123
|
|
443
|
-
# format option defaults and values
|
444
|
-
#
|
445
|
-
class SavedAsset
|
446
|
-
def initialize(filename:, prefix:, time:, blockname:)
|
447
|
-
@filename = filename
|
448
|
-
@prefix = prefix
|
449
|
-
@time = time
|
450
|
-
@blockname = blockname
|
451
|
-
end
|
452
|
-
|
453
|
-
def script_name
|
454
|
-
fne = @filename.gsub(FNR11, FNR12)
|
455
|
-
"#{[@prefix, @time.strftime('%F-%H-%M-%S'), fne, ',',
|
456
|
-
@blockname].join('_')}.sh"
|
457
|
-
end
|
458
|
-
|
459
|
-
def stdout_name
|
460
|
-
"#{[@prefix, @time.strftime('%F-%H-%M-%S'), @filename,
|
461
|
-
@blockname].join('_')}.out.txt"
|
462
|
-
end
|
463
|
-
end # class SavedAsset
|
464
|
-
|
465
|
-
# format option defaults and values
|
466
|
-
#
|
467
|
-
class OptionValue
|
468
|
-
def initialize(value)
|
469
|
-
@value = value
|
470
|
-
end
|
471
|
-
|
472
|
-
# as default value in env_str()
|
473
|
-
#
|
474
|
-
def for_hash(default = nil)
|
475
|
-
return default if @value.nil?
|
476
|
-
|
477
|
-
case @value.class.to_s
|
478
|
-
when 'String', 'Integer'
|
479
|
-
@value
|
480
|
-
when 'FalseClass', 'TrueClass'
|
481
|
-
@value ? true : false
|
482
|
-
when @value.empty?
|
483
|
-
default
|
484
|
-
else
|
485
|
-
@value.to_s
|
486
|
-
end
|
487
|
-
end
|
488
|
-
|
489
|
-
# for output as default value in list_default_yaml()
|
490
|
-
#
|
491
|
-
def for_yaml(default = nil)
|
492
|
-
return default if @value.nil?
|
493
|
-
|
494
|
-
case @value.class.to_s
|
495
|
-
when 'String'
|
496
|
-
"'#{@value}'"
|
497
|
-
when 'Integer'
|
498
|
-
@value
|
499
|
-
when 'FalseClass', 'TrueClass'
|
500
|
-
@value ? true : false
|
501
|
-
when @value.empty?
|
502
|
-
default
|
503
|
-
else
|
504
|
-
@value.to_s
|
505
|
-
end
|
506
|
-
end
|
507
|
-
end # class OptionValue
|
508
|
-
|
509
|
-
# a generated list of saved files
|
510
|
-
#
|
511
|
-
class Sfiles
|
512
|
-
def initialize(folder, glob)
|
513
|
-
@folder = folder
|
514
|
-
@glob = glob
|
515
|
-
end
|
516
|
-
|
517
|
-
def list_all
|
518
|
-
Dir.glob(File.join(@folder, @glob))
|
519
|
-
end
|
520
|
-
|
521
|
-
def most_recent(arr = nil)
|
522
|
-
arr = list_all if arr.nil?
|
523
|
-
return if arr.count < 1
|
524
|
-
|
525
|
-
arr.max
|
526
|
-
end
|
527
|
-
|
528
|
-
def most_recent_list(list_count, arr = nil)
|
529
|
-
arr = list_all if arr.nil?
|
530
|
-
return if (ac = arr.count) < 1
|
531
|
-
|
532
|
-
arr.sort[-[ac, list_count].min..].reverse
|
533
|
-
end
|
534
|
-
end # class Sfiles
|
535
|
-
|
536
124
|
##
|
537
125
|
#
|
538
126
|
# rubocop:disable Layout/LineLength
|
@@ -571,7 +159,7 @@ module MarkdownExec
|
|
571
159
|
[]
|
572
160
|
else
|
573
161
|
argv[0..ind - 1]
|
574
|
-
end
|
162
|
+
end
|
575
163
|
end
|
576
164
|
|
577
165
|
# return arguments after `--`
|
@@ -582,7 +170,7 @@ module MarkdownExec
|
|
582
170
|
[]
|
583
171
|
else
|
584
172
|
argv[ind + 1..-1]
|
585
|
-
end
|
173
|
+
end
|
586
174
|
end
|
587
175
|
|
588
176
|
##
|
@@ -590,16 +178,14 @@ module MarkdownExec
|
|
590
178
|
#
|
591
179
|
def base_options
|
592
180
|
menu_iter do |item|
|
593
|
-
# noisy item.tap_yaml name: :item
|
594
181
|
next unless item[:opt_name].present?
|
595
182
|
|
596
183
|
item_default = item[:default]
|
597
|
-
# noisy item_default.tap_inspect name: :item_default
|
598
184
|
value = if item_default.nil?
|
599
185
|
item_default
|
600
186
|
else
|
601
187
|
env_str(item[:env_var],
|
602
|
-
default: OptionValue.
|
188
|
+
default: OptionValue.for_hash(item_default))
|
603
189
|
end
|
604
190
|
[item[:opt_name], item[:proccode] ? item[:proccode].call(value) : value]
|
605
191
|
end.compact.to_h
|
@@ -663,10 +249,7 @@ module MarkdownExec
|
|
663
249
|
end
|
664
250
|
|
665
251
|
def cfile
|
666
|
-
# puts @options.inspect
|
667
|
-
# binding.pry
|
668
252
|
@cfile ||= CachedNestedFileReader.new(import_pattern: @options.fetch(:import_pattern))
|
669
|
-
# @cfile ||= CachedNestedFileReader.new(import_pattern: /^ *#insert (.+)$/)
|
670
253
|
end
|
671
254
|
|
672
255
|
# :reek:DuplicateMethodCall
|
@@ -761,7 +344,7 @@ module MarkdownExec
|
|
761
344
|
|
762
345
|
# :reek:DuplicateMethodCall
|
763
346
|
def exec_block(options, _block_name = '')
|
764
|
-
options = calculated_options.merge(options)
|
347
|
+
options = calculated_options.merge(options)
|
765
348
|
update_options options, over: false
|
766
349
|
|
767
350
|
# document and block reports
|
@@ -939,13 +522,15 @@ module MarkdownExec
|
|
939
522
|
# return body if not struct
|
940
523
|
#
|
941
524
|
def list_blocks_in_file(call_options = {}, &options_block)
|
942
|
-
opts = optsmerge(call_options, options_block)
|
525
|
+
opts = optsmerge(call_options, options_block)
|
526
|
+
use_chrome = !opts[:no_chrome]
|
527
|
+
|
943
528
|
blocks = []
|
944
|
-
if opts[:menu_initial_divider].present?
|
529
|
+
if opts[:menu_initial_divider].present? && use_chrome
|
945
530
|
blocks.push FCB.new({
|
946
531
|
# name: '',
|
947
532
|
chrome: true,
|
948
|
-
|
533
|
+
name: format(
|
949
534
|
opts[:menu_divider_format],
|
950
535
|
opts[:menu_initial_divider]
|
951
536
|
).send(opts[:menu_divider_color].to_sym),
|
@@ -954,7 +539,6 @@ module MarkdownExec
|
|
954
539
|
end
|
955
540
|
|
956
541
|
iter_blocks_in_file(opts) do |btype, fcb|
|
957
|
-
# binding.pry
|
958
542
|
case btype
|
959
543
|
when :filter
|
960
544
|
## return type of blocks to select
|
@@ -964,24 +548,28 @@ module MarkdownExec
|
|
964
548
|
when :line
|
965
549
|
## convert line to block
|
966
550
|
#
|
967
|
-
# binding.pry
|
968
551
|
if opts[:menu_divider_match].present? &&
|
969
552
|
(mbody = fcb.body[0].match opts[:menu_divider_match])
|
970
|
-
|
971
|
-
|
972
|
-
|
973
|
-
|
974
|
-
|
975
|
-
|
976
|
-
|
553
|
+
if use_chrome
|
554
|
+
blocks.push FCB.new(
|
555
|
+
{ chrome: true,
|
556
|
+
disabled: '',
|
557
|
+
name: format(opts[:menu_divider_format],
|
558
|
+
mbody[:name]).send(opts[:menu_divider_color].to_sym) }
|
559
|
+
)
|
560
|
+
end
|
977
561
|
elsif opts[:menu_task_match].present? &&
|
978
562
|
(mbody = fcb.body[0].match opts[:menu_task_match])
|
979
|
-
|
980
|
-
|
981
|
-
|
982
|
-
|
983
|
-
|
984
|
-
|
563
|
+
if use_chrome
|
564
|
+
blocks.push FCB.new(
|
565
|
+
{ chrome: true,
|
566
|
+
disabled: '',
|
567
|
+
name: format(
|
568
|
+
opts[:menu_task_format],
|
569
|
+
$~.named_captures.transform_keys(&:to_sym)
|
570
|
+
).send(opts[:menu_task_color].to_sym) }
|
571
|
+
)
|
572
|
+
end
|
985
573
|
else
|
986
574
|
# line not added
|
987
575
|
end
|
@@ -992,16 +580,16 @@ module MarkdownExec
|
|
992
580
|
end
|
993
581
|
end
|
994
582
|
|
995
|
-
if opts[:menu_divider_format].present? && opts[:menu_final_divider].present?
|
583
|
+
if opts[:menu_divider_format].present? && opts[:menu_final_divider].present? && use_chrome && use_chrome
|
996
584
|
blocks.push FCB.new(
|
997
585
|
{ chrome: true,
|
998
586
|
disabled: '',
|
999
|
-
|
587
|
+
name: format(opts[:menu_divider_format],
|
1000
588
|
opts[:menu_final_divider])
|
1001
589
|
.send(opts[:menu_divider_color].to_sym) }
|
1002
590
|
)
|
1003
591
|
end
|
1004
|
-
blocks
|
592
|
+
blocks
|
1005
593
|
rescue StandardError => err
|
1006
594
|
warn(error = "ERROR ** MarkParse.list_blocks_in_file(); #{err.inspect}")
|
1007
595
|
warn(caller[0..4])
|
@@ -1024,7 +612,7 @@ module MarkdownExec
|
|
1024
612
|
next unless item[:opt_name].present? && item[:default].present?
|
1025
613
|
|
1026
614
|
[
|
1027
|
-
"#{item[:opt_name]}: #{OptionValue.
|
615
|
+
"#{item[:opt_name]}: #{OptionValue.for_yaml(item[:default])}",
|
1028
616
|
item[:description].present? ? item[:description] : nil
|
1029
617
|
].compact.join(' # ')
|
1030
618
|
end.compact.sort
|
@@ -1081,7 +669,7 @@ module MarkdownExec
|
|
1081
669
|
blocks.map do |block|
|
1082
670
|
block.fetch(:text, nil) || block.fetch(:name, nil)
|
1083
671
|
end
|
1084
|
-
end.compact.reject(&:empty?)
|
672
|
+
end.compact.reject(&:empty?)
|
1085
673
|
end
|
1086
674
|
|
1087
675
|
## output type (body string or full object) per option struct and bash
|
@@ -1093,19 +681,21 @@ module MarkdownExec
|
|
1093
681
|
# fcb.fetch(:name, '') != '' && Filter.fcb_select?(opts, fcb)
|
1094
682
|
Filter.fcb_select?(opts.merge(no_chrome: true), fcb)
|
1095
683
|
end
|
1096
|
-
blocks_per_opts(blocks, opts)
|
684
|
+
blocks_per_opts(blocks, opts)
|
1097
685
|
end
|
1098
686
|
|
1099
687
|
def make_block_labels(call_options = {})
|
1100
688
|
opts = options.merge(call_options)
|
1101
689
|
list_blocks_in_file(opts).map do |fcb|
|
1102
|
-
BlockLabel.
|
1103
|
-
|
1104
|
-
|
1105
|
-
|
1106
|
-
|
1107
|
-
|
1108
|
-
|
690
|
+
BlockLabel.make(
|
691
|
+
filename: opts[:filename],
|
692
|
+
headings: fcb.fetch(:headings, []),
|
693
|
+
menu_blocks_with_docname: opts[:menu_blocks_with_docname],
|
694
|
+
menu_blocks_with_headings: opts[:menu_blocks_with_headings],
|
695
|
+
title: fcb[:title],
|
696
|
+
text: fcb[:text],
|
697
|
+
body: fcb[:body]
|
698
|
+
)
|
1109
699
|
end.compact
|
1110
700
|
end
|
1111
701
|
|
@@ -1278,18 +868,24 @@ module MarkdownExec
|
|
1278
868
|
}
|
1279
869
|
end
|
1280
870
|
|
871
|
+
## insert exit option at head or tail
|
872
|
+
#
|
873
|
+
def prompt_menu_add_exit(_prompt_text, items, exit_option, _opts = {})
|
874
|
+
if @options[:menu_exit_at_top]
|
875
|
+
(@options[:menu_with_exit] ? [exit_option] : []) + items
|
876
|
+
else
|
877
|
+
items + (@options[:menu_with_exit] ? [exit_option] : [])
|
878
|
+
end
|
879
|
+
end
|
880
|
+
|
1281
881
|
## tty prompt to select
|
1282
882
|
# insert exit option at head or tail
|
1283
883
|
# return selected option or nil
|
1284
884
|
#
|
1285
885
|
def prompt_with_quit(prompt_text, items, opts = {})
|
1286
886
|
exit_option = '* Exit'
|
1287
|
-
|
1288
|
-
|
1289
|
-
else
|
1290
|
-
items + (@options[:menu_with_exit] ? [exit_option] : [])
|
1291
|
-
end
|
1292
|
-
sel = @prompt.select(prompt_text, all_items, opts.merge(filter: true))
|
887
|
+
sel = @prompt.select(prompt_text, prompt_menu_add_exit(prompt_text, items, exit_option, opts),
|
888
|
+
opts.merge(filter: true))
|
1293
889
|
sel == exit_option ? nil : sel
|
1294
890
|
end
|
1295
891
|
|
@@ -1353,8 +949,8 @@ module MarkdownExec
|
|
1353
949
|
end
|
1354
950
|
|
1355
951
|
def run_last_script
|
1356
|
-
filename =
|
1357
|
-
|
952
|
+
filename = SavedFilesMatcher.most_recent(@options[:saved_script_folder],
|
953
|
+
@options[:saved_script_glob])
|
1358
954
|
return unless filename
|
1359
955
|
|
1360
956
|
saved_name_split filename
|
@@ -1390,7 +986,7 @@ module MarkdownExec
|
|
1390
986
|
|
1391
987
|
def select_approve_and_execute_block(call_options, &options_block)
|
1392
988
|
opts = optsmerge call_options, options_block
|
1393
|
-
blocks_in_file = list_blocks_in_file(opts.merge(struct: true))
|
989
|
+
blocks_in_file = list_blocks_in_file(opts.merge(struct: true))
|
1394
990
|
mdoc = MDoc.new(blocks_in_file) do |nopts|
|
1395
991
|
opts.merge!(nopts)
|
1396
992
|
end
|
@@ -1406,7 +1002,7 @@ module MarkdownExec
|
|
1406
1002
|
# next unless fcb.fetch(:name, '').present?
|
1407
1003
|
|
1408
1004
|
fcb.merge!(
|
1409
|
-
label: BlockLabel.
|
1005
|
+
label: BlockLabel.make(
|
1410
1006
|
body: fcb[:body],
|
1411
1007
|
filename: opts[:filename],
|
1412
1008
|
headings: fcb.fetch(:headings, []),
|
@@ -1414,15 +1010,13 @@ module MarkdownExec
|
|
1414
1010
|
menu_blocks_with_headings: opts[:menu_blocks_with_headings],
|
1415
1011
|
text: fcb[:text],
|
1416
1012
|
title: fcb[:title]
|
1417
|
-
)
|
1013
|
+
)
|
1418
1014
|
)
|
1419
1015
|
|
1420
1016
|
fcb.to_h
|
1421
1017
|
end.compact
|
1422
1018
|
return nil if bm.count.zero?
|
1423
1019
|
|
1424
|
-
# binding.pry
|
1425
|
-
|
1426
1020
|
sel = prompt_with_quit pt, bm,
|
1427
1021
|
per_page: opts[:select_page_height]
|
1428
1022
|
return nil if sel.nil?
|
@@ -1532,12 +1126,12 @@ module MarkdownExec
|
|
1532
1126
|
|
1533
1127
|
dirname = File.dirname(@options[:saved_filespec])
|
1534
1128
|
FileUtils.mkdir_p dirname
|
1535
|
-
|
1536
|
-
|
1537
|
-
|
1538
|
-
|
1539
|
-
|
1540
|
-
|
1129
|
+
shebang = if @options[:shebang]&.present?
|
1130
|
+
"#{@options[:shebang]} #{@options[:shell]}\n"
|
1131
|
+
else
|
1132
|
+
''
|
1133
|
+
end
|
1134
|
+
|
1541
1135
|
File.write(@options[:saved_filespec], shebang +
|
1542
1136
|
"# file_name: #{opts[:filename]}\n" \
|
1543
1137
|
"# block_name: #{opts[:block_name]}\n" \
|
@@ -1549,3 +1143,5 @@ module MarkdownExec
|
|
1549
1143
|
end
|
1550
1144
|
end # class MarkParse
|
1551
1145
|
end # module MarkdownExec
|
1146
|
+
|
1147
|
+
require 'minitest/autorun' if $PROGRAM_NAME == __FILE__
|