lib/markdown_exec.rb in markdown_exec-1.3.7 vs lib/markdown_exec.rb in markdown_exec-1.3.8
- old
+ new
@@ -197,51 +197,69 @@
saved_script_filename: nil, # calculated
struct: true # allow get_block_summary()
}
end
+ # Execute a code block after approval and provide user interaction options.
+ #
+ # This method displays required code blocks, asks for user approval, and
+ # executes the code block if approved. It also allows users to copy the
+ # code to the clipboard or save it to a file.
+ #
+ # @param opts [Hash] Options hash containing configuration settings.
+ # @param mdoc [YourMDocClass] An instance of the MDoc class.
+ # @return [String] The name of the executed code block.
def approve_and_execute_block(opts, mdoc)
+ # Collect required code blocks based on the provided options.
required_blocks = mdoc.collect_recursively_required_code(opts[:block_name])
+ # Display required code blocks if requested or required approval.
if opts[:output_script] || opts[:user_must_approve]
display_required_code(opts,
required_blocks)
end
allow = true
+ # If user approval is required, prompt the user for approval.
if opts[:user_must_approve]
loop do
- (sel = @prompt.select(opts[:prompt_approve_block],
- filter: true) do |menu|
- menu.default 1
- menu.choice opts[:prompt_yes], 1
- menu.choice opts[:prompt_no], 2
- menu.choice opts[:prompt_script_to_clipboard], 3
- menu.choice opts[:prompt_save_script], 4
- end)
+ # Present a selection menu for user approval.
+ sel = @prompt.select(opts[:prompt_approve_block],
+ filter: true) do |menu|
+ menu.default 1
+ menu.choice opts[:prompt_yes], 1
+ menu.choice opts[:prompt_no], 2
+ menu.choice opts[:prompt_script_to_clipboard], 3
+ menu.choice opts[:prompt_save_script], 4
+ end
allow = (sel == 1)
if sel == 3
+ # Copy the code to the clipboard.
text = required_blocks.flatten.join($INPUT_RECORD_SEPARATOR)
Clipboard.copy(text)
fout "Clipboard updated: #{required_blocks.count} blocks," /
" #{required_blocks.flatten.count} lines," /
" #{text.length} characters"
end
if sel == 4
+ # Save the code to a file.
write_command_file(opts.merge(save_executed_script: true),
required_blocks)
fout "File saved: #{@options[:saved_filespec]}"
end
break if [1, 2].include? sel
end
end
- (opts[:ir_approve] = allow)
- selected = mdoc.get_block_by_name opts[:block_name]
+ opts[:ir_approve] = allow
+ # Get the selected code block by name.
+ selected = mdoc.get_block_by_name(opts[:block_name])
+
+ # If approved, write the code to a file, execute it, and provide output.
if opts[:ir_approve]
- write_command_file opts, required_blocks
- command_execute opts, required_blocks.flatten.join("\n")
+ write_command_file(opts, required_blocks)
+ command_execute(opts, required_blocks.flatten.join("\n"))
save_execution_output
output_execution_summary
output_execution_result
end
@@ -471,11 +489,12 @@
if fcb.body
if fcb.title.nil? || fcb.title.empty?
fcb.title = fcb.body.join(' ').gsub(/ +/, ' ')[0..64]
end
- if block_given? && selected_messages.include?(:blocks) &&
+ if block_given? &&
+ selected_messages.include?(:blocks) &&
Filter.fcb_select?(opts, fcb)
yield :blocks, fcb
end
end
in_block = false
@@ -494,12 +513,14 @@
# selected fcb
#
fcb.body = []
rest = fcb_title_groups.fetch(:rest, '')
- fcb.reqs = rest.scan(/\+[^\s]+/).map { |req| req[1..-1] }
-
+ fcb.reqs, fcb.wraps =
+ split_array(rest.scan(/\+[^\s]+/).map { |req| req[1..-1] }) do |name|
+ !name.match(Regexp.new(opts[:block_name_wrapper_match]))
+ end
fcb.call = rest.match(Regexp.new(opts[:block_calls_scan]))&.to_a&.first
fcb.stdin = if (tn = rest.match(/<(?<type>\$)?(?<name>[A-Za-z_-]\S+)/))
tn.named_captures.sym_keys
end
fcb.stdout = if (tn = rest.match(/>(?<type>\$)?(?<name>[A-Za-z_\-.\w]+)/))
@@ -516,10 +537,31 @@
yield :line, fcb
end
end
end
+ def split_array(arr)
+ true_list = []
+ false_list = []
+
+ arr.each do |element|
+ if yield(element)
+ true_list << element
+ else
+ false_list << element
+ end
+ end
+
+ [true_list, false_list]
+ end
+
+ # # Example usage:
+ # array = [1, 2, 3, 4, 5]
+ # result = split_array(array) { |num| num.even? }
+ # puts "True List: #{result[0]}" # Output: True List: [2, 4]
+ # puts "False List: #{result[1]}" # Output: False List: [1, 3, 5]
+
# return body, title if option.struct
# return body if not struct
#
def list_blocks_in_file(call_options = {}, &options_block)
opts = optsmerge(call_options, options_block)
@@ -982,22 +1024,30 @@
ol += @execute_files&.fetch(EF_STDIN, [])
ol += ["\n"]
File.write(@options[:logged_stdout_filespec], ol.join)
end
+ # Select and execute a code block from a Markdown document.
+ #
+ # This method allows the user to interactively select a code block from a
+ # Markdown document, obtain approval, and execute the chosen block of code.
+ #
+ # @param call_options [Hash] Initial options for the method.
+ # @param options_block [Block] Block of options to be merged with call_options.
+ # @return [Nil] Returns nil if no code block is selected or an error occurs.
def select_approve_and_execute_block(call_options, &options_block)
- opts = optsmerge call_options, options_block
+ opts = optsmerge(call_options, options_block)
blocks_in_file = list_blocks_in_file(opts.merge(struct: true))
mdoc = MDoc.new(blocks_in_file) do |nopts|
opts.merge!(nopts)
end
blocks_menu = mdoc.fcbs_per_options(opts.merge(struct: true))
repeat_menu = true && !opts[:block_name].present?
loop do
unless opts[:block_name].present?
- pt = (opts[:prompt_select_block]).to_s
+ pt = opts[:prompt_select_block].to_s
bm = blocks_menu.map do |fcb|
# next if fcb.fetch(:disabled, false)
# next unless fcb.fetch(:name, '').present?
@@ -1015,21 +1065,20 @@
fcb.to_h
end.compact
return nil if bm.count.zero?
- sel = prompt_with_quit pt, bm,
- per_page: opts[:select_page_height]
+ sel = prompt_with_quit(pt, bm, per_page: opts[:select_page_height])
return nil if sel.nil?
## store selected option
#
label_block = blocks_in_file.select do |fcb|
fcb[:label] == sel
end.fetch(0, nil)
opts[:block_name] = @options[:block_name] = label_block.fetch(:name, '')
end
- approve_and_execute_block opts, mdoc
+ approve_and_execute_block(opts, mdoc)
break unless repeat_menu
opts[:block_name] = ''
end
rescue StandardError => err