markdown_exec 1.3.3.4 → 1.3.6
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/.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__
|