lib/hash_delegator.rb in markdown_exec-1.8.8 vs lib/hash_delegator.rb in markdown_exec-1.8.9

- old
+ new

@@ -183,20 +183,24 @@ def initialize_fcb_names(fcb) fcb.oname = fcb.dname = fcb.title || '' end + def join_code_lines(lines) + ((lines || [])+ ['']).join("\n") + end + def merge_lists(*args) # Filters out nil values, flattens the arrays, and ensures an empty list is returned if no valid lists are provided merged = args.compact.flatten merged.empty? ? [] : merged end - def next_link_state(block_name_from_cli, was_using_cli, block_state) + def next_link_state(block_name_from_cli, was_using_cli, block_state, block_name: nil) # &bsp 'next_link_state', block_name_from_cli, was_using_cli, block_state # Set block_name based on block_name_from_cli - block_name = block_name_from_cli ? @cli_block_name : nil + block_name = block_name_from_cli ? @cli_block_name : block_name # &bsp 'block_name:', block_name # Determine the state of breaker based on was_using_cli and the block type breaker = !block_name && !block_name_from_cli && was_using_cli && block_state.block[:shell] == BlockType::BASH # &bsp 'breaker:', breaker @@ -598,12 +602,10 @@ # # @param mdoc [YourMDocClass] An instance of the MDoc class. # @param selected [Hash] The selected block. # @return [Array<String>] Required code blocks as an array of lines. def collect_required_code_lines(mdoc, selected, link_state = LinkState.new, block_source:) - set_environment_variables_for_block(selected) if selected[:shell] == BlockType::VARS - required = mdoc.collect_recursively_required_code( selected[:nickname] || selected[:oname], label_format_above: @delegate_object[:shell_code_label_format_above], label_format_below: @delegate_object[:shell_code_label_format_below], block_source: block_source @@ -622,11 +624,13 @@ elsif true warn format_and_highlight_dependencies(dependencies, highlight: [@delegate_object[:block_name]]) end - HashDelegator.code_merge(link_state&.inherited_lines, required[:code]) + code_lines = selected[:shell] == BlockType::VARS ? set_environment_variables_for_block(selected) : [] + + HashDelegator.code_merge(link_state&.inherited_lines, required[:code] + code_lines) end def command_execute(command, args: []) @run_state.files = Hash.new([]) @run_state.options = @delegate_object @@ -924,10 +928,26 @@ options_state = read_show_options_and_trigger_reuse(selected, link_state) @menu_base_options.merge!(options_state.options) @delegate_object.merge!(options_state.options) options_state.load_file_link_state + elsif selected[:shell] == BlockType::VARS + debounce_reset + block_names = [] + code_lines = set_environment_variables_for_block(selected) + dependencies = {} + link_history_push_and_next( + curr_block_name: selected[:oname], + curr_document_filename: @delegate_object[:filename], + inherited_block_names: ((link_state&.inherited_block_names || []) + block_names).sort.uniq, + inherited_dependencies: (link_state&.inherited_dependencies || {}).merge(dependencies || {}), ### merge, not replace, key data + inherited_lines: HashDelegator.code_merge(link_state&.inherited_lines, code_lines), + next_block_name: '', + next_document_filename: @delegate_object[:filename], + next_load_file: LoadFile::Reuse + ) + elsif debounce_allows compile_execute_and_trigger_reuse(mdoc, selected, link_state, block_source: block_source) else LoadFileLinkState.new(LoadFile::Reuse, link_state) @@ -1087,11 +1107,11 @@ end def link_block_data_eval(link_state, code_lines, selected, link_block_data) all_code = HashDelegator.code_merge(link_state&.inherited_lines, code_lines) - if link_block_data.fetch(LinkDataKeys::Exec, false) + if link_block_data.fetch(LinkKeys::Exec, false) @run_state.files = Hash.new([]) output_lines = [] Open3.popen3( @delegate_object[:shell], @@ -1336,11 +1356,11 @@ curr_block_name: selected[:oname], curr_document_filename: @delegate_object[:filename], inherited_block_names: ((link_state&.inherited_block_names || []) + block_names).sort.uniq, inherited_dependencies: (link_state&.inherited_dependencies || {}).merge(dependencies || {}), ### merge, not replace, key data inherited_lines: HashDelegator.code_merge(link_state&.inherited_lines, code_lines), - next_block_name: '', # not link_block_data['block'] || '' + next_block_name: '', # not link_block_data[LinkKeys::Block] || '' next_document_filename: @delegate_object[:filename], # not next_document_filename next_load_file: LoadFile::Reuse # not next_document_filename == @delegate_object[:filename] ? LoadFile::Reuse : LoadFile::Load ) # LoadFileLinkState.new(LoadFile::Reuse, link_state) end @@ -1537,17 +1557,10 @@ # @return [LoadFileLinkState] Object indicating the next action for file loading. def push_link_history_and_trigger_load(link_block_body, mdoc, selected, link_state = LinkState.new) link_block_data = HashDelegator.parse_yaml_data_from_body(link_block_body) - # load key and values from link block into current environment - # - (link_block_data['vars'] || []).each do |(key, value)| - ENV[key] = value.to_s - ### add to inherited_lines - end - ## collect blocks specified by block # if mdoc code_info = mdoc.collect_recursively_required_code( selected[:oname], @@ -1561,37 +1574,55 @@ else block_names = [] code_lines = [] dependencies = {} end - next_document_filename = link_block_data['file'] || @delegate_object[:filename] + next_document_filename = link_block_data[LinkKeys::File] || @delegate_object[:filename] - ## append blocks loaded per LinkDataKeys::Load + # load key and values from link block into current environment # - if (load_filespec = link_block_data.fetch(LinkDataKeys::Load, '')).present? + if link_block_data[LinkKeys::Vars] + code_lines.push "# #{selected[:oname]}" + (link_block_data[LinkKeys::Vars] || []).each do |(key, value)| + ENV[key] = value.to_s + require 'shellwords' + code_lines.push "#{key}=\"#{Shellwords.escape(value)}\"" + end + end + + ## append blocks loaded, apply LinkKeys::Eval + # + if (load_filespec = link_block_data.fetch(LinkKeys::Load, '')).present? code_lines += File.readlines(load_filespec, chomp: true) end # if an eval link block, evaluate code_lines and return its standard output # - if link_block_data.fetch(LinkDataKeys::Eval, - false) || link_block_data.fetch(LinkDataKeys::Exec, false) + if link_block_data.fetch(LinkKeys::Eval, + false) || link_block_data.fetch(LinkKeys::Exec, false) code_lines = link_block_data_eval(link_state, code_lines, selected, link_block_data) end - if link_block_data[LinkDataKeys::Return] + ## write variables + # + if (save_filespec = link_block_data.fetch(LinkKeys::Save, '')).present? + File.write(save_filespec, HashDelegator.join_code_lines(link_state&.inherited_lines)) + next_document_filename = @delegate_object[:filename] + end + + if link_block_data[LinkKeys::Return] pop_add_current_code_to_head_and_trigger_load(link_state, block_names, code_lines, dependencies, selected) else link_history_push_and_next( curr_block_name: selected[:oname], curr_document_filename: @delegate_object[:filename], inherited_block_names: ((link_state&.inherited_block_names || []) + block_names).sort.uniq, inherited_dependencies: (link_state&.inherited_dependencies || {}).merge(dependencies || {}), ### merge, not replace, key data inherited_lines: HashDelegator.code_merge(link_state&.inherited_lines, code_lines), - next_block_name: link_block_data['block'] || '', + next_block_name: link_block_data.fetch(LinkKeys::NextBlock, nil) || link_block_data[LinkKeys::Block] || '', next_document_filename: next_document_filename, next_load_file: next_document_filename == @delegate_object[:filename] ? LoadFile::Reuse : LoadFile::Load ) end end @@ -1666,12 +1697,17 @@ if prompt_user_exit(@run_state.block_name_from_cli, block_state.block) # &bsp 'prompt_user_exit -> break' break end + ## order of block name processing + # from link block + # from cli + # from user + # link_state.block_name, @run_state.block_name_from_cli, cli_break = \ - HashDelegator.next_link_state(!shift_cli_argument, now_using_cli, block_state) + HashDelegator.next_link_state(!link_state.block_name && !shift_cli_argument, now_using_cli, block_state, block_name: link_state.block_name) if !block_state.block[:block_name_from_ui] && cli_break # &bsp '!block_name_from_ui + cli_break -> break' break end @@ -1812,18 +1848,24 @@ rescue StandardError HashDelegator.error_handler('select_option_with_metadata') end def set_environment_variables_for_block(selected) + code_lines = [] YAML.load(selected[:body].join("\n"))&.each do |key, value| ENV[key] = value.to_s + + require 'shellwords' + code_lines.push "#{key}=\"#{Shellwords.escape(value)}\"" + next unless @delegate_object[:menu_vars_set_format].present? formatted_string = format(@delegate_object[:menu_vars_set_format], { key: key, value: value }) print string_send_color(formatted_string, :menu_vars_set_color) end + code_lines end def should_add_back_option? @delegate_object[:menu_with_back] && @link_history.prior_state_exist? end @@ -2109,11 +2151,11 @@ body = ["file: sample_file\nblock: sample_block\nvars:\n KEY: VALUE"] expected_result = LoadFileLinkState.new(LoadFile::Load, LinkState.new(block_name: 'sample_block', document_filename: 'sample_file', inherited_dependencies: {}, - inherited_lines: [])) + inherited_lines: ['# ', 'KEY="VALUE"'])) assert_equal expected_result, @hd.push_link_history_and_trigger_load(body, nil, FCB.new(block_name: 'sample_block', filename: 'sample_file')) end @@ -2280,10 +2322,10 @@ def test_collect_required_code_lines_with_vars YAML.stubs(:load).returns({ 'key' => 'value' }) @mdoc.stubs(:collect_recursively_required_code).returns({ code: ['code line'] }) result = @hd.collect_required_code_lines(@mdoc, @selected, block_source: {}) - assert_equal ['code line'], result + assert_equal ['code line', 'key="value"'], result end end class TestHashDelegatorCommandOrUserSelectedBlock < Minitest::Test def setup