markdown_exec 2.0.2 → 2.0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ece122ac9b2994b3a0ee90b6a6b07f637abd015f45b2275c0bcf740a2fbfb173
4
- data.tar.gz: f8c79187fc3f1fb4f8d53750dbb6078cb81ab58c04114bc484cd66ed22f890a5
3
+ metadata.gz: f8472bfcb1c813c87b1094fa2d9789b48b864e1bb8ab76d0f8ae1001237af3e0
4
+ data.tar.gz: 2699ed15974d6b89ffc3dea6c172044b4fb427e8a8d5184c25fb0cc7d5ad33ae
5
5
  SHA512:
6
- metadata.gz: 57246f8b67613bdf55911dcc5274b7bad32b3702c3070ee75f30754ea8a816ebeee42b930bceb363313256b1b5368fd05bf2c1ccfbde545ea934d6b9d66d8e86
7
- data.tar.gz: fefcd1ed4b825a81cd9e5bfa79c0c3124550778908ad2200dd6ac9cd5db1ba6c70d2cc4987df05700ba2dd554461fd0b39ba330a32209f2edc7a7ad80cdadff3
6
+ metadata.gz: 9fbf04758308b522967bb9587eae0ac1d9bb0517697260a228b5c56bf1e2aac582f7aaa5b94aa021d5112a34327865c9535b3aa62fe62e00cd590c541077a6fd
7
+ data.tar.gz: 2a200effafe807181c6e9bda44e67dcb3978e02333ea61d06d30cb934a5e8bcf4e9f117fddb258cfd0397f833574c2abbb451ab061ff654f654c934f9dddbf65
data/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.0.3] - 2024-04-15
4
+
5
+ ### Added
6
+
7
+ - Option to set menu line count to fill console height.
8
+ - Rescue when named block in link block is missing.
9
+
10
+ ### Changed
11
+
12
+ - Fix handling of variables with spaces in link blocks.
13
+ - Fix substitution for '/' in block names used in file names.
14
+
3
15
  ## [2.0.2] - 2024-02-09
4
16
 
5
17
  ### Changed
data/Gemfile CHANGED
@@ -9,7 +9,6 @@ gemspec
9
9
  gem 'clipboard'
10
10
  gem 'debug'
11
11
  gem 'erb'
12
- # gem 'httparty' # 2024-01-01 for ChatGPI API
13
12
  gem 'irb', '>= 1.8.0'
14
13
  gem 'mocha', require: false
15
14
  gem 'minitest', require: false
@@ -24,6 +23,5 @@ gem 'rubocop-minitest', require: false
24
23
  gem 'rubocop-rake', require: false
25
24
  gem 'rubocop-rspec', require: false
26
25
  gem 'shellwords'
27
- # gem 'tty-file'
28
26
  gem 'uri', '0.12.2'
29
27
  gem 'yaml', '~> 0.2.1'
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- markdown_exec (2.0.2)
4
+ markdown_exec (2.0.3.1)
5
5
  clipboard (~> 1.3.6)
6
6
  open3 (~> 0.1.1)
7
7
  optparse (~> 0.1.1)
@@ -13,7 +13,7 @@ __filedirs_all()
13
13
  }
14
14
 
15
15
  _mde_echo_version() {
16
- echo "2.0.2"
16
+ echo "2.0.3.1"
17
17
  }
18
18
 
19
19
  _mde() {
@@ -186,4 +186,4 @@ _mde() {
186
186
 
187
187
  complete -o filenames -o nospace -F _mde mde
188
188
  # _mde_echo_version
189
- # echo "Updated: 2024-02-09 19:26:00 UTC"
189
+ # echo "Updated: 2024-04-18 00:17:10 UTC"
data/examples/linked.md CHANGED
@@ -5,6 +5,11 @@ pause_after_script_execution: false
5
5
  user_must_approve: false
6
6
  ```
7
7
 
8
+ ```link :missing_block
9
+ block: (display_variable)
10
+ eval: true
11
+ ```
12
+
8
13
  ```link :link_with_vars_with_spaces
9
14
  vars:
10
15
  test: "1 2 3"
@@ -33,11 +33,15 @@ class AnsiFormatter
33
33
  def scan_and_process_multiple_substrings(str, substrings, plain_sym, color_sym)
34
34
  return string_send_color(str, plain_sym) if substrings.empty? || substrings.any?(&:empty?)
35
35
 
36
+ substring_patterns = substrings.map do |value|
37
+ [value, Regexp.new(value, Regexp::IGNORECASE)]
38
+ end
39
+
36
40
  results = []
37
41
  remaining_str = str.dup
38
42
 
39
43
  while remaining_str.length.positive?
40
- match_indices = substrings.map { |substring| remaining_str.index(substring) }.compact
44
+ match_indices = substring_patterns.map { |_, pattern| remaining_str.index(pattern) }.compact
41
45
  earliest_match = match_indices.min
42
46
 
43
47
  if earliest_match
@@ -48,12 +52,12 @@ class AnsiFormatter
48
52
  end
49
53
 
50
54
  # Find which substring has this earliest match
51
- matching_substring = substrings.find do |substring|
52
- remaining_str.index(substring) == earliest_match
55
+ matching_substring = substring_patterns.find do |_, pattern|
56
+ remaining_str.index(pattern) == earliest_match
53
57
  end
54
58
 
55
59
  if matching_substring
56
- matching_segment = remaining_str.slice!(0...matching_substring.length)
60
+ matching_segment = remaining_str.slice!(0...matching_substring[0].length)
57
61
  results << string_send_color(matching_segment, color_sym)
58
62
  end
59
63
  else
@@ -102,7 +102,7 @@ class DirectorySearcher
102
102
  # @param include_subdirectories [Boolean] Whether to search in subdirectories.
103
103
  # @param filename_glob [String, nil] Glob pattern for file names.
104
104
  def initialize(pattern, paths, include_subdirectories: true, filename_glob: '*.[Mm][Dd]') #'*.md'
105
- @pattern = pattern
105
+ @pattern = Regexp.new(pattern, Regexp::IGNORECASE)
106
106
  @paths = paths
107
107
  @include_subdirectories = include_subdirectories
108
108
  @filename_glob = filename_glob
@@ -8,10 +8,11 @@ require 'clipboard'
8
8
  require 'fileutils'
9
9
  require 'open3'
10
10
  require 'optparse'
11
+ require 'ostruct'
11
12
  require 'set'
12
13
  require 'shellwords'
14
+ require 'tempfile'
13
15
  require 'tmpdir'
14
- # require 'tty-file'
15
16
  require 'tty-prompt'
16
17
  require 'yaml'
17
18
 
@@ -21,6 +22,7 @@ require_relative 'block_label'
21
22
  require_relative 'block_types'
22
23
  require_relative 'cached_nested_file_reader'
23
24
  require_relative 'constants'
25
+ require_relative 'std_out_err_logger'
24
26
  require_relative 'directory_searcher'
25
27
  require_relative 'exceptions'
26
28
  require_relative 'fcb'
@@ -193,18 +195,15 @@ module HashDelegatorSelf
193
195
  end
194
196
 
195
197
  def next_link_state(block_name_from_cli:, was_using_cli:, block_state:, block_name: nil)
196
- # &bsp 'next_link_state', block_name_from_cli, was_using_cli, block_state
197
198
  # Set block_name based on block_name_from_cli
198
199
  block_name = @cli_block_name if block_name_from_cli
199
- # &bsp 'block_name:', block_name
200
200
 
201
201
  # Determine the state of breaker based on was_using_cli and the block type
202
+ # true only when block_name is nil, block_name_from_cli is false, was_using_cli is true, and the block_state.block[:shell] equals BlockType::BASH. In all other scenarios, breaker is false.
202
203
  breaker = !block_name && !block_name_from_cli && was_using_cli && block_state.block[:shell] == BlockType::BASH
203
- # &bsp 'breaker:', breaker
204
204
 
205
205
  # Reset block_name_from_cli if the conditions are not met
206
206
  block_name_from_cli ||= false
207
- # &bsp 'block_name_from_cli:', block_name_from_cli
208
207
 
209
208
  [block_name, block_name_from_cli, breaker]
210
209
  end
@@ -352,6 +351,20 @@ module CompactionHelpers
352
351
  end
353
352
  end
354
353
 
354
+ module PathUtils
355
+ # Determines if a given path is absolute or substitutes a placeholder in an expression with the path.
356
+ # @param path [String] The input path to check or fill in.
357
+ # @param expression [String] The expression where a wildcard '*' is replaced by the path if it's not absolute.
358
+ # @return [String] The absolute path or the expression with the wildcard replaced by the path.
359
+ def self.resolve_path_or_substitute(path, expression)
360
+ if path.include?('/')
361
+ path
362
+ else
363
+ expression.gsub('*', path)
364
+ end
365
+ end
366
+ end
367
+
355
368
  module MarkdownExec
356
369
  class DebugHelper
357
370
  # Class-level variable to store history of printed messages
@@ -368,7 +381,7 @@ module MarkdownExec
368
381
  end
369
382
  end
370
383
 
371
- class HashDelegator
384
+ class HashDelegatorParent
372
385
  attr_accessor :most_recent_loaded_filename, :pass_args, :run_state
373
386
 
374
387
  extend HashDelegatorSelf
@@ -559,11 +572,11 @@ module MarkdownExec
559
572
 
560
573
  # private
561
574
 
562
- def calc_logged_stdout_filename
575
+ def calc_logged_stdout_filename(block_name:)
563
576
  return unless @delegate_object[:saved_stdout_folder]
564
577
 
565
578
  @delegate_object[:logged_stdout_filename] =
566
- SavedAsset.stdout_name(blockname: @delegate_object[:block_name],
579
+ SavedAsset.stdout_name(blockname: block_name,
567
580
  filename: File.basename(@delegate_object[:filename],
568
581
  '.*'),
569
582
  prefix: @delegate_object[:logged_stdout_filename_prefix],
@@ -898,7 +911,7 @@ module MarkdownExec
898
911
  # @param selected [FCB] The selected functional code block object.
899
912
  def execute_required_lines(required_lines: [], selected: FCB.new)
900
913
  write_command_file(required_lines: required_lines, selected: selected) if @delegate_object[:save_executed_script]
901
- calc_logged_stdout_filename
914
+ calc_logged_stdout_filename(block_name: @dml_block_state.block[:oname]) if @dml_block_state
902
915
  format_and_execute_command(code_lines: required_lines)
903
916
  post_execution_process
904
917
  end
@@ -950,7 +963,6 @@ module MarkdownExec
950
963
  next_load_file: LoadFile::Reuse
951
964
  )
952
965
 
953
-
954
966
  elsif selected[:shell] == BlockType::VARS
955
967
  debounce_reset
956
968
  block_names = []
@@ -972,6 +984,7 @@ module MarkdownExec
972
984
  selected: selected,
973
985
  link_state: link_state,
974
986
  block_source: block_source)
987
+
975
988
  else
976
989
  LoadFileLinkState.new(LoadFile::Reuse, link_state)
977
990
  end
@@ -1131,43 +1144,46 @@ module MarkdownExec
1131
1144
 
1132
1145
  def link_block_data_eval(link_state, code_lines, selected, link_block_data, block_source:)
1133
1146
  all_code = HashDelegator.code_merge(link_state&.inherited_lines, code_lines)
1147
+ cmd = "#{@delegate_object[:shell]} #{file.path}"
1148
+ output_lines = []
1134
1149
 
1135
- if link_block_data.fetch(LinkKeys::Exec, false)
1136
- @run_state.files = Hash.new([])
1137
- output_lines = []
1150
+ Tempfile.open do |file|
1151
+ file.write(all_code.join("\n"))
1152
+ file.rewind
1138
1153
 
1139
- Open3.popen3(
1140
- @delegate_object[:shell],
1141
- '-c', all_code.join("\n")
1142
- ) do |stdin, stdout, stderr, _exec_thr|
1143
- handle_stream(stream: stdout, file_type: ExecutionStreams::StdOut) do |line|
1144
- output_lines.push(line)
1145
- end
1146
- handle_stream(stream: stderr, file_type: ExecutionStreams::StdErr) do |line|
1147
- output_lines.push(line)
1148
- end
1154
+ if link_block_data.fetch(LinkKeys::Exec, false)
1155
+ @run_state.files = Hash.new([])
1149
1156
 
1150
- in_thr = handle_stream(stream: $stdin, file_type: ExecutionStreams::StdIn) do |line|
1151
- stdin.puts(line)
1152
- end
1157
+ Open3.popen3(cmd) do |stdin, stdout, stderr, _exec_thr|
1158
+ handle_stream(stream: stdout, file_type: ExecutionStreams::StdOut) do |line|
1159
+ output_lines.push(line)
1160
+ end
1161
+ handle_stream(stream: stderr, file_type: ExecutionStreams::StdErr) do |line|
1162
+ output_lines.push(line)
1163
+ end
1153
1164
 
1154
- wait_for_stream_processing
1155
- sleep 0.1
1156
- in_thr.kill if in_thr&.alive?
1157
- end
1165
+ in_thr = handle_stream(stream: $stdin, file_type: ExecutionStreams::StdIn) do |line|
1166
+ stdin.puts(line)
1167
+ end
1158
1168
 
1159
- ## select output_lines that look like assignment or match other specs
1160
- #
1161
- output_lines = process_string_array(
1162
- output_lines,
1163
- begin_pattern: @delegate_object.fetch(:output_assignment_begin, nil),
1164
- end_pattern: @delegate_object.fetch(:output_assignment_end, nil),
1165
- scan1: @delegate_object.fetch(:output_assignment_match, nil),
1166
- format1: @delegate_object.fetch(:output_assignment_format, nil)
1167
- )
1169
+ wait_for_stream_processing
1170
+ sleep 0.1
1171
+ in_thr.kill if in_thr&.alive?
1172
+ end
1168
1173
 
1169
- else
1170
- output_lines = `#{all_code.join("\n")}`.split("\n")
1174
+ ## select output_lines that look like assignment or match other specs
1175
+ #
1176
+ output_lines = process_string_array(
1177
+ output_lines,
1178
+ begin_pattern: @delegate_object.fetch(:output_assignment_begin, nil),
1179
+ end_pattern: @delegate_object.fetch(:output_assignment_end, nil),
1180
+ scan1: @delegate_object.fetch(:output_assignment_match, nil),
1181
+ format1: @delegate_object.fetch(:output_assignment_format, nil)
1182
+ )
1183
+
1184
+ else
1185
+ output_lines = `#{cmd}`.split("\n")
1186
+ end
1171
1187
  end
1172
1188
 
1173
1189
  HashDelegator.error_handler('all_code eval output_lines is nil', { abort: true }) unless output_lines
@@ -1285,7 +1301,7 @@ module MarkdownExec
1285
1301
  puts format(@delegate_object[:prompt_show_expr_format],
1286
1302
  { expr: filespec })
1287
1303
  puts @delegate_object[:prompt_enter_filespec]
1288
- resolve_path_or_substitute(gets.chomp, filespec)
1304
+ PathUtils.resolve_path_or_substitute(gets.chomp, filespec)
1289
1305
  end
1290
1306
 
1291
1307
  # Handle expression with wildcard characters
@@ -1320,11 +1336,34 @@ module MarkdownExec
1320
1336
  }
1321
1337
  end
1322
1338
 
1339
+ # # Loads auto link block.
1340
+ # def load_auto_link_block(all_blocks, link_state, mdoc, block_source:)
1341
+ # block_name = @delegate_object[:document_load_link_block_name]
1342
+ # return unless block_name.present? && @most_recent_loaded_filename != @delegate_object[:filename]
1343
+
1344
+ # block = HashDelegator.block_find(all_blocks, :oname, block_name)
1345
+ # return unless block
1346
+
1347
+ # if block.fetch(:shell, '') != BlockType::LINK
1348
+ # HashDelegator.error_handler('must be Link block type', { abort: true })
1349
+
1350
+ # else
1351
+ # # debounce_reset
1352
+ # push_link_history_and_trigger_load(
1353
+ # link_block_body: block.fetch(:body, ''),
1354
+ # mdoc: mdoc,
1355
+ # selected: block,
1356
+ # link_state: link_state,
1357
+ # block_source: block_source
1358
+ # )
1359
+ # end
1360
+ # end
1361
+
1323
1362
  # Loads auto blocks based on delegate object settings and updates if new filename is detected.
1324
1363
  # Executes a specified block once per filename.
1325
1364
  # @param all_blocks [Array] Array of all block elements.
1326
1365
  # @return [Boolean, nil] True if values were modified, nil otherwise.
1327
- def load_auto_blocks(all_blocks)
1366
+ def load_auto_opts_block(all_blocks)
1328
1367
  block_name = @delegate_object[:document_load_opts_block_name]
1329
1368
  return unless block_name.present? && @most_recent_loaded_filename != @delegate_object[:filename]
1330
1369
 
@@ -1354,7 +1393,8 @@ module MarkdownExec
1354
1393
 
1355
1394
  # recreate menu with new options
1356
1395
  #
1357
- all_blocks, mdoc = mdoc_and_blocks_from_nested_files if load_auto_blocks(all_blocks)
1396
+ all_blocks, mdoc = mdoc_and_blocks_from_nested_files if load_auto_opts_block(all_blocks)
1397
+ # load_auto_link_block(all_blocks, link_state, mdoc, block_source: {})
1358
1398
 
1359
1399
  menu_blocks = mdoc.fcbs_per_options(@delegate_object)
1360
1400
  add_menu_chrome_blocks!(menu_blocks: menu_blocks, link_state: link_state)
@@ -1756,18 +1796,6 @@ module MarkdownExec
1756
1796
  end
1757
1797
  end
1758
1798
 
1759
- # Determines if a given path is absolute or substitutes a placeholder in an expression with the path.
1760
- # @param path [String] The input path to check or fill in.
1761
- # @param expression [String] The expression where a wildcard '*' is replaced by the path if it's not absolute.
1762
- # @return [String] The absolute path or the expression with the wildcard replaced by the path.
1763
- def resolve_path_or_substitute(path, expression)
1764
- if path.include?('/')
1765
- path
1766
- else
1767
- expression.gsub('*', path)
1768
- end
1769
- end
1770
-
1771
1799
  def runtime_exception(exception_sym, name, items)
1772
1800
  if @delegate_object[exception_sym] != 0
1773
1801
  data = { name: name, detail: items.join(', ') }
@@ -1841,12 +1869,20 @@ module MarkdownExec
1841
1869
  @delegate_object[:block_name] = nil
1842
1870
 
1843
1871
  when :user_choice
1844
- # puts "? - Select a block to execute (or type #{$texit} to exit):"
1845
- break if ii_user_choice == :break # into @dml_block_state
1846
- break if @dml_block_state.block.nil? # no block matched
1847
-
1872
+ if @dml_link_state.block_name.present?
1873
+ # @prior_block_was_link = true
1874
+ @dml_block_state.block = @dml_blocks_in_file.find do |item|
1875
+ item[:oname] == @dml_link_state.block_name
1876
+ end
1877
+ @dml_link_state.block_name = nil
1878
+ else
1879
+ # puts "? - Select a block to execute (or type #{$texit} to exit):"
1880
+ break if ii_user_choice == :break # into @dml_block_state
1881
+ break if @dml_block_state.block.nil? # no block matched
1882
+ end
1848
1883
  # puts "! - Executing block: #{data}"
1849
- @dml_block_state.block[:oname]
1884
+ # @dml_block_state.block[:oname]
1885
+ @dml_block_state.block&.fetch(:oname, nil)
1850
1886
 
1851
1887
  when :execute_block
1852
1888
  block_name = data
@@ -1888,13 +1924,12 @@ module MarkdownExec
1888
1924
 
1889
1925
  ## order of block name processing: link block, cli, from user
1890
1926
  #
1891
- @cli_block_name = block_name
1892
1927
  @dml_link_state.block_name, @run_state.block_name_from_cli, cli_break = \
1893
1928
  HashDelegator.next_link_state(
1894
- block_name_from_cli: !@dml_link_state.block_name,
1895
- was_using_cli: @dml_now_using_cli,
1929
+ block_name: @dml_link_state.block_name,
1930
+ block_name_from_cli: !@dml_link_state.block_name.present?,
1896
1931
  block_state: @dml_block_state,
1897
- block_name: @dml_link_state.block_name
1932
+ was_using_cli: @dml_now_using_cli
1898
1933
  )
1899
1934
 
1900
1935
  if !@dml_block_state.block[:block_name_from_ui] && cli_break
@@ -2282,7 +2317,12 @@ module MarkdownExec
2282
2317
  @delegate_object
2283
2318
  end
2284
2319
 
2285
- selection_opts.merge!(per_page: @delegate_object[:select_page_height])
2320
+ sph = @delegate_object[:select_page_height]
2321
+ unless sph.positive?
2322
+ require 'io/console'
2323
+ sph = [IO.console.winsize[0] - 3, 4].max
2324
+ end
2325
+ selection_opts.merge!(per_page: sph)
2286
2326
 
2287
2327
  selected_option = select_option_with_metadata(prompt_title, block_menu,
2288
2328
  selection_opts)
@@ -2331,13 +2371,63 @@ module MarkdownExec
2331
2371
  if save_expr.present?
2332
2372
  save_filespec = save_filespec_from_expression(save_expr)
2333
2373
  File.write(save_filespec, HashDelegator.join_code_lines(link_state&.inherited_lines))
2334
- # TTY::File.create_file save_filespec, HahDelegator.join_code_lines(link_state&.inherited_lines), force: true
2335
2374
  @delegate_object[:filename]
2336
2375
  else
2337
2376
  link_block_data[LinkKeys::File] || @delegate_object[:filename]
2338
2377
  end
2339
2378
  end
2340
2379
  end
2380
+
2381
+ class HashDelegator < HashDelegatorParent
2382
+ # Cleans a value, handling both Hash and Struct types.
2383
+ # For Structs, the cleaned version is converted to a hash.
2384
+ def self.clean_value(value)
2385
+ case value
2386
+ when Hash
2387
+ clean_hash_recursively(value)
2388
+ when Struct
2389
+ struct_hash = value.to_h # Convert the Struct to a hash
2390
+ cleaned_hash = clean_hash_recursively(struct_hash) # Clean the hash
2391
+ # Return the cleaned hash instead of updating the Struct
2392
+ return cleaned_hash
2393
+ else
2394
+ value
2395
+ end
2396
+ end
2397
+
2398
+ # Recursively cleans the given object (hash or struct) from unwanted values.
2399
+ def self.clean_hash_recursively(obj)
2400
+ obj.each do |key, value|
2401
+ cleaned_value = clean_value(value) # Clean and possibly convert value
2402
+ obj[key] = cleaned_value if value.is_a?(Hash) || value.is_a?(Struct)
2403
+ end
2404
+
2405
+ if obj.is_a?(Hash)
2406
+ obj.select! { |key, value| ![nil, '', [], {}, nil].include?(value) }
2407
+ end
2408
+
2409
+ obj
2410
+ end
2411
+
2412
+ def self.next_link_state(*args, **kwargs, &block)
2413
+ super
2414
+ # result = super
2415
+
2416
+ # @logger ||= StdOutErrLogger.new
2417
+ # @logger.unknown(
2418
+ # HashDelegator.clean_hash_recursively(
2419
+ # { "HashDelegator.next_link_state":
2420
+ # { 'args': args,
2421
+ # 'at': Time.now.strftime('%FT%TZ'),
2422
+ # 'for': /[^\/]+:\d+/.match(caller.first)[0],
2423
+ # 'kwargs': kwargs,
2424
+ # 'return': result } }
2425
+ # )
2426
+ # )
2427
+
2428
+ # result
2429
+ end
2430
+ end
2341
2431
  end
2342
2432
 
2343
2433
  return if $PROGRAM_NAME != __FILE__
@@ -2348,12 +2438,20 @@ Bundler.require(:default)
2348
2438
  require 'minitest/autorun'
2349
2439
  require 'mocha/minitest'
2350
2440
 
2351
- ####
2352
- require_relative 'instance_method_wrapper'
2353
- # MarkdownExec::HashDelegator.prepend(InstanceMethodWrapper)
2354
- # MarkdownExec::HashDelegator.singleton_class.prepend(ClassMethodWrapper)
2441
+ require_relative 'std_out_err_logger'
2355
2442
 
2356
2443
  module MarkdownExec
2444
+ class TestHashDelegator0 < Minitest::Test
2445
+ def setup
2446
+ @hd = HashDelegator.new
2447
+ end
2448
+
2449
+ # Test case for empty body
2450
+ def test_next_link_state
2451
+ @hd.next_link_state(block_name_from_cli: nil, was_using_cli: nil, block_state: nil, block_name: nil)
2452
+ end
2453
+ end
2454
+
2357
2455
  class TestHashDelegator < Minitest::Test
2358
2456
  def setup
2359
2457
  @hd = HashDelegator.new
@@ -3194,29 +3292,33 @@ module MarkdownExec
3194
3292
  end
3195
3293
  end
3196
3294
 
3197
- def test_resolves_absolute_path
3198
- absolute_path = '/usr/local/bin'
3199
- assert_equal '/usr/local/bin', resolve_path_or_substitute(absolute_path, 'prefix/*/suffix')
3200
- end
3295
+ class PathUtilsTest < Minitest::Test
3296
+ def test_absolute_path_returns_unchanged
3297
+ absolute_path = "/usr/local/bin"
3298
+ expression = "path/to/*/directory"
3299
+ assert_equal absolute_path, PathUtils.resolve_path_or_substitute(absolute_path, expression)
3300
+ end
3201
3301
 
3202
- def test_substitutes_wildcard_with_path
3203
- path = 'bin'
3204
- expression = 'prefix/*/suffix'
3205
- expected_result = 'prefix/bin/suffix'
3206
- assert_equal expected_result, resolve_path_or_substitute(path, expression)
3207
- end
3302
+ def test_relative_path_gets_substituted
3303
+ relative_path = "my_folder"
3304
+ expression = "path/to/*/directory"
3305
+ expected_output = "path/to/my_folder/directory"
3306
+ assert_equal expected_output, PathUtils.resolve_path_or_substitute(relative_path, expression)
3307
+ end
3208
3308
 
3209
- def test_handles_path_with_no_separator_as_is
3210
- path = 'bin'
3211
- expression = 'prefix*suffix'
3212
- expected_result = 'prefixbinsuffix'
3213
- assert_equal expected_result, resolve_path_or_substitute(path, expression)
3214
- end
3309
+ def test_path_with_no_slash_substitutes_correctly
3310
+ relative_path = "data"
3311
+ expression = "path/to/*/directory"
3312
+ expected_output = "path/to/data/directory"
3313
+ assert_equal expected_output, PathUtils.resolve_path_or_substitute(relative_path, expression)
3314
+ end
3215
3315
 
3216
- def test_returns_expression_unchanged_for_empty_path
3217
- path = ''
3218
- expression = 'prefix/*/suffix'
3219
- expected_result = 'prefix/*/suffix'
3220
- assert_equal expected_result, resolve_path_or_substitute(path, expression)
3316
+ def test_empty_path_substitution
3317
+ empty_path = ""
3318
+ expression = "path/to/*/directory"
3319
+ expected_output = "path/to//directory"
3320
+ assert_equal expected_output, PathUtils.resolve_path_or_substitute(empty_path, expression)
3321
+ end
3221
3322
  end
3323
+
3222
3324
  end # module MarkdownExec
@@ -34,7 +34,8 @@ class InputSequencer
34
34
  prior_block_was_link: next_state.prior_block_was_link.nil? ? current.prior_block_was_link : next_state.prior_block_was_link
35
35
  )
36
36
  rescue
37
- binding.irb
37
+ pp $!, $@
38
+ exit 1
38
39
  end
39
40
 
40
41
  # Generates the next menu state based on provided attributes.
@@ -75,11 +76,14 @@ class InputSequencer
75
76
 
76
77
  if now_menu.display_menu
77
78
  exit_when_bq_empty = false
78
-
79
79
  run_yield :display_menu, &block
80
80
 
81
81
  choice = run_yield :user_choice, &block
82
82
 
83
+ if choice.nil?
84
+ raise "Block not recognized."
85
+ break
86
+ end
83
87
  break if run_yield(:exit?, choice&.downcase, &block) # Exit loop and method to terminate the app
84
88
 
85
89
  next_state = run_yield :execute_block, choice, &block
@@ -115,7 +119,8 @@ class InputSequencer
115
119
  now_menu = InputSequencer.merge_link_state(now_menu, next_menu)
116
120
  end
117
121
  rescue
118
- binding.irb
122
+ pp $!, $@
123
+ exit 1
119
124
  end
120
125
  end
121
126
 
@@ -7,5 +7,5 @@ module MarkdownExec
7
7
  BIN_NAME = 'mde'
8
8
  GEM_NAME = 'markdown_exec'
9
9
  TAP_DEBUG = 'MDE_DEBUG'
10
- VERSION = '2.0.2'
10
+ VERSION = '2.0.3.1'
11
11
  end
data/lib/markdown_exec.rb CHANGED
@@ -10,7 +10,6 @@ require 'open3'
10
10
  require 'optparse'
11
11
  require 'shellwords'
12
12
  require 'tmpdir'
13
- # require 'tty-file'
14
13
  require 'tty-prompt'
15
14
  require 'yaml'
16
15
 
data/lib/menu.src.yml CHANGED
@@ -99,6 +99,12 @@
99
99
  :opt_name: display_level_xbase_prefix
100
100
  :procname: val_as_str
101
101
 
102
+ # - :default: "(document_link)"
103
+ # :description: Name of Link block to load with the document
104
+ # :env_var: MDE_DOCUMENT_LOAD_LINK_BLOCK_NAME
105
+ # :opt_name: document_load_link_block_name
106
+ # :procname: val_as_str
107
+
102
108
  - :default: "(document_options)"
103
109
  :description: Name of Opts block to load with the document
104
110
  :env_var: MDE_DOCUMENT_LOAD_OPTS_BLOCK_NAME
@@ -108,7 +114,6 @@
108
114
  - :arg_name: BOOL
109
115
  :default: false
110
116
  :description: Dump @delegate_object
111
- :env_var: MDE_DUMP_DELEGATE_OBJECT
112
117
  :long_name: dump-dump-delegate-object
113
118
  :opt_name: dump_delegate_object
114
119
  :procname: val_as_bool
@@ -116,7 +121,6 @@
116
121
  - :arg_name: BOOL
117
122
  :default: false
118
123
  :description: Dump BlocksInFile (stage 1)
119
- :env_var: MDE_DUMP_BLOCKS_IN_FILE
120
124
  :long_name: dump-blocks-in-file
121
125
  :opt_name: dump_blocks_in_file
122
126
  :procname: val_as_bool
@@ -124,7 +128,6 @@
124
128
  - :arg_name: BOOL
125
129
  :default: false
126
130
  :description: Dump inherited block_names
127
- :env_var: MDE_DUMP_INHERITED_BLOCK_NAMES
128
131
  :long_name: dump-dump-inherited-block_names
129
132
  :opt_name: dump_inherited_block_names
130
133
  :procname: val_as_bool
@@ -132,7 +135,6 @@
132
135
  - :arg_name: BOOL
133
136
  :default: false
134
137
  :description: Dump inherited dependencies
135
- :env_var: MDE_DUMP_INHERITED_DEPENDENCIES
136
138
  :long_name: dump-dump-inherited-dependencies
137
139
  :opt_name: dump_inherited_dependencies
138
140
  :procname: val_as_bool
@@ -140,7 +142,6 @@
140
142
  - :arg_name: BOOL
141
143
  :default: false
142
144
  :description: Dump inherited lines
143
- :env_var: MDE_DUMP_INHERITED_LINES
144
145
  :long_name: dump-dump-inherited-lines
145
146
  :opt_name: dump_inherited_lines
146
147
  :procname: val_as_bool
@@ -148,7 +149,6 @@
148
149
  - :arg_name: BOOL
149
150
  :default: false
150
151
  :description: Dump MenuBlocks (stage 2)
151
- :env_var: MDE_DUMP_MENU_BLOCKS
152
152
  :long_name: dump-menu-blocks
153
153
  :opt_name: dump_menu_blocks
154
154
  :procname: val_as_bool
@@ -156,7 +156,6 @@
156
156
  - :arg_name: BOOL
157
157
  :default: false
158
158
  :description: Dump selected block
159
- :env_var: MDE_DUMP_SELECTED_BLOCK
160
159
  :long_name: dump-selected-block
161
160
  :opt_name: dump_selected_block
162
161
  :procname: val_as_bool
@@ -206,35 +205,30 @@
206
205
  :opt_name: exclude_expect_blocks
207
206
  :procname: val_as_bool
208
207
 
208
+ # - :default: >
209
+ # osascript scripts/applescript/mde.applescript "%{batch_index}" "%{home}" " %{started_at} - %{document_filename} - %{block_name} " "%{script_filespec}" "%{output_filespec}"
209
210
  - :default: >
210
211
  osascript -e '
211
- tell application "iTerm"
212
- tell application "System Events"
213
- tell application "Finder"
214
- set {posx, posy, screenWidth, screenHeight} to bounds of window of desktop
215
- end tell
216
- tell application process "Finder"
217
- set {missing value, menubarHeight} to the size of menu bar 1
218
- end tell
219
- end tell
220
-
221
- set winHeight to (screenHeight * 2 / 3)
222
- set winWidth to (screenWidth * 2 / 3)
223
- set xoff to menubarHeight * %{batch_index}
224
- set yoff to xoff mod (screenHeight - winHeight)
225
-
226
- create window with default profile
227
- tell the first window
228
- set bounds to {xoff, yoff, xoff + winWidth, yoff + winHeight}
229
- tell the current session
230
- write text "s=\"%{script_filespec}\""
231
- write text "o=\"%{output_filespec}\""
232
- write text "cd \"%{home}\""
233
- write text "echo -ne \"\\033]; %{started_at} - %{document_filename} - %{block_name} \\007\""
234
- write text "\"$s\" | tee -a \"$o\""
235
- end tell
236
- end tell
237
- end tell'
212
+ on run argv
213
+ set batch_index to "%{batch_index}"
214
+ set home to "%{home}"
215
+ set output_filespec to "%{output_filespec}"
216
+ set script_filespec to "%{script_filespec}"
217
+ set title to " %{started_at} - %{document_filename} - %{block_name} "
218
+
219
+ tell application "iTerm"
220
+ create window with default profile
221
+ tell the first window
222
+ tell the current session
223
+ write text "s=" & quoted form of script_filespec & ""
224
+ write text "o=" & quoted form of output_filespec & ""
225
+ write text "cd " & quoted form of home & ""
226
+ write text "echo -ne \"\\033]; " & title & " \\007\""
227
+ write text "\"$s\" 2>&1 | tee -a \"$o\""
228
+ end tell
229
+ end tell
230
+ end tell
231
+ end run'
238
232
  :description: execute_command_format
239
233
  :env_var: MDE_EXECUTE_COMMAND_FORMAT
240
234
  :opt_name: execute_command_format
@@ -247,7 +241,7 @@
247
241
  :procname: val_as_str
248
242
 
249
243
  - :arg_name: BOOL
250
- :default: true
244
+ :default: false
251
245
  :description: Execute script in own window
252
246
  :env_var: MDE_EXECUTE_IN_OWN_WINDOW
253
247
  :opt_name: execute_in_own_window
@@ -301,7 +295,7 @@
301
295
 
302
296
  - :arg_name: FIND
303
297
  :default: ''
304
- :description: Find in documents
298
+ :description: Find argument in documents
305
299
  :long_name: find
306
300
  :procname: find
307
301
  :short_name: "?"
@@ -1056,8 +1050,8 @@
1056
1050
  :opt_name: select_by_shell_regex
1057
1051
  :procname: val_as_str
1058
1052
 
1059
- - :default: 36
1060
- :description: 'Maximum # of rows in select list'
1053
+ - :default: 0
1054
+ :description: 'Maximum # of rows in select list. Detects current limit if not specified.'
1061
1055
  :env_var: MDE_SELECT_PAGE_HEIGHT
1062
1056
  :opt_name: select_page_height
1063
1057
  :procname: val_as_int
data/lib/menu.yml CHANGED
@@ -1,4 +1,4 @@
1
- # MDE - Markdown Executor (2.0.2)
1
+ # MDE - Markdown Executor (2.0.3.1)
2
2
  ---
3
3
  - :description: Show current configuration values
4
4
  :procname: show_config
@@ -91,49 +91,42 @@
91
91
  - :arg_name: BOOL
92
92
  :default: false
93
93
  :description: Dump @delegate_object
94
- :env_var: MDE_DUMP_DELEGATE_OBJECT
95
94
  :long_name: dump-dump-delegate-object
96
95
  :opt_name: dump_delegate_object
97
96
  :procname: val_as_bool
98
97
  - :arg_name: BOOL
99
98
  :default: false
100
99
  :description: Dump BlocksInFile (stage 1)
101
- :env_var: MDE_DUMP_BLOCKS_IN_FILE
102
100
  :long_name: dump-blocks-in-file
103
101
  :opt_name: dump_blocks_in_file
104
102
  :procname: val_as_bool
105
103
  - :arg_name: BOOL
106
104
  :default: false
107
105
  :description: Dump inherited block_names
108
- :env_var: MDE_DUMP_INHERITED_BLOCK_NAMES
109
106
  :long_name: dump-dump-inherited-block_names
110
107
  :opt_name: dump_inherited_block_names
111
108
  :procname: val_as_bool
112
109
  - :arg_name: BOOL
113
110
  :default: false
114
111
  :description: Dump inherited dependencies
115
- :env_var: MDE_DUMP_INHERITED_DEPENDENCIES
116
112
  :long_name: dump-dump-inherited-dependencies
117
113
  :opt_name: dump_inherited_dependencies
118
114
  :procname: val_as_bool
119
115
  - :arg_name: BOOL
120
116
  :default: false
121
117
  :description: Dump inherited lines
122
- :env_var: MDE_DUMP_INHERITED_LINES
123
118
  :long_name: dump-dump-inherited-lines
124
119
  :opt_name: dump_inherited_lines
125
120
  :procname: val_as_bool
126
121
  - :arg_name: BOOL
127
122
  :default: false
128
123
  :description: Dump MenuBlocks (stage 2)
129
- :env_var: MDE_DUMP_MENU_BLOCKS
130
124
  :long_name: dump-menu-blocks
131
125
  :opt_name: dump_menu_blocks
132
126
  :procname: val_as_bool
133
127
  - :arg_name: BOOL
134
128
  :default: false
135
129
  :description: Dump selected block
136
- :env_var: MDE_DUMP_SELECTED_BLOCK
137
130
  :long_name: dump-selected-block
138
131
  :opt_name: dump_selected_block
139
132
  :procname: val_as_bool
@@ -177,21 +170,28 @@
177
170
  :env_var: MDE_EXCLUDE_EXPECT_BLOCKS
178
171
  :opt_name: exclude_expect_blocks
179
172
  :procname: val_as_bool
180
- - :default: "osascript -e '\n tell application \"iTerm\"\n tell application
181
- \"System Events\"\n tell application \"Finder\"\n set
182
- {posx, posy, screenWidth, screenHeight} to bounds of window of desktop\n end
183
- tell\n tell application process \"Finder\"\n set {missing
184
- value, menubarHeight} to the size of menu bar 1\n end tell\n end
185
- tell\n\n set winHeight to (screenHeight * 2 / 3)\n set winWidth
186
- to (screenWidth * 2 / 3)\n set xoff to menubarHeight * %{batch_index}\n
187
- \ set yoff to xoff mod (screenHeight - winHeight)\n \n create
188
- window with default profile\n tell the first window\n set bounds
189
- to {xoff, yoff, xoff + winWidth, yoff + winHeight}\n tell the current
190
- session\n write text \"s=\\\"%{script_filespec}\\\"\"\n write
191
- text \"o=\\\"%{output_filespec}\\\"\"\n write text \"cd \\\"%{home}\\\"\"\n
192
- \ write text \"echo -ne \\\"\\\\033]; %{started_at} - %{document_filename}
193
- - %{block_name} \\\\007\\\"\"\n write text \"\\\"$s\\\" | tee -a
194
- \\\"$o\\\"\"\n end tell\n end tell\n end tell'\n"
173
+ - :default: |
174
+ osascript -e '
175
+ on run argv
176
+ set batch_index to "%{batch_index}"
177
+ set home to "%{home}"
178
+ set output_filespec to "%{output_filespec}"
179
+ set script_filespec to "%{script_filespec}"
180
+ set title to " %{started_at} - %{document_filename} - %{block_name} "
181
+
182
+ tell application "iTerm"
183
+ create window with default profile
184
+ tell the first window
185
+ tell the current session
186
+ write text "s=" & quoted form of script_filespec & ""
187
+ write text "o=" & quoted form of output_filespec & ""
188
+ write text "cd " & quoted form of home & ""
189
+ write text "echo -ne \"\\033]; " & title & " \\007\""
190
+ write text "\"$s\" 2>&1 | tee -a \"$o\""
191
+ end tell
192
+ end tell
193
+ end tell
194
+ end run'
195
195
  :description: execute_command_format
196
196
  :env_var: MDE_EXECUTE_COMMAND_FORMAT
197
197
  :opt_name: execute_command_format
@@ -202,7 +202,7 @@
202
202
  :opt_name: execute_command_title_time_format
203
203
  :procname: val_as_str
204
204
  - :arg_name: BOOL
205
- :default: true
205
+ :default: false
206
206
  :description: Execute script in own window
207
207
  :env_var: MDE_EXECUTE_IN_OWN_WINDOW
208
208
  :opt_name: execute_in_own_window
@@ -249,7 +249,7 @@
249
249
  :short_name: f
250
250
  - :arg_name: FIND
251
251
  :default: ''
252
- :description: Find in documents
252
+ :description: Find argument in documents
253
253
  :long_name: find
254
254
  :procname: find
255
255
  :short_name: "?"
@@ -901,8 +901,8 @@
901
901
  :env_var: MDE_SELECT_BY_SHELL_REGEX
902
902
  :opt_name: select_by_shell_regex
903
903
  :procname: val_as_str
904
- - :default: 36
905
- :description: 'Maximum # of rows in select list'
904
+ - :default: 0
905
+ :description: 'Maximum # of rows in select list. Detects current limit if not specified.'
906
906
  :env_var: MDE_SELECT_PAGE_HEIGHT
907
907
  :opt_name: select_page_height
908
908
  :procname: val_as_int
data/lib/saved_assets.rb CHANGED
@@ -19,43 +19,45 @@ module MarkdownExec
19
19
  # Generates a formatted script name based on the provided parameters.
20
20
  def self.script_name(filename:, prefix:, time:, blockname:, ftime: DEFAULT_FTIME, join_str: '_', pattern: FNR11, replace: FNR12, exts: '.sh')
21
21
  fne = filename.gsub(pattern, replace)
22
- "#{[prefix, time.strftime(ftime), fne, ',', blockname].join(join_str)}#{exts}"
22
+ bne = blockname.gsub(pattern, replace)
23
+ "#{[prefix, time.strftime(ftime), fne, ',', bne].join(join_str)}#{exts}"
23
24
  end
24
25
 
25
26
  # Generates a formatted stdout name based on the provided parameters.
26
27
  def self.stdout_name(filename:, prefix:, time:, blockname:, ftime: DEFAULT_FTIME, join_str: '_', pattern: FNR11, replace: FNR12, exts: '.out.txt')
27
28
  fne = filename.gsub(pattern, replace)
28
- "#{[prefix, time.strftime(ftime), fne, ',', blockname].join(join_str)}#{exts}"
29
+ bne = blockname.gsub(pattern, replace)
30
+ "#{[prefix, time.strftime(ftime), fne, ',', bne].join(join_str)}#{exts}"
29
31
  end
30
32
  end
31
33
  end
32
34
 
33
- if $PROGRAM_NAME == __FILE__
34
- require 'minitest/autorun'
35
+ return if $PROGRAM_NAME != __FILE__
35
36
 
36
- class SavedAssetTest < Minitest::Test
37
- def test_script_name
38
- filename = 'sample.txt'
39
- prefix = 'test'
40
- time = Time.new(2023, 1, 1, 12, 0, 0) # Sample date-time for consistency in testing
41
- blockname = 'block1'
37
+ require 'minitest/autorun'
42
38
 
43
- expected_name = 'test_2023-01-01-12-00-00_sample.txt_,_block1.sh'
44
- assert_equal expected_name,
45
- MarkdownExec::SavedAsset.script_name(filename: filename, prefix: prefix, time: time,
46
- blockname: blockname)
47
- end
39
+ class SavedAssetTest < Minitest::Test
40
+ def test_script_name_with_special_characters_in_blockname
41
+ filename = 'sample.txt'
42
+ prefix = 'test'
43
+ time = Time.new(2023, 1, 1, 12, 0, 0)
44
+ blockname = 'block/1:2'
45
+
46
+ expected_name = 'test_2023-01-01-12-00-00_sample.txt_,_block_1_2.sh'
47
+ assert_equal expected_name, MarkdownExec::SavedAsset.script_name(
48
+ filename: filename, prefix: prefix, time: time, blockname: blockname
49
+ )
50
+ end
48
51
 
49
- def test_stdout_name
50
- filename = 'sample.txt'
51
- prefix = 'test'
52
- time = Time.new(2023, 1, 1, 12, 0, 0)
53
- blockname = 'block1'
52
+ def test_stdout_name_with_special_characters_in_blockname
53
+ filename = 'sample.txt'
54
+ prefix = 'test'
55
+ time = Time.new(2023, 1, 1, 12, 0, 0)
56
+ blockname = 'block/1:2'
54
57
 
55
- expected_name = 'test_2023-01-01-12-00-00_sample.txt_,_block1.out.txt'
56
- assert_equal expected_name,
57
- MarkdownExec::SavedAsset.stdout_name(filename: filename, prefix: prefix, time: time,
58
- blockname: blockname)
59
- end
58
+ expected_name = 'test_2023-01-01-12-00-00_sample.txt_,_block_1_2.out.txt'
59
+ assert_equal expected_name, MarkdownExec::SavedAsset.stdout_name(
60
+ filename: filename, prefix: prefix, time: time, blockname: blockname
61
+ )
60
62
  end
61
63
  end
@@ -0,0 +1,121 @@
1
+ #!/usr/bin/env -S bundle exec ruby
2
+ # frozen_string_literal: true
3
+
4
+ # encoding=utf-8
5
+ require 'logger'
6
+
7
+ # Logger::LogDevice is used by Logger, the parent class of StdOutErrLogger
8
+ class Logger::LogDevice
9
+ # remove header
10
+ def add_log_header(file); end
11
+ end
12
+
13
+ # Custom logger to direct info to stdout and warn and above to stderr
14
+ #
15
+ class StdOutErrLogger < Logger
16
+ attr_reader :file
17
+
18
+ # def initialize(file = nil)
19
+ def initialize(file = "#{__dir__}/../tmp/hash_delegator_next_link_state.yaml")
20
+ @file = file
21
+ super(file || STDOUT)
22
+ self.formatter = proc do |severity, datetime, progname, msg|
23
+ "#{msg}\n"
24
+ end
25
+ end
26
+
27
+ def add(severity, message = nil, progname = nil, &block)
28
+ message = (message || block&.call || progname) if message.nil?
29
+ message = "- #{message.to_json}\n"
30
+ ### message = message.join("\n") if message.is_a? Array
31
+ out = format_message(format_severity(severity), Time.now, progname, message)
32
+ if severity == Logger::UNKNOWN # does not follow spec, outputs to stderr for IO
33
+ # $stderr.puts(out)
34
+ super
35
+ elsif severity >= Logger::WARN
36
+ if @file
37
+ super
38
+ else
39
+ $stderr.puts(out)
40
+ end
41
+ else
42
+ if @file
43
+ super
44
+ else
45
+ $stdout.puts(out)
46
+ end
47
+ end
48
+ end
49
+ end
50
+
51
+ return if $PROGRAM_NAME != __FILE__
52
+
53
+ require 'minitest/autorun'
54
+
55
+ class StdOutErrLoggerTest < Minitest::Test
56
+ # Redirect STDOUT and STDERR to capture them for assertions
57
+ def setup
58
+ @original_stdout = $stdout
59
+ @original_stderr = $stderr
60
+ $stdout = StringIO.new
61
+ $stderr = StringIO.new
62
+ end
63
+
64
+ def teardown
65
+ $stdout = @original_stdout
66
+ $stderr = @original_stderr
67
+ end
68
+
69
+ def test_initialize_without_file
70
+ logger = StdOutErrLogger.new
71
+ assert_nil logger.file
72
+ assert_equal Logger::DEBUG, logger.level
73
+ end
74
+
75
+ def test_initialize_with_file
76
+ Tempfile.open do |file|
77
+ logger = StdOutErrLogger.new(file.path)
78
+ assert_equal file.path, logger.file
79
+ end
80
+ end
81
+
82
+ def test_logging_info
83
+ logger = StdOutErrLogger.new
84
+ logger.info("Info message")
85
+ assert_equal "Info message\n", $stdout.string
86
+ assert_empty $stderr.string
87
+ end
88
+
89
+ def test_logging_warning
90
+ logger = StdOutErrLogger.new
91
+ logger.warn("Warning message")
92
+ assert_empty $stdout.string
93
+ assert_equal "Warning message\n", $stderr.string
94
+ end
95
+
96
+ def test_logging_error
97
+ logger = StdOutErrLogger.new
98
+ logger.error("Error message")
99
+ assert_empty $stdout.string
100
+ assert_equal "Error message\n", $stderr.string
101
+ end
102
+
103
+ def test_logging_with_array
104
+ logger = StdOutErrLogger.new
105
+ logger.info(["Message line 1", "Message line 2"])
106
+ assert_equal "Message line 1\nMessage line 2\n", $stdout.string
107
+ end
108
+
109
+ def test_logging_with_block
110
+ logger = StdOutErrLogger.new
111
+ logger.info { "Block message" }
112
+ assert_equal "Block message\n", $stdout.string
113
+ end
114
+
115
+ def test_logging_unknown_severity
116
+ logger = StdOutErrLogger.new
117
+ logger.add(Logger::UNKNOWN, "Unknown severity message")
118
+ assert_empty $stdout.string
119
+ assert_equal "Unknown severity message\n", $stderr.string
120
+ end
121
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: markdown_exec
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.2
4
+ version: 2.0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fareed Stevenson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-02-09 00:00:00.000000000 Z
11
+ date: 2024-04-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: clipboard
@@ -169,6 +169,7 @@ files:
169
169
  - lib/saved_assets.rb
170
170
  - lib/saved_files_matcher.rb
171
171
  - lib/shared.rb
172
+ - lib/std_out_err_logger.rb
172
173
  - lib/string_util.rb
173
174
  - lib/tap.rb
174
175
  homepage: https://rubygems.org/gems/markdown_exec