lib/hash_delegator.rb in markdown_exec-2.0.3.2 vs lib/hash_delegator.rb in markdown_exec-2.0.4

- old
+ new

@@ -1,12 +1,12 @@ #!/usr/bin/env bundle exec ruby # frozen_string_literal: true # encoding=utf-8 -require 'English' require 'clipboard' +require 'English' require 'fileutils' require 'open3' require 'optparse' require 'ostruct' require 'set' @@ -20,20 +20,20 @@ require_relative 'array_util' require_relative 'block_label' require_relative 'block_types' require_relative 'cached_nested_file_reader' require_relative 'constants' -require_relative 'std_out_err_logger' require_relative 'directory_searcher' require_relative 'exceptions' require_relative 'fcb' require_relative 'filter' require_relative 'fout' require_relative 'hash' require_relative 'link_history' require_relative 'mdoc' require_relative 'regexp' +require_relative 'std_out_err_logger' require_relative 'string_util' class String # Checks if the string is not empty. # @return [Boolean] Returns true if the string is not empty, false otherwise. @@ -363,10 +363,27 @@ expression.gsub('*', path) end end end +class BashCommentFormatter + # Formats a multi-line string into a format safe for use in Bash comments. + def self.format_comment(input_string) + return '# ' if input_string.nil? + return '# ' if input_string.empty? + + formatted = input_string.split("\n").map do |line| + "# #{line.gsub('#', '\#')}" + end + formatted.join("\n") + end + # # fit oname in single bash comment + # def oname_for_bash_comment(oname) + # oname.gsub("\n", ' ~ ').gsub(/ +/, ' ') + # end +end + module MarkdownExec class DebugHelper # Class-level variable to store history of printed messages @@printed_messages = Set.new @@ -1334,32 +1351,32 @@ home: Dir.pwd, started_at: Time.now.utc.strftime(@delegate_object[:execute_command_title_time_format]) } end -# # Loads auto link block. -# def load_auto_link_block(all_blocks, link_state, mdoc, block_source:) -# block_name = @delegate_object[:document_load_link_block_name] -# return unless block_name.present? && @most_recent_loaded_filename != @delegate_object[:filename] + # # Loads auto link block. + # def load_auto_link_block(all_blocks, link_state, mdoc, block_source:) + # block_name = @delegate_object[:document_load_link_block_name] + # return unless block_name.present? && @most_recent_loaded_filename != @delegate_object[:filename] -# block = HashDelegator.block_find(all_blocks, :oname, block_name) -# return unless block + # block = HashDelegator.block_find(all_blocks, :oname, block_name) + # return unless block -# if block.fetch(:shell, '') != BlockType::LINK -# HashDelegator.error_handler('must be Link block type', { abort: true }) + # if block.fetch(:shell, '') != BlockType::LINK + # HashDelegator.error_handler('must be Link block type', { abort: true }) -# else -# # debounce_reset -# push_link_history_and_trigger_load( -# link_block_body: block.fetch(:body, ''), -# mdoc: mdoc, -# selected: block, -# link_state: link_state, -# block_source: block_source -# ) -# end -# end + # else + # # debounce_reset + # push_link_history_and_trigger_load( + # link_block_body: block.fetch(:body, ''), + # mdoc: mdoc, + # selected: block, + # link_state: link_state, + # block_source: block_source + # ) + # end + # end # Loads auto blocks based on delegate object settings and updates if new filename is detected. # Executes a specified block once per filename. # @param all_blocks [Array] Array of all block elements. # @return [Boolean, nil] True if values were modified, nil otherwise. @@ -1752,11 +1769,11 @@ end # load key and values from link block into current environment # if link_block_data[LinkKeys::Vars] - code_lines.push "# #{selected[:oname]}" + code_lines.push BashCommentFormatter.format_comment(selected[:oname]) (link_block_data[LinkKeys::Vars] || []).each do |(key, value)| ENV[key] = value.to_s code_lines.push(assign_key_value_in_bash(key, value)) end end @@ -1905,13 +1922,13 @@ @dml_block_state = block_state_for_name_from_cli(block_name) if @dml_block_state.block[:shell] == BlockType::OPTS debounce_reset link_state = LinkState.new options_state = read_show_options_and_trigger_reuse( - selected: @dml_block_state.block, - link_state: link_state - ) + selected: @dml_block_state.block, + link_state: link_state + ) @menu_base_options.merge!(options_state.options) @delegate_object.merge!(options_state.options) options_state.load_file_link_state.link_state else @@ -2101,19 +2118,29 @@ warn selected.to_yaml.sub(/^(?:---\n)?/, "Block:\n") end # Presents a TTY prompt to select an option or exit, returns metadata including option and selected def select_option_with_metadata(prompt_text, names, opts = {}) + + ## configure to environment + # + unless opts[:select_page_height].positive? + require 'io/console' + opts[:per_page] = opts[:select_page_height] = [IO.console.winsize[0] - 3, 4].max + end + selection = @prompt.select(prompt_text, names, opts.merge(filter: true)) - - item = if names.first.instance_of?(String) - { dname: selection } - else - names.find { |item| item[:dname] == selection } - end + item = names.find do |item| + if item.instance_of?(String) + item == selection + else + item[:dname] == selection + end + end + item = { dname: item } if item.instance_of?(String) unless item HashDelegator.error_handler('select_option_with_metadata', error: 'menu item not found') exit 1 end @@ -2316,14 +2343,10 @@ else @delegate_object end sph = @delegate_object[:select_page_height] - unless sph.positive? - require 'io/console' - sph = [IO.console.winsize[0] - 3, 4].max - end selection_opts.merge!(per_page: sph) selected_option = select_option_with_metadata(prompt_title, block_menu, selection_opts) determine_block_state(selected_option) @@ -2385,13 +2408,13 @@ case value when Hash clean_hash_recursively(value) when Struct struct_hash = value.to_h # Convert the Struct to a hash - cleaned_hash = clean_hash_recursively(struct_hash) # Clean the hash + clean_hash_recursively(struct_hash) # Clean the hash # Return the cleaned hash instead of updating the Struct - return cleaned_hash + else value end end @@ -2400,13 +2423,11 @@ obj.each do |key, value| cleaned_value = clean_value(value) # Clean and possibly convert value obj[key] = cleaned_value if value.is_a?(Hash) || value.is_a?(Struct) end - if obj.is_a?(Hash) - obj.select! { |key, value| ![nil, '', [], {}, nil].include?(value) } - end + obj.reject! { |_key, value| [nil, '', [], {}, nil].include?(value) } if obj.is_a?(Hash) obj end def self.next_link_state(*args, **kwargs, &block) @@ -2436,12 +2457,47 @@ Bundler.require(:default) require 'minitest/autorun' require 'mocha/minitest' -require_relative 'std_out_err_logger' +class BashCommentFormatterTest < Minitest::Test + # Test formatting a normal string without special characters + def test_format_simple_string + input = 'This is a simple comment.' + expected = '# This is a simple comment.' + assert_equal expected, BashCommentFormatter.format_comment(input) + end + # Test formatting a string containing hash characters + def test_format_string_with_hash + input = 'This is a #comment with hash.' + expected = '# This is a \\#comment with hash.' + assert_equal expected, BashCommentFormatter.format_comment(input) + end + + # Test formatting an empty string + def test_format_empty_string + input = '' + expected = '# ' + assert_equal expected, BashCommentFormatter.format_comment(input) + end + + # Test formatting a multi-line string + def test_format_multi_line_string + input = "This is the first line.\nThis is the second line." + expected = "# This is the first line.\n# This is the second line." + assert_equal expected, BashCommentFormatter.format_comment(input) + end + + # Test formatting strings with leading and trailing whitespace + def test_format_whitespace + input = ' This has leading and trailing spaces ' + expected = '# This has leading and trailing spaces ' + assert_equal expected, BashCommentFormatter.format_comment(input) + end +end + module MarkdownExec class TestHashDelegator0 < Minitest::Test def setup @hd = HashDelegator.new end @@ -3292,33 +3348,39 @@ end end class PathUtilsTest < Minitest::Test def test_absolute_path_returns_unchanged - absolute_path = "/usr/local/bin" - expression = "path/to/*/directory" + absolute_path = '/usr/local/bin' + expression = 'path/to/*/directory' assert_equal absolute_path, PathUtils.resolve_path_or_substitute(absolute_path, expression) end def test_relative_path_gets_substituted - relative_path = "my_folder" - expression = "path/to/*/directory" - expected_output = "path/to/my_folder/directory" + relative_path = 'my_folder' + expression = 'path/to/*/directory' + expected_output = 'path/to/my_folder/directory' assert_equal expected_output, PathUtils.resolve_path_or_substitute(relative_path, expression) end def test_path_with_no_slash_substitutes_correctly - relative_path = "data" - expression = "path/to/*/directory" - expected_output = "path/to/data/directory" + relative_path = 'data' + expression = 'path/to/*/directory' + expected_output = 'path/to/data/directory' assert_equal expected_output, PathUtils.resolve_path_or_substitute(relative_path, expression) end def test_empty_path_substitution - empty_path = "" - expression = "path/to/*/directory" - expected_output = "path/to//directory" + empty_path = '' + expression = 'path/to/*/directory' + expected_output = 'path/to//directory' assert_equal expected_output, PathUtils.resolve_path_or_substitute(empty_path, expression) end - end + # Test formatting a string containing UTF-8 characters + def test_format_utf8_characters + input = 'Unicode test: ā, ΓΆ, πŸ’», and πŸš€ are fun!' + expected = '# Unicode test: ā, ΓΆ, πŸ’», and πŸš€ are fun!' + assert_equal expected, BashCommentFormatter.format_comment(input) + end + end end # module MarkdownExec