Class: MarkdownExec::HashDelegatorParent
- Extended by:
- HashDelegatorSelf
- Includes:
- CompactionHelpers, TextAnalyzer
- Defined in:
- lib/hash_delegator.rb
Direct Known Subclasses
Instance Attribute Summary collapse
-
#p_all_arguments ⇒ Object
Returns the value of attribute p_all_arguments.
-
#p_options_parsed ⇒ Object
Returns the value of attribute p_options_parsed.
-
#p_params ⇒ Object
Returns the value of attribute p_params.
-
#p_rest ⇒ Object
Returns the value of attribute p_rest.
-
#pass_args ⇒ Object
Returns the value of attribute pass_args.
-
#run_state ⇒ Object
Returns the value of attribute run_state.
Instance Method Summary collapse
-
#absolute_path(file_path) ⇒ String
Returns the absolute path of the given file path.
- #add_back_option(menu_blocks:, source_id: '') ⇒ Object
- #add_exit_option(menu_blocks:, source_id: '') ⇒ Object
- #add_inherited_lines(link_state:, menu_blocks:) ⇒ Object
-
#add_menu_chrome_blocks!(link_state:, menu_blocks:, source_id: '') ⇒ Object
Modifies the provided menu blocks array by adding ‘Back’ and ‘Exit’ options, along with initial and final dividers, based on the delegate object’s configuration.
- #annotate_required_lines(name, lines, block_name:) ⇒ Object
-
#append_chrome_block(menu_blocks:, menu_state:, source_id: '') ⇒ Object
Appends a chrome block, which is a menu option for Back or Exit.
-
#append_divider(menu_blocks:, position:, source_id: '') ⇒ Object
Appends a formatted divider to the specified position in a menu block array.
-
#append_inherited_lines(link_state:, menu_blocks:, position: top) ⇒ Object
Appends a formatted divider to the specified position in a menu block array.
-
#apply_block_type_color_option(name, block_type_color_option) ⇒ String
Applies shell color options to the given string if applicable.
- #apply_tree_decorations(text, color_method, decor_patterns) ⇒ Object
- #assign_key_value_in_bash(key, value) ⇒ Object
- #block_is_back(fcb) ⇒ Object
- #block_is_edit(fcb) ⇒ Object
- #block_is_exit(fcb) ⇒ Object
- #block_is_history(fcb) ⇒ Object
- #block_is_load(fcb) ⇒ Object
- #block_is_save(fcb) ⇒ Object
- #block_is_shell(fcb) ⇒ Object
- #block_is_view(fcb) ⇒ Object
-
#blocks_as_menu_items(menu_blocks) ⇒ Array<Hash>
Filter blocks per block_name_include_match, block_name_wrapper_match.
-
#blocks_from_nested_files(link_state: @dml_link_state || LinkState.new, source_id: nil) ⇒ Array<FCB>
Iterates through nested files to collect various types of blocks, including dividers, tasks, and others.
- #build_menu_options(exit_option, display_mode_option, menu_entries, display_format) ⇒ Object
- #build_replacement_dictionary(commands, link_state, initial_code_required: false, occurrence_expressions: nil) ⇒ Object
- #calc_logged_stdout_filename(block_name:) ⇒ Object
- #cfile ⇒ Object
-
#check_file_existence(filename) ⇒ Object
Check whether the document exists and is readable.
-
#code_from_auto_blocks(all_blocks, mdoc: nil, default_only: true) ⇒ Object
return code resulting from evaluating all automatic blocks in order.
-
#code_from_auto_shell_blocks(all_blocks, mdoc: nil) ⇒ Object
return code resulting from evaluating all automatic SHELL blocks in order.
-
#code_from_auto_ux_blocks(all_blocks, mdoc) ⇒ Object
return code resulting from evaluating all UX blocks in order.
-
#code_from_auto_vars_blocks(all_blocks, block_name: ) ⇒ Object
return code resulting from evaluating all automatic VARS blocks in order.
-
#code_from_ux_block_to_set_environment_variables(selected, mdoc, inherited_code: nil, force: true, only_default: false, required: nil, silent:) ⇒ Object
parse YAML body defining the UX for a single variable set ENV value for the variable and return code lines for the same for BlockType::UX.
-
#code_from_vars_block_to_set_environment_variables(selected) ⇒ Object
def sets ENV.
-
#code_line_to_assign_a_variable(name, value, force:) ⇒ Object
make a single line of shell code to assign an escaped value to a variable force/default.
- #collect_line_decor_patterns(delegate_object) ⇒ Object
- #command_execute(command, erls:, shell:, args: []) ⇒ Object
- #command_execute_in_own_window(args:, erls:, script:) ⇒ Object
- #command_execute_in_own_window_format_arguments(erls:, home: Dir.pwd, rest: '') ⇒ Object
- #command_execute_in_process(args:, command:, erls:, filename:, shell:) ⇒ Object
-
#compile_execute_and_trigger_reuse(mdoc:, selected:, block_source:, link_state:) ⇒ LoadFileLinkState
This method is responsible for handling the execution of generic blocks in a markdown document.
-
#contains_glob?(str) ⇒ Boolean
Check if the expression contains wildcard characters.
- #copy_to_clipboard(required_lines) ⇒ Object
-
#count_blocks_in_filename ⇒ Integer
Counts the number of fenced code blocks in a file.
- #count_named_group_occurrences(blocks, pattern, exclude_types: [BlockType::SHELL], group_name:) ⇒ Object
- #count_named_group_occurrences_block_body_fix_indent(block) ⇒ Object
-
#create_and_add_chrome_block(blocks:, case_conversion: nil, center: nil, collapse: nil, color_method:, decor_patterns: [], disabled: true, fcb: nil, format_option:, id: '', level: 0, match_data:, type: '', wrap: nil) ⇒ Object
Creates and adds a formatted block to the blocks array based on the provided match and format options.
-
#create_and_add_chrome_blocks(blocks, fcb, id: '', init_ids: false) ⇒ Object
Processes lines within the file and converts them into blocks if they match certain criteria.
- #create_divider(position, source_id: '') ⇒ Object
-
#debounce_allows ⇒ Boolean
Prompts user if named block is the same as the prior execution.
- #debounce_reset ⇒ Object
-
#determine_block_state(selected_option) ⇒ SelectedBlockMenuState
Determines the state of a selected block in the menu based on the selected option.
-
#display_required_code(required_lines:) ⇒ Object
Displays the required lines of code with color formatting for the preview section.
- #divider_formatting_present?(position) ⇒ Boolean
- #dml_menu_append_chrome_item(name, count, type, always_create: true, always_enable: true, menu_state: MenuState::LOAD, source_id: '') ⇒ Object
- #do_save_execution_output ⇒ Object
-
#document_name_in_glob_as_file_name(document_filename: @dml_link_state.document_filename, format_glob: , remove_regexp: %r{^\./}, subst_regexp: /[\/:\.\* ]/, subst_string: '_') ⇒ Object
remove leading “./” replace characters: / : .
- #dump_and_warn_block_state(name:, selected:) ⇒ Object
-
#dump_delobj(blocks_in_file, menu_blocks, link_state) ⇒ Object
Outputs warnings based on the delegate object’s configuration.
-
#edit_text(initial_text, temp_name: 'edit_text') ⇒ String?
Opens text in an editor for user modification and returns the modified text.
- #env_set(name, value) ⇒ Object
-
#execute_block_by_type_for_lfls(selected:, mdoc:, block_source:, link_state: LinkState.new) ⇒ Object
Execute a code block after approval and provide user interaction options.
- #execute_block_for_state_and_name(selected:, mdoc:, link_state:, block_source: {}) ⇒ Object
- #execute_block_in_state(block_name) ⇒ Object
- #execute_block_type_history_ux(directory: , filename: '*', form: '%{line}', link_state:, regexp: '^(?<line>.*)$', selected:) ⇒ Object
-
#execute_block_type_link_with_state(link_block_body: [], mdoc: nil, selected: FCB.new, link_state: LinkState.new, block_source: {}) ⇒ LoadFileLinkState
Handles the processing of a link block in Markdown Execution.
- #execute_block_type_load_code_lines(selected, directory: , exit_prompt: , filename_pattern: , glob: , menu_options: HashDelegator.options_for_tty_menu(@delegate_object), view: ) ⇒ Object
-
#execute_block_type_port_code_lines(mdoc:, selected:, block_source:, link_state: LinkState.new) ⇒ Array<String>
Collects required code lines based on the selected block and the delegate object’s configuration.
- #execute_block_type_save(code_lines:, selected:) ⇒ Object
-
#execute_command_with_streams(command) {|stdin, stdout, stderr, thread| ... } ⇒ Integer
Executes a given command and processes its input, output, and error streams.
- #execute_history_select(files_table_rows, exit_prompt: , pause_refresh: false, stream:) ⇒ Object
- #execute_inherited_save(code_lines: @dml_link_state.inherited_lines) ⇒ Object
- #execute_navigate_back ⇒ Object
-
#execute_required_lines(blockname: '', erls: {}, required_lines: [], shell:) ⇒ Object
Executes a block of code that has been approved for execution.
- #expand_blocks_with_replacements(menu_blocks, replacements, exclude_types: [BlockType::SHELL]) ⇒ Object
- #expand_references!(fcb, link_state) ⇒ Object
- #expand_variable_references!(blocks:, echo_formatter:, group_name:, initial_code_required: false, link_state:, pattern:) ⇒ Object
-
#fetch_color(default: '', data_sym: :execution_report_preview_head, color_sym: :execution_report_preview_frame_color) ⇒ String
Retrieves a specific data symbol from the delegate object, converts it to a string, and applies a color style based on the specified color symbol.
-
#file_info(file_path) ⇒ Object
size of a file in bytes and the number of lines.
-
#find_block_by_name(blocks, block_name) ⇒ Object
Search in @dml_blocks_in_file first, fallback to @dml_menu_blocks if not found.
-
#find_block_state_by_name(block_name) ⇒ Object
find a block by its original (undecorated) name or nickname (not visible in menu) if matched, the block returned has properties that it is from cli and not ui.
- #find_option_by_name(name) ⇒ Object
- #format_and_execute_command(code_lines:, erls:, shell:) ⇒ Object
- #format_echo_command(payload) ⇒ Object
-
#format_expression(expr) ⇒ Object
Format expression using environment variables and run state.
-
#format_references_send_color(color_sym: :execution_report_preview_frame_color, context: {}, default: '', format_sym: :output_execution_label_format) ⇒ String
Formats a string based on a given context and applies color styling to it.
-
#formatted_block_name(block_name, format_sym = :publish_block_name_format) ⇒ Object
for inherited code comments for external automation.
-
#formatted_expression(expr) ⇒ Object
Expand expression if it contains format specifiers.
- #fout_execution_report ⇒ Object
- #generate_echo_commands(variable_counts, formatter: nil) ⇒ Object
- #generate_temp_filename(ext = '.sh') ⇒ Object
-
#handle_back_or_continue(block_state) ⇒ Object
Updates the delegate object’s state based on the provided block state.
-
#handle_consecutive_inactive_items!(menu_blocks) ⇒ Object
enable scroll targets in long sequences of inactive lines.
- #handle_selection(menu_entries, selection, current_display_format) {|selected_item| ... } ⇒ Object
- #handle_stream(stream:, file_type:, swap: false) ⇒ Object
- #history_files(direction: :reverse, filename: nil, home: Dir.pwd, order: :chronological, path: '') ⇒ Object
-
#initial_state ⇒ Object
Initializes variables for regex and other states.
-
#initialize(delegate_object = {}) ⇒ HashDelegatorParent
constructor
A new instance of HashDelegatorParent.
- #interactive_menu_with_display_modes(menu_entries, display_formats:, display_mode_option:, exit_option:, menu_title:, pause_after_selection:) ⇒ Object
-
#iter_blocks_from_nested_files {|Symbol| ... } ⇒ Object
Iterates through blocks in a file, applying the provided block to each line.
- #iter_source_blocks(source, source_id: nil, &block) ⇒ Object
-
#join_array_of_arrays(*args) ⇒ Object
join a list of arrays into a single array convert single items to arrays.
- #link_block_data_eval(link_state, code_lines, selected, link_block_data, block_source:, shell:) ⇒ Object
- #link_history_push_and_next(curr_block_name:, curr_document_filename:, inherited_block_names:, inherited_dependencies:, inherited_lines:, keep_code:, next_block_name:, next_document_filename:, next_keep_code:, next_load_file:) ⇒ Object
- #link_load_format_data ⇒ Object
- #list_blocks(source_id: nil) ⇒ Object
-
#load_auto_opts_block(all_blocks, mdoc:) ⇒ Boolean?
Loads and updates auto options for document blocks if the current filename has changed.
- #load_cli_or_user_selected_block(all_blocks: [], menu_blocks: [], prior_answer: nil) ⇒ Object
-
#load_filespec_from_expression(expression) ⇒ Object
format + glob + select for file in load block name has references to ENV vars and doc and batch vars incl.
-
#load_filespec_wildcard_expansion(expr, auto_load_single: false) ⇒ Object
Handle expression with wildcard characters.
- #manage_cli_selection_state(block_name_from_cli:, now_using_cli:, link_state:) ⇒ Object
- #mdoc_and_blocks_from_nested_files(source_id: nil, link_state: nil) ⇒ Object
-
#mdoc_menu_and_blocks_from_nested_files(link_state, source_id: '') ⇒ Object
Handles the file loading and returns the blocks in the file and MDoc instance.
- #menu_add_disabled_option(document_glob, id) ⇒ Object
-
#menu_chrome_colored_option(option_symbol = :menu_option_back_name) ⇒ String
Formats and optionally colors a menu option based on delegate object’s configuration.
-
#menu_chrome_formatted_option(option_symbol = :menu_option_back_name) ⇒ String
Formats a menu option based on the delegate object’s configuration.
- #menu_from_list_with_back(list) ⇒ Object
- #menu_toggle_collapsible_block(selected) ⇒ Object
-
#method_missing(method_name, *args, &block) ⇒ Object
If a method is missing, treat it as a key for the @delegate_object.
- #next_item(list, current_item) ⇒ Object
- #next_state_append_code(selected, link_state, code_lines, mode: LoadMode::APPEND) ⇒ Object
- #next_state_set_code(selected, link_state, code_lines) ⇒ Object
- #options_command_substitution_regexp ⇒ Object
- #options_import_paths ⇒ Object
- #options_variable_expansion_regexp ⇒ Object
- #output_color_formatted(data_sym, color_sym) ⇒ Object
- #output_execution_summary ⇒ Object
- #output_from_adhoc_bash_script_file(bash_script_lines, export = nil, force:) ⇒ Object
- #output_labeled_value(label, value, level) ⇒ Object
- #pause_user_exit ⇒ Object
- #persist_fcb(options) ⇒ Object
- #pop_add_current_code_to_head_and_trigger_load(link_state, block_names, code_lines, dependencies, selected, next_block_name: nil) ⇒ Object
-
#pop_link_history_new_state ⇒ LinkState
This method handles the back-link operation in the Markdown execution context.
- #post_execution_process ⇒ Object
- #print_formatted_option(key, value) ⇒ Object
-
#process_command_result_lines(command_result_w_e_t_nl, export, required_lines) ⇒ Object
private.
- #process_string_array(arr, begin_pattern: nil, end_pattern: nil, scan1: nil, format1: nil, name: '') ⇒ Object
- #prompt_approve_repeat ⇒ Object
- #prompt_for_command(prompt) ⇒ Object
-
#prompt_for_filespec_with_wildcard(filespec) ⇒ String?
Prompts the user to enter a path or name to substitute into the wildcard expression.
-
#prompt_for_user_approval(required_lines:, selected:) ⇒ Boolean
Presents a menu to the user for approving an action and performs additional tasks based on the selection.
- #prompt_margin_left_text ⇒ Object
- #prompt_margin_left_width ⇒ Object
- #prompt_margin_right_width ⇒ Object
- #prompt_select_continue(filter: true, quiet: true) ⇒ Object
-
#prompt_select_from_list(filenames, color_sym: :prompt_color_after_script_execution, cycle: true, enum: false, quiet: true, string: ) ⇒ Object
public.
-
#prompt_user_exit(block_name_from_cli:, selected:) ⇒ Object
user prompt to exit if the menu will be displayed again.
- #publish_for_external_automation(message:) ⇒ Object
- #read_saved_assets_for_history_table(asset: nil, filename: nil, form: , path: , regexp: ) ⇒ Object
-
#read_show_options_and_trigger_reuse(selected:, mdoc:, link_state: LinkState.new) ⇒ LoadFileLinkState
Processes YAML data from the selected menu item, updating delegate objects and optionally printing formatted output.
-
#register_console_attributes(opts) ⇒ Object
Registers console attributes by modifying the options hash.
-
#replace_keys_in_lines(replacement_dictionary, lines) ⇒ Object
private.
- #report_error(err) ⇒ Object
-
#respond_to?(method_name, include_private = false) ⇒ Boolean
Check if the delegate object responds to a given method.
- #runtime_exception(exception_sym, name, items) ⇒ Object
- #safe_yaml_load(body) ⇒ Object
-
#save_filespec_from_expression(expression) ⇒ Object
allow user to select or enter.
-
#save_filespec_wildcard_expansion(filespec) ⇒ Object
Handle expression with wildcard characters allow user to select or enter.
- #save_to_file(erls:, required_lines:, selected:, shell:) ⇒ Object
- #saved_asset_filename(filename, link_state = LinkState.new) ⇒ Object
- #saved_asset_for_history(file:, form:, match_info:) ⇒ Object
- #screen_width ⇒ Object
- #screen_width_for_table ⇒ Object
- #screen_width_for_wrapping ⇒ Object
-
#select_automatic_ux_blocks(blocks) ⇒ Object
all UX blocks are automatic for the document.
-
#select_blocks(menu_blocks) ⇒ Object
Filter blocks per block_name_include_match, block_name_wrapper_match.
- #select_document_if_multiple(options, files, prompt:) ⇒ Object
-
#select_option_with_metadata(prompt_text, tty_menu_items, opts = {}, menu_blocks: nil) ⇒ Object
Presents a TTY prompt to select an option or exit, returns metadata including option and selected.
- #selected_id_name(selected) ⇒ Object
- #selected_shell(shell_name) ⇒ Object
- #shell ⇒ Object
- #shell=(value) ⇒ Object
- #shell_escape_asset_format(code_lines:, enable: , raw: , shell:) ⇒ Object
- #should_add_back_option?(menu_with_back: ) ⇒ Boolean
- #simple_menu_options ⇒ Object
-
#start_fenced_block(line, headings, fenced_start_extended_regex, source_id: nil) ⇒ MarkdownExec::FCB
Initializes a new fenced code block (FCB) object based on the provided line and heading information.
-
#string_send_color(string, color_sym) ⇒ String
Applies a color method to a string based on the provided color symbol.
- #transform_export_value(value, export) ⇒ Object
-
#update_line_and_block_state(nested_line, state, selected_types, source_id:, &block) ⇒ Void
Processes an individual line within a loop, updating headings and handling fenced code blocks.
-
#update_menu_base(options) ⇒ Object
apply options to current state.
- #ux_block_eval_for_export(bash_script_lines, export, data:, first_only: false, force:, printf_expand: false, silent:, string: nil) ⇒ Object
- #ux_block_export_activated(bash_script_lines, export, exit_prompt) ⇒ Object
- #ux_block_export_automatic(bash_script_lines, export) ⇒ Object
-
#variable_is_exportable(name) ⇒ Object
true if the variable is exported in a series of evaluations.
- #vux_await_user_selection(prior_answer: @dml_block_selection) ⇒ Object
- #vux_clear_menu_state ⇒ Object
- #vux_edit_inherited ⇒ Object
- #vux_execute_and_prompt(block_name) ⇒ Object
- #vux_execute_block_per_type(block_name, formatted_choice_ostructs) ⇒ Object
- #vux_formatted_names_for_state_chrome_blocks(names: %w[back edit history load save shell view]) ⇒ Object
- #vux_history_files_table_rows ⇒ Object
- #vux_init ⇒ Object
- #vux_input_and_execute_shell_commands(stream:, shell:) ⇒ Object
-
#vux_load_code_files_into_state ⇒ Object
load file with code lines per options.
- #vux_load_inherited ⇒ Object
-
#vux_main_loop(menu_from_yaml: nil) ⇒ Nil
Select and execute a code block from a Markdown document.
- #vux_menu_append_history_files(formatted_choice_ostructs, source_id: '') ⇒ Object
- #vux_navigate_back_for_ls ⇒ Object
- #vux_parse_document(source_id: '') ⇒ Object
- #vux_publish_block_name_for_external_automation(block_name) ⇒ Object
- #vux_publish_document_file_name_for_external_automation ⇒ Object
-
#vux_user_selected_block_name ⇒ Object
return :break to break from loop.
- #vux_view_inherited(stream:) ⇒ Object
- #wait_for_stream_processing ⇒ Object
- #wait_for_user_selected_block(all_blocks, menu_blocks, prior_answer) ⇒ Object
- #wait_for_user_selection(_all_blocks, menu_blocks, prior_answer) ⇒ Object
- #warning_required_empty(export) ⇒ Object
-
#write_command_file(required_lines:, blockname:, shell: nil) ⇒ Object
Handles the core logic for generating the command file’s metadata and content.
-
#write_file_with_directory_creation(content:, filespec:) ⇒ Object
Ensure the directory exists before writing the file.
-
#write_inherited_lines_to_file(link_state, link_block_data) ⇒ Object
return next document file name.
Methods included from HashDelegatorSelf
apply_color_from_hash, block_find, block_match, block_select, chrome_block_criteria, count_matches_in_lines, create_directory_for_file, create_file_and_write_string_with_permissions, default_block_title_from_body, delete_consecutive_blank_lines!, error_handler, flatten_and_compact_arrays, indent_all_lines, initialize_fcb_names, join_code_lines, next_link_state, parse_yaml_data_from_body, persist_fcb_self, read_required_blocks_from_temp_file, remove_file_without_standard_errors, safeval, set_file_permissions, tables_into_columns!, tty_prompt_without_disabled_symbol, update_menu_attrib_yield_selected, yield_line_if_selected
Methods included from TextAnalyzer
analyze_hierarchy, highlight_segments, yield_matches_and_non_matches
Methods included from CompactionHelpers
#compact_and_convert_array_to_hash, #compact_and_index_hash, #compact_hash
Constructor Details
#initialize(delegate_object = {}) ⇒ HashDelegatorParent
Returns a new instance of HashDelegatorParent.
646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 |
# File 'lib/hash_delegator.rb', line 646 def initialize(delegate_object = {}) @delegate_object = delegate_object @prompt = HashDelegator.tty_prompt_without_disabled_symbol @opts_most_recent_filename = nil @ux_most_recent_filename = nil @vars_most_recent_filename = nil @pass_args = [] @run_state = OpenStruct.new( link_history: [], source: OpenStruct.new ) @link_history = LinkHistory.new @fout = FOut.new(@delegate_object) ### slice only relevant keys @process_mutex = Mutex.new @process_cv = ConditionVariable.new @dml_link_state = Struct.new(:document_filename, :inherited_lines) .new(@delegate_object[:filename], []) = [] @fcb_store = [] # all fcbs created @p_all_arguments = [] = [] @p_params = {} @p_rest = [] @compressed_ids = {} = {} rescue StandardError wwe $! end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method_name, *args, &block) ⇒ Object
If a method is missing, treat it as a key for the @delegate_object.
3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 |
# File 'lib/hash_delegator.rb', line 3880 def method_missing(method_name, *args, &block) if @delegate_object.respond_to?(method_name) @delegate_object.send(method_name, *args, &block) elsif method_name.to_s.end_with?('=') && args.size == 1 @delegate_object[method_name.to_s.chop.to_sym] = args.first else @delegate_object[method_name] # super end end |
Instance Attribute Details
#p_all_arguments ⇒ Object
Returns the value of attribute p_all_arguments.
639 640 641 |
# File 'lib/hash_delegator.rb', line 639 def p_all_arguments @p_all_arguments end |
#p_options_parsed ⇒ Object
Returns the value of attribute p_options_parsed.
639 640 641 |
# File 'lib/hash_delegator.rb', line 639 def end |
#p_params ⇒ Object
Returns the value of attribute p_params.
639 640 641 |
# File 'lib/hash_delegator.rb', line 639 def p_params @p_params end |
#p_rest ⇒ Object
Returns the value of attribute p_rest.
639 640 641 |
# File 'lib/hash_delegator.rb', line 639 def p_rest @p_rest end |
#pass_args ⇒ Object
Returns the value of attribute pass_args.
639 640 641 |
# File 'lib/hash_delegator.rb', line 639 def pass_args @pass_args end |
#run_state ⇒ Object
Returns the value of attribute run_state.
639 640 641 |
# File 'lib/hash_delegator.rb', line 639 def run_state @run_state end |
Instance Method Details
#absolute_path(file_path) ⇒ String
Returns the absolute path of the given file path. If the provided path is already absolute, it returns it as is. Otherwise, it prefixes the path with the current working directory.
Example usage:
absolute_path('/absolute/path/to/file.txt') # => '/absolute/path/to/file.txt'
absolute_path('relative/path/to/file.txt') # => '/current/working/directory/relative/path/to/file.txt'
691 692 693 694 695 696 697 |
# File 'lib/hash_delegator.rb', line 691 def absolute_path(file_path) if File.absolute_path?(file_path) file_path else File.join(Dir.getwd, file_path) end end |
#add_back_option(menu_blocks:, source_id: '') ⇒ Object
699 700 701 702 703 704 705 |
# File 'lib/hash_delegator.rb', line 699 def add_back_option(menu_blocks:, source_id: '') append_chrome_block( menu_blocks: , menu_state: MenuState::BACK, source_id: source_id ) end |
#add_exit_option(menu_blocks:, source_id: '') ⇒ Object
707 708 709 710 711 712 713 |
# File 'lib/hash_delegator.rb', line 707 def add_exit_option(menu_blocks:, source_id: '') append_chrome_block( menu_blocks: , menu_state: MenuState::EXIT, source_id: source_id ) end |
#add_inherited_lines(link_state:, menu_blocks:) ⇒ Object
715 716 717 718 719 720 |
# File 'lib/hash_delegator.rb', line 715 def add_inherited_lines(link_state:, menu_blocks:) append_inherited_lines( link_state: link_state, menu_blocks: ) end |
#add_menu_chrome_blocks!(link_state:, menu_blocks:, source_id: '') ⇒ Object
Modifies the provided menu blocks array by adding ‘Back’ and ‘Exit’ options, along with initial and final dividers, based on the delegate object’s configuration.
726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 |
# File 'lib/hash_delegator.rb', line 726 def (link_state:, menu_blocks:, source_id: '') return unless @delegate_object[:menu_link_format].present? add_inherited_lines( link_state: link_state, menu_blocks: ) if @delegate_object[:menu_with_inherited_lines] # back before exit add_back_option( menu_blocks: , source_id: "#{source_id}.back" ) if should_add_back_option? # exit after other options add_exit_option( menu_blocks: , source_id: "#{source_id}.exit" ) if @delegate_object[:menu_with_exit] append_divider( menu_blocks: , position: :initial, source_id: "#{source_id}.init" ) append_divider( menu_blocks: , position: :final, source_id: "#{source_id}.final" ) end |
#annotate_required_lines(name, lines, block_name:) ⇒ Object
760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 |
# File 'lib/hash_delegator.rb', line 760 def annotate_required_lines(name, lines, block_name:) if @delegate_object[:required_lines_with_source_comments] && !lines.empty? formatted = formatted_block_name(block_name, :script_comment_block_name_format) ['', "#‡¯¯¯ #{name} ¯¯¯ #{formatted}", '', *lines, '', "#‡___ #{name} ___ #{formatted}", ''] else lines || [] end end |
#append_chrome_block(menu_blocks:, menu_state:, source_id: '') ⇒ Object
Appends a chrome block, which is a menu option for Back or Exit
780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 |
# File 'lib/hash_delegator.rb', line 780 def append_chrome_block(menu_blocks:, menu_state:, source_id: '') case when MenuState::BACK history_state_partition option_name = @delegate_object[:menu_option_back_name] insert_at_top = @delegate_object[:menu_back_at_top] when MenuState::EDIT option_name = @delegate_object[:menu_option_edit_name] insert_at_top = @delegate_object[:menu_load_at_top] when MenuState::EXIT option_name = @delegate_object[:menu_option_exit_name] insert_at_top = @delegate_object[:menu_exit_at_top] when MenuState::HISTORY option_name = @delegate_object[:menu_option_history_name] insert_at_top = @delegate_object[:menu_load_at_top] when MenuState::LOAD option_name = @delegate_object[:menu_option_load_name] insert_at_top = @delegate_object[:menu_load_at_top] when MenuState::SAVE option_name = @delegate_object[:menu_option_save_name] insert_at_top = @delegate_object[:menu_load_at_top] when MenuState::SHELL option_name = @delegate_object[:menu_option_shell_name] insert_at_top = @delegate_object[:menu_load_at_top] when MenuState::VIEW option_name = @delegate_object[:menu_option_view_name] insert_at_top = @delegate_object[:menu_load_at_top] else raise "Missing MenuState: #{menu_state}" end formatted_name = format(@delegate_object[:menu_link_format], HashDelegator.safeval(option_name)) chrome_block = persist_fcb( chrome: true, dname: HashDelegator.new(@delegate_object).string_send_color( formatted_name, :menu_chrome_color ), id: source_id.to_s, type: BlockType::CHROME, nickname: formatted_name, oname: formatted_name ) if insert_at_top .unshift(chrome_block) else .push(chrome_block) end chrome_block end |
#append_divider(menu_blocks:, position:, source_id: '') ⇒ Object
Appends a formatted divider to the specified position in a menu block array. The method checks for the presence of formatting options before appending.
838 839 840 841 842 843 |
# File 'lib/hash_delegator.rb', line 838 def append_divider(menu_blocks:, position:, source_id: '') return unless divider_formatting_present?(position) divider = create_divider(position, source_id: source_id) position == :initial ? .unshift(divider) : .push(divider) end |
#append_inherited_lines(link_state:, menu_blocks:, position: top) ⇒ Object
Appends a formatted divider to the specified position in a menu block array. The method checks for the presence of formatting options before appending.
850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 |
# File 'lib/hash_delegator.rb', line 850 def append_inherited_lines(link_state:, menu_blocks:, position: top) return unless link_state.inherited_lines_present? insert_at_top = @delegate_object[:menu_inherited_lines_at_top] chrome_blocks = link_state.inherited_lines_map do |line| formatted = format(@delegate_object[:menu_inherited_lines_format], { line: line }) persist_fcb( chrome: true, disabled: TtyMenu::DISABLE, dname: HashDelegator.new(@delegate_object).string_send_color( formatted, :menu_inherited_lines_color ), oname: formatted ) end if insert_at_top # Prepend an array of elements to the beginning .unshift(*chrome_blocks) else # Append an array of elements to the end .concat(chrome_blocks) end rescue StandardError HashDelegator.error_handler('append_inherited_lines') end |
#apply_block_type_color_option(name, block_type_color_option) ⇒ String
Applies shell color options to the given string if applicable.
885 886 887 888 889 890 891 892 |
# File 'lib/hash_delegator.rb', line 885 def apply_block_type_color_option(name, block_type_color_option) ### accept string for color if block_type_color_option && @delegate_object[block_type_color_option].present? string_send_color(name, block_type_color_option) else name end end |
#apply_tree_decorations(text, color_method, decor_patterns) ⇒ Object
894 895 896 897 898 899 900 901 902 903 904 905 906 |
# File 'lib/hash_delegator.rb', line 894 def apply_tree_decorations(text, color_method, decor_patterns) tree = HierarchyString.new([{ text: text, color: color_method }]) if color_method decor_patterns.each do |pc| analyzed_hierarchy = TextAnalyzer.analyze_hierarchy( tree.substrings, pc[:pattern], color_method, pc[:color_method] ) tree = HierarchyString.new(analyzed_hierarchy) end end tree.decorate end |
#assign_key_value_in_bash(key, value) ⇒ Object
908 909 910 911 912 913 914 915 |
# File 'lib/hash_delegator.rb', line 908 def assign_key_value_in_bash(key, value) if value.to_s =~ /["$\\`]/ # requiring ShellWords to write into Bash scripts "#{key}=#{Shellwords.escape(value)}" else "#{key}=\"#{value}\"" end end |
#block_is_back(fcb) ⇒ Object
5407 5408 5409 5410 5411 |
# File 'lib/hash_delegator.rb', line 5407 def block_is_back(fcb) fcb.oname == HashDelegator.safeval( @delegate_object[:menu_option_back_name] )[:line] end |
#block_is_edit(fcb) ⇒ Object
5413 5414 5415 5416 5417 |
# File 'lib/hash_delegator.rb', line 5413 def block_is_edit(fcb) fcb.oname == HashDelegator.safeval( @delegate_object[:menu_option_edit_name] )[:line] end |
#block_is_exit(fcb) ⇒ Object
5419 5420 5421 5422 5423 |
# File 'lib/hash_delegator.rb', line 5419 def block_is_exit(fcb) fcb.oname == HashDelegator.safeval( @delegate_object[:menu_option_exit_name] )[:line] end |
#block_is_history(fcb) ⇒ Object
5425 5426 5427 5428 5429 |
# File 'lib/hash_delegator.rb', line 5425 def block_is_history(fcb) fcb.oname == HashDelegator.safeval( @delegate_object[:menu_option_history_name] )[:line] end |
#block_is_load(fcb) ⇒ Object
5431 5432 5433 5434 5435 |
# File 'lib/hash_delegator.rb', line 5431 def block_is_load(fcb) fcb.oname == HashDelegator.safeval( @delegate_object[:menu_option_load_name] )[:line] end |
#block_is_save(fcb) ⇒ Object
5437 5438 5439 5440 5441 |
# File 'lib/hash_delegator.rb', line 5437 def block_is_save(fcb) fcb.oname == HashDelegator.safeval( @delegate_object[:menu_option_save_name] )[:line] end |
#block_is_shell(fcb) ⇒ Object
5443 5444 5445 5446 5447 |
# File 'lib/hash_delegator.rb', line 5443 def block_is_shell(fcb) fcb.oname == HashDelegator.safeval( @delegate_object[:menu_option_shell_name] )[:line] end |
#block_is_view(fcb) ⇒ Object
5449 5450 5451 5452 5453 |
# File 'lib/hash_delegator.rb', line 5449 def block_is_view(fcb) fcb.oname == HashDelegator.safeval( @delegate_object[:menu_option_view_name] )[:line] end |
#blocks_as_menu_items(menu_blocks) ⇒ Array<Hash>
Filter blocks per block_name_include_match, block_name_wrapper_match. Set name displayed by tty-prompt.
4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 |
# File 'lib/hash_delegator.rb', line 4130 def () # prefix first active line, inactive for rest active = @delegate_object[:prompt_margin_left_text] inactive = ' ' * active.length select_blocks().map do |fcb| multiline = fcb.indented_decorated || (fcb.indent + (fcb.s1decorated || fcb.dname)) fcb.name = multiline.split("\n", -1).each_with_index.map do |line, index| if fcb.fetch(:disabled, nil).nil? index.zero? ? active : inactive else inactive end + line end.join("\n") fcb.value = fcb.id || fcb.name.split("\n").first fcb.to_h end end |
#blocks_from_nested_files(link_state: @dml_link_state || LinkState.new, source_id: nil) ⇒ Array<FCB>
Iterates through nested files to collect various types
of blocks, including dividers, tasks, and others.
The method categorizes blocks based on their type and processes them accordingly.
922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 |
# File 'lib/hash_delegator.rb', line 922 def blocks_from_nested_files( link_state: @dml_link_state || LinkState.new, source_id: nil ) register_console_attributes(@delegate_object) @decor_patterns_from_delegate_object_for_block_create = collect_line_decor_patterns(@delegate_object) count = 0 blocks = [] results = {} iter_blocks_from_nested_files do |btype, fcb| count += 1 wwt :iter, 'count:', count, 'btype:', btype, 'fcb.id:', fcb&.id case btype when :blocks result = SuccessResult.instance if @delegate_object[:bash] begin mf = MenuFilter.new(@delegate_object) if fcb.body.count > 1 && mf.(fcb) && fcb.is_split_displayed?(@delegate_object) # make multiple FCB blocks, one for each line; only the first is active id_prefix = "#{fcb.id}¤BlkFrmNstFls®block:#{count}©body:" fcb0 = fcb = fcb.body .each.with_index do |, index| is_enabled_but_inactive = ((index + 1) % (@delegate_object[:select_page_height] / 2)).zero? if index.zero? # fcb.body = [menu_line] # fcb.center = center # fcb.collapse = collapse.nil? ? (line_obj[:collapse] == COLLAPSIBLE_TOKEN_COLLAPSE) : collapse # fcb.disabled = disabled ? TtyMenu::DISABLE : nil fcb.dname = fcb.indent + fcb.id = "#{id_prefix}#{index}" # fcb.indent = line_obj[:indent] fcb.is_split_first = true # the first block in a split fcb.is_split_rest = false # fcb.level = level # fcb.oname # computed # fcb.s0indent = indent fcb.s0printable = fcb.s1decorated = fcb.text = # fcb.token = line_obj[:collapse] # fcb.type = type else fcb = persist_fcb( block: nil, body: fcb0.body, center: fcb0.center, chrome: true, collapse: false, disabled: if is_enabled_but_inactive TtyMenu::ENABLE else TtyMenu::DISABLE end, dname: fcb0.indent + , id: "#{id_prefix}#{index}", indent: fcb0.indent, is_enabled_but_inactive: is_enabled_but_inactive, is_split_first: false, is_split_rest: true, # subsequent blocks in a split level: fcb0.level, s0indent: fcb0.s0indent, s0printable: , s1decorated: , start_line: fcb0.start_line, text: , # token: , type: fcb0.type ) end result = fcb.( appopts: @delegate_object, block_calls_scan: @delegate_object[:block_calls_scan], block_name_match: @delegate_object[:block_name_match], block_name_nick_match: @delegate_object[:block_name_nick_match], id: fcb.id, menu_format: @delegate_object[:menu_ux_row_format], prompt: @delegate_object[:prompt_ux_enter_a_value], table_center: @delegate_object[:table_center] ) do |oname, color| apply_block_type_color_option(oname, color) end results[fcb.id] = result if result.failure? blocks << fcb unless result.failure? end else # prepare block for menu, may fail and call HashDelegator.error_handler result = fcb.( appopts: @delegate_object, block_calls_scan: @delegate_object[:block_calls_scan], block_name_match: @delegate_object[:block_name_match], block_name_nick_match: @delegate_object[:block_name_nick_match], id: fcb.id, menu_format: @delegate_object[:menu_ux_row_format], prompt: @delegate_object[:prompt_ux_enter_a_value], table_center: @delegate_object[:table_center] ) do |oname, color| # decorate the displayed line apply_block_type_color_option(oname, color) end results[fcb.id] = result if result.failure? blocks << fcb unless result.failure? end rescue StandardError ww $@, $!, caller.deref HashDelegator.error_handler('blocks_from_nested_files', { abort: true }) end else (fcb, link_state) blocks << fcb unless result.failure? end when :filter # types accepted i[blocks line] when :line unless @delegate_object[:no_chrome] # expand references only if block is recognized (not a comment) create_and_add_chrome_blocks( blocks, fcb, id: "#{source_id}¤BlkFrmNstFls:#{count}®line", init_ids: init_ids ) do # expand references only if block is recognized (not a comment) (fcb, link_state) end end end end OpenStruct.new(blocks: blocks, results: results) rescue StandardError wwe $!, 'link_state:', link_state, 'source_id:', source_id, 'btype:', btype, 'fcb:', fcb end |
#build_menu_options(exit_option, display_mode_option, menu_entries, display_format) ⇒ Object
1060 1061 1062 1063 1064 1065 |
# File 'lib/hash_delegator.rb', line 1060 def (exit_option, display_mode_option, , display_format) [exit_option, display_mode_option, *.map(&display_format)].compact end |
#build_replacement_dictionary(commands, link_state, initial_code_required: false, occurrence_expressions: nil) ⇒ Object
1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 |
# File 'lib/hash_delegator.rb', line 1067 def build_replacement_dictionary( commands, link_state, initial_code_required: false, occurrence_expressions: nil ) evaluate_shell_expressions( (link_state&.inherited_lines_block || ''), commands, initial_code_required: initial_code_required, occurrence_expressions: occurrence_expressions ) end |
#calc_logged_stdout_filename(block_name:) ⇒ Object
1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 |
# File 'lib/hash_delegator.rb', line 1080 def calc_logged_stdout_filename(block_name:) return unless @delegate_object[:saved_stdout_folder] @delegate_object[:logged_stdout_filename] = SavedAsset.new( blockname: block_name, filename: @delegate_object[:filename], prefix: @delegate_object[:logged_stdout_filename_prefix], time: Time.now.utc, exts: '.out.txt', saved_asset_format: shell_escape_asset_format( code_lines: @dml_link_state.inherited_lines, shell: ShellType::BASH ) ).generate_name @logged_stdout_filespec = @delegate_object[:logged_stdout_filespec] = File.join @delegate_object[:saved_stdout_folder], @delegate_object[:logged_stdout_filename] end |
#cfile ⇒ Object
1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 |
# File 'lib/hash_delegator.rb', line 1103 def cfile @cfile ||= CachedNestedFileReader.new( import_directive_line_pattern: @delegate_object.fetch(:import_directive_line_pattern), import_directive_parameter_scan: Regexp.new( @delegate_object.fetch(:import_directive_parameter_scan, '') ), import_parameter_variable_assignment: @delegate_object[:import_parameter_variable_assignment], shell: @delegate_object[:shell], shell_block_name: @delegate_object[:document_load_shell_block_name], symbol_command_substitution: @delegate_object[:import_symbol_command_substitution], symbol_evaluated_expression: @delegate_object[:import_symbol_evaluated_expression], symbol_force_quoted_literal: @delegate_object[:import_symbol_force_quoted_literal], symbol_raw_literal: @delegate_object[:import_symbol_raw_literal], symbol_variable_reference: @delegate_object[:import_symbol_variable_reference] ) end |
#check_file_existence(filename) ⇒ Object
Check whether the document exists and is readable
1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 |
# File 'lib/hash_delegator.rb', line 1131 def check_file_existence(filename) unless filename&.present? @fout.fout 'No blocks found.' return false end unless File.exist? filename @fout.fout 'Document is missing.' return false end true end |
#code_from_auto_blocks(all_blocks, mdoc: nil, default_only: true) ⇒ Object
return code resulting from evaluating all automatic blocks in order
1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 |
# File 'lib/hash_delegator.rb', line 1145 def code_from_auto_blocks(all_blocks, mdoc: nil, default_only: true) shell_block_name = @delegate_object[:document_load_shell_block_name] vars_block_name = @delegate_object[:document_load_vars_block_name] # do not reload the same document read_shell = @shell_most_recent_filename != @delegate_object[:filename] read_ux = @ux_most_recent_filename != @delegate_object[:filename] read_vars = @vars_most_recent_filename != @delegate_object[:filename] @shell_most_recent_filename = @delegate_object[:filename] @ux_most_recent_filename = @delegate_object[:filename] @vars_most_recent_filename = @delegate_object[:filename] all_code = [] all_blocks.each do |fcb| block_code = [] if fcb.oname == shell_block_name if read_shell # collect code from shell block code = if mdoc mdoc.collect_recursively_required_code( anyname: fcb.id, ### anyname: fcb.pub_name, label_format_above: @delegate_object[:shell_code_label_format_above], label_format_below: @delegate_object[:shell_code_label_format_below], block_source: block_source )[:code] else fcb.body end block_code = annotate_required_lines('blk:SHELL', code, block_name: fcb.id) end elsif fcb.oname == vars_block_name if read_vars block_code = code_from_vars_block_to_set_environment_variables(fcb) end elsif fcb.type == 'ux' if !read_ux # skip elsif fcb.is_split_rest? # ignore else command_result_w_e_t_nl = code_from_ux_block_to_set_environment_variables( fcb, mdoc, force: @delegate_object[:ux_auto_load_force_default], only_default: default_only, silent: true ) block_code = if command_result_w_e_t_nl&.success? command_result_w_e_t_nl.new_lines else [] end end else # do nothing end wwt :code, 'block_code:', block_code unless block_code&.empty? all_code += block_code end all_code.tap { wwt :code, _1 } rescue StandardError wwe 'all_blocks.count:', all_blocks.count end |
#code_from_auto_shell_blocks(all_blocks, mdoc: nil) ⇒ Object
return code resulting from evaluating all automatic SHELL blocks in order
1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 |
# File 'lib/hash_delegator.rb', line 1218 def code_from_auto_shell_blocks(all_blocks, mdoc: nil) # a block name is required # do not reload the most recent filename block_name = @delegate_object[:document_load_shell_block_name] unless block_name.present? && @shell_most_recent_filename != @delegate_object[:filename] return end @shell_most_recent_filename = @delegate_object[:filename] # select the first block with the given name fcb = HashDelegator.block_find(all_blocks, :oname, block_name) return unless fcb # collect code from shell block code = if mdoc mdoc.collect_recursively_required_code( anyname: fcb.pub_name, label_format_above: @delegate_object[:shell_code_label_format_above], label_format_below: @delegate_object[:shell_code_label_format_below], block_source: block_source )[:code] else fcb.body end annotate_required_lines('blk:SHELL', code, block_name: fcb.id) end |
#code_from_auto_ux_blocks(all_blocks, mdoc) ⇒ Object
return code resulting from evaluating all UX blocks in order
1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 |
# File 'lib/hash_delegator.rb', line 1250 def code_from_auto_ux_blocks( all_blocks, mdoc ) # do not reload the most recent filename unless @ux_most_recent_filename != @delegate_object[:filename] return end @ux_most_recent_filename = @delegate_object[:filename] # select all UX blocks, rejecting non-primary split blocks = select_automatic_ux_blocks( all_blocks.reject(&:is_split_rest?) ) return if blocks.empty? # collect code from all ux blocks (blocks.each.with_object([]) do |block, | command_result_w_e_t_nl = code_from_ux_block_to_set_environment_variables( block, mdoc, force: @delegate_object[:ux_auto_load_force_default], only_default: true, silent: true ) if command_result_w_e_t_nl.failure? # if a block fails, proceed with next block else .push(command_result_w_e_t_nl.new_lines) end end).to_a end |
#code_from_auto_vars_blocks(all_blocks, block_name: ) ⇒ Object
return code resulting from evaluating all automatic VARS blocks in order
1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 |
# File 'lib/hash_delegator.rb', line 1287 def code_from_auto_vars_blocks( all_blocks, block_name: @delegate_object[:document_load_vars_block_name] ) # a block name is required # do not reload the most recent filename unless block_name.present? && @vars_most_recent_filename != @delegate_object[:filename] return end @vars_most_recent_filename = @delegate_object[:filename] # select all blocks with the given name blocks = HashDelegator.block_select(all_blocks, :oname, block_name) return if blocks.empty? # collect code for vars from all blocks (blocks.each.with_object([]) do |block, | .push( code_from_vars_block_to_set_environment_variables(block) ) end).to_a end |
#code_from_ux_block_to_set_environment_variables(selected, mdoc, inherited_code: nil, force: true, only_default: false, required: nil, silent:) ⇒ Object
parse YAML body defining the UX for a single variable set ENV value for the variable and return code lines for the same for BlockType::UX
1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 |
# File 'lib/hash_delegator.rb', line 1319 def code_from_ux_block_to_set_environment_variables( selected, mdoc, inherited_code: nil, force: true, only_default: false, required: nil, silent: ) wwt :fcb, 'selected:', selected ret_command_result = nil exit_prompt = @delegate_object[:prompt_filespec_back] required ||= mdoc.collect_recursively_required_code( anyname: selected_id_name(selected), label_format_above: @delegate_object[:shell_code_label_format_above], label_format_below: @delegate_object[:shell_code_label_format_below], block_source: block_source ) wwt :required, required # process each ux block in sequence, setting ENV and collecting lines concatenated_code_from_required_blocks = [] required[:blocks]&.each do |block| next unless block.type == BlockType::UX wwt :fcb, 'a required block', block body1 = block.raw_body || block.body case data = safe_yaml_load(body1.join("\n")) when Hash export = parse_yaml_of_ux_block( data, prompt: @delegate_object[:prompt_ux_enter_a_value], validate: '^(?<name>[^ ].*)$' ) block.export = export block.export_act = FCB.act_source(export) block.export_init = FCB.init_source(export) # required are variable names that must be set before the UX block is executed. # if any precondition is not set, the sequence is aborted. required_variables = [] export.required&.each do |precondition| required_variables.push "[[ -z $#{precondition} ]] && exit #{EXIT_STATUS_REQUIRED_EMPTY}" end wwt :required_variables, 'required_variables', required_variables eval_code = join_array_of_arrays( inherited_code, # inherited code concatenated_code_from_required_blocks, # current block requirements required_variables, # test conditions required[:code] # required by selected ) wwt :eval_code, 'eval_code:', eval_code if only_default command_result_w_e_t_nl = ux_block_export_automatic(eval_code, export) # do not display warnings on initializing call return command_result_w_e_t_nl if command_result_w_e_t_nl.failure? else command_result_w_e_t_nl = ux_block_export_activated(eval_code, export, exit_prompt) if command_result_w_e_t_nl.failure? if command_result_w_e_t_nl.warning&.present? && !silent warn command_result_w_e_t_nl.warning end return command_result_w_e_t_nl end end return command_result_w_e_t_nl if command_result_w_e_t_nl.failure? # update the required lines for this and subsequent blocks command_result_w_e_t_nl.new_lines = process_command_result_lines(command_result_w_e_t_nl, export, concatenated_code_from_required_blocks) concatenated_code_from_required_blocks.concat(command_result_w_e_t_nl.new_lines) concatenated_code_from_required_blocks = annotate_required_lines( 'blk:UX', concatenated_code_from_required_blocks, block_name: selected.id ) command_result_w_e_t_nl.new_lines = concatenated_code_from_required_blocks ret_command_result = command_result_w_e_t_nl else raise "Invalid data type: #{data.inspect}" end end wwt :concatenated_code_from_required_blocks, concatenated_code_from_required_blocks (ret_command_result || CommandResult.new( stdout: annotate_required_lines( 'blk:UX', concatenated_code_from_required_blocks, block_name: selected.id ) )).tap do |ret| wwt :cr, ret, caller.deref end rescue StandardError wwe 'selected:', selected, 'required:', required, 'block:', block, 'data:', data end |
#code_from_vars_block_to_set_environment_variables(selected) ⇒ Object
def sets ENV
1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 |
# File 'lib/hash_delegator.rb', line 1420 def code_from_vars_block_to_set_environment_variables(selected) code_lines = [] case data = YAML.load(selected.body.join("\n")) when Hash data.each do |key, value| EnvInterface.set(key, value.to_s) code_lines << assign_key_value_in_bash(key, value) next unless @delegate_object[:menu_vars_set_format].present? # in-menu display formatted_string = format(@delegate_object[:menu_vars_set_format], { key: key, value: value }) # activity dump print string_send_color(formatted_string, :menu_vars_set_color) end end annotate_required_lines('blk:VARS', code_lines, block_name: selected.id) rescue StandardError wwe 'selected:', selected, 'data:', data, 'key:', key, 'value:', value, 'code_lines:', code_lines, 'formatted_string:', formatted_string end |
#code_line_to_assign_a_variable(name, value, force:) ⇒ Object
make a single line of shell code to assign an escaped value to a variable force/default
1446 1447 1448 1449 1450 1451 1452 |
# File 'lib/hash_delegator.rb', line 1446 def code_line_to_assign_a_variable(name, value, force:) if force "#{name}=#{Shellwords.escape(value)}" else "[[ -z $#{name} ]] && #{name}=#{Shellwords.escape(value)}" end end |
#collect_line_decor_patterns(delegate_object) ⇒ Object
1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 |
# File 'lib/hash_delegator.rb', line 1454 def collect_line_decor_patterns(delegate_object) extract_patterns = lambda do |key| return [] unless delegate_object[key].present? begin (value = HashDelegator.safeval(delegate_object[key])).map do |pc| { color_method: pc[:color_method].to_sym, pattern: Regexp.new(pc[:pattern]) } end rescue StandardError wwe({ error: $!, callback: $@[0], key: key, value: value }) end end i[line_decor_pre line_decor_main line_decor_post].flat_map do |key| extract_patterns.call(key) end end |
#command_execute(command, erls:, shell:, args: []) ⇒ Object
1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 |
# File 'lib/hash_delegator.rb', line 1475 def command_execute( command, erls:, shell:, args: [] ) @run_state.files = StreamsOut.new @run_state. = @delegate_object @run_state.started_at = Time.now.utc if @delegate_object[:execute_in_own_window] && @delegate_object[:execute_command_format].present? && @run_state.saved_filespec.present? @run_state.in_own_window = true command_execute_in_own_window( args: args, erls: erls, script: @delegate_object[:execute_command_format] ) else @run_state.in_own_window = false command_execute_in_process( args: args, command: command, erls: erls, filename: @delegate_object[:filename], shell: shell ) end @run_state.completed_at = Time.now.utc rescue Errno::ENOENT report_error($ERROR_INFO) rescue SignalException => err # Handle SignalException @run_state.aborted_at = Time.now.utc @run_state. = 'SIGTERM' @run_state.error = err @run_state.files.append_stream_line(ExecutionStreams::STD_ERR, @run_state.) @fout.fout "Error ENOENT: #{err.inspect}" end |
#command_execute_in_own_window(args:, erls:, script:) ⇒ Object
1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 |
# File 'lib/hash_delegator.rb', line 1518 def command_execute_in_own_window( args:, erls:, script: ) system( format( script, command_execute_in_own_window_format_arguments( erls: erls, rest: args ? args.join(' ') : '' ) ) ) end |
#command_execute_in_own_window_format_arguments(erls:, home: Dir.pwd, rest: '') ⇒ Object
1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 |
# File 'lib/hash_delegator.rb', line 1534 def command_execute_in_own_window_format_arguments( erls:, home: Dir.pwd, rest: '' ) { batch_index: @run_state.batch_index, batch_random: @run_state.batch_random, block_name: @delegate_object[:block_name], document_filename: File.basename(@delegate_object[:filename]), document_filespec: @delegate_object[:filename], home: home, output_filename: File.basename( @delegate_object[:logged_stdout_filespec] ), output_filespec: @delegate_object[:logged_stdout_filespec], play_command: erls[:play_bin], rest: rest, script_filename: @run_state.saved_filespec, script_filespec: File.join(home, @run_state.saved_filespec), started_at: @run_state.started_at.strftime( @delegate_object[:execute_command_title_time_format] ) } end |
#command_execute_in_process(args:, command:, erls:, filename:, shell:) ⇒ Object
1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 |
# File 'lib/hash_delegator.rb', line 1558 def command_execute_in_process( args:, command:, erls:, filename:, shell: ) execute_command_with_streams( [shell, '-c', command, @delegate_object[:filename], *args] ) end |
#compile_execute_and_trigger_reuse(mdoc:, selected:, block_source:, link_state:) ⇒ LoadFileLinkState
This method is responsible for handling the execution of
generic blocks in a markdown document.
It collects the required code lines from the document and,
depending on the configuration, may display the code for
user approval before execution. It then executes the approved block.
1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 |
# File 'lib/hash_delegator.rb', line 1582 def compile_execute_and_trigger_reuse( mdoc:, selected:, block_source:, link_state: ) # play_bin matches the name in mde.applescript, called by .mde.macos.yml bim = @delegate_object[:block_interactive_match] play_bin = if bim.present? && selected.start_line =~ Regexp.new(bim) @delegate_object[:play_bin_interactive] else bbm = @delegate_object[:block_batch_match] if bbm.present? && selected.start_line =~ Regexp.new(bbm) @delegate_object[:play_bin_batch] else @delegate_object[:document_play_bin] end end required_lines = execute_block_type_port_code_lines( mdoc: mdoc, selected: selected, link_state: link_state, block_source: block_source ) output_or_approval = @delegate_object[:output_script] || @delegate_object[:user_must_approve] if output_or_approval display_required_code(required_lines: required_lines) end allow_execution = if @delegate_object[:user_must_approve] prompt_for_user_approval( required_lines: required_lines, selected: selected ) else true end if allow_execution execute_required_lines( blockname: selected_id_name(selected), erls: { play_bin: play_bin, shell: selected_shell(selected.shell) }, required_lines: required_lines, shell: selected_shell(selected.shell) ) end link_state.block_name = nil end |
#contains_glob?(str) ⇒ Boolean
Check if the expression contains wildcard characters
1630 1631 1632 1633 1634 |
# File 'lib/hash_delegator.rb', line 1630 def contains_glob?(str) return false if str.nil? str.match?(/[\*\?\[\{\}]/) end |
#copy_to_clipboard(required_lines) ⇒ Object
1636 1637 1638 1639 1640 1641 1642 |
# File 'lib/hash_delegator.rb', line 1636 def copy_to_clipboard(required_lines) text = required_lines.flatten.join($INPUT_RECORD_SEPARATOR) Clipboard.copy(text) @fout.fout "Clipboard updated: #{required_lines.count} blocks," \ " #{required_lines.flatten.count} lines," \ " #{text.length} characters" end |
#count_blocks_in_filename ⇒ Integer
Counts the number of fenced code blocks in a file. It reads lines from a file and counts occurrences of lines
matching the fenced block regex.
Assumes that every fenced block starts and ends with a
distinct line (hence divided by 2).
1651 1652 1653 1654 1655 1656 1657 1658 |
# File 'lib/hash_delegator.rb', line 1651 def count_blocks_in_filename regex = Regexp.new(@delegate_object[:fenced_start_and_end_regex]) lines = cfile.readlines( @delegate_object[:filename], import_paths: @delegate_object[:import_paths]&.split(':') ) HashDelegator.count_matches_in_lines(lines, regex) / 2 end |
#count_named_group_occurrences(blocks, pattern, exclude_types: [BlockType::SHELL], group_name:) ⇒ Object
1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 |
# File 'lib/hash_delegator.rb', line 1660 def count_named_group_occurrences( blocks, pattern, exclude_types: [BlockType::SHELL], group_name: ) # Initialize a counter for named group occurrences occurrence_count = Hash.new(0) occurrence_expressions = {} return [occurrence_count, occurrence_expressions] if pattern.nil? || pattern == // blocks.each do |block| # Skip processing for shell-type blocks next if exclude_types.include?(block.type) # Scan each block name for matches of the pattern count_named_group_occurrences_block_body_fix_indent(block).scan(pattern) do |(_, _variable_name)| pattern.match($LAST_MATCH_INFO.to_s) # Reapply match for named groups id = $LAST_MATCH_INFO[group_name] occurrence_count[id] += 1 occurrence_expressions[id] = $LAST_MATCH_INFO['expression'] end end [occurrence_count, occurrence_expressions] end |
#count_named_group_occurrences_block_body_fix_indent(block) ⇒ Object
1686 1687 1688 1689 |
# File 'lib/hash_delegator.rb', line 1686 def count_named_group_occurrences_block_body_fix_indent(block) ### actually double the entries, but not a problem since it's used as a boolean ([block.oname || ''] + (block.body || [''])).join("\n") end |
#create_and_add_chrome_block(blocks:, case_conversion: nil, center: nil, collapse: nil, color_method:, decor_patterns: [], disabled: true, fcb: nil, format_option:, id: '', level: 0, match_data:, type: '', wrap: nil) ⇒ Object
Creates and adds a formatted block to the blocks array
based on the provided match and format .
return number of lines added
1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 |
# File 'lib/hash_delegator.rb', line 1702 def create_and_add_chrome_block( blocks:, case_conversion: nil, center: nil, collapse: nil, color_method:, decor_patterns: [], disabled: true, fcb: nil, format_option:, id: '', level: 0, match_data:, type: '', wrap: nil ) line_cap = NamedCaptureExtractor.extract_named_group_match_data(match_data) # replace tabs in indent line_cap[:indent] ||= '' line_cap[:indent] = line_cap[:indent].dup if line_cap[:indent].frozen? line_cap[:indent].gsub!("\t", ' ') # TAB_SIZE = 4 # replace tabs in text line_cap[:text] ||= '' line_cap[:text] = line_cap[:text].dup if line_cap[:text].frozen? line_cap[:text].gsub!("\t", ' ') # missing capture line_cap[:collapse] ||= '' line_cap[:line] ||= '' line_caps = [line_cap] # split text with newlines, from variable expansion if line_cap[:text].include?("\n") lines = line_cap[:text].split("\n") line_caps = lines.map do |line| line_cap.dup.merge(text: line) end.to_a end # wrap text on multiple lines to screen width, replacing line_caps if wrap line_caps = line_caps.flat_map do |line_cap| text = line_cap[:text] wrapper = StringWrapper.new( width: screen_width_for_wrapping - line_cap[:indent].length ) if text.length > screen_width_for_wrapping # Wrap this text and create line_cap objects for each part wrapper.wrap(text).map do |wrapped_text| line_cap.dup.merge(text: wrapped_text) end else # No change needed for this line line_cap end end end if center line_caps.each do |line_obj| line_obj[:indent] = if line_obj[:text].length < screen_width_for_wrapping ' ' * ((screen_width_for_wrapping - line_obj[:text].length) / 2) else '' end end end use_fcb = !fcb.nil? # fcb only for the first record if any line_caps.each_with_index do |line_obj, index| next if line_obj[:text].nil? case case_conversion when :upcase line_obj[:text].upcase! when :downcase line_obj[:text].downcase! end # format expects :line to be text only line_obj[:line] = line_obj[:text] oname = if format_option format(format_option, line_obj) else line_obj[:line] end decorated = apply_tree_decorations( oname, color_method, decor_patterns ) line_obj[:line] = line_obj[:indent] + line_obj[:text] if use_fcb fcb.center = center fcb.chrome = true fcb.collapse = if collapse.nil? (line_obj[:collapse] == COLLAPSIBLE_TOKEN_COLLAPSE) else collapse end fcb.disabled = disabled ? TtyMenu::DISABLE : nil fcb.dname = line_obj[:indent] + decorated fcb.id = "#{id}.#{index}" fcb.indent = line_obj[:indent] fcb.level = level fcb.oname = line_obj[:text] fcb.s0indent = indent fcb.s0printable = line_obj[:text] fcb.s1decorated = decorated fcb.text = line_obj[:text] fcb.token = line_obj[:collapse] fcb.type = type use_fcb = false # next line is new record else fcb = persist_fcb( center: center, chrome: true, collapse: if collapse.nil? (line_obj[:collapse] == COLLAPSIBLE_TOKEN_COLLAPSE) else collapse end, disabled: disabled ? TtyMenu::DISABLE : nil, dname: line_obj[:indent] + decorated, id: "#{id}.#{index}", indent: line_obj[:indent], level: level, oname: line_obj[:text], s0indent: indent, s0printable: line_obj[:text], s1decorated: decorated, text: line_obj[:text], token: line_obj[:collapse], type: type ) end blocks.push fcb end line_caps.count end |
#create_and_add_chrome_blocks(blocks, fcb, id: '', init_ids: false) ⇒ Object
Processes lines within the file and converts them into
blocks if they match certain criteria.
1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 |
# File 'lib/hash_delegator.rb', line 1854 def create_and_add_chrome_blocks(blocks, fcb, id: '', init_ids: false) index = nil # find the first criteria with a pattern matching the body of the fcb unless (criteria = fcb.criteria) HashDelegator.chrome_block_criteria.each_with_index do |criteria1, index1| # rubocop:disable Lint/UselessAssignment if !@delegate_object[criteria1[:match]].present? || !(match_data = fcb.body[0].match @delegate_object[criteria1[:match]]) next end # rubocop:enable Lint/UselessAssignment criteria = criteria1 index = index1 break end end return unless criteria if block_given? # expand references only if block is recognized (not a comment) yield if block_given? # parse multiline to capture output of variable expansion match_data = fcb.body[0].match Regexp.new( @delegate_object[criteria[:match]], Regexp::MULTILINE ) end create_and_add_chrome_block( blocks: blocks, case_conversion: criteria[:case_conversion], center: criteria[:center] && @delegate_object[criteria[:center]], collapse: case fcb.collapse_token when COLLAPSIBLE_TOKEN_COLLAPSE true when COLLAPSIBLE_TOKEN_EXPAND false else false end, color_method: criteria[:color] && @delegate_object[criteria[:color]].to_sym, decor_patterns: @decor_patterns_from_delegate_object_for_block_create, disabled: !(criteria[:collapsible] && @delegate_object[criteria[:collapsible]]), fcb: fcb, id: "#{id}.#{index}", format_option: criteria[:format] && @delegate_object[criteria[:format]], level: criteria[:level], match_data: match_data, type: criteria[:type], wrap: criteria[:wrap] ) end |
#create_divider(position, source_id: '') ⇒ Object
1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 |
# File 'lib/hash_delegator.rb', line 1917 def create_divider(position, source_id: '') divider_key = if position == :initial :menu_initial_divider else :menu_final_divider end oname = format( @delegate_object[:menu_divider_format], HashDelegator.safeval(@delegate_object[divider_key]) ) persist_fcb( chrome: true, disabled: TtyMenu::DISABLE, dname: string_send_color(oname, :menu_divider_color), id: source_id, oname: oname ) end |
#debounce_allows ⇒ Boolean
Prompts user if named block is the same as the prior execution.
1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 |
# File 'lib/hash_delegator.rb', line 1940 def debounce_allows return true unless @delegate_object[:debounce_execution] # filter block if selected in menu return true if @run_state.source.block_name_from_cli # return false if @prior_execution_block == @delegate_object[:block_name] if @prior_execution_block == @delegate_object[:block_name] return @allowed_execution_block == @prior_execution_block || prompt_approve_repeat end @prior_execution_block = @delegate_object[:block_name] @allowed_execution_block = nil true end |
#debounce_reset ⇒ Object
1957 1958 1959 |
# File 'lib/hash_delegator.rb', line 1957 def debounce_reset @prior_execution_block = nil end |
#determine_block_state(selected_option) ⇒ SelectedBlockMenuState
Determines the state of a selected block in the menu based
on the selected option.
It categorizes the selected option into either EXIT, BACK,
or CONTINUE state.
1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 |
# File 'lib/hash_delegator.rb', line 1969 def determine_block_state(selected_option) return if selected_option.nil? option_name = selected_option[:oname] if option_name == (:menu_option_exit_name) return SelectedBlockMenuState.new(nil, OpenStruct.new, MenuState::EXIT) end if option_name == (:menu_option_back_name) return SelectedBlockMenuState.new(selected_option, OpenStruct.new, MenuState::BACK) end SelectedBlockMenuState.new(selected_option, OpenStruct.new, MenuState::CONTINUE) end |
#display_required_code(required_lines:) ⇒ Object
Displays the required lines of code with color formatting
for the preview section.
It wraps the code lines between a formatted header and
tail.
1995 1996 1997 1998 1999 2000 2001 |
# File 'lib/hash_delegator.rb', line 1995 def display_required_code(required_lines:) output_color_formatted(:script_preview_head, :script_preview_frame_color) required_lines.each { |cb| @fout.fout cb } output_color_formatted(:script_preview_tail, :script_preview_frame_color) end |
#divider_formatting_present?(position) ⇒ Boolean
2003 2004 2005 2006 2007 2008 2009 2010 2011 |
# File 'lib/hash_delegator.rb', line 2003 def divider_formatting_present?(position) divider_key = if position == :initial :menu_initial_divider else :menu_final_divider end @delegate_object[:menu_divider_format].present? && @delegate_object[divider_key].present? end |
#dml_menu_append_chrome_item(name, count, type, always_create: true, always_enable: true, menu_state: MenuState::LOAD, source_id: '') ⇒ Object
2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 |
# File 'lib/hash_delegator.rb', line 2013 def ( name, count, type, always_create: true, always_enable: true, menu_state: MenuState::LOAD, source_id: '' ) raise unless name.present? raise if .nil? item = .find { |block| block.oname == name } # create menu item when it is needed (count > 0) # if item.nil? && (always_create || count.positive?) item = append_chrome_block(source_id: source_id, menu_blocks: , menu_state: ) end # update item if it exists # return unless item item.dname = type.present? ? "#{name} (#{count} #{type})" : name if always_enable || count.positive? item.delete(:disabled) else item[:disabled] = TtyMenu::DISABLE end end |
#do_save_execution_output ⇒ Object
2045 2046 2047 2048 2049 2050 2051 2052 |
# File 'lib/hash_delegator.rb', line 2045 def do_save_execution_output return unless @delegate_object[:save_execution_output] return if @run_state.in_own_window @run_state.files.write_execution_output_to_file( @delegate_object[:logged_stdout_filespec] ) end |
#document_name_in_glob_as_file_name(document_filename: @dml_link_state.document_filename, format_glob: , remove_regexp: %r{^\./}, subst_regexp: /[\/:\.\* ]/, subst_string: '_') ⇒ Object
remove leading “./” replace characters: / : . * (space) with: (underscore)
2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 |
# File 'lib/hash_delegator.rb', line 2056 def document_name_in_glob_as_file_name( document_filename: @dml_link_state.document_filename, format_glob: @delegate_object[:document_saved_lines_glob], remove_regexp: %r{^\./}, subst_regexp: /[\/:\.\* ]/, subst_string: '_' ) if document_filename.nil? || document_filename.empty? return document_filename end format( format_glob, { document_filename: document_filename.gsub(remove_regexp, '') .gsub(subst_regexp, subst_string) } ) end |
#dump_and_warn_block_state(name:, selected:) ⇒ Object
2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 |
# File 'lib/hash_delegator.rb', line 2075 def dump_and_warn_block_state(name:, selected:) if selected.nil? Exceptions.warn_format("Block not found -- name: #{name}", { abort: true }) end return unless @delegate_object[:dump_selected_block] warn selected.to_yaml.sub(/^(?:---\n)?/, "Block:\n") end |
#dump_delobj(blocks_in_file, menu_blocks, link_state) ⇒ Object
Outputs warnings based on the delegate object’s configuration
2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 |
# File 'lib/hash_delegator.rb', line 2094 def dump_delobj(blocks_in_file, , link_state) if @delegate_object[:dump_delegate_object] warn format_and_highlight_hash(@delegate_object, label: '@delegate_object') end if @delegate_object[:dump_blocks_in_file] warn format_and_highlight_dependencies( compact_and_index_hash(blocks_in_file), label: 'blocks_in_file' ) end if @delegate_object[:dump_menu_blocks] warn format_and_highlight_dependencies( compact_and_index_hash(), label: 'menu_blocks' ) end if @delegate_object[:dump_inherited_block_names] warn format_and_highlight_lines(link_state.inherited_block_names, label: 'inherited_block_names') end if @delegate_object[:dump_inherited_dependencies] warn format_and_highlight_lines(link_state.inherited_dependencies, label: 'inherited_dependencies') end return unless @delegate_object[:dump_inherited_lines] warn format_and_highlight_lines(link_state.inherited_lines, label: 'inherited_lines') end |
#edit_text(initial_text, temp_name: 'edit_text') ⇒ String?
Opens text in an editor for user modification and
returns the modified text.
This method reads the provided text, opens it in the default editor, and allows the user to modify it. If the user makes changes, the modified text is returned. If the user exits the editor without making changes or the editor is closed abruptly, appropriate messages are displayed.
2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 |
# File 'lib/hash_delegator.rb', line 2142 def edit_text(initial_text, temp_name: 'edit_text') # Create a temporary file to store the initial text temp_file = Tempfile.new(temp_name) temp_file.write(initial_text) temp_file.rewind # Capture the modification time of the temporary file before editing before_mtime = temp_file.mtime # Open the temporary file in the default editor system("#{EnvInterface.get('EDITOR', default: 'vi')} #{temp_file.path}") # Capture the exit status of the editor editor_exit_status = $?.exitstatus # Reopen the file to ensure the updated modification time is read temp_file.open after_mtime = temp_file.mtime # Check if the editor was exited normally or was interrupted if editor_exit_status != 0 warn 'The editor was closed abruptly. No changes were made.' temp_file.close temp_file.unlink return end result_text = nil # Read the file if it was modified if before_mtime != after_mtime temp_file.rewind result_text = temp_file.read end # Remove the temporary file temp_file.close temp_file.unlink result_text end |
#env_set(name, value) ⇒ Object
2183 2184 2185 |
# File 'lib/hash_delegator.rb', line 2183 def env_set(name, value) EnvInterface.set(name, value) end |
#execute_block_by_type_for_lfls(selected:, mdoc:, block_source:, link_state: LinkState.new) ⇒ Object
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.
2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 |
# File 'lib/hash_delegator.rb', line 2196 def execute_block_by_type_for_lfls( selected:, mdoc:, block_source:, link_state: LinkState.new ) # order should not be important other than else clause if selected.type == BlockType::TEXT && !selected.truncated_table_cell.nil? debounce_reset $table_cell_truncate = !$table_cell_truncate LoadFileLinkState.new(LoadFile::REUSE, link_state) elsif selected.type == BlockType::EDIT debounce_reset vux_edit_inherited return :break if pause_user_exit next_state_append_code(selected, link_state, []) elsif selected.type == BlockType::HISTORY debounce_reset return :break if execute_block_type_history_ux( selected: selected, link_state: link_state ) == :no_history LoadFileLinkState.new(LoadFile::REUSE, link_state) elsif selected.type == BlockType::LINK debounce_reset execute_block_type_link_with_state(link_block_body: selected.body, mdoc: mdoc, selected: selected, link_state: link_state, block_source: block_source) elsif selected.type == BlockType::LOAD debounce_reset load_result = execute_block_type_load_code_lines(selected) next_state_append_code(selected, link_state, load_result.code, mode: load_result.mode) elsif selected.type == BlockType::SAVE debounce_reset execute_block_type_save( code_lines: link_state&.inherited_lines, selected: selected ) LoadFileLinkState.new(LoadFile::REUSE, link_state) elsif selected.type == BlockType::VIEW debounce_reset vux_view_inherited(stream: $stderr) return :break if pause_user_exit LoadFileLinkState.new(LoadFile::REUSE, link_state) elsif debounce_reset LoadFileLinkState.new( LoadFile::LOAD, pop_link_history_new_state ) elsif selected.type == BlockType::OPTS debounce_reset code_lines = [] = ( link_state: link_state, mdoc: @dml_mdoc, selected: selected ) (.) link_state = LinkState.new next_state_append_code(selected, link_state, code_lines) elsif selected.type == BlockType::PORT debounce_reset required_lines = execute_block_type_port_code_lines( mdoc: @dml_mdoc, selected: selected, link_state: link_state, block_source: block_source ) next_state_set_code(selected, link_state, required_lines) elsif selected.type == BlockType::UX debounce_reset command_result_w_e_t_nl = code_from_ux_block_to_set_environment_variables( selected, @dml_mdoc, inherited_code: @dml_link_state.inherited_lines, only_default: false, silent: true ) ### TBD if command_result_w_e_t_nl.failure? next_state_append_code( selected, link_state, command_result_w_e_t_nl.failure? ? [] : command_result_w_e_t_nl.new_lines ) elsif selected.type == BlockType::VARS debounce_reset next_state_append_code( selected, link_state, code_from_vars_block_to_set_environment_variables(selected) ) elsif COLLAPSIBLE_TYPES.include?(selected.type) debounce_reset (selected) LoadFileLinkState.new(LoadFile::REUSE, link_state) elsif debounce_allows compile_execute_and_trigger_reuse(mdoc: mdoc, selected: selected, link_state: link_state, block_source: block_source) LoadFileLinkState.new(LoadFile::REUSE, link_state) else LoadFileLinkState.new(LoadFile::REUSE, link_state) end end |
#execute_block_for_state_and_name(selected:, mdoc:, link_state:, block_source: {}) ⇒ Object
2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 |
# File 'lib/hash_delegator.rb', line 2324 def execute_block_for_state_and_name( selected:, mdoc:, link_state:, block_source: {} ) lfls = execute_block_by_type_for_lfls( selected: selected, mdoc: mdoc, link_state: link_state, block_source: block_source ) # dname is not fixed for some block types, use block id if lfls.load_file != LoadFile::LOAD block_selection = BlockSelection.new(selected.id) end { link_state: lfls.link_state, block_selection: block_selection, quit: lfls.load_file == LoadFile::EXIT } end |
#execute_block_in_state(block_name) ⇒ Object
2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 |
# File 'lib/hash_delegator.rb', line 2344 def execute_block_in_state(block_name) @dml_block_state = find_block_state_by_name(block_name) dump_and_warn_block_state(name: block_name, selected: @dml_block_state.block) if @dml_block_state.block.fetch(:is_enabled_but_inactive, false) @dml_block_selection = BlockSelection.new(@dml_block_state.block.id) return # do nothing end next_block_state = execute_block_for_state_and_name( selected: @dml_block_state.block, mdoc: @dml_mdoc, link_state: @dml_link_state, block_source: { document_filename: @delegate_object[:filename], time_now_date: Time.now.utc.strftime( @delegate_object[:shell_code_label_time_format] ) } ) @dml_link_state = next_block_state[:link_state] @dml_block_selection = next_block_state[:block_selection] :break if next_block_state[:quit] end |
#execute_block_type_history_ux(directory: , filename: '*', form: '%{line}', link_state:, regexp: '^(?<line>.*)$', selected:) ⇒ Object
2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 |
# File 'lib/hash_delegator.rb', line 2371 def execute_block_type_history_ux( directory: @delegate_object[:document_configurations_directory], filename: '*', form: '%{line}', link_state:, regexp: '^(?<line>.*)$', selected: ) block_data = HashDelegator.parse_yaml_data_from_body(selected.body) files_table_rows = read_saved_assets_for_history_table( filename: filename, form: form, path: block_data['directory'] || directory, regexp: regexp ) return :no_history unless files_table_rows execute_history_select(files_table_rows, stream: $stderr) end |
#execute_block_type_link_with_state(link_block_body: [], mdoc: nil, selected: FCB.new, link_state: LinkState.new, block_source: {}) ⇒ LoadFileLinkState
Handles the processing of a link block in Markdown Execution. It loads YAML data from the link_block_body content,
pushes the state to history, sets environment variables,
and decides on the next block to load.
2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 |
# File 'lib/hash_delegator.rb', line 2402 def execute_block_type_link_with_state( link_block_body: [], mdoc: nil, selected: FCB.new, link_state: LinkState.new, block_source: {} ) link_block_data = HashDelegator.parse_yaml_data_from_body(link_block_body) ## collect blocks specified by block # if mdoc code_info = mdoc.collect_recursively_required_code( anyname: selected_id_name(selected), block_source: block_source, label_format_above: @delegate_object[:shell_code_label_format_above], label_format_below: @delegate_object[:shell_code_label_format_below] ) code_lines = annotate_required_lines( 'blk:LINK', code_info[:code], block_name: selected.id ) block_names = code_info[:block_names] dependencies = code_info[:dependencies] else block_names = [] code_lines = [] dependencies = {} end # load key and values from link block into current environment # if link_block_data[LinkKeys::VARS] code_lines << BashCommentFormatter.format_comment(selected.pub_name) link_block_data[LinkKeys::VARS].each do |key, value| code_lines << assign_key_value_in_bash(key, value) EnvInterface.set(key, value.to_s) end end ## append blocks loaded # if (load_expr = link_block_data.fetch(LinkKeys::LOAD, '')).present? load_filespec = load_filespec_from_expression(load_expr) if load_filespec begin code_lines += File.readlines(load_filespec, chomp: true) rescue Errno::ENOENT report_error($ERROR_INFO) end end end # if an eval link block, evaluate code_lines and return its standard output # 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, block_source: block_source, shell: @delegate_object[:block_type_default] ) end # config next state # next_document_filename = write_inherited_lines_to_file(link_state, link_block_data) next_block_name = link_block_data.fetch( LinkKeys::NEXT_BLOCK, nil ) || link_block_data.fetch(LinkKeys::BLOCK, nil) || '' code_lines = annotate_required_lines( 'blk:LINK', code_lines, block_name: selected.id ) if link_block_data[LinkKeys::RETURN] pop_add_current_code_to_head_and_trigger_load( link_state, block_names, code_lines, dependencies, selected, next_block_name: next_block_name ) else next_keep_code = link_state&.keep_code || link_block_data.fetch('keep', false) #/*LinkKeys::KEEP*/ link_history_push_and_next( curr_block_name: selected.pub_name, 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.flatten_and_compact_arrays( link_state&.inherited_lines, code_lines ), keep_code: link_state&.keep_code, next_block_name: next_block_name, next_document_filename: next_document_filename, next_keep_code: next_keep_code, next_load_file: if next_document_filename == @delegate_object[:filename] LoadFile::REUSE else LoadFile::LOAD end ) end end |
#execute_block_type_load_code_lines(selected, directory: , exit_prompt: , filename_pattern: , glob: , menu_options: HashDelegator.options_for_tty_menu(@delegate_object), view: ) ⇒ Object
2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 |
# File 'lib/hash_delegator.rb', line 2508 def execute_block_type_load_code_lines( selected, directory: @delegate_object[:document_configurations_directory], exit_prompt: @delegate_object[:prompt_filespec_back], filename_pattern: @delegate_object[:vars_block_filename_pattern], glob: @delegate_object[:document_configurations_glob], menu_options: HashDelegator.(@delegate_object), view: @delegate_object[:vars_block_filename_view] ) block_data = HashDelegator.parse_yaml_data_from_body(selected.body) dirs = Dir.glob( File.join( Dir.pwd, block_data['directory'] || directory, block_data['glob'] || glob ) ) dirs.sort_by! { |f| File.mtime(f) }.reverse! code = if !contains_glob?(block_data['directory']) && !contains_glob?(block_data['glob']) if dirs[0] File.readlines(dirs[0], chomp: true) else warn 'No matching file found.' end elsif (selected_option = ( prompt_title, [exit_prompt] + dirs.map do |file| # tty_menu_items { name: format( block_data['view'] || view, NamedCaptureExtractor.extract_named_group_match_data( file.match( Regexp.new( block_data['filename_pattern'] || filename_pattern ) ) ) ), oname: file } end, .merge( cycle: true, match_dml: false ) )) if selected_option.dname != exit_prompt File.readlines(selected_option.oname, chomp: true) end else warn 'No matching files found.' end if (mode = block_data['mode']&.to_sym) reason = 'specified Load mode' unless [LoadMode::APPEND, LoadMode::REPLACE].include? mode wwe 'Invalid mode', 'block_data:', block_data end else reason = 'default Load mode' mode = LoadMode::APPEND end wwt :state, '@dml_block_state:', @dml_block_state OpenStruct.new( code: annotate_required_lines('blk:LOAD', code, block_name: selected.id), mode: mode, reason: reason ) end |
#execute_block_type_port_code_lines(mdoc:, selected:, block_source:, link_state: LinkState.new) ⇒ Array<String>
Collects required code lines based on the selected block and
the delegate object's configuration.
If the block type is VARS, it also sets environment variables
based on the block's content.
2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 |
# File 'lib/hash_delegator.rb', line 2590 def execute_block_type_port_code_lines(mdoc:, selected:, block_source:, link_state: LinkState.new) required = mdoc.collect_recursively_required_code( anyname: selected_id_name(selected), label_format_above: @delegate_object[:shell_code_label_format_above], label_format_below: @delegate_object[:shell_code_label_format_below], block_source: block_source ) # !!t 'required' dependencies = ( link_state&.inherited_dependencies || {} ).merge(required[:dependencies] || {}) required[:unmet_dependencies] = ( required[:unmet_dependencies] || [] ) - (link_state&.inherited_block_names || []) if required[:unmet_dependencies].present? ### filter against link_state.inherited_block_names warn format_and_highlight_dependencies( dependencies, highlight: required[:unmet_dependencies] ) runtime_exception( :runtime_exception_error_level, 'unmet_dependencies, flag: runtime_exception_error_level', required[:unmet_dependencies] ) elsif @delegate_object[:dump_dependencies] warn format_and_highlight_dependencies( dependencies, highlight: [@delegate_object[:block_name]] ) end if selected[:type] == BlockType::OPTS # body of blocks is returned as a list of lines to be read an YAML HashDelegator.flatten_and_compact_arrays( required[:blocks].map(&:body).flatten(1) ) else # code from the selected VARS block vars_code = if selected.type == BlockType::VARS code_from_vars_block_to_set_environment_variables(selected) else [] end # activate UX blocks in the required list command_result_w_e_t_nl = code_from_ux_block_to_set_environment_variables( selected, @dml_mdoc, inherited_code: vars_code, only_default: false, required: required, silent: false ) ux_code = command_result_w_e_t_nl.failure? ? [] : command_result_w_e_t_nl.new_lines HashDelegator.flatten_and_compact_arrays( link_state&.inherited_lines, annotate_required_lines( 'blk:PORT', required[:code] + vars_code + ux_code, block_name: selected.id ) ) end rescue StandardError wwe(required[:code], ux_code, { error: $!, callback: $@[0] }) end |
#execute_block_type_save(code_lines:, selected:) ⇒ Object
2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 |
# File 'lib/hash_delegator.rb', line 2660 def execute_block_type_save(code_lines:, selected:) block_data = HashDelegator.parse_yaml_data_from_body(selected.body) directory_glob = if block_data['directory'] File.join( block_data['directory'], block_data['glob'] || @delegate_object[:document_saved_lines_glob].split('/').last ) else @delegate_object[:document_saved_lines_glob] end save_filespec_from_expression(directory_glob).tap do |save_filespec| if save_filespec && save_filespec != exit_prompt begin if @delegate_object[:document_save_make_directory] # make directory if it doesn't exist FileUtils.mkdir_p(File.dirname(save_filespec)) end File.write(save_filespec, HashDelegator.join_code_lines(code_lines)) rescue Errno::ENOENT report_error($ERROR_INFO) end end end end |
#execute_command_with_streams(command) {|stdin, stdout, stderr, thread| ... } ⇒ Integer
Executes a given command and processes its
input, output, and error streams.
2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 |
# File 'lib/hash_delegator.rb', line 2705 def execute_command_with_streams(command) exit_status = nil Open3.popen3(*command) do |stdin, stdout, stderr, exec_thread| # Handle stdout stream handle_stream(stream: stdout, file_type: ExecutionStreams::STD_OUT) do |line| yield nil, line, nil, exec_thread if block_given? end # Handle stderr stream handle_stream(stream: stderr, file_type: ExecutionStreams::STD_ERR) do |line| yield nil, nil, line, exec_thread if block_given? end # Handle stdin stream input_thread = handle_stream( stream: $stdin, file_type: ExecutionStreams::STD_IN ) do |line| stdin.puts(line) yield line, nil, nil, exec_thread if block_given? end # Wait for all streams to be processed wait_for_stream_processing exec_thread.join # Ensure the input thread is killed if it's still alive sleep 0.1 input_thread.kill if input_thread&.alive? # Retrieve the exit status exit_status = exec_thread.value.exitstatus end exit_status end |
#execute_history_select(files_table_rows, exit_prompt: , pause_refresh: false, stream:) ⇒ Object
2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 |
# File 'lib/hash_delegator.rb', line 2745 def execute_history_select( files_table_rows, exit_prompt: @delegate_object[:prompt_filespec_back], pause_refresh: false, stream: ) # repeat select+display until user exits ( files_table_rows, display_formats: i[row file], display_mode_option: @delegate_object[:prompt_filespec_facet], exit_option: exit_prompt, menu_title: @delegate_object[:prompt_select_history_file], pause_after_selection: pause_refresh ) do |file| info = file_info(file.file) stream.puts "#{file.file} - #{info[:lines]} lines / " \ "#{info[:size]} bytes" stream.puts( File.readlines(file.file, chomp: false).map.with_index do |line, ind| format(' %s. %s', AnsiString.new(format('% 4d', ind + 1)).send(:violet), line) end ) end end |
#execute_inherited_save(code_lines: @dml_link_state.inherited_lines) ⇒ Object
2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 |
# File 'lib/hash_delegator.rb', line 2775 def execute_inherited_save( code_lines: @dml_link_state.inherited_lines ) return unless (save_filespec = save_filespec_from_expression( document_name_in_glob_as_file_name )) unless write_file_with_directory_creation( content: HashDelegator.join_code_lines(code_lines), filespec: save_filespec ) :break end end |
#execute_navigate_back ⇒ Object
2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 |
# File 'lib/hash_delegator.rb', line 2790 def execute_navigate_back = true keep_code = @dml_link_state.keep_code inherited_lines = keep_code ? @dml_link_state.inherited_lines_block : nil @dml_link_state = pop_link_history_new_state { block_name: @dml_link_state.block_name, document_filename: @dml_link_state.document_filename, inherited_lines: inherited_lines, keep_code: keep_code } end |
#execute_required_lines(blockname: '', erls: {}, required_lines: [], shell:) ⇒ Object
Executes a block of code that has been approved for execution. It sets the script block name, writes command files if
required,
and handles the execution
including output formatting and summarization.
2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 |
# File 'lib/hash_delegator.rb', line 2814 def execute_required_lines( blockname: '', erls: {}, required_lines: [], shell: ) if @delegate_object[:save_executed_script] write_command_file(blockname: blockname, required_lines: required_lines, shell: selected_shell(shell)) end if @dml_block_state calc_logged_stdout_filename(block_name: @dml_block_state.block.oname) end format_and_execute_command( code_lines: required_lines, erls: erls, shell: selected_shell(shell) ) post_execution_process end |
#expand_blocks_with_replacements(menu_blocks, replacements, exclude_types: [BlockType::SHELL]) ⇒ Object
2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 |
# File 'lib/hash_delegator.rb', line 2836 def ( , replacements, exclude_types: [BlockType::SHELL] ) # update blocks # Regexp.union(replacements.keys.map do |word| # match multiline text from variable expansion Regexp.new(Regexp.escape(word), Regexp::MULTILINE) end).tap do |pattern| .each do |block| next if exclude_types.include?(block.type) block.(pattern, replacements) end end end |
#expand_references!(fcb, link_state) ⇒ Object
2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 |
# File 'lib/hash_delegator.rb', line 2853 def (fcb, link_state) wwt :expand_references, 'fcb.id', fcb.id, 'link_state:', link_state # options expansions ( blocks: [fcb], echo_formatter: method(:format_echo_command), group_name: :payload, initial_code_required: false, link_state: link_state, pattern: @delegate_object[:option_expansion_expression_regexp].present? && Regexp.new(@delegate_object[:option_expansion_expression_regexp]) ) # variable expansions ( blocks: [fcb], echo_formatter: lambda do |variable| %(echo "$#{variable}") end, group_name: @delegate_object[:variable_expansion_name_capture_group]&.to_sym, initial_code_required: false, link_state: link_state, pattern: ) # command substitutions ( blocks: [fcb], echo_formatter: lambda { |command| command }, group_name: @delegate_object[:command_substitution_name_capture_group]&.to_sym, initial_code_required: false, link_state: link_state, pattern: ) # no return rescue StandardError wwe 'fcb:', fcb, 'link_state:', link_state end |
#expand_variable_references!(blocks:, echo_formatter:, group_name:, initial_code_required: false, link_state:, pattern:) ⇒ Object
2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 |
# File 'lib/hash_delegator.rb', line 2895 def ( blocks:, echo_formatter:, group_name:, initial_code_required: false, link_state:, pattern: ) variable_counts, occurrence_expressions = count_named_group_occurrences( blocks, pattern, group_name: group_name ) return if variable_counts.nil? || variable_counts == {} echo_commands = generate_echo_commands( variable_counts, formatter: echo_formatter ) replacements = build_replacement_dictionary( echo_commands, link_state, initial_code_required: initial_code_required, occurrence_expressions: occurrence_expressions ) return if replacements.nil? if replacements == EvaluateShellExpression::StatusFail # happens on first processing of blocks before requirements are met return end (blocks, replacements) # no return end |
#fetch_color(default: '', data_sym: :execution_report_preview_head, color_sym: :execution_report_preview_frame_color) ⇒ String
Retrieves a specific data symbol from the delegate object, converts it to a string, and applies a color style based on the specified color symbol.
3023 3024 3025 3026 3027 3028 |
# File 'lib/hash_delegator.rb', line 3023 def fetch_color(default: '', data_sym: :execution_report_preview_head, color_sym: :execution_report_preview_frame_color) data_string = @delegate_object.fetch(data_sym, default).to_s string_send_color(data_string, color_sym) end |
#file_info(file_path) ⇒ Object
size of a file in bytes and the number of lines
3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 |
# File 'lib/hash_delegator.rb', line 3031 def file_info(file_path) file_size = 0 line_count = 0 File.open(file_path, 'r') do |file| file.each_line do |_line| line_count += 1 end file_size = file.size end { size: file_size, lines: line_count } end |
#find_block_by_name(blocks, block_name) ⇒ Object
Search in @dml_blocks_in_file first, fallback to @dml_menu_blocks if not found.
3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 |
# File 'lib/hash_delegator.rb', line 3047 def find_block_by_name(blocks, block_name) match_block = ->(item) do [ selected_id_name(item), item.pub_name, item.nickname, item.oname, item.s2title ].include?(block_name) end @dml_blocks_in_file.find(&match_block) || .find(&match_block) end |
#find_block_state_by_name(block_name) ⇒ Object
find a block by its original (undecorated) name or nickname (not visible in menu) if matched, the block returned has properties that it is from cli and not ui
3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 |
# File 'lib/hash_delegator.rb', line 3064 def find_block_state_by_name(block_name) SelectedBlockMenuState.new( find_block_by_name(@dml_blocks_in_file, block_name), OpenStruct.new( block_name_from_cli: true, block_name_from_ui: false ), MenuState::CONTINUE ) end |
#find_option_by_name(name) ⇒ Object
3075 3076 3077 3078 3079 3080 |
# File 'lib/hash_delegator.rb', line 3075 def find_option_by_name(name) name_sym = name.to_sym .find do |option| option[:opt_name] == name_sym end end |
#format_and_execute_command(code_lines:, erls:, shell:) ⇒ Object
3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 |
# File 'lib/hash_delegator.rb', line 3082 def format_and_execute_command( code_lines:, erls:, shell: ) formatted_command = code_lines.flatten.join("\n") @fout.fout fetch_color(data_sym: :script_execution_head, color_sym: :script_execution_frame_color) command_execute( formatted_command, args: @pass_args, erls: erls, shell: selected_shell(shell) ) @fout.fout fetch_color(data_sym: :script_execution_tail, color_sym: :script_execution_frame_color) end |
#format_echo_command(payload) ⇒ Object
3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 |
# File 'lib/hash_delegator.rb', line 3101 def format_echo_command(payload) payload_match = payload.match( @delegate_object[:option_expansion_payload_regexp] ) variable = payload_match[:option] property = payload_match[:property] echo_value = case property when 'default', 'description' item = find_option_by_name(variable) item ? item[property.to_sym] : '' when 'length' @delegate_object[variable.to_sym].to_s.length else @delegate_object[variable.to_sym] end "echo #{Shellwords.escape(echo_value)}" end |
#format_expression(expr) ⇒ Object
Format expression using environment variables and run state
3122 3123 3124 3125 3126 |
# File 'lib/hash_delegator.rb', line 3122 def format_expression(expr) data = link_load_format_data EnvInterface.each { |key, value| data[key.to_sym] = value } format(expr, data) end |
#format_references_send_color(color_sym: :execution_report_preview_frame_color, context: {}, default: '', format_sym: :output_execution_label_format) ⇒ String
Formats a string based on a given context and
applies color styling to it.
It retrieves format and color information from
the delegate object and processes accordingly.
3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 |
# File 'lib/hash_delegator.rb', line 3141 def format_references_send_color( color_sym: :execution_report_preview_frame_color, context: {}, default: '', format_sym: :output_execution_label_format ) formatted_string = format(@delegate_object.fetch(format_sym, ''), context).to_s string_send_color(formatted_string, color_sym) end |
#formatted_block_name(block_name, format_sym = :publish_block_name_format) ⇒ Object
for inherited code comments for external automation
3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 |
# File 'lib/hash_delegator.rb', line 3154 def formatted_block_name(block_name, format_sym = :publish_block_name_format) format( @delegate_object[format_sym], { block: block_name, document: @delegate_object[:filename], time: Time.now.utc.strftime( @delegate_object[:publish_time_format] ) } ) end |
#formatted_expression(expr) ⇒ Object
Expand expression if it contains format specifiers
3167 3168 3169 |
# File 'lib/hash_delegator.rb', line 3167 def formatted_expression(expr) expr.include?('%{') ? format_expression(expr) : expr end |
#fout_execution_report ⇒ Object
3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 |
# File 'lib/hash_delegator.rb', line 3171 def fout_execution_report @fout.fout fetch_color(data_sym: :execution_report_preview_head, color_sym: :execution_report_preview_frame_color) [ ['Block', @run_state.script_block_name], ['Command', ([MarkdownExec::BIN_NAME, @delegate_object[:filename]] + (@run_state.link_history.map { |item| item[:block_name] }) + [@run_state.script_block_name]).join(' ')], ['Script', @run_state.saved_filespec], ['StdOut', @delegate_object[:logged_stdout_filespec]] ].each do |label, value| next unless value output_labeled_value(label, value, DISPLAY_LEVEL_ADMIN) end @fout.fout fetch_color(data_sym: :execution_report_preview_tail, color_sym: :execution_report_preview_frame_color) end |
#generate_echo_commands(variable_counts, formatter: nil) ⇒ Object
3192 3193 3194 3195 3196 3197 3198 3199 3200 |
# File 'lib/hash_delegator.rb', line 3192 def generate_echo_commands(variable_counts, formatter: nil) # commands to echo variables # commands = {} variable_counts.each_key do |variable| commands[variable] = formatter.call(variable) end commands end |
#generate_temp_filename(ext = '.sh') ⇒ Object
3202 3203 3204 3205 3206 3207 3208 3209 3210 |
# File 'lib/hash_delegator.rb', line 3202 def generate_temp_filename(ext = '.sh') filename = begin Dir::Tmpname.make_tmpname(['x', ext], nil) rescue NoMethodError require 'securerandom' "#{SecureRandom.urlsafe_base64}#{ext}" end File.join(Dir.tmpdir, filename) end |
#handle_back_or_continue(block_state) ⇒ Object
Updates the delegate object’s state based on the provided block state. It sets the block name and determines
if the user clicked the back link in the .
3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 |
# File 'lib/hash_delegator.rb', line 3218 def handle_back_or_continue(block_state) return if block_state.nil? unless [MenuState::BACK, MenuState::CONTINUE].include?(block_state.state) return end @delegate_object[:block_name] = block_state.block.pub_name = block_state.state == MenuState::BACK end |
#handle_consecutive_inactive_items!(menu_blocks) ⇒ Object
enable scroll targets in long sequences of inactive lines
3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 |
# File 'lib/hash_delegator.rb', line 3776 def handle_consecutive_inactive_items!() consecutive_inactive_count = 0 .each do |fcb| unless fcb.is_disabled? consecutive_inactive_count = 0 else consecutive_inactive_count += 1 if (consecutive_inactive_count % (@delegate_object[:select_page_height] / @delegate_object[:select_page_ratio]) ).zero? fcb.disabled = TtyMenu::ENABLE fcb.is_enabled_but_inactive = true end end end end |
#handle_selection(menu_entries, selection, current_display_format) {|selected_item| ... } ⇒ Object
3331 3332 3333 3334 3335 3336 |
# File 'lib/hash_delegator.rb', line 3331 def handle_selection(, selection, current_display_format) selected_item = .find do |entry| entry.send(current_display_format) == selection end yield selected_item if selected_item end |
#handle_stream(stream:, file_type:, swap: false) ⇒ Object
3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 |
# File 'lib/hash_delegator.rb', line 3229 def handle_stream(stream:, file_type:, swap: false) @process_mutex.synchronize do Thread.new do stream.each_line do |line| if @run_state.files.streams @run_state.files.append_stream_line(file_type, line) end puts line if @delegate_object[:output_stdout] yield line if block_given? end rescue IOError # Handle IOError ensure @process_cv.signal end end end |
#history_files(direction: :reverse, filename: nil, home: Dir.pwd, order: :chronological, path: '') ⇒ Object
3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 |
# File 'lib/hash_delegator.rb', line 3249 def history_files( direction: :reverse, filename: nil, home: Dir.pwd, order: :chronological, path: '' ) files = Dir.glob( File.join(home, path, filename) ) sorted_files = case order when :alphabetical files.sort when :chronological files.sort_by { |file| File.mtime(file) } else raise ArgumentError, "Invalid order: #{order}" end direction == :reverse ? sorted_files.reverse : sorted_files end |
#initial_state ⇒ Object
Initializes variables for regex and other states
3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 |
# File 'lib/hash_delegator.rb', line 3272 def initial_state { fenced_start_and_end_regex: Regexp.new(@delegate_object.fetch( :fenced_start_and_end_regex, '^(?<indent> *)`{3,}' )), fenced_start_extended_regex: Regexp.new(@delegate_object.fetch( :fenced_start_and_end_regex, '^(?<indent> *)`{3,}' )), fcb: persist_fcb(id: 'INIT'), in_fenced_block: false, headings: [] } end |
#interactive_menu_with_display_modes(menu_entries, display_formats:, display_mode_option:, exit_option:, menu_title:, pause_after_selection:) ⇒ Object
3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 |
# File 'lib/hash_delegator.rb', line 3288 def ( , display_formats:, display_mode_option:, exit_option:, menu_title:, pause_after_selection: ) = false current_display_format = display_formats.first loop do break if && (prompt_select_continue == MenuState::EXIT) = ( exit_option, display_mode_option, , current_display_format ) selection = prompt_select_from_list( , string: , color_sym: :prompt_color_after_script_execution ) case selection when exit_option break when display_mode_option current_display_format = next_item( display_formats, current_display_format ) = false else handle_selection(, selection, current_display_format) do |item| yield item if block_given? end = pause_after_selection end end end |
#iter_blocks_from_nested_files {|Symbol| ... } ⇒ Object
Iterates through blocks in a file, applying the provided block to each line. The iteration only occurs if the file exists.
3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 |
# File 'lib/hash_delegator.rb', line 3341 def iter_blocks_from_nested_files(&block) return unless check_file_existence(@delegate_object[:filename]) state = initial_state selected_types = yield :filter index = 0 cfile.readlines( @delegate_object[:filename], import_paths: ) do |nested_line| next if nested_line.nil? wwt :iterlines, 'nested_line:', nested_line update_line_and_block_state( nested_line, state, selected_types, source_id: "ItrBlkFrmNstFls:#{index}¤#{nested_line.filename}:#{nested_line.index}", &block ) index += 1 end rescue StandardError wwe $!, 'state:', state, 'nested_line:', nested_line end |
#iter_source_blocks(source, source_id: nil, &block) ⇒ Object
3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 |
# File 'lib/hash_delegator.rb', line 3366 def iter_source_blocks(source, source_id: nil, &block) case source when 1 blocks_from_nested_files(source_id: source_id).blocks.each(&block) when 2 @dml_blocks_in_file.each(&block) when 3 .each(&block) else iter_blocks_from_nested_files do |btype, fcb| case btype when :blocks then yield fcb when :filter then i[blocks] end end end end |
#join_array_of_arrays(*args) ⇒ Object
join a list of arrays into a single array convert single items to arrays
3386 3387 3388 3389 3390 3391 3392 3393 3394 |
# File 'lib/hash_delegator.rb', line 3386 def join_array_of_arrays(*args) args.map do |item| if item.nil? nil else (item.is_a?(Array) ? item : [item]) end end.compact.flatten(1) end |
#link_block_data_eval(link_state, code_lines, selected, link_block_data, block_source:, shell:) ⇒ Object
3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 |
# File 'lib/hash_delegator.rb', line 3396 def link_block_data_eval(link_state, code_lines, selected, link_block_data, block_source:, shell:) all_code = HashDelegator.flatten_and_compact_arrays( link_state&.inherited_lines, code_lines ) output_lines = [] Tempfile.open do |file| file.write(all_code.join("\n")) file.rewind if link_block_data.fetch(LinkKeys::EXEC, false) # exec: true @run_state.files = StreamsOut.new execute_command_with_streams( ["#{shell} #{file.path}"] ) do |_stdin, stdout, stderr, _thread| line = stdout || stderr output_lines.push(line) if line end if link_block_data.fetch(LinkKeys::EVAL, true) # eval: true ## select output_lines that look like assignment or match other specs # output_lines = process_string_array( output_lines, begin_pattern: @delegate_object.fetch(:output_assignment_begin, nil), end_pattern: @delegate_object.fetch(:output_assignment_end, nil), scan1: @delegate_object.fetch(:output_assignment_match, nil), format1: @delegate_object.fetch(:output_assignment_format, nil), name: '' ) else # eval: false ## select all output_lines # output_lines = process_string_array( output_lines, begin_pattern: @delegate_object.fetch(:output_assignment_begin, nil), end_pattern: @delegate_object.fetch(:output_assignment_end, nil), name: '' ) end else output_lines = `bash #{file.path}`.split("\n") end end unless output_lines HashDelegator.error_handler('all_code eval output_lines is nil', { abort: true }) end label_format_above = @delegate_object[:shell_code_label_format_above] label_format_below = @delegate_object[:shell_code_label_format_below] ([ if label_format_above.present? format( label_format_above, block_source.merge({ block_name: selected.pub_name }) ) else nil end ] + output_lines.map do |line| re = Regexp.new(link_block_data.fetch('pattern', '(?<line>.*)')) next unless re =~ line re.gsub_format( line, link_block_data.fetch('format', '%{line}') ) end + [ if label_format_below.present? format( label_format_below, block_source.merge({ block_name: selected.pub_name }) ) else nil end ]).compact end |
#link_history_push_and_next(curr_block_name:, curr_document_filename:, inherited_block_names:, inherited_dependencies:, inherited_lines:, keep_code:, next_block_name:, next_document_filename:, next_keep_code:, next_load_file:) ⇒ Object
3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 |
# File 'lib/hash_delegator.rb', line 3490 def link_history_push_and_next( curr_block_name:, curr_document_filename:, inherited_block_names:, inherited_dependencies:, inherited_lines:, keep_code:, next_block_name:, next_document_filename:, next_keep_code:, next_load_file: ) @link_history.push( LinkState.new( block_name: curr_block_name, document_filename: curr_document_filename, inherited_block_names: inherited_block_names, inherited_dependencies: inherited_dependencies, inherited_lines: inherited_lines, keep_code: keep_code ) ) LoadFileLinkState.new( next_load_file, LinkState.new( block_name: next_block_name, document_filename: next_document_filename, inherited_block_names: inherited_block_names, inherited_dependencies: inherited_dependencies, inherited_lines: inherited_lines, keep_code: next_keep_code ) ) end |
#link_load_format_data ⇒ Object
3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 |
# File 'lib/hash_delegator.rb', line 3521 def link_load_format_data { batch_index: @run_state.batch_index, batch_random: @run_state.batch_random, block_name: @delegate_object[:block_name], document_filename: File.basename(@delegate_object[:filename]), document_filespec: @delegate_object[:filename], home: Dir.pwd, started_at: Time.now.utc.strftime( @delegate_object[:execute_command_title_time_format] ) } end |
#list_blocks(source_id: nil) ⇒ Object
3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 |
# File 'lib/hash_delegator.rb', line 3535 def list_blocks(source_id: nil) = @delegate_object[:list_blocks_message] block_eval = @delegate_object[:list_blocks_eval] list = [] iter_source_blocks( @delegate_object[:list_blocks_type], source_id: source_id ) do |block| list << (block_eval.present? ? eval(block_eval) : block.send()) end list.compact! @fout.fout_list(list) end |
#load_auto_opts_block(all_blocks, mdoc:) ⇒ Boolean?
Loads and updates auto options for document blocks if the current filename has changed.
This method checks if the delegate object specifies a document load options block name and if the filename has been updated. It then selects the appropriate blocks, collects their dependencies, processes their options, and updates the menu base with the merged options.
3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 |
# File 'lib/hash_delegator.rb', line 3561 def load_auto_opts_block(all_blocks, mdoc:) opts_block_name = @delegate_object[:document_load_opts_block_name] current_filename = @delegate_object[:filename] return unless opts_block_name.present? && @opts_most_recent_filename != current_filename selected_blocks = HashDelegator.block_select(all_blocks, :oname, opts_block_name) return if selected_blocks.empty? dependency_map = selected_blocks.to_h do |block| [block.id, block.reqs] end selected_blocks.each do |block| mdoc.collect_dependencies(memo: dependency_map, block: block) end = dependency_map.each.with_object({}) do |(block_id, _), | matching_block = HashDelegator.block_find(all_blocks, :id, block_id) = ( mdoc: mdoc, selected: matching_block ) .merge!(.) end () @opts_most_recent_filename = current_filename true end |
#load_cli_or_user_selected_block(all_blocks: [], menu_blocks: [], prior_answer: nil) ⇒ Object
3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 |
# File 'lib/hash_delegator.rb', line 3594 def load_cli_or_user_selected_block(all_blocks: [], menu_blocks: [], prior_answer: nil) if @delegate_object[:block_name].present? block = all_blocks.find do |item| item.pub_name == @delegate_object[:block_name] end source = OpenStruct.new(block_name_from_ui: false) else block_state = wait_for_user_selected_block(all_blocks, , prior_answer) return if block_state.nil? block = block_state.block source = OpenStruct.new(block_name_from_ui: true) state = block_state.state end SelectedBlockMenuState.new(block, source, state) end |
#load_filespec_from_expression(expression) ⇒ Object
format + glob + select for file in load block name has references to ENV vars and doc and batch vars
incl.
3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 |
# File 'lib/hash_delegator.rb', line 3617 def load_filespec_from_expression(expression) # Process expression with embedded formatting = formatted_expression(expression) # Handle wildcards or direct file specification if contains_glob?() load_filespec_wildcard_expansion() else end end |
#load_filespec_wildcard_expansion(expr, auto_load_single: false) ⇒ Object
Handle expression with wildcard characters
3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 |
# File 'lib/hash_delegator.rb', line 3630 def load_filespec_wildcard_expansion(expr, auto_load_single: false) files = find_files(expr) if files.count.zero? HashDelegator.error_handler("no files found with '#{expr}' ", { abort: true }) elsif auto_load_single && files.count == 1 files.first else ## user selects from existing files or other # case (name = prompt_select_from_list( [@delegate_object[:prompt_filespec_back]] + files, string: @delegate_object[:prompt_select_code_file], color_sym: :prompt_color_after_script_execution )) when @delegate_object[:prompt_filespec_back] # do nothing else name end end end |
#manage_cli_selection_state(block_name_from_cli:, now_using_cli:, link_state:) ⇒ Object
3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 |
# File 'lib/hash_delegator.rb', line 3653 def manage_cli_selection_state(block_name_from_cli:, now_using_cli:, link_state:) if block_name_from_cli && @cli_block_name == [:menu_persist_block_name] block_name_from_cli = false now_using_cli = false [:block_name] = @delegate_object[:block_name] = \ link_state.block_name = @cli_block_name = nil end @delegate_object = .dup = false [block_name_from_cli, now_using_cli] end |
#mdoc_and_blocks_from_nested_files(source_id: nil, link_state: nil) ⇒ Object
3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 |
# File 'lib/hash_delegator.rb', line 3670 def mdoc_and_blocks_from_nested_files(source_id: nil, link_state: nil) blocks_results = blocks_from_nested_files( link_state: link_state, source_id: source_id ) blocks_results.results.select do |_id, result| result.failure? end.each do |id, result| HashDelegator.error_handler("#{id} - #{result.to_yaml}") end mdoc = MDoc.new(blocks_results.blocks) do |nopts| @delegate_object.merge!(nopts) end [blocks_results.blocks, mdoc] end |
#mdoc_menu_and_blocks_from_nested_files(link_state, source_id: '') ⇒ Object
Handles the file loading and returns the blocks
in the file and MDoc instance
3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 |
# File 'lib/hash_delegator.rb', line 3692 def (link_state, source_id: '') # read blocks, load document opts block, and re-process blocks # reload_blocks = false all_blocks, mdoc = mdoc_and_blocks_from_nested_files( link_state: link_state, source_id: source_id ) if load_auto_opts_block(all_blocks, mdoc: mdoc) reload_blocks = true end # return code resulting from evaluating all SHELL, UX, VARS blocks; # each set in sequence; with its own order # if (code_lines = code_from_auto_blocks( all_blocks, default_only: true, mdoc: mdoc ))&.select_by(:empty?, false)&.compact&.count&.positive? new_code = code_lines wwt :code_lines, 'code_lines:', code_lines next_state_set_code(nil, link_state, new_code) link_state.inherited_lines = new_code reload_blocks = true else link_state&.inherited_lines end if reload_blocks all_blocks, mdoc = mdoc_and_blocks_from_nested_files( link_state: link_state, source_id: source_id ) end # filter by name, collapsed # = mdoc.( @delegate_object.merge!(compressed_ids: @compressed_ids, expanded_ids: ) ) # restore pre-expansion (raw) values # .each do |fcb| fcb.dname = fcb.raw_dname unless fcb.raw_dname.nil? fcb.s0printable = fcb.raw_s0printable unless fcb.raw_s0printable.nil? fcb.s1decorated = fcb.raw_s1decorated unless fcb.raw_s1decorated.nil? fcb.body = fcb.raw_body unless fcb.raw_body.nil? end # re-expand blocks # .each do |fcb| fcb.body = fcb.raw_body || fcb.body || [] fcb.(fcb.raw_dname || fcb.dname) fcb.s0printable = fcb.raw_s0printable || fcb.s0printable fcb.s1decorated = fcb.raw_s1decorated || fcb.s1decorated (fcb, link_state) end # chrome for menu # ( link_state: link_state, menu_blocks: , source_id: source_id ) HashDelegator.delete_consecutive_blank_lines!() begin HashDelegator.tables_into_columns!(, @delegate_object, screen_width_for_table) rescue NoMethodError # an invalid table format end handle_consecutive_inactive_items!() [all_blocks, , mdoc] end |
#menu_add_disabled_option(document_glob, id) ⇒ Object
3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 |
# File 'lib/hash_delegator.rb', line 3794 def (document_glob, id) raise unless document_glob.present? raise if .nil? block = .find { |item| item.oname == document_glob } # create menu item when it is needed (count > 0) # return unless block.nil? dname = HashDelegator.new(@delegate_object).string_send_color( document_glob, :menu_inherited_lines_color ) chrome_block = persist_fcb( chrome: true, disabled: TtyMenu::DISABLE, dname: dname, # 2025-01-03 menu item is disabled ∴ does not need a recall id id: id, oname: formatted_name ) if insert_at_top .unshift(chrome_block) else .push(chrome_block) end end |
#menu_chrome_colored_option(option_symbol = :menu_option_back_name) ⇒ String
Formats and optionally colors a menu option based on delegate
object's configuration.
3830 3831 3832 3833 3834 3835 |
# File 'lib/hash_delegator.rb', line 3830 def (option_symbol = :menu_option_back_name) formatted_option = (option_symbol) return formatted_option unless @delegate_object[:menu_chrome_color] string_send_color(formatted_option, :menu_chrome_color) end |
#menu_chrome_formatted_option(option_symbol = :menu_option_back_name) ⇒ String
Formats a menu option based on the delegate object’s configuration. It safely evaluates the value of the option and optionally formats it.
3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 |
# File 'lib/hash_delegator.rb', line 3842 def (option_symbol = :menu_option_back_name) option_value = HashDelegator.safeval(@delegate_object.fetch( option_symbol, '' )) if @delegate_object[:menu_chrome_format] format(@delegate_object[:menu_chrome_format], option_value) else option_value end end |
#menu_from_list_with_back(list) ⇒ Object
3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 |
# File 'lib/hash_delegator.rb', line 3854 def (list) case (name = prompt_select_from_list( [@delegate_object[:prompt_filespec_back]] + list, string: @delegate_object[:prompt_select_code_file], color_sym: :prompt_color_after_script_execution )) when @delegate_object[:prompt_filespec_back] SelectResponse::BACK else name end end |
#menu_toggle_collapsible_block(selected) ⇒ Object
3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 |
# File 'lib/hash_delegator.rb', line 3867 def (selected) # return true if @compress_ids.key?(fcb.id) && !!@compress_ids[fcb.id] # return false if @expand_ids.key?(fcb.id) && !!@expand_ids[fcb.id] if @compressed_ids.key?(selected.id) && !!@compressed_ids[selected.id] @compressed_ids.delete(selected.id) [selected.id] = selected.level else # @expand_ids.key?(fcb.id) && !!@expand_ids[fcb.id] @compressed_ids[selected.id] = selected.level .delete(selected.id) end end |
#next_item(list, current_item) ⇒ Object
3891 3892 3893 3894 3895 3896 |
# File 'lib/hash_delegator.rb', line 3891 def next_item(list, current_item) index = list.index(current_item) return nil unless index # Return nil if the item is not in the list list[(index + 1) % list.size] # Get the next item, wrap around if at the end end |
#next_state_append_code(selected, link_state, code_lines, mode: LoadMode::APPEND) ⇒ Object
3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 |
# File 'lib/hash_delegator.rb', line 3898 def next_state_append_code(selected, link_state, code_lines, mode: LoadMode::APPEND) next_state_set_code( selected, link_state, HashDelegator.flatten_and_compact_arrays( mode == LoadMode::APPEND ? link_state&.inherited_lines : [], code_lines.is_a?(Array) ? code_lines : [] # no code for :ux_exec_prohibited ) ) end |
#next_state_set_code(selected, link_state, code_lines) ⇒ Object
3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 |
# File 'lib/hash_delegator.rb', line 3910 def next_state_set_code(selected, link_state, code_lines) block_names = [] dependencies = {} link_history_push_and_next( curr_block_name: selected&.pub_name, 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.flatten_and_compact_arrays(code_lines), keep_code: link_state&.keep_code, next_block_name: '', next_document_filename: @delegate_object[:filename], next_keep_code: false, next_load_file: LoadFile::REUSE ) end |
#options_command_substitution_regexp ⇒ Object
3929 3930 3931 |
# File 'lib/hash_delegator.rb', line 3929 def Regexp.new(@delegate_object[:command_substitution_regexp] || '') end |
#options_import_paths ⇒ Object
3933 3934 3935 |
# File 'lib/hash_delegator.rb', line 3933 def @delegate_object[:import_paths]&.split(':') || '' end |
#options_variable_expansion_regexp ⇒ Object
3937 3938 3939 3940 |
# File 'lib/hash_delegator.rb', line 3937 def @delegate_object[:variable_expansion_regexp].present? && Regexp.new(@delegate_object[:variable_expansion_regexp]) end |
#output_color_formatted(data_sym, color_sym) ⇒ Object
3942 3943 3944 3945 3946 |
# File 'lib/hash_delegator.rb', line 3942 def output_color_formatted(data_sym, color_sym) formatted_string = string_send_color(@delegate_object[data_sym], color_sym) @fout.fout formatted_string end |
#output_execution_summary ⇒ Object
3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 |
# File 'lib/hash_delegator.rb', line 3948 def output_execution_summary return unless @delegate_object[:output_execution_summary] @fout.fout_section 'summary', { execute_aborted_at: @run_state.aborted_at, execute_completed_at: @run_state.completed_at, execute_error: @run_state.error, execute_error_message: @run_state., execute_options: @run_state., execute_started_at: @run_state.started_at, saved_filespec: @run_state.saved_filespec, script_block_name: @run_state.script_block_name, streamed_lines: @run_state.files.streams } end |
#output_from_adhoc_bash_script_file(bash_script_lines, export = nil, force:) ⇒ Object
3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 |
# File 'lib/hash_delegator.rb', line 3964 def output_from_adhoc_bash_script_file( bash_script_lines, export = nil, force: ) Tempfile.create('script_exec') do |temp_file| temp_file.write( HashDelegator.join_code_lines( bash_script_lines ) ) temp_file.close # Close the file before chmod and execution File.chmod(0o755, temp_file.path) if @delegate_object[:archive_ad_hoc_scripts] archive_filename = format( @delegate_object[:archive_path_format], time: Time.now.strftime(@delegate_object[:archive_time_format]) ) `cp #{temp_file.path} #{archive_filename}` end output = `#{shell} #{temp_file.path}` exportable = if export&.exportable.nil? true else (export ? export.exportable : false) end new_lines = [] # new_lines << { comment: 'output_from_adhoc_bash_script_file' } command_result = CommandResult.new( stdout: output, exit_status: $?.exitstatus ) exportable &&= command_result.success? if exportable new_lines << { name: export.name, force: force, text: command_result.stdout } end [ command_result, exportable, new_lines ] end rescue StandardError => err # wwe 'bash_script_lines:', bash_script_lines, 'export:', export warn "Error executing script: #{err.message}" nil end |
#output_labeled_value(label, value, level) ⇒ Object
4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 |
# File 'lib/hash_delegator.rb', line 4018 def output_labeled_value(label, value, level) @fout.lout format_references_send_color( context: { name: string_send_color(label, :output_execution_label_name_color), value: string_send_color(value.to_s, :output_execution_label_value_color) }, format_sym: :output_execution_label_format ), level: level end |
#pause_user_exit ⇒ Object
4029 4030 4031 4032 |
# File 'lib/hash_delegator.rb', line 4029 def pause_user_exit @delegate_object[:pause_after_script_execution] && prompt_select_continue == MenuState::EXIT end |
#persist_fcb(options) ⇒ Object
4034 4035 4036 |
# File 'lib/hash_delegator.rb', line 4034 def persist_fcb() HashDelegator.persist_fcb_self(@fcb_store, ) end |
#pop_add_current_code_to_head_and_trigger_load(link_state, block_names, code_lines, dependencies, selected, next_block_name: nil) ⇒ Object
4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 |
# File 'lib/hash_delegator.rb', line 4038 def pop_add_current_code_to_head_and_trigger_load( link_state, block_names, code_lines, dependencies, selected, next_block_name: nil ) pop = @link_history.pop # updatable if pop.document_filename next_state = LinkState.new( block_name: pop.block_name, document_filename: pop.document_filename, inherited_block_names: (pop.inherited_block_names + block_names).sort.uniq, inherited_dependencies: dependencies.merge(pop.inherited_dependencies || {}), ### merge, not replace, key data inherited_lines: HashDelegator.flatten_and_compact_arrays(pop.inherited_lines, code_lines) ) @link_history.push(next_state) next_state.block_name = nil LoadFileLinkState.new(LoadFile::LOAD, next_state) else # no history exists; must have been called independently # => retain script link_history_push_and_next( curr_block_name: selected.pub_name, 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.flatten_and_compact_arrays( link_state&.inherited_lines, code_lines ), keep_code: link_state&.keep_code, next_block_name: next_block_name, next_document_filename: @delegate_object[:filename], # not next_document_filename next_keep_code: false, next_load_file: LoadFile::REUSE # not next_document_filename == @delegate_object[:filename] ? LoadFile::REUSE : LoadFile::LOAD ) # LoadFileLinkState.new(LoadFile::REUSE, link_state) end end |
#pop_link_history_new_state ⇒ LinkState
This method handles the back-link operation in the Markdown execution context. It updates the history state for the next block.
4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 |
# File 'lib/hash_delegator.rb', line 4089 def pop_link_history_new_state pop = @link_history.pop peek = @link_history.peek LinkState.new( document_filename: pop.document_filename, inherited_block_names: peek.inherited_block_names, inherited_dependencies: peek.inherited_dependencies, inherited_lines: peek.inherited_lines ) end |
#post_execution_process ⇒ Object
4100 4101 4102 4103 4104 |
# File 'lib/hash_delegator.rb', line 4100 def post_execution_process do_save_execution_output output_execution_summary fout_execution_report if @delegate_object[:output_execution_report] end |
#print_formatted_option(key, value) ⇒ Object
4154 4155 4156 4157 4158 |
# File 'lib/hash_delegator.rb', line 4154 def print_formatted_option(key, value) formatted_str = format(@delegate_object[:menu_opts_set_format], { key: key, value: value }) print string_send_color(formatted_str, :menu_opts_set_color) end |
#process_command_result_lines(command_result_w_e_t_nl, export, required_lines) ⇒ Object
private
4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 |
# File 'lib/hash_delegator.rb', line 4162 def process_command_result_lines(command_result_w_e_t_nl, export, required_lines) command_result_w_e_t_nl.new_lines.map do |name_force| comment = name_force.fetch(:comment, '') name = name_force.fetch(:name, '') if name.empty? "# #{comment}" unless comment.empty? else transformed = if command_result_w_e_t_nl.transformable transform_export_value(name_force[:text], export) else name_force[:text] end # store the transformed value in ENV EnvInterface.set(name, transformed) set = code_line_to_assign_a_variable( name, transformed, force: name_force[:force] ) comment.empty? ? set : "#{set} # #{comment}" end end rescue StandardError ww $@, $!, caller.deref raise StandardError, $! end |
#process_string_array(arr, begin_pattern: nil, end_pattern: nil, scan1: nil, format1: nil, name: '') ⇒ Object
4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 |
# File 'lib/hash_delegator.rb', line 4191 def process_string_array( arr, begin_pattern: nil, end_pattern: nil, scan1: nil, format1: nil, name: '' ) in_block = !begin_pattern.present? collected_lines = [] arr.each do |line| if in_block if end_pattern.present? && line.match?(end_pattern) in_block = false elsif scan1.present? if format1.present? caps = NamedCaptureExtractor.extract_named_groups(line, scan1) if caps formatted = format(format1, caps) collected_lines << formatted end else caps = line.match(scan1) if caps formatted = caps[0] collected_lines << formatted end end elsif format1.present? formatted = format(format1, { value: line }) collected_lines << formatted else collected_lines << line end elsif begin_pattern.present? && line.match?(begin_pattern) in_block = true end end collected_lines end |
#prompt_approve_repeat ⇒ Object
4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 |
# File 'lib/hash_delegator.rb', line 4230 def prompt_approve_repeat sel = @prompt.select( string_send_color(@delegate_object[:prompt_debounce], :prompt_color_after_script_execution), default: @delegate_object[:prompt_no], filter: true, quiet: true ) do || .choice @delegate_object[:prompt_yes] .choice @delegate_object[:prompt_no] .choice @delegate_object[:prompt_uninterrupted] end return false if sel == @delegate_object[:prompt_no] return true if sel == @delegate_object[:prompt_yes] @allowed_execution_block = @prior_execution_block true rescue TTY::Reader::InputInterrupt # treat as denial false end |
#prompt_for_command(prompt) ⇒ Object
4252 4253 4254 4255 4256 4257 4258 |
# File 'lib/hash_delegator.rb', line 4252 def prompt_for_command(prompt) print prompt gets.chomp rescue Interrupt nil end |
#prompt_for_filespec_with_wildcard(filespec) ⇒ String?
Prompts the user to enter a path or name to substitute
into the wildcard expression.
If interrupted by the user (e.g., pressing Ctrl-C), it
returns nil.
4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 |
# File 'lib/hash_delegator.rb', line 4269 def prompt_for_filespec_with_wildcard(filespec) puts format(@delegate_object[:prompt_show_expr_format], { expr: filespec }) puts @delegate_object[:prompt_enter_filespec] begin input = $stdin.gets.chomp PathUtils.resolve_path_or_substitute(input, filespec) rescue Interrupt puts "\nOperation interrupted. Returning nil." nil end end |
#prompt_for_user_approval(required_lines:, selected:) ⇒ Boolean
Presents a menu to the user for approving an action
and performs additional tasks based on the selection.
The function provides options for approval, rejection,
data to clipboard, or saving data to a file.
4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 |
# File 'lib/hash_delegator.rb', line 4307 def prompt_for_user_approval(required_lines:, selected:) # Present a selection menu for user approval. sel = @prompt.select( string_send_color(@delegate_object[:prompt_approve_block], :prompt_color_after_script_execution), filter: true ) do || .default MenuOptions::YES .choice @delegate_object[:prompt_yes], MenuOptions::YES .choice @delegate_object[:prompt_no], MenuOptions::NO .choice @delegate_object[:prompt_script_to_clipboard], MenuOptions::SCRIPT_TO_CLIPBOARD .choice @delegate_object[:prompt_save_script], MenuOptions::SAVE_SCRIPT end if sel == MenuOptions::SCRIPT_TO_CLIPBOARD copy_to_clipboard(required_lines) elsif sel == MenuOptions::SAVE_SCRIPT save_to_file( required_lines: required_lines, selected: selected, shell: selected_shell(selected.shell) ) end sel == MenuOptions::YES rescue TTY::Reader::InputInterrupt # treat as denial false end |
#prompt_margin_left_text ⇒ Object
4338 4339 4340 |
# File 'lib/hash_delegator.rb', line 4338 def prompt_margin_left_text @delegate_object[:prompt_margin_left_text] end |
#prompt_margin_left_width ⇒ Object
4342 4343 4344 |
# File 'lib/hash_delegator.rb', line 4342 def prompt_margin_left_width prompt_margin_left_text.length end |
#prompt_margin_right_width ⇒ Object
4346 4347 4348 |
# File 'lib/hash_delegator.rb', line 4346 def prompt_margin_right_width 0 end |
#prompt_select_continue(filter: true, quiet: true) ⇒ Object
4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 |
# File 'lib/hash_delegator.rb', line 4350 def prompt_select_continue(filter: true, quiet: true) sel = @prompt.select( string_send_color(@delegate_object[:prompt_after_script_execution], :prompt_color_after_script_execution), filter: filter, quiet: quiet ) do || .choice @delegate_object[:prompt_yes] .choice @delegate_object[:prompt_exit] end sel == if @delegate_object[:prompt_exit] MenuState::EXIT else MenuState::CONTINUE end rescue TTY::Reader::InputInterrupt # treat as denial MenuState::EXIT end |
#prompt_select_from_list(filenames, color_sym: :prompt_color_after_script_execution, cycle: true, enum: false, quiet: true, string: ) ⇒ Object
public
4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 |
# File 'lib/hash_delegator.rb', line 4372 def prompt_select_from_list( filenames, color_sym: :prompt_color_after_script_execution, cycle: true, enum: false, quiet: true, string: @delegate_object[:prompt_select_code_file] ) @prompt.select( string_send_color(string, color_sym), cycle: cycle, filter: !enum, per_page: @delegate_object[:select_page_height], quiet: quiet ) do || .enum '.' if enum filenames.each.with_index do |filename, ind| if enum .choice filename, ind + 1 else .choice filename end end end rescue TTY::Reader::InputInterrupt # treat as no selection nil end |
#prompt_user_exit(block_name_from_cli:, selected:) ⇒ Object
user prompt to exit if the menu will be displayed again
4403 4404 4405 4406 4407 |
# File 'lib/hash_delegator.rb', line 4403 def prompt_user_exit(block_name_from_cli:, selected:) selected.type == BlockType::SHELL && @delegate_object[:pause_after_script_execution] && prompt_select_continue == MenuState::EXIT end |
#publish_for_external_automation(message:) ⇒ Object
4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 4432 4433 |
# File 'lib/hash_delegator.rb', line 4409 def publish_for_external_automation(message:) return if @delegate_object[:publish_document_file_name].empty? pipe_path = absolute_path(@delegate_object[:publish_document_file_name]) case @delegate_object[:publish_document_file_mode] when 'append' File.write(pipe_path, "#{message}\n", mode: 'a') when 'fifo' unless @vux_pipe_open unless File.exist?(pipe_path) File.mkfifo(pipe_path) @vux_pipe_created = pipe_path end @vux_pipe_open = File.open(pipe_path, 'w') end @vux_pipe_open.puts("#{message}\n") @vux_pipe_open.flush when 'write' File.write(pipe_path, ) else raise 'Invalid publish_document_file_mode:' \ " #{@delegate_object[:publish_document_file_mode]}" end end |
#read_saved_assets_for_history_table(asset: nil, filename: nil, form: , path: , regexp: ) ⇒ Object
4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 |
# File 'lib/hash_delegator.rb', line 4435 def read_saved_assets_for_history_table( asset: nil, filename: nil, form: @delegate_object[:saved_history_format], path: @delegate_object[:saved_script_folder], regexp: @delegate_object[:saved_asset_match] ) history_files( filename: if asset.present? saved_asset_filename(asset, @dml_link_state) else filename end, path: path )&.map do |file| unless Regexp.new(regexp) =~ file warn "Cannot parse name: #{file}" next end saved_asset = saved_asset_for_history( file: file, form: form, match_info: $LAST_MATCH_INFO ) saved_asset == :break ? nil : saved_asset end&.compact end |
#read_show_options_and_trigger_reuse(selected:, mdoc:, link_state: LinkState.new) ⇒ LoadFileLinkState
Processes YAML data from the selected menu item, updating delegate
objects and optionally printing formatted output.
4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 |
# File 'lib/hash_delegator.rb', line 4471 def (selected:, mdoc:, link_state: LinkState.new) obj = {} # concatenated body of all required blocks loaded a YAML data = (YAML.load( execute_block_type_port_code_lines( mdoc: mdoc, selected: selected, link_state: link_state, block_source: {} ).join("\n") ) || {}).transform_keys(&:to_sym) if selected.type == BlockType::OPTS obj = data else (data || []).each do |key, value| sym_key = key.to_sym obj[sym_key] = value if @delegate_object[:menu_opts_set_format].present? print_formatted_option(key, value) end end end link_state.block_name = nil OpenStruct.new(options: obj, load_file_link_state: LoadFileLinkState.new( LoadFile::REUSE, link_state )) end |
#register_console_attributes(opts) ⇒ Object
Registers console attributes by modifying the options hash. This method handles terminal resizing and adjusts the console dimensions and pagination settings based on the current terminal size.
4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 |
# File 'lib/hash_delegator.rb', line 4534 def register_console_attributes(opts) return unless IO.console if (resized = @delegate_object[:menu_resize_terminal]) resize_terminal end if resized || !opts[:console_width] opts[:console_height], opts[:console_width] = opts[:console_winsize] = IO.console.winsize end unless opts[:select_page_height]&.positive? opts[:per_page] = opts[:select_page_height] = [opts[:console_height] - 3, 4].max end rescue StandardError HashDelegator.error_handler('register_console_attributes', { abort: true }) end |
#replace_keys_in_lines(replacement_dictionary, lines) ⇒ Object
private
4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 |
# File 'lib/hash_delegator.rb', line 4558 def replace_keys_in_lines(replacement_dictionary, lines) # Create a regex pattern that matches any key in the replacement dictionary pattern = Regexp.union(replacement_dictionary.keys.map do |key| "%<#{key}>" end) # Iterate over each line and apply gsub with the replacement hash lines.map do |line| line.gsub(pattern) { |match| replacement_dictionary[match] } end end |
#report_error(err) ⇒ Object
4570 4571 4572 4573 4574 4575 4576 4577 4578 |
# File 'lib/hash_delegator.rb', line 4570 def report_error(err) # Handle ENOENT error @run_state.aborted_at = Time.now.utc @run_state. = err. @run_state.error = err @run_state.files.append_stream_line(ExecutionStreams::STD_ERR, @run_state.) @fout.fout err.inspect end |
#respond_to?(method_name, include_private = false) ⇒ Boolean
Check if the delegate object responds to a given method.
4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 |
# File 'lib/hash_delegator.rb', line 4586 def respond_to?(method_name, include_private = false) if super true elsif @delegate_object.respond_to?(method_name, include_private) true elsif method_name.to_s.end_with?('=') && @delegate_object.respond_to?(:[]=, include_private) true else @delegate_object.respond_to?(method_name, include_private) end end |
#runtime_exception(exception_sym, name, items) ⇒ Object
4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 |
# File 'lib/hash_delegator.rb', line 4599 def runtime_exception(exception_sym, name, items) if @delegate_object[exception_sym] != 0 data = { name: name, detail: items.join(', ') } warn( AnsiString.new( format( @delegate_object.fetch(:exception_format_name, "\n%{name}"), data ) ).send(@delegate_object.fetch(:exception_color_name, :red)) + AnsiString.new( format( @delegate_object.fetch(:exception_format_detail, " - %{detail}\n"), data ) ).send(@delegate_object.fetch(:exception_color_detail, :yellow)) ) end return unless (@delegate_object[exception_sym]).positive? exit @delegate_object[exception_sym] end |
#safe_yaml_load(body) ⇒ Object
6083 6084 6085 6086 6087 6088 6089 6090 6091 6092 |
# File 'lib/hash_delegator.rb', line 6083 def safe_yaml_load(body) caller.deref(12) return {} unless body&.present? YAML.load(body.to_s) rescue Psych::SyntaxError => err wwe 'YAML parsing error', { body: body, error: err. } rescue StandardError => err wwe 'YAML loading error', { body: body, error: err. } end |
#save_filespec_from_expression(expression) ⇒ Object
allow user to select or enter
4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 |
# File 'lib/hash_delegator.rb', line 4624 def save_filespec_from_expression(expression) # Process expression with embedded formatting formatted = formatted_expression(expression) # Handle wildcards or direct file specification if contains_glob?(formatted) save_filespec_wildcard_expansion(formatted) else formatted end end |
#save_filespec_wildcard_expansion(filespec) ⇒ Object
Handle expression with wildcard characters allow user to select or enter
4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 |
# File 'lib/hash_delegator.rb', line 4638 def save_filespec_wildcard_expansion(filespec) files = find_files(filespec) case files.count when 0 prompt_for_filespec_with_wildcard(filespec) else ## user selects from existing files or other # input into path with wildcard for easy entry # case (name = prompt_select_from_list( [@delegate_object[:prompt_filespec_back], @delegate_object[:prompt_filespec_other]] + files, string: @delegate_object[:prompt_select_code_file], color_sym: :prompt_color_after_script_execution )) when @delegate_object[:prompt_filespec_back] # do nothing when @delegate_object[:prompt_filespec_other] prompt_for_filespec_with_wildcard(filespec) else name end end end |
#save_to_file(erls:, required_lines:, selected:, shell:) ⇒ Object
4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 |
# File 'lib/hash_delegator.rb', line 4663 def save_to_file( erls:, required_lines:, selected:, shell: ) write_command_file( required_lines: required_lines, blockname: selected.pub_name, shell: selected_shell(shell) ) @fout.fout "File saved: #{@run_state.saved_filespec}" end |
#saved_asset_filename(filename, link_state = LinkState.new) ⇒ Object
4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 |
# File 'lib/hash_delegator.rb', line 4675 def saved_asset_filename(filename, link_state = LinkState.new) SavedAsset.new( filename: filename, saved_asset_format: shell_escape_asset_format( code_lines: link_state&.inherited_lines, shell: selected_shell(shell) ) ).generate_name end |
#saved_asset_for_history(file:, form:, match_info:) ⇒ Object
4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703 4704 4705 |
# File 'lib/hash_delegator.rb', line 4686 def saved_asset_for_history( file:, form:, match_info: ) OpenStruct.new( file: file[(Dir.pwd.length + 1)..-1], full: file, row: format( form, # default '*' so unknown parameters are given a wildcard match_info.names.each_with_object(Hash.new('*')) do |name, hash| hash[name.to_sym] = match_info[name] end ) ) rescue KeyError # pp $!, $@ warn "Cannot format with: #{@delegate_object[:saved_history_format]}" error_handler('saved_history_format') :break end |
#screen_width ⇒ Object
4707 4708 4709 4710 4711 4712 4713 4714 |
# File 'lib/hash_delegator.rb', line 4707 def screen_width width = @delegate_object[:screen_width] if width&.positive? width else @delegate_object[:console_width] end end |
#screen_width_for_table ⇒ Object
4716 4717 4718 4719 4720 |
# File 'lib/hash_delegator.rb', line 4716 def screen_width_for_table # menu adds newline after some lines if sized to the edge # menu prompt symbol (1) + space (1) + gap (1) screen_width - prompt_margin_left_width - prompt_margin_right_width - 3 end |
#screen_width_for_wrapping ⇒ Object
4722 4723 4724 |
# File 'lib/hash_delegator.rb', line 4722 def screen_width_for_wrapping screen_width_for_table end |
#select_automatic_ux_blocks(blocks) ⇒ Object
all UX blocks are automatic for the document
4107 4108 4109 |
# File 'lib/hash_delegator.rb', line 4107 def select_automatic_ux_blocks(blocks) blocks.select { |item| item.type == 'ux' } end |
#select_blocks(menu_blocks) ⇒ Object
Filter blocks per block_name_include_match, block_name_wrapper_match.
4114 4115 4116 4117 4118 4119 4120 4121 4122 |
# File 'lib/hash_delegator.rb', line 4114 def select_blocks() .reject do |fcb| Filter.( @delegate_object, fcb, i[block_name_include_match block_name_wrapper_match] ) end end |
#select_document_if_multiple(options, files, prompt:) ⇒ Object
4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 |
# File 'lib/hash_delegator.rb', line 4726 def select_document_if_multiple(, files, prompt:) return files if files.instance_of?(String) return files[0] if (count = files.count) == 1 return unless count >= 2 opts = .dup select_option_or_exit( string_send_color( prompt, :prompt_color_after_script_execution ), files, opts.merge(per_page: opts[:select_page_height]) ) end |
#select_option_with_metadata(prompt_text, tty_menu_items, opts = {}, menu_blocks: nil) ⇒ Object
Presents a TTY prompt to select an option or exit,
returns including option and selected
4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 |
# File 'lib/hash_delegator.rb', line 4745 def ( prompt_text, , opts = {}, menu_blocks: nil ) = if ## configure to environment # register_console_attributes(opts) active_color_pastel = Pastel.new active_color_pastel = opts[:menu_active_color_pastel_messages] .inject(active_color_pastel) do |p, | p.send() end begin props = { active_color: active_color_pastel.detach, # activate dynamic list searching on letter/number key presses cycle: true, filter: true, per_page: @delegate_object[:select_page_height] }.freeze if .all? do |item| !item.is_a?(String) && item[:disabled] end .each do |prompt_item| puts prompt_item[:dname] end return end # crashes if all menu options are disabled # crashes if default is not an existing item # selection = @prompt.select(prompt_text, , opts.merge(props)) rescue TTY::Prompt::ConfigurationError # prompt fails when collapsible block name has changed; clear default selection = @prompt.select(prompt_text, , opts.merge(props).merge(default: nil)) rescue NoMethodError # no enabled options in page return end = opts.fetch(:match_dml, true) ? : ||= selected = .find do |item| if item.instance_of?(Hash) [item[:id], item[:name], item[:dname]].include?(selection) elsif item.instance_of?(MarkdownExec::FCB) item.id == selection else item == selection end end # new FCB if selected is not an object if selected.instance_of?(String) selected = FCB.new(dname: selected) elsif selected.instance_of?(Hash) selected = FCB.new(selected) end unless selected report_and_reraise('menu item not found') HashDelegator.error_handler('select_option_with_metadata', error: 'menu item not found') exit 1 end if selected.oname == HashDelegator.safeval( @delegate_object.fetch(:menu_option_back_name, '') )[:line] selected.option = selection selected.type = BlockType::LINK elsif selected.oname == HashDelegator.safeval( @delegate_object.fetch(:menu_option_exit_name, '') )[:line] selected.option = selection else selected.selected = selection end selected end |
#selected_id_name(selected) ⇒ Object
1312 1313 1314 |
# File 'lib/hash_delegator.rb', line 1312 def selected_id_name(selected) selected.id end |
#selected_shell(shell_name) ⇒ Object
4836 4837 4838 |
# File 'lib/hash_delegator.rb', line 4836 def selected_shell(shell_name) shell_name.empty? ? shell : shell_name end |
#shell ⇒ Object
4840 4841 4842 |
# File 'lib/hash_delegator.rb', line 4840 def shell @delegate_object[:shell] end |
#shell=(value) ⇒ Object
4844 4845 4846 |
# File 'lib/hash_delegator.rb', line 4844 def shell=(value) @delegate_object[:shell] = value end |
#shell_escape_asset_format(code_lines:, enable: , raw: , shell:) ⇒ Object
4848 4849 4850 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 |
# File 'lib/hash_delegator.rb', line 4848 def shell_escape_asset_format( code_lines:, enable: @delegate_object[:shell_parameter_expansion], raw: @delegate_object[:saved_asset_format], shell: ) return raw unless enable # unchanged if no parameter expansion takes place return raw unless /$/ =~ raw filespec = generate_temp_filename cmd = [shell, '-c', filespec].join(' ') marker = Random.new.rand.to_s code = (code_lines || []) + ["echo -n \"#{marker}#{raw}\""] File.write filespec, HashDelegator.join_code_lines(code) File.chmod 0o755, filespec out = `#{cmd}`.sub(/.*?#{marker}/m, '') File.delete filespec out end |
#should_add_back_option?(menu_with_back: ) ⇒ Boolean
4873 4874 4875 4876 4877 |
# File 'lib/hash_delegator.rb', line 4873 def should_add_back_option?( menu_with_back: @delegate_object[:menu_with_back] ) && @link_history.prior_state_exist? end |
#simple_menu_options ⇒ Object
4879 |
# File 'lib/hash_delegator.rb', line 4879 def ; end |
#start_fenced_block(line, headings, fenced_start_extended_regex, source_id: nil) ⇒ MarkdownExec::FCB
Initializes a new fenced code block (FCB) object based
on the provided line and heading information.
4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 4902 4903 4904 4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958 4959 |
# File 'lib/hash_delegator.rb', line 4888 def start_fenced_block( line, headings, fenced_start_extended_regex, source_id: nil ) fcb_title_groups = NamedCaptureExtractor.extract_named_groups( line, fenced_start_extended_regex ) rest = fcb_title_groups.fetch(:rest, '') reqs, wraps = ArrayUtil.partition_by_predicate(rest.scan(/\+[^\s]+/).map do |req| req[1..-1] end) do |name| !name.match(Regexp.new(@delegate_object[:block_name_wrapper_match])) end # adjust captured type if fcb_title_groups[:type].present? case fcb_title_groups[:type] when *ShellType::ALL # convert type to shell fcb_title_groups[:shell] = fcb_title_groups[:type] fcb_title_groups[:type] = BlockType::SHELL end else # treat as the default shell fcb_title_groups[:shell] = @delegate_object[:block_type_default] fcb_title_groups[:type] = BlockType::SHELL end dname = oname = title = '' nickname = nil if @delegate_object[:block_name_nick_match].present? && oname =~ Regexp.new(@delegate_object[:block_name_nick_match]) nickname = $~[0] else dname = oname = title = fcb_title_groups.fetch(:name, '') end # disable fcb for data blocks disabled = if fcb_title_groups.fetch(:type, '') == BlockType::YAML TtyMenu::DISABLE else TtyMenu::ENABLE end persist_fcb( block: [line], body: [], call: rest.match( Regexp.new(@delegate_object[:block_calls_scan]) )&.to_a&.first, disabled: disabled, dname: dname, headings: headings, id: source_id.to_s, indent: fcb_title_groups.fetch(:indent, ''), nickname: nickname, oname: oname, reqs: reqs, shell: fcb_title_groups.fetch(:shell, ''), start_line: line, stdin: if (tn = rest.match(/<(?<type>\$)?(?<name>[A-Za-z_-]\S+)/)) NamedCaptureExtractor.extract_named_group_match_data(tn) end, stdout: if (tn = rest.match(/>(?<type>\$)?(?<name>[\w.\-]+)/)) NamedCaptureExtractor.extract_named_group_match_data(tn) end, title: title, type: fcb_title_groups.fetch(:type, ''), wraps: wraps ) end |
#string_send_color(string, color_sym) ⇒ String
Applies a color method to a string based on the provided color symbol. The color method is fetched from @delegate_object and applied to the string.
4968 4969 4970 4971 |
# File 'lib/hash_delegator.rb', line 4968 def string_send_color(string, color_sym) ### accept string with color as well as symbol for color_hash HashDelegator.apply_color_from_hash(string, @delegate_object, color_sym) end |
#transform_export_value(value, export) ⇒ Object
4973 4974 4975 4976 4977 4978 4979 4980 4981 4982 4983 4984 4985 4986 4987 4988 |
# File 'lib/hash_delegator.rb', line 4973 def transform_export_value(value, export) return value unless export.transform.present? if export.transform.is_a? Symbol value.send(export.transform) else format( export.transform, NamedCaptureExtractor.extract_named_groups( value, export.validate ) ) end rescue StandardError wwe $!, 'value:', value end |
#update_line_and_block_state(nested_line, state, selected_types, source_id:, &block) ⇒ Void
Processes an individual line within a loop, updating headings
and handling fenced code blocks.
This function is designed to be called within a loop that iterates
through each line of a document.
the current fenced code block being processed.
5021 5022 5023 5024 5025 5026 5027 5028 5029 5030 5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 5041 5042 5043 5044 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 |
# File 'lib/hash_delegator.rb', line 5021 def update_line_and_block_state( nested_line, state, selected_types, source_id:, &block ) line = nested_line.to_s if line.match(@delegate_object[:fenced_start_and_end_regex]) if state[:in_fenced_block] ## end of code block # state[:fcb].append_block_line(line) HashDelegator.( fcb: state[:fcb], messages: selected_types, configuration: @delegate_object, &block ) state[:in_fenced_block] = false else ## start of code block # state[:fcb] = start_fenced_block( line, state[:headings], @delegate_object[:fenced_start_extended_regex], source_id: source_id ) state[:fcb][:depth] = nested_line[:depth] state[:fcb][:indention] = nested_line[:indention] state[:in_fenced_block] = true end elsif state[:in_fenced_block] && state[:fcb].body ## add line to fenced code block # remove fcb indent if possible # tline = line.chomp.sub(/^#{state[:fcb].indent}/, '') state[:fcb].append_block_line(tline) state[:fcb].body += [tline] elsif nested_line[:depth].zero? || @delegate_object[:menu_include_imported_notes] # add line if it is depth 0 or option allows it # criteria = nil if @delegate_object[:table_row_single_line_match]&.present? && line.match(@delegate_object[:table_row_single_line_match]) criteria = { center: :table_center, match: :table_row_single_line_match } end HashDelegator.yield_line_if_selected( line, selected_types, all_fcbs: @fcb_store, criteria: criteria, source_id: source_id, &block ) end rescue StandardError wwe $!, 'state:', state, 'nested_line:', nested_line end |
#update_menu_base(options) ⇒ Object
apply options to current state
5083 5084 5085 5086 5087 |
# File 'lib/hash_delegator.rb', line 5083 def () # under simple uses, @menu_base_options may be nil &.merge!() @delegate_object.merge!() end |
#ux_block_eval_for_export(bash_script_lines, export, data:, first_only: false, force:, printf_expand: false, silent:, string: nil) ⇒ Object
2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 |
# File 'lib/hash_delegator.rb', line 2928 def ux_block_eval_for_export( bash_script_lines, export, data:, first_only: false, force:, printf_expand: false, silent:, string: nil ) exportable = true command_result = nil new_lines = [] export_string = string.nil? ? data : string = ->(expression) { %(printf '%s' "#{expression}") } case export_string when String, Integer, Float, TrueClass, FalseClass command_result, exportable, = output_from_adhoc_bash_script_file( join_array_of_arrays( bash_script_lines, ? .call(export_string) : [export_string] ), export, force: force ) if command_result.exit_status == EXIT_STATUS_REQUIRED_EMPTY exportable = false unless silent command_result.warning = warning_required_empty(export) end else # store the transformed value in ENV EnvInterface.set(export.name, command_result.stdout.to_s) new_lines << { name: export.name, force: force, text: command_result.stdout } end when Hash required_lines = [] # each item in the hash is a variable name and value export_string.each do |name, expression| command_result, = output_from_adhoc_bash_script_file( join_array_of_arrays( bash_script_lines, required_lines, ? .call(expression) : [expression] ), export, force: force ) if command_result.exit_status == EXIT_STATUS_REQUIRED_EMPTY unless silent command_result.warning = warning_required_empty(export) end else transformed = command_result.stdout.to_s # code for subsequent expression evaluations required_lines << code_line_to_assign_a_variable( name, transformed, force: force ) if variable_is_exportable(name) # store the transformed value in ENV EnvInterface.set(name, transformed) new_lines << { name: name, force: force, text: command_result.stdout } end end break if first_only end else # do nothing end [command_result, exportable, new_lines] rescue StandardError wwe bash_script_lines, export, force, silent, string end |
#ux_block_export_activated(bash_script_lines, export, exit_prompt) ⇒ Object
5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 |
# File 'lib/hash_delegator.rb', line 5089 def ux_block_export_activated( bash_script_lines, export, exit_prompt ) command_result = nil exportable = true force = export.force.nil? ? true : export.force new_lines = [] silent = false transformable = true case FCB.act_source(export) when false, UxActSource::FALSE # read-only command_result = CommandResult.new exportable = false transformable = false when :allow, UxActSource::ALLOW raise unless export.allow.present? case export.allow when :echo, ExportValueSource::ECHO command_result, exportable, new_lines = ux_block_eval_for_export( bash_script_lines, export, data: export.echo, first_only: true, force: force, printf_expand: true, silent: silent ) if command_result.failure? command_result else command_result = CommandResult.new( stdout: ( command_result.stdout.split("\n") ) ) end when :exec, UxActSource::EXEC command_result, exportable, new_lines = ux_block_eval_for_export( bash_script_lines, export, data: export.exec, first_only: true, force: force, silent: silent ) if command_result.exit_status == EXIT_STATUS_REQUIRED_EMPTY command_result else command_result = CommandResult.new( stdout: ( command_result.stdout.split("\n") ) ) end else export_init = (export.allow) command_result, exportable, new_lines = ux_block_eval_for_export( [assign_key_value_in_bash(export.name, export_init)], export, data: export.echo, first_only: true, force: force, printf_expand: true, silent: silent, string: export_init ) end when :echo, UxActSource::ECHO command_result, exportable, new_lines = ux_block_eval_for_export( bash_script_lines, export, data: export.echo, force: force, printf_expand: true, silent: silent ) when :edit, UxActSource::EDIT output = '' begin loop do print "#{export.prompt} [#{export.default}]: " output = gets.chomp output = export.default.to_s if output.empty? caps = NamedCaptureExtractor.extract_named_groups(output, export.validate) break if caps # invalid input, retry end rescue Interrupt exportable = false transformable = false end if exportable EnvInterface.set(export.name, output) new_lines << { name: export.name, force: force, text: output } end command_result = CommandResult.new(stdout: output) when :exec, UxActSource::EXEC command_result, exportable, new_lines = ux_block_eval_for_export( bash_script_lines, export, data: export.exec, force: force, silent: silent ) else transformable = false command_result = CommandResult.new(stdout: export.default.to_s) end # add message for required variables if command_result.exit_status == EXIT_STATUS_REQUIRED_EMPTY command_result.warning = warning_required_empty(export) warn command_result.warning unless silent end command_result.exportable = exportable command_result.transformable = transformable command_result.new_lines = new_lines command_result rescue StandardError wwe bash_script_lines, export, exit_prompt end |
#ux_block_export_automatic(bash_script_lines, export) ⇒ Object
5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295 5296 5297 5298 5299 5300 5301 5302 5303 5304 5305 5306 5307 5308 5309 5310 5311 5312 5313 5314 5315 5316 5317 5318 5319 5320 5321 5322 5323 5324 5325 5326 5327 5328 5329 5330 5331 5332 5333 5334 5335 5336 5337 5338 5339 5340 5341 5342 5343 5344 5345 5346 5347 5348 5349 5350 5351 5352 5353 5354 5355 5356 5357 5358 5359 5360 5361 5362 5363 |
# File 'lib/hash_delegator.rb', line 5229 def ux_block_export_automatic( bash_script_lines, export ) command_result = nil exportable = true force = export.force.nil? ? false : export.force new_lines = [] silent = true transformable = true case FCB.init_source(export) when false, UxActSource::FALSE exportable = false transformable = false command_result = CommandResult.new when :allow, UxActSource::ALLOW raise unless export.allow.present? case export.allow when :echo, ExportValueSource::ECHO cr_echo, = ux_block_eval_for_export( bash_script_lines, export, data: export.echo, first_only: true, force: force, printf_expand: true, silent: silent ) export_init = cr_echo.stdout.split("\n").first command_result, exportable, new_lines = ux_block_eval_for_export( [assign_key_value_in_bash(export.name, export_init)], export, data: export.echo, first_only: true, force: force, printf_expand: true, silent: silent, string: export_init ) when :exec, ExportValueSource::EXEC # extract first line from 'exec' output command_result, exportable, new_lines = ux_block_eval_for_export( bash_script_lines, export, data: export.exec, first_only: true, force: force, silent: silent ) unless command_result.failure? export_init = command_result.stdout.split("\n").first command_result, exportable, new_lines = ux_block_eval_for_export( [assign_key_value_in_bash(export.name, export_init)], export, data: export.exec, force: force, printf_expand: true, silent: silent, string: export_init ) end else # first item from 'allow' list export_init = export.allow.first command_result, exportable, new_lines = ux_block_eval_for_export( [assign_key_value_in_bash(export.name, export_init)], export, data: export.allow, force: force, printf_expand: true, silent: silent, string: export_init ) end when :default, UxActSource::DEFAULT transformable = false command_result = CommandResult.new(stdout: export.default.to_s) when :echo, UxActSource::ECHO raise unless export.echo.present? command_result, exportable, new_lines = ux_block_eval_for_export( bash_script_lines, export, data: export.echo, force: force, printf_expand: true, silent: silent ) when :exec, UxActSource::EXEC raise unless export.exec.present? command_result, exportable, new_lines = ux_block_eval_for_export( bash_script_lines, export, data: export.exec, force: force, silent: silent ) else export_init = export.init.to_s command_result, exportable, new_lines = ux_block_eval_for_export( [assign_key_value_in_bash(export.name, export_init)], export, data: export.exec, force: force, printf_expand: true, silent: silent, string: export_init ) end # add message for required variables if command_result.exit_status == EXIT_STATUS_REQUIRED_EMPTY command_result.warning = warning_required_empty(export) warn command_result.warning unless silent end command_result.exportable = exportable command_result.transformable = transformable command_result.new_lines = new_lines command_result rescue StandardError wwe bash_script_lines, export end |
#variable_is_exportable(name) ⇒ Object
true if the variable is exported in a series of evaluations
5366 5367 5368 5369 5370 5371 5372 5373 5374 |
# File 'lib/hash_delegator.rb', line 5366 def variable_is_exportable(name) local_name_pattern = @delegate_object.fetch(:local_name_pattern, '') # export all if rule is empty return true if local_name_pattern.empty? # export if it its name does not match the rule name !~ Regexp.new(local_name_pattern) end |
#vux_await_user_selection(prior_answer: @dml_block_selection) ⇒ Object
5376 5377 5378 5379 5380 5381 5382 5383 5384 5385 5386 5387 5388 5389 |
# File 'lib/hash_delegator.rb', line 5376 def vux_await_user_selection(prior_answer: @dml_block_selection) @dml_block_state = load_cli_or_user_selected_block( all_blocks: @dml_blocks_in_file, menu_blocks: , prior_answer: prior_answer ) if !@dml_block_state # HashDelegator.error_handler('block_state missing', { abort: true }) # document has no enabled items :break elsif @dml_block_state.state == MenuState::EXIT :break end end |
#vux_clear_menu_state ⇒ Object
5391 5392 5393 5394 5395 |
# File 'lib/hash_delegator.rb', line 5391 def @dml_block_selection = @dml_block_state.block @dml_block_state = SelectedBlockMenuState.new @delegate_object[:block_name] = nil end |
#vux_edit_inherited ⇒ Object
5397 5398 5399 5400 5401 5402 5403 5404 5405 |
# File 'lib/hash_delegator.rb', line 5397 def vux_edit_inherited edited = edit_text(@dml_link_state.inherited_lines_block) return unless edited @dml_link_state.inherited_lines = annotate_required_lines( 'blk:EDIT', edited.split("\n"), block_name: 'EDIT' ) end |
#vux_execute_and_prompt(block_name) ⇒ Object
5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 5465 5466 5467 5468 5469 5470 5471 5472 5473 5474 5475 5476 5477 5478 5479 5480 5481 5482 5483 5484 5485 5486 5487 5488 5489 5490 5491 5492 5493 5494 5495 5496 5497 5498 5499 5500 5501 5502 5503 5504 5505 5506 5507 5508 5509 5510 5511 5512 5513 5514 5515 5516 5517 5518 5519 5520 5521 5522 5523 5524 5525 5526 5527 5528 5529 5530 5531 5532 5533 5534 5535 5536 5537 5538 5539 5540 5541 5542 |
# File 'lib/hash_delegator.rb', line 5455 def vux_execute_and_prompt(block_name) @dml_block_state = find_block_state_by_name(block_name) if @dml_block_state.block if block_is_back(@dml_block_state.block) debounce_reset vux_navigate_back_for_ls return elsif block_is_edit(@dml_block_state.block) debounce_reset vux_edit_inherited return pause_user_exit ? :break : nil elsif block_is_exit(@dml_block_state.block) debounce_reset ### LoadFileLinkState.new(LoadFile::EXIT, link_state) return :break elsif block_is_history(@dml_block_state.block) debounce_reset return :break unless (files_table_rows = vux_history_files_table_rows) execute_history_select(files_table_rows, stream: $stderr) return :break if pause_user_exit return elsif block_is_load(@dml_block_state.block) debounce_reset vux_load_inherited return pause_user_exit ? :break : nil elsif block_is_save(@dml_block_state.block) debounce_reset return execute_inherited_save == :break ? :break : nil elsif block_is_shell(@dml_block_state.block) debounce_reset vux_input_and_execute_shell_commands(stream: $stderr, shell: shell) return pause_user_exit ? :break : nil elsif block_is_view(@dml_block_state.block) debounce_reset vux_view_inherited(stream: $stderr) return pause_user_exit ? :break : nil end end if @dml_block_state.block && @dml_block_state.block.type == BlockType::OPTS debounce_reset link_state = LinkState.new = ( link_state: link_state, mdoc: @dml_mdoc, selected: @dml_block_state.block ) (.) .load_file_link_state.link_state return end return :break if execute_block_in_state(block_name) == :break if prompt_user_exit( block_name_from_cli: @run_state.source.block_name_from_cli, selected: @dml_block_state.block ) return :break end ## order of block name processing: link block, cli, from # user # @dml_link_state.block_name, @run_state.source.block_name_from_cli, cli_break = HashDelegator.next_link_state( block_name: @dml_link_state.block_name, block_name_from_cli: @dml_now_using_cli, block_state: @dml_block_state, was_using_cli: @dml_now_using_cli ) !@dml_block_state.source.block_name_from_ui && cli_break && :break end |
#vux_execute_block_per_type(block_name, formatted_choice_ostructs) ⇒ Object
5544 5545 5546 5547 5548 5549 5550 5551 |
# File 'lib/hash_delegator.rb', line 5544 def vux_execute_block_per_type(block_name, formatted_choice_ostructs) return :break if vux_execute_and_prompt(block_name) == :break InputSequencer.next_link_state( block_name: @dml_link_state.block_name, prior_block_was_link: @dml_block_state.block.type != BlockType::SHELL ) end |
#vux_formatted_names_for_state_chrome_blocks(names: %w[back edit history load save shell view]) ⇒ Object
5553 5554 5555 5556 5557 5558 5559 5560 5561 5562 5563 5564 5565 5566 5567 |
# File 'lib/hash_delegator.rb', line 5553 def vux_formatted_names_for_state_chrome_blocks( names: %w[back edit history load save shell view] ) names.each_with_object({}) do |name, result| do_key = :"menu_option_#{name}_name" oname = HashDelegator.safeval(@delegate_object[do_key]) dname = format(@delegate_object[:menu_link_format], oname) result[name.to_sym] = OpenStruct.new( dname: dname, name: dname, oname: dname, pub_name: dname.pub_name ) end end |
#vux_history_files_table_rows ⇒ Object
5569 5570 5571 5572 5573 5574 |
# File 'lib/hash_delegator.rb', line 5569 def vux_history_files_table_rows read_saved_assets_for_history_table( asset: @delegate_object[:filename], form: @delegate_object[:saved_history_format] ) end |
#vux_init ⇒ Object
5576 5577 5578 5579 5580 5581 5582 5583 5584 5585 5586 5587 5588 5589 5590 5591 5592 5593 5594 |
# File 'lib/hash_delegator.rb', line 5576 def vux_init = @delegate_object @dml_link_state = LinkState.new( block_name: @delegate_object[:block_name], document_filename: @delegate_object[:filename] ) @run_state.source.block_name_from_cli = @dml_link_state.block_name.present? @cli_block_name = @dml_link_state.block_name @dml_now_using_cli = @run_state.source.block_name_from_cli @dml_block_selection = nil @dml_block_state = SelectedBlockMenuState.new @doc_saved_lines_files = [] @run_state.batch_random = Random.new.rand @run_state.batch_index = 0 @run_state.files = StreamsOut.new end |
#vux_input_and_execute_shell_commands(stream:, shell:) ⇒ Object
5596 5597 5598 5599 5600 5601 5602 5603 5604 5605 5606 5607 5608 5609 5610 5611 5612 5613 |
# File 'lib/hash_delegator.rb', line 5596 def vux_input_and_execute_shell_commands(stream:, shell:) loop do command = prompt_for_command( AnsiString.new(":MDE #{Time.now.strftime('%FT%TZ')}> ").send(:bgreen) ) break if !command.present? || command == 'exit' exit_status = execute_command_with_streams( [shell, '-c', command] ) case exit_status when 0 stream.puts "#{AnsiString.new('OK').green} #{exit_status}" else stream.puts "#{AnsiString.new('ERR').bred} #{exit_status}" end end end |
#vux_load_code_files_into_state ⇒ Object
load file with code lines per options
5617 5618 5619 5620 5621 5622 5623 5624 5625 5626 5627 5628 5629 5630 5631 5632 5633 |
# File 'lib/hash_delegator.rb', line 5617 def vux_load_code_files_into_state return unless [:load_code].present? @dml_link_state.inherited_lines = [:load_code].split(':').map do |path| File.readlines(path, chomp: true) end.flatten(1) inherited_block_names = [] inherited_dependencies = {} selected = persist_fcb(oname: 'load_code') pop_add_current_code_to_head_and_trigger_load( @dml_link_state, inherited_block_names, code_lines, inherited_dependencies, selected ) end |
#vux_load_inherited ⇒ Object
5635 5636 5637 5638 5639 5640 5641 5642 5643 |
# File 'lib/hash_delegator.rb', line 5635 def vux_load_inherited return unless (filespec = load_filespec_from_expression( document_name_in_glob_as_file_name )) @dml_link_state.inherited_lines_append( File.readlines(filespec, chomp: true) ) end |
#vux_main_loop(menu_from_yaml: nil) ⇒ Nil
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.
5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 5662 5663 5664 5665 5666 5667 5668 5669 5670 5671 5672 5673 5674 5675 5676 5677 5678 5679 5680 5681 5682 5683 5684 5685 5686 5687 5688 5689 5690 5691 5692 5693 5694 5695 5696 5697 5698 5699 5700 5701 5702 5703 5704 5705 5706 5707 5708 5709 5710 5711 5712 5713 5714 5715 5716 5717 5718 5719 5720 5721 5722 5723 5724 5725 5726 5727 5728 5729 5730 5731 5732 5733 5734 5735 5736 5737 5738 5739 5740 5741 5742 5743 5744 5745 5746 5747 5748 5749 5750 5751 5752 5753 5754 5755 5756 5757 5758 5759 5760 5761 5762 5763 5764 5765 5766 5767 5768 5769 5770 |
# File 'lib/hash_delegator.rb', line 5652 def vux_main_loop(menu_from_yaml: nil) = vux_init vux_load_code_files_into_state formatted_choice_ostructs = vux_formatted_names_for_state_chrome_blocks block_list = [@delegate_object[:block_name]].select(&:present?).compact + @delegate_object[:input_cli_rest] @delegate_object[:block_name] = nil process_commands( arguments: @p_all_arguments, named_procs: yield(:command_names, @delegate_object), options_parsed: , rest: @p_rest, enable_search: @delegate_object[:default_find_select_open] ) do |type, data| case type when ArgPro::ActSetBlockName @delegate_object[:block_name] = data @delegate_object[:input_cli_rest] = '' when ArgPro::ConvertValue # call for side effects, output, or exit data[0].call(data[1]) when ArgPro::ActFileIsMissing raise FileMissingError, data, caller when ArgPro::ActFind find_value(data, execute_chosen_found: true) when ArgPro::ActSetFileName @delegate_object[:filename] = data when ArgPro::ActSetPath @delegate_object[:path] = data when ArgPro::CallProcess yield :call_proc, [@delegate_object, data] when ArgPro::ActSetOption @delegate_object[data[0]] = data[1] else raise end end count = 0 InputSequencer.new( @delegate_object[:filename], block_list ).run do |msg, data| count += 1 wwt :id, 'count:', count, 'msg:', msg, 'data:', data case msg when :parse_document # once for each menu count = 0 vux_parse_document( source_id: "#{@delegate_object[:filename]}¤VuxMainLoop®PrsDoc" ) ( formatted_choice_ostructs, source_id: "#{@delegate_object[:filename]}¤VuxMainLoop®HstFls" ) vux_publish_document_file_name_for_external_automation when :display_menu # does not display when :end_of_cli # yield :end_of_cli, @delegate_object if @delegate_object[:blocks].present? @delegate_object[:list_blocks_message] = @delegate_object[:blocks].to_sym @delegate_object[:list_blocks_type] = 3 list_blocks( source_id: "#{@delegate_object[:filename]}¤VuxMainLoop®EndCLI" ) :exit elsif @delegate_object[:list_blocks] list_blocks( source_id: "#{@delegate_object[:filename]}¤VuxMainLoop®EndCLI" ) :exit end when :user_choice vux_user_selected_block_name when :execute_block begin ret = vux_execute_block_per_type(data, formatted_choice_ostructs) vux_publish_block_name_for_external_automation(data) ret rescue StandardError # error executing block, do not abort InputSequencer.next_link_state(prior_block_was_link: false) end when :close_ux if @vux_pipe_open.present? && File.exist?(@vux_pipe_open) @vux_pipe_open.close @vux_pipe_open = nil end if @vux_pipe_created.present? && File.exist?(@vux_pipe_created) File.delete(@vux_pipe_created) @vux_pipe_created = nil end when :exit? data == $texit when :stay? data == $stay else raise "Invalid message: #{msg}" end end end |
#vux_menu_append_history_files(formatted_choice_ostructs, source_id: '') ⇒ Object
5772 5773 5774 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784 5785 5786 5787 5788 5789 5790 5791 5792 5793 5794 5795 5796 5797 5798 5799 5800 5801 5802 5803 5804 5805 5806 5807 5808 5809 5810 5811 5812 5813 5814 5815 5816 5817 5818 5819 5820 5821 5822 5823 5824 5825 5826 5827 5828 5829 5830 5831 5832 5833 5834 5835 5836 5837 5838 5839 5840 5841 5842 5843 |
# File 'lib/hash_delegator.rb', line 5772 def ( formatted_choice_ostructs, source_id: '' ) if @delegate_object[:menu_for_history] history_files( filename: saved_asset_filename(@delegate_object[:filename], @dml_link_state), path: @delegate_object[:saved_script_folder] ).tap do |files| if files.count.positive? ( formatted_choice_ostructs[:history].oname, files.count, 'files', menu_state: MenuState::HISTORY, source_id: source_id ) end end end return unless @delegate_object[:menu_for_saved_lines] && @delegate_object[:document_saved_lines_glob].present? document_glob = document_name_in_glob_as_file_name files = document_glob ? Dir.glob(document_glob) : [] @doc_saved_lines_files = files.count.positive? ? files : [] lines_count = @dml_link_state.inherited_lines_count # add menu items (glob, load, save) and enable selectively if files.count.positive? || lines_count.positive? (document_glob, "#{source_id}_vmahf_glob") end if files.count.positive? ( formatted_choice_ostructs[:load].dname, files.count, 'files', menu_state: MenuState::LOAD, source_id: "#{source_id}_vmahf_load" ) end if @delegate_object[:menu_inherited_lines_edit_always] || lines_count.positive? ( formatted_choice_ostructs[:edit].dname, lines_count, 'lines', menu_state: MenuState::EDIT, source_id: "#{source_id}_vmahf_edit" ) end if lines_count.positive? ( formatted_choice_ostructs[:save].dname, 1, '', menu_state: MenuState::SAVE, source_id: "#{source_id}_vmahf_save" ) end if lines_count.positive? ( formatted_choice_ostructs[:view].dname, 1, '', menu_state: MenuState::VIEW, source_id: "#{source_id}_vmahf_view" ) end # rubocop:disable Style/GuardClause if @delegate_object[:menu_with_shell] ( formatted_choice_ostructs[:shell].dname, 1, '', menu_state: MenuState::SHELL, source_id: "#{source_id}_vmahf_shell" ) end # rubocop:enable Style/GuardClause end |
#vux_navigate_back_for_ls ⇒ Object
5845 5846 5847 5848 5849 5850 5851 5852 |
# File 'lib/hash_delegator.rb', line 5845 def vux_navigate_back_for_ls InputSequencer.merge_link_state( @dml_link_state, InputSequencer.next_link_state( **execute_navigate_back.merge(prior_block_was_link: true) ) ) end |
#vux_parse_document(source_id: '') ⇒ Object
5854 5855 5856 5857 5858 5859 5860 5861 5862 5863 5864 5865 5866 5867 5868 5869 5870 5871 5872 5873 5874 5875 5876 5877 5878 5879 5880 |
# File 'lib/hash_delegator.rb', line 5854 def vux_parse_document(source_id: '') @run_state.batch_index += 1 @run_state.in_own_window = false @run_state.source.block_name_from_cli, @dml_now_using_cli = manage_cli_selection_state( block_name_from_cli: @run_state.source.block_name_from_cli, now_using_cli: @dml_now_using_cli, link_state: @dml_link_state ) @delegate_object[:filename] = @dml_link_state.document_filename @dml_link_state.block_name = @delegate_object[:block_name] = if @run_state.source.block_name_from_cli @cli_block_name else @dml_link_state.block_name end # update @delegate_object and @menu_base_options in auto_load # @dml_blocks_in_file, , @dml_mdoc = ( @dml_link_state, source_id: source_id ) dump_delobj(@dml_blocks_in_file, , @dml_link_state) end |
#vux_publish_block_name_for_external_automation(block_name) ⇒ Object
5882 5883 5884 5885 5886 |
# File 'lib/hash_delegator.rb', line 5882 def vux_publish_block_name_for_external_automation(block_name) publish_for_external_automation( message: formatted_block_name(block_name) ) end |
#vux_publish_document_file_name_for_external_automation ⇒ Object
5888 5889 5890 5891 5892 5893 5894 5895 5896 5897 5898 5899 5900 |
# File 'lib/hash_delegator.rb', line 5888 def vux_publish_document_file_name_for_external_automation return unless @delegate_object[:publish_document_file_name].present? publish_for_external_automation( message: format( @delegate_object[:publish_document_name_format], { document: @delegate_object[:filename], time: Time.now.utc.strftime( @delegate_object[:publish_time_format] ) } ) ) end |
#vux_user_selected_block_name ⇒ Object
return :break to break from loop
5903 5904 5905 5906 5907 5908 5909 5910 5911 5912 5913 5914 5915 5916 5917 5918 5919 5920 5921 |
# File 'lib/hash_delegator.rb', line 5903 def vux_user_selected_block_name if @dml_link_state.block_name.present? # @prior_block_was_link = true @dml_block_state.block = find_block_by_name( @dml_blocks_in_file, @dml_link_state.block_name ) @dml_link_state.block_name = nil else # puts "? - Select a block to execute (or type #{$texit} # to exit):" return :break if vux_await_user_selection( prior_answer: @dml_block_selection ) == :break return :break if @dml_block_state.block.nil? # no block matched end # puts "! - Executing block: #{data}" @dml_block_state.block&.id end |
#vux_view_inherited(stream:) ⇒ Object
5923 5924 5925 |
# File 'lib/hash_delegator.rb', line 5923 def vux_view_inherited(stream:) stream.puts @dml_link_state.inherited_lines_block end |
#wait_for_stream_processing ⇒ Object
5927 5928 5929 5930 5931 5932 5933 |
# File 'lib/hash_delegator.rb', line 5927 def wait_for_stream_processing @process_mutex.synchronize do @process_cv.wait(@process_mutex) end rescue Interrupt # user interrupts process end |
#wait_for_user_selected_block(all_blocks, menu_blocks, prior_answer) ⇒ Object
5935 5936 5937 5938 5939 5940 |
# File 'lib/hash_delegator.rb', line 5935 def wait_for_user_selected_block(all_blocks, , prior_answer) block_state = wait_for_user_selection(all_blocks, , prior_answer) handle_back_or_continue(block_state) block_state end |
#wait_for_user_selection(_all_blocks, menu_blocks, prior_answer) ⇒ Object
5942 5943 5944 5945 5946 5947 5948 5949 5950 5951 5952 5953 5954 5955 5956 5957 5958 5959 5960 5961 5962 5963 5964 5965 5966 5967 5968 5969 5970 5971 5972 5973 5974 5975 5976 5977 5978 5979 5980 5981 5982 5983 5984 5985 5986 5987 5988 5989 5990 5991 5992 5993 |
# File 'lib/hash_delegator.rb', line 5942 def wait_for_user_selection(_all_blocks, , prior_answer) if @delegate_object[:clear_screen_for_select_block] printf("\e[1;1H\e[2J") end prompt_title = string_send_color( @delegate_object[:prompt_select_block].to_s, :prompt_color_after_script_execution ) = () if .empty? return SelectedBlockMenuState.new(nil, OpenStruct.new, MenuState::EXIT) end selected_answer = case prior_answer when nil nil when String .find do |block| block.id == prior_answer end&.name when Struct, MarkdownExec::FCB if prior_answer.id # when switching documents, # the prior answer will not be found (.find_index do |block| block[:id] == prior_answer.id end || 0) + 1 else prior_answer.index || prior_answer.name end end # prior_answer value may not match if color is different from # originating menu (opts changed while processing) selection_opts = if selected_answer @delegate_object.merge(default: selected_answer) else @delegate_object end selection_opts.merge!( { cycle: @delegate_object[:select_page_cycle], per_page: @delegate_object[:select_page_height] } ) selected_option = ( prompt_title, , selection_opts ) determine_block_state(selected_option) end |
#warning_required_empty(export) ⇒ Object
5995 5996 5997 |
# File 'lib/hash_delegator.rb', line 5995 def warning_required_empty(export) "A value must exist for: #{export.required.join(', ')}" end |
#write_command_file(required_lines:, blockname:, shell: nil) ⇒ Object
Handles the core logic for generating the command file’s metadata and content.
6001 6002 6003 6004 6005 6006 6007 6008 6009 6010 6011 6012 6013 6014 6015 6016 6017 6018 6019 6020 6021 6022 6023 6024 6025 6026 6027 6028 6029 6030 6031 6032 6033 6034 6035 6036 6037 6038 6039 6040 6041 |
# File 'lib/hash_delegator.rb', line 6001 def write_command_file(required_lines:, blockname:, shell: nil) return unless @delegate_object[:save_executed_script] time_now = Time.now.utc @run_state.saved_script_filename = SavedAsset.new( blockname: blockname, exts: '.sh', filename: @delegate_object[:filename], prefix: @delegate_object[:saved_script_filename_prefix], saved_asset_format: shell_escape_asset_format( code_lines: @dml_link_state.inherited_lines, shell: shell ), time: time_now ).generate_name @run_state.saved_filespec = File.join(@delegate_object[:saved_script_folder], @run_state.saved_script_filename) shebang = if @delegate_object[:shebang]&.present? "#{@delegate_object[:shebang]} #{shell}\n" else '' end content = shebang + "# file_name: #{@delegate_object[:filename]}\n" \ "# block_name: #{@delegate_object[:block_name]}\n" \ "# time: #{time_now}\n" \ "#{required_lines.flatten.join("\n")}\n" HashDelegator.( @run_state.saved_filespec, content, @delegate_object[:saved_script_chmod] ) rescue StandardError HashDelegator.error_handler('write_command_file') end |
#write_file_with_directory_creation(content:, filespec:) ⇒ Object
Ensure the directory exists before writing the file
6044 6045 6046 6047 6048 6049 6050 6051 6052 6053 6054 6055 6056 6057 6058 6059 6060 6061 6062 |
# File 'lib/hash_delegator.rb', line 6044 def write_file_with_directory_creation(content:, filespec:) directory = File.dirname(filespec) begin FileUtils.mkdir_p(directory) File.write(filespec, content) rescue Errno::EACCES warn "Permission denied: Unable to write to file '#{filespec}'" nil rescue Errno::EROFS warn 'Read-only file system: Unable to write to file ' \ "'#{filespec}'" nil rescue StandardError => err warn 'An error occurred while writing to file ' \ "'#{filespec}': #{err.message}" nil end end |
#write_inherited_lines_to_file(link_state, link_block_data) ⇒ Object
return next document file name
6065 6066 6067 6068 6069 6070 6071 6072 6073 6074 6075 6076 6077 6078 6079 6080 6081 |
# File 'lib/hash_delegator.rb', line 6065 def write_inherited_lines_to_file(link_state, link_block_data) save_expr = link_block_data.fetch(LinkKeys::SAVE, '') if save_expr.present? save_filespec = save_filespec_from_expression(save_expr) if save_filespec.present? File.write( save_filespec, HashDelegator.join_code_lines(link_state&.inherited_lines) ) @delegate_object[:filename] else link_block_data[LinkKeys::FILE] || @delegate_object[:filename] end else link_block_data[LinkKeys::FILE] || @delegate_object[:filename] end end |