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