markdown_exec 2.0.4 → 2.0.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: eadeecd7019d53202aabe57d9486ee616826e6b5f42fce0fa24f8e377c1b50e5
4
- data.tar.gz: cde007bddd4821263045eeba415cc1e2f42591d03294fc678c4093384373146b
3
+ metadata.gz: eb96e0d1b92398066dedcaf7017ee6d7deea37ef9ba19fa089de6c4e5aebf27d
4
+ data.tar.gz: f8b8ffcb0f30fbec9321a4a9f14ae7568b16b31e40833046fb1ab16ddcf28c1b
5
5
  SHA512:
6
- metadata.gz: 5a4a3a36d420c41403be33dbc7ac8e53f446dac53ba3ce8e9cd2fafb1ff0c1026aa1df633f6d79e1742ea11a07f71bd3f64df95f772798ff4624b8c36a8f93b2
7
- data.tar.gz: 1acc6cb2bf716b30a1ab8037ad0e43ff3646b23b991cd1bd9d31b1aad37ccf6ae97bd01eaeecc57e644ceb580a9aa9bf61742075777a528ffc180a43a955ccb1
6
+ metadata.gz: 96a95683c52b4a7546d2cb1ce399dd6c278a7783305d70e12a0a8ac5c70df739705a0ccb06a14f8861ca5794193f201ab185cd7e994e6fcc4eef56a0f038504e
7
+ data.tar.gz: 51991405ec7dae5c31dcc1ff6294172279d046975647ca8676b4e28918d2ff954a19e671bae4cc7381963816f8b0826b4723c4bf61fb6a35fd8fce25e808ed63
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## [2.0.5] - 2024-04-24
4
+
5
+ ### Changed
6
+
7
+ - Open option: Search for keyword in block names instead of entire document.
8
+
3
9
  ## [2.0.4] - 2024-04-22
4
10
 
5
11
  ### Added
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- markdown_exec (2.0.4)
4
+ markdown_exec (2.0.5)
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.4"
16
+ echo "2.0.5"
17
17
  }
18
18
 
19
19
  _mde() {
@@ -194,4 +194,4 @@ _mde() {
194
194
 
195
195
  complete -o filenames -o nospace -F _mde mde
196
196
  # _mde_echo_version
197
- # echo "Updated: 2024-04-23 01:25:22 UTC"
197
+ # echo "Updated: 2024-04-26 15:37:23 UTC"
@@ -0,0 +1,21 @@
1
+ Demonstrate keyword search in documents.
2
+ Keywords in body: monkey secret
3
+
4
+ Keyword in untyped block name.
5
+ ``` :monkey1
6
+ ```
7
+
8
+ Keyword in Bash block name.
9
+ ```bash :monkey2
10
+ ```
11
+
12
+ Keyword in block body.
13
+ ```
14
+ monkey3
15
+ ```
16
+
17
+ Keyword in Link block body.
18
+ ```link
19
+ vars:
20
+ monkey4: 4
21
+ ```
@@ -160,9 +160,11 @@ class DirectorySearcher
160
160
  begin
161
161
  File.foreach(p).with_index(1) do |line, line_num| # Index starts from 1 for line numbers
162
162
  line_utf8 = line.encode('UTF-8', invalid: :replace, undef: :replace, replace: '')
163
- if line_utf8.match?(@pattern)
163
+
164
+ line_utf8 = yield(line_utf8) if block_given?
165
+
166
+ if line_utf8&.match?(@pattern)
164
167
  match_details[p] ||= []
165
- # match_details[p] << { number: line_num, line: line_utf8.chomp }
166
168
  match_details[p] << IndexedLine.new(line_num, line_utf8.chomp)
167
169
  end
168
170
  end
data/lib/find_files.rb CHANGED
@@ -37,9 +37,7 @@ def find_files(pattern, paths = ['', Dir.pwd], exclude_dirs: false)
37
37
  files = Dir.glob(search_pattern, File::FNM_DOTMATCH)
38
38
 
39
39
  # Optionally exclude "." and ".." and directory names
40
- if exclude_dirs
41
- files.reject! { |file| file.end_with?('/.', '/..') || File.directory?(file) }
42
- end
40
+ files.reject! { |file| file.end_with?('/.', '/..') || File.directory?(file) } if exclude_dirs
43
41
 
44
42
  matched_files += files
45
43
  end
@@ -232,16 +232,46 @@ module HashDelegatorSelf
232
232
  FileUtils.rm_f(path)
233
233
  end
234
234
 
235
- # Evaluates the given string as Ruby code and rescues any StandardErrors.
235
+ # Evaluates the given string as Ruby code within a safe context.
236
236
  # If an error occurs, it calls the error_handler method with 'safeval'.
237
237
  # @param str [String] The string to be evaluated.
238
238
  # @return [Object] The result of evaluating the string.
239
239
  def safeval(str)
240
- eval(str)
240
+ # # Restricting to evaluate only expressions
241
+ # unless str.match?(/\A\s*\w+\s*[\+\-\*\/\=\%\&\|\<\>\!]+\s*\w+\s*\z/)
242
+ # error_handler('safeval') # 'Invalid expression'
243
+ # return
244
+ # end
245
+
246
+ # # Whitelisting allowed operations
247
+ # allowed_methods = %w[+ - * / == != < > <= >= && || % & |]
248
+ # unless allowed_methods.any? { |op| str.include?(op) }
249
+ # error_handler('safeval', 'Operation not allowed')
250
+ # return
251
+ # end
252
+
253
+ # # Sanitize input (example: removing potentially harmful characters)
254
+ # str = str.gsub(/[^0-9\+\-\*\/\(\)\<\>\!\=\%\&\|]/, '')
255
+
256
+ # Evaluate the sanitized string
257
+ result = nil
258
+ binding.eval("result = #{str}")
259
+
260
+ result
241
261
  rescue StandardError # catches NameError, StandardError
242
262
  error_handler('safeval')
243
263
  end
244
264
 
265
+ # # Evaluates the given string as Ruby code and rescues any StandardErrors.
266
+ # # If an error occurs, it calls the error_handler method with 'safeval'.
267
+ # # @param str [String] The string to be evaluated.
268
+ # # @return [Object] The result of evaluating the string.
269
+ # def safeval(str)
270
+ # eval(str)
271
+ # rescue StandardError # catches NameError, StandardError
272
+ # error_handler('safeval')
273
+ # end
274
+
245
275
  def set_file_permissions(file_path, chmod_value)
246
276
  File.chmod(chmod_value, file_path)
247
277
  end
@@ -1321,6 +1351,18 @@ module MarkdownExec
1321
1351
  PathUtils.resolve_path_or_substitute(gets.chomp, filespec)
1322
1352
  end
1323
1353
 
1354
+ # def read_block_name(line)
1355
+ # bm = extract_named_captures_from_option(line, @delegate_object[:block_name_match])
1356
+ # name = bm[:title]
1357
+
1358
+ # if @delegate_object[:block_name_nick_match].present? && line =~ Regexp.new(@delegate_object[:block_name_nick_match])
1359
+ # name = $~[0]
1360
+ # else
1361
+ # name = bm && bm[1] ? bm[:title] : name
1362
+ # end
1363
+ # name
1364
+ # end
1365
+
1324
1366
  # Handle expression with wildcard characters
1325
1367
  # allow user to select or enter
1326
1368
  def save_filespec_wildcard_expansion(filespec)
@@ -1813,6 +1855,22 @@ module MarkdownExec
1813
1855
  end
1814
1856
  end
1815
1857
 
1858
+ # Check if the delegate object responds to a given method.
1859
+ # @param method_name [Symbol] The name of the method to check.
1860
+ # @param include_private [Boolean] Whether to include private methods in the check.
1861
+ # @return [Boolean] true if the delegate object responds to the method, false otherwise.
1862
+ def respond_to?(method_name, include_private = false)
1863
+ if super
1864
+ true
1865
+ elsif @delegate_object.respond_to?(method_name, include_private)
1866
+ true
1867
+ elsif method_name.to_s.end_with?('=') && @delegate_object.respond_to?(:[]=, include_private)
1868
+ true
1869
+ else
1870
+ @delegate_object.respond_to?(method_name, include_private)
1871
+ end
1872
+ end
1873
+
1816
1874
  def runtime_exception(exception_sym, name, items)
1817
1875
  if @delegate_object[exception_sym] != 0
1818
1876
  data = { name: name, detail: items.join(', ') }
@@ -2120,7 +2178,6 @@ module MarkdownExec
2120
2178
 
2121
2179
  # Presents a TTY prompt to select an option or exit, returns metadata including option and selected
2122
2180
  def select_option_with_metadata(prompt_text, names, opts = {})
2123
-
2124
2181
  ## configure to environment
2125
2182
  #
2126
2183
  unless opts[:select_page_height].positive?
@@ -2128,14 +2185,15 @@ module MarkdownExec
2128
2185
  opts[:per_page] = opts[:select_page_height] = [IO.console.winsize[0] - 3, 4].max
2129
2186
  end
2130
2187
 
2188
+ # crashes if all menu options are disabled
2131
2189
  selection = @prompt.select(prompt_text,
2132
2190
  names,
2133
2191
  opts.merge(filter: true))
2134
2192
  item = names.find do |item|
2135
- if item.instance_of?(String)
2136
- item == selection
2137
- else
2193
+ if item.instance_of?(Hash)
2138
2194
  item[:dname] == selection
2195
+ else
2196
+ item == selection
2139
2197
  end
2140
2198
  end
2141
2199
  item = { dname: item } if item.instance_of?(String)
@@ -19,7 +19,7 @@ class InputSequencer
19
19
  @document_filename = document_filename
20
20
  @current_block = nil
21
21
  @block_queue = initial_blocks
22
- @debug = Env::env_bool('INPUT_SEQUENCER_DEBUG', default: false) ### false e
22
+ @debug = Env.env_bool('INPUT_SEQUENCER_DEBUG', default: false)
23
23
  end
24
24
 
25
25
  # Merges the current menu state with the next, prioritizing the next state's values.
@@ -33,9 +33,11 @@ class InputSequencer
33
33
  inherited_lines: next_state.inherited_lines,
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
+ # rubocop:disable Style/RescueStandardError
36
37
  rescue
37
38
  pp $!, $@
38
39
  exit 1
40
+ # rubocop:enable Style/RescueStandardError
39
41
  end
40
42
 
41
43
  # Generates the next menu state based on provided attributes.
@@ -69,7 +71,6 @@ class InputSequencer
69
71
  loop do
70
72
  break if run_yield(:parse_document, now_menu.document_filename, &block) == :break
71
73
 
72
- pp [__LINE__, 'exit_when_bq_empty', exit_when_bq_empty, '@block_queue', @block_queue, 'now_menu', now_menu] if @debug
73
74
  # self.imw_ins now_menu, 'now_menu'
74
75
 
75
76
  break if exit_when_bq_empty && bq_is_empty? && !now_menu.prior_block_was_link
@@ -81,14 +82,13 @@ class InputSequencer
81
82
  choice = run_yield :user_choice, &block
82
83
 
83
84
  if choice.nil?
84
- raise "Block not recognized."
85
+ raise 'Block not recognized.'
85
86
  break
86
87
  end
87
88
  break if run_yield(:exit?, choice&.downcase, &block) # Exit loop and method to terminate the app
88
89
 
89
90
  next_state = run_yield :execute_block, choice, &block
90
91
  # imw_ins next_state, 'next_state'
91
- pp [__LINE__, 'next_state', next_state] if @debug
92
92
  return :break if next_state == :break
93
93
 
94
94
  next_menu = next_state
@@ -102,7 +102,6 @@ class InputSequencer
102
102
  block_name = @block_queue.shift
103
103
  end
104
104
  # self.imw_ins block_name, 'block_name'
105
- pp [__LINE__, 'block_name', block_name] if @debug
106
105
 
107
106
  next_menu = if block_name == '.'
108
107
  exit_when_bq_empty = false
@@ -112,15 +111,16 @@ class InputSequencer
112
111
  state.display_menu = bq_is_empty?
113
112
  state
114
113
  end
115
- pp [__LINE__, 'next_menu', next_menu] if @debug
116
114
  next_menu
117
115
  # imw_ins next_menu, 'next_menu'
118
116
  end
119
117
  now_menu = InputSequencer.merge_link_state(now_menu, next_menu)
120
118
  end
119
+ # rubocop:disable Style/RescueStandardError
121
120
  rescue
122
121
  pp $!, $@
123
122
  exit 1
123
+ # rubocop:enable Style/RescueStandardError
124
124
  end
125
125
  end
126
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.4'
10
+ VERSION = '2.0.5'
11
11
  end
data/lib/markdown_exec.rb CHANGED
@@ -9,6 +9,7 @@ require 'fileutils'
9
9
  require 'open3'
10
10
  require 'optparse'
11
11
  require 'shellwords'
12
+ require 'time'
12
13
  require 'tmpdir'
13
14
  require 'tty-prompt'
14
15
  require 'yaml'
@@ -103,6 +104,79 @@ end
103
104
  module MarkdownExec
104
105
  include Exceptions
105
106
 
107
+ class FileInMenu
108
+ # Prepends the age of the file in days to the file name for display in a menu.
109
+ # @param filename [String] the name of the file
110
+ # @return [String] modified file name with age prepended
111
+ def self.for_menu(filename)
112
+ file_age = (Time.now - File.mtime(filename)) / (60 * 60 * 24 * 30)
113
+
114
+ " #{Histogram.display(file_age, 0, 11, 12, inverse: false)}: #{filename}"
115
+ end
116
+
117
+ # Removes the age from the string to retrieve the original file name.
118
+ # @param filename_with_age [String] the modified file name with age
119
+ # @return [String] the original file name
120
+ def self.from_menu(filename_with_age)
121
+ filename_with_age.split(': ', 2).last
122
+ end
123
+ end
124
+
125
+ # A class that generates a histogram bar in terminal using xterm-256 color codes.
126
+ class Histogram
127
+ # Generates and prints a histogram bar for a given value within a specified range and width, with an option for inverse display.
128
+ # @param integer_value [Integer] the value to represent in the histogram
129
+ # @param min [Integer] the minimum value of the range
130
+ # @param max [Integer] the maximum value of the range
131
+ # @param width [Integer] the total width of the histogram in characters
132
+ # @param inverse [Boolean] whether the histogram is displayed in inverse order (right to left)
133
+ def self.display(integer_value, min, max, width, inverse: false)
134
+ return if max <= min # Ensure the range is valid
135
+
136
+ # Normalize the value within the range 0 to 1
137
+ normalized_value = [0, [(integer_value - min).to_f / (max - min), 1].min].max
138
+
139
+ # Calculate how many characters should be filled
140
+ filled_length = (normalized_value * width).round
141
+
142
+ # # Generate the histogram bar using xterm-256 colors (color code 42 is green)
143
+ # filled_bar = "\e[48;5;42m" + ' ' * filled_length + "\e[0m"
144
+ filled_bar = ('¤' * filled_length).fg_rgbh_AF_AF_00
145
+ empty_bar = ' ' * (width - filled_length)
146
+
147
+ # Determine the order of filled and empty parts based on the inverse flag
148
+ inverse ? (empty_bar + filled_bar) : (filled_bar + empty_bar)
149
+ end
150
+ end
151
+
152
+ class MenuBuilder
153
+ def initialize
154
+ @chrome_color = :cyan
155
+ @o_color = :red
156
+ end
157
+
158
+ def build_menu(file_names, directory_names, found_in_block_names, files_in_directories, vbn)
159
+ choices = []
160
+
161
+ # Adding section title and data for file names
162
+ choices << { disabled: '', name: "in #{file_names[:section_title]}".send(@chrome_color) }
163
+ choices += file_names[:data].map { |str| FileInMenu.for_menu(str) }
164
+
165
+ # Conditionally add directory names if data is present
166
+ unless directory_names[:data].count.zero?
167
+ choices << { disabled: '', name: "in #{directory_names[:section_title]}".send(@chrome_color) }
168
+ choices += files_in_directories
169
+ end
170
+
171
+ # Adding found in block names
172
+ choices << { disabled: '', name: "in #{found_in_block_names[:section_title]}".send(@chrome_color) }
173
+
174
+ choices += vbn
175
+
176
+ choices
177
+ end
178
+ end
179
+
106
180
  class SearchResultsReport < DirectorySearcher
107
181
  def directory_names(search_options, highlight_value)
108
182
  matched_directories = find_directory_names
@@ -113,20 +187,24 @@ module MarkdownExec
113
187
  }
114
188
  end
115
189
 
116
- def file_contents(search_options, highlight_value)
117
- matched_contents = find_file_contents.map.with_index do |(file, contents), index|
118
- [file, contents.map { |detail| format('=%4.d: %s', detail.index, detail.line) }, index]
190
+ def found_in_block_names(search_options, highlight_value, formspec: '=%<index>4.d: %<line>s')
191
+ matched_contents = (find_file_contents do |line|
192
+ read_block_name(line, search_options[:fenced_start_and_end_regex], search_options[:block_name_match], search_options[:block_name_nick_match])
193
+ end).map.with_index do |(file, contents), index|
194
+ # [file, contents.map { |detail| format(formspec, detail.index, detail.line) }, index]
195
+ [file, contents.map { |detail| format(formspec, { index: detail.index, line: detail.line }) }, index]
119
196
  end
120
197
  {
121
- section_title: 'file contents',
198
+ section_title: 'block names',
122
199
  data: matched_contents.map(&:first),
123
200
  formatted_text: matched_contents.map do |(file, details, index)|
124
- { header: format('- %3.d: %s', index + 1, file),
125
- content: AnsiFormatter.new(search_options).format_and_highlight_array(
126
- details,
127
- highlight: [highlight_value]
128
- ) }
129
- end
201
+ { header: format('- %3.d: %s', index + 1, file),
202
+ content: AnsiFormatter.new(search_options).format_and_highlight_array(
203
+ details,
204
+ highlight: [highlight_value]
205
+ ) }
206
+ end,
207
+ matched_contents: matched_contents
130
208
  }
131
209
  end
132
210
 
@@ -140,6 +218,21 @@ module MarkdownExec
140
218
  ).join("\n") }]
141
219
  }
142
220
  end
221
+
222
+ def read_block_name(line, fenced_start_and_end_regex, block_name_match, block_name_nick_match)
223
+ return unless line.match(fenced_start_and_end_regex)
224
+
225
+ bm = extract_named_captures_from_option(line, block_name_match)
226
+ return if bm.nil?
227
+
228
+ name = bm[:title]
229
+
230
+ if block_name_nick_match.present? && line =~ Regexp.new(block_name_nick_match)
231
+ $~[0]
232
+ else
233
+ bm && bm[1] ? bm[:title] : name
234
+ end
235
+ end
143
236
  end
144
237
 
145
238
  ##
@@ -353,16 +446,17 @@ module MarkdownExec
353
446
  :menu_chrome_color)}"
354
447
  searcher = SearchResultsReport.new(value, [find_path])
355
448
  file_names = searcher.file_names(options, value)
356
- file_contents = searcher.file_contents(options, value)
449
+ found_in_block_names = searcher.found_in_block_names(options, value, formspec: '%<line>s')
357
450
  directory_names = searcher.directory_names(options, value)
358
451
 
359
452
  ### search in file contents (block names, chrome, or text)
360
- [file_contents,
453
+ [found_in_block_names,
361
454
  directory_names,
362
455
  file_names].each do |data|
363
- @fout.fout "In #{data[:section_title]}" if data[:section_title]
456
+ next if data[:data].count.zero?
364
457
  next unless data[:formatted_text]
365
458
 
459
+ @fout.fout "In #{data[:section_title]}" if data[:section_title]
366
460
  data[:formatted_text].each do |fi|
367
461
  @fout.fout fi[:header] if fi[:header]
368
462
  @fout.fout fi[:content] if fi[:content]
@@ -372,17 +466,29 @@ module MarkdownExec
372
466
 
373
467
  ## pick a document to open
374
468
  #
375
- files = directory_names[:data].map do |dn|
469
+ files_in_directories = directory_names[:data].map do |dn|
376
470
  find_files('*', [dn], exclude_dirs: true)
377
- end.flatten(1)
378
- choices = \
379
- [{ disabled: '', name: "in #{file_names[:section_title]}".cyan }] \
380
- + file_names[:data] \
381
- + [{ disabled: '', name: "in #{directory_names[:section_title]}".cyan }] \
382
- + files \
383
- + [{ disabled: '', name: "in #{file_contents[:section_title]}".cyan }] \
384
- + file_contents[:data]
385
- @options[:filename] = select_document_if_multiple(choices)
471
+ end.flatten(1).map { |str| FileInMenu.for_menu(str) }
472
+
473
+ return { exit: true } unless file_names[:data]&.count.positive? || files_in_directories&.count.positive? || found_in_block_names[:data]&.count.positive?
474
+
475
+ vbn = found_in_block_names[:matched_contents].map do |matched_contents|
476
+ filename, details, = matched_contents
477
+ nexo = AnsiFormatter.new(@options).format_and_highlight_array(
478
+ details,
479
+ highlight: [value]
480
+ )
481
+ [FileInMenu.for_menu(filename)] + nexo.map { |str| { disabled: '', name: (' ' * 20) + str } }
482
+ end.flatten
483
+
484
+ choices = MenuBuilder.new.build_menu(file_names, directory_names, found_in_block_names, files_in_directories, vbn)
485
+
486
+ @options[:filename] = FileInMenu.from_menu(
487
+ select_document_if_multiple(
488
+ choices,
489
+ prompt: options[:prompt_select_md].to_s + ' ¤ Age in months'.fg_rgbh_AF_AF_00
490
+ )
491
+ )
386
492
  { exit: false }
387
493
  end
388
494
 
@@ -618,13 +724,13 @@ module MarkdownExec
618
724
  @options[:saved_filename_replacement])
619
725
  end
620
726
 
621
- def select_document_if_multiple(files = list_markdown_files_in_path)
727
+ def select_document_if_multiple(files = list_markdown_files_in_path, prompt: options[:prompt_select_md].to_s)
622
728
  return files[0] if (count = files.count) == 1
623
729
 
624
730
  return unless count >= 2
625
731
 
626
732
  opts = options.dup
627
- select_option_or_exit(HashDelegator.new(@options).string_send_color(opts[:prompt_select_md].to_s, :prompt_color_after_script_execution),
733
+ select_option_or_exit(HashDelegator.new(@options).string_send_color(prompt, :prompt_color_after_script_execution),
628
734
  files,
629
735
  opts.merge(per_page: opts[:select_page_height]))
630
736
  end
data/lib/menu.yml CHANGED
@@ -1,4 +1,4 @@
1
- # MDE - Markdown Executor (2.0.4)
1
+ # MDE - Markdown Executor (2.0.5)
2
2
  ---
3
3
  - :description: Show current configuration values
4
4
  :procname: show_config
@@ -18,8 +18,8 @@ class StdOutErrLogger < Logger
18
18
  # def initialize(file = nil)
19
19
  def initialize(file = "#{__dir__}/../tmp/hash_delegator_next_link_state.yaml")
20
20
  @file = file
21
- super(file || STDOUT)
22
- self.formatter = proc do |severity, datetime, progname, msg|
21
+ super(file || $stdout)
22
+ self.formatter = proc do |_severity, _datetime, _progname, msg|
23
23
  "#{msg}\n"
24
24
  end
25
25
  end
@@ -36,14 +36,12 @@ class StdOutErrLogger < Logger
36
36
  if @file
37
37
  super
38
38
  else
39
- $stderr.puts(out)
39
+ warn(out)
40
40
  end
41
+ elsif @file
42
+ super
41
43
  else
42
- if @file
43
- super
44
- else
45
- $stdout.puts(out)
46
- end
44
+ $stdout.puts(out)
47
45
  end
48
46
  end
49
47
  end
@@ -81,40 +79,40 @@ class StdOutErrLoggerTest < Minitest::Test
81
79
 
82
80
  def test_logging_info
83
81
  logger = StdOutErrLogger.new
84
- logger.info("Info message")
82
+ logger.info('Info message')
85
83
  assert_equal "Info message\n", $stdout.string
86
84
  assert_empty $stderr.string
87
85
  end
88
86
 
89
87
  def test_logging_warning
90
88
  logger = StdOutErrLogger.new
91
- logger.warn("Warning message")
89
+ logger.warn('Warning message')
92
90
  assert_empty $stdout.string
93
91
  assert_equal "Warning message\n", $stderr.string
94
92
  end
95
93
 
96
94
  def test_logging_error
97
95
  logger = StdOutErrLogger.new
98
- logger.error("Error message")
96
+ logger.error('Error message')
99
97
  assert_empty $stdout.string
100
98
  assert_equal "Error message\n", $stderr.string
101
99
  end
102
100
 
103
101
  def test_logging_with_array
104
102
  logger = StdOutErrLogger.new
105
- logger.info(["Message line 1", "Message line 2"])
103
+ logger.info(['Message line 1', 'Message line 2'])
106
104
  assert_equal "Message line 1\nMessage line 2\n", $stdout.string
107
105
  end
108
106
 
109
107
  def test_logging_with_block
110
108
  logger = StdOutErrLogger.new
111
- logger.info { "Block message" }
109
+ logger.info { 'Block message' }
112
110
  assert_equal "Block message\n", $stdout.string
113
111
  end
114
112
 
115
113
  def test_logging_unknown_severity
116
114
  logger = StdOutErrLogger.new
117
- logger.add(Logger::UNKNOWN, "Unknown severity message")
115
+ logger.add(Logger::UNKNOWN, 'Unknown severity message')
118
116
  assert_empty $stdout.string
119
117
  assert_equal "Unknown severity message\n", $stderr.string
120
118
  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.4
4
+ version: 2.0.5
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-04-23 00:00:00.000000000 Z
11
+ date: 2024-04-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: clipboard
@@ -133,6 +133,7 @@ files:
133
133
  - examples/pass-through.md
134
134
  - examples/plant.md
135
135
  - examples/port.md
136
+ - examples/search.md
136
137
  - examples/vars.md
137
138
  - examples/wrap.md
138
139
  - lib/ansi_formatter.rb