markdown_exec 2.0.8.4 → 2.1.0

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: 858c301950e3ca7d43bc8c8c9a87f1c340b75710c28743a02ed0811a649b46ba
4
- data.tar.gz: 4c7445f2d0e05e974cadd163894772b865bd7f94717f6f070fda6b2db2a0ef8c
3
+ metadata.gz: f49177c09809e5635f448181166f2fe60dffe9b942f1c23eeb29b2ecd43b55a8
4
+ data.tar.gz: 43488e384c44c757e1c7b95ad68e755a60a5bd617f3532c4e3213604984097e5
5
5
  SHA512:
6
- metadata.gz: c157d1ec261a140205eabe4d2ec8a30839e8b8f1c716c2d24710d3630c587e03282b11a5f27e269e02b8e1a568fbca7bf2e37537cc04d4b9d4cfce9ef1ab4803
7
- data.tar.gz: d991a308e029da9078adb996d8735951e3100eb117bc5a1f196db040513d4e20c715c6a4a805dcd528a93bd98d1a7b125eb2d88c4d9fea7449af1ad04add67be
6
+ metadata.gz: 9c923456c84259f80f53a839d48d4ed54c91f3bdc3ddb06fb96a1014b79a4640f21eed0bdb1f58635869fa70a5fb786259745a6e2a46cba2780a0093b81bc3e9
7
+ data.tar.gz: fbccdda04147b4a9ac0c9dd31bff501a626c60112fd70d0554aa89d2e005494e755abc0f63714c417e25461da23de3a960478cc1dd65fef9c126e927b6bbf037
data/CHANGELOG.md CHANGED
@@ -1,14 +1,23 @@
1
1
  # Changelog
2
2
 
3
- Pass-through arguments after "--" to the script
4
- M Gemfile.lock
5
- M bin/tab_completion.sh
6
- M examples/pass-through.md
7
- M lib/hash_delegator.rb
8
- M lib/markdown_exec.rb
9
- M lib/markdown_exec/version.rb
10
- M lib/menu.src.yml
11
- M lib/menu.yml
3
+ ## [2.1.0] - 2024-07-15
4
+
5
+ ### Added
6
+
7
+ - Option to toggle the output of an execution report.
8
+ - Option to toggle a menu entry to view saved script and output files.
9
+ - Options for formatting and parsing saved script and output file names.
10
+
11
+ ### Changed
12
+
13
+ - Fix handling of output streams for executed scripts to improve logging out output and addition to inherited code.
14
+ - YAML blocks are not executable from the menu.
15
+ - Fix collection of output of Link blocks.
16
+ - Pass-through arguments after "--" to the script.
17
+ - Remove app info from menu.yml.
18
+ - Remove test for unwanted arguments.
19
+ - Fix Link next_block_name when filename is used.
20
+ - In example doc, use nicknames to allow block content to be displayed.
12
21
 
13
22
  ## [2.0.8] - 2024-06-05
14
23
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- markdown_exec (2.0.8.4)
4
+ markdown_exec (2.1.0)
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.8.4"
16
+ echo "2.1.0"
17
17
  }
18
18
 
19
19
  _mde() {
@@ -178,4 +178,4 @@ _mde() {
178
178
 
179
179
  complete -o filenames -o nospace -F _mde mde
180
180
  # _mde_echo_version
181
- # echo "Updated: 2024-06-24 04:53:41 UTC"
181
+ # echo "Updated: 2024-07-16 20:54:59 UTC"
@@ -0,0 +1,50 @@
1
+ # Demonstrate data blocks
2
+
3
+ ```opts :(document_options)
4
+ pause_after_script_execution: true
5
+ ```
6
+
7
+ ## Create a data file by requiring a YAML block.
8
+ ::: YAML into a file
9
+ / YAML block that loads data into a file.
10
+ ```yaml :(test1) >test1.yml
11
+ a: species
12
+ b: genus
13
+ ```
14
+ This is a Bash block that
15
+ - requires a hidden YAML block (that creates a file), and
16
+ - displays the file.
17
+ ```bash +(test1)
18
+ echo "- The data file created"
19
+ ls -al *.yml
20
+ echo -e "\n- Contents of the file"
21
+ cat -n test1.yml
22
+ echo -e "\n- Remove the data file"
23
+ rm test1.yml
24
+ ```
25
+
26
+ ## Load data by requiring a yaml block.
27
+ ::: YAML into a shell variable
28
+ / YAML block that loads data into a variable.
29
+ ```yaml :(test2) >$test2
30
+ c: family
31
+ d: order
32
+ ```
33
+ This is a Bash block that
34
+ - requires a hidden YAML block (that sets a variable), and
35
+ - displays the variable.
36
+ ```bash +(test2)
37
+ echo 'data:'
38
+ echo "$test2"
39
+ ```
40
+
41
+ ## Visible YAML block that is not executable.
42
+ ::: Non-interactive data
43
+ ```yaml
44
+ e: class
45
+ f: phylum
46
+ ```
47
+
48
+ # Related MDE options
49
+ block_stdin_scan | Match to place block body into a file or a variable
50
+ block_stdout_scan | Match to place block body into a file or a variable
@@ -0,0 +1,46 @@
1
+ # Demo options: output_execution_report, output_execution_summary
2
+
3
+ ::: Options are initially True
4
+ ```opts :(document_options) +[document_options]
5
+ output_execution_report: true
6
+ output_execution_summary: true
7
+ pause_after_script_execution: true
8
+ ```
9
+ ```bash
10
+ whoami
11
+ pwd >&2
12
+ date >&1 1>&2
13
+ ```
14
+
15
+ ## output_execution_report
16
+ ### Example
17
+ -^-
18
+ Command: mde ./examples/opt_output_execution_summary.md
19
+ StdOut: logs/mde_2024-07-08-03-21-59_opt_output_execution_summary_,_whoami___pwd__&2___date__&1_1_&2_.out.txt
20
+ -v-
21
+ ### Toggle
22
+ ```opts
23
+ output_execution_report: false
24
+ ```
25
+ ```opts
26
+ output_execution_report: true
27
+ ```
28
+
29
+ ## output_execution_summary
30
+ ### Example (edited)
31
+ :execute_aborted_at:
32
+ :execute_completed_at: 2024-07-08 03:21:59.988451000 Z
33
+ :execute_error:
34
+ :execute_error_message:
35
+ :execute_options: { ... }
36
+ :execute_started_at: 2024-07-08 03:21:59.864442000 Z
37
+ :saved_filespec:
38
+ :script_block_name:
39
+ :streamed_lines: { ... }
40
+ ### Toggle
41
+ ```opts
42
+ output_execution_summary: false
43
+ ```
44
+ ```opts
45
+ output_execution_summary: true
46
+ ```
data/examples/save.md ADDED
@@ -0,0 +1,7 @@
1
+ ```opts :(document_options)
2
+ execute_in_own_window: false
3
+ save_execution_output: true
4
+ ```
5
+ ```bash :test
6
+ echo "$(date -u)"
7
+ ```
data/lib/constants.rb CHANGED
@@ -48,6 +48,7 @@ class MenuState
48
48
  CONTINUE = :continue
49
49
  EDIT = :edit
50
50
  EXIT = :exit
51
+ HISTORY = :history
51
52
  LOAD = :load
52
53
  SAVE = :save
53
54
  SHELL = :shell
@@ -34,6 +34,7 @@ require_relative 'mdoc'
34
34
  require_relative 'regexp'
35
35
  require_relative 'resize_terminal'
36
36
  require_relative 'std_out_err_logger'
37
+ require_relative 'streams_out'
37
38
  require_relative 'string_util'
38
39
 
39
40
  class String
@@ -163,15 +164,6 @@ module HashDelegatorSelf
163
164
  # end.join("\n")
164
165
  # end
165
166
 
166
- # Formats and returns the execution streams (like stdin, stdout, stderr) for a given key.
167
- # It concatenates the array of strings found under the specified key in the run_state's files.
168
- #
169
- # @param key [Symbol] The key corresponding to the desired execution stream.
170
- # @return [String] A concatenated string of the execution stream's contents.
171
- def format_execution_streams(key, files = {})
172
- (files || {}).fetch(key, []).join
173
- end
174
-
175
167
  # Indents all lines in a given string with a specified indentation string.
176
168
  # @param body [String] A multi-line string to be indented.
177
169
  # @param indent [String] The string used for indentation (default is an empty string).
@@ -266,16 +258,6 @@ module HashDelegatorSelf
266
258
  exit 1
267
259
  end
268
260
 
269
- # # Evaluates the given string as Ruby code and rescues any StandardErrors.
270
- # # If an error occurs, it calls the error_handler method with 'safeval'.
271
- # # @param str [String] The string to be evaluated.
272
- # # @return [Object] The result of evaluating the string.
273
- # def safeval(str)
274
- # eval(str)
275
- # rescue StandardError # catches NameError, StandardError
276
- # error_handler('safeval')
277
- # end
278
-
279
261
  def set_file_permissions(file_path, chmod_value)
280
262
  File.chmod(chmod_value, file_path)
281
263
  end
@@ -309,21 +291,6 @@ module HashDelegatorSelf
309
291
  &block)
310
292
  end
311
293
 
312
- def write_execution_output_to_file(files, filespec)
313
- FileUtils.mkdir_p File.dirname(filespec)
314
-
315
- File.write(
316
- filespec,
317
- ["-STDOUT-\n",
318
- format_execution_streams(ExecutionStreams::STD_OUT, files),
319
- "-STDERR-\n",
320
- format_execution_streams(ExecutionStreams::STD_ERR, files),
321
- "-STDIN-\n",
322
- format_execution_streams(ExecutionStreams::STD_IN, files),
323
- "\n"].join
324
- )
325
- end
326
-
327
294
  # Yields a line as a new block if the selected message type includes :line.
328
295
  # @param [String] line The line to be processed.
329
296
  # @param [Array<Symbol>] selected_messages A list of message types to check.
@@ -587,6 +554,9 @@ module MarkdownExec
587
554
  when MenuState::EXIT
588
555
  option_name = @delegate_object[:menu_option_exit_name]
589
556
  insert_at_top = @delegate_object[:menu_exit_at_top]
557
+ when MenuState::HISTORY
558
+ option_name = @delegate_object[:menu_option_history_name]
559
+ insert_at_top = @delegate_object[:menu_load_at_top]
590
560
  when MenuState::LOAD
591
561
  option_name = @delegate_object[:menu_option_load_name]
592
562
  insert_at_top = @delegate_object[:menu_load_at_top]
@@ -599,6 +569,8 @@ module MarkdownExec
599
569
  when MenuState::VIEW
600
570
  option_name = @delegate_object[:menu_option_view_name]
601
571
  insert_at_top = @delegate_object[:menu_load_at_top]
572
+ else
573
+ raise "Missing MenuState: #{menu_state}"
602
574
  end
603
575
 
604
576
  formatted_name = format(@delegate_object[:menu_link_format],
@@ -726,11 +698,12 @@ module MarkdownExec
726
698
  return unless @delegate_object[:saved_stdout_folder]
727
699
 
728
700
  @delegate_object[:logged_stdout_filename] =
729
- SavedAsset.stdout_name(blockname: block_name,
730
- filename: File.basename(@delegate_object[:filename],
731
- '.*'),
732
- prefix: @delegate_object[:logged_stdout_filename_prefix],
733
- time: Time.now.utc)
701
+ SavedAsset.new(blockname: block_name,
702
+ filename: @delegate_object[:filename],
703
+ prefix: @delegate_object[:logged_stdout_filename_prefix],
704
+ time: Time.now.utc,
705
+ exts: '.out.txt',
706
+ saved_asset_format: @delegate_object[:saved_asset_format]).generate_name
734
707
 
735
708
  @logged_stdout_filespec =
736
709
  @delegate_object[:logged_stdout_filespec] =
@@ -793,7 +766,7 @@ module MarkdownExec
793
766
  end
794
767
 
795
768
  def command_execute(command, args: [])
796
- run_state_reset_stream_logs
769
+ @run_state.files = StreamsOut.new
797
770
  @run_state.options = @delegate_object
798
771
  @run_state.started_at = Time.now.utc
799
772
 
@@ -820,14 +793,14 @@ module MarkdownExec
820
793
  @run_state.aborted_at = Time.now.utc
821
794
  @run_state.error_message = err.message
822
795
  @run_state.error = err
823
- @run_state.files[ExecutionStreams::STD_ERR] += [@run_state.error_message]
796
+ @run_state.files.append_stream_line(ExecutionStreams::STD_ERR, @run_state.error_message)
824
797
  @fout.fout "Error ENOENT: #{err.inspect}"
825
798
  rescue SignalException => err
826
799
  # Handle SignalException
827
800
  @run_state.aborted_at = Time.now.utc
828
801
  @run_state.error_message = 'SIGTERM'
829
802
  @run_state.error = err
830
- @run_state.files[ExecutionStreams::STD_ERR] += [@run_state.error_message]
803
+ @run_state.files.append_stream_line(ExecutionStreams::STD_ERR, @run_state.error_message)
831
804
  @fout.fout "Error ENOENT: #{err.inspect}"
832
805
  end
833
806
 
@@ -1080,8 +1053,7 @@ module MarkdownExec
1080
1053
  return unless @delegate_object[:save_execution_output]
1081
1054
  return if @run_state.in_own_window
1082
1055
 
1083
- HashDelegator.write_execution_output_to_file(@run_state.files,
1084
- @delegate_object[:logged_stdout_filespec])
1056
+ @run_state.files.write_execution_output_to_file(@delegate_object[:logged_stdout_filespec])
1085
1057
  end
1086
1058
 
1087
1059
  # Select and execute a code block from a Markdown document.
@@ -1117,12 +1089,14 @@ module MarkdownExec
1117
1089
  pop_add_current_code_to_head_and_trigger_load(@dml_link_state, inherited_block_names, code_lines, inherited_dependencies, selected)
1118
1090
  end
1119
1091
 
1120
- item_back = format(@delegate_object[:menu_link_format], HashDelegator.safeval(@delegate_object[:menu_option_back_name]))
1121
- item_edit = format(@delegate_object[:menu_link_format], HashDelegator.safeval(@delegate_object[:menu_option_edit_name]))
1122
- item_load = format(@delegate_object[:menu_link_format], HashDelegator.safeval(@delegate_object[:menu_option_load_name]))
1123
- item_save = format(@delegate_object[:menu_link_format], HashDelegator.safeval(@delegate_object[:menu_option_save_name]))
1124
- item_shell = format(@delegate_object[:menu_link_format], HashDelegator.safeval(@delegate_object[:menu_option_shell_name]))
1125
- item_view = format(@delegate_object[:menu_link_format], HashDelegator.safeval(@delegate_object[:menu_option_view_name]))
1092
+ fdo = ->(mo) { format(@delegate_object[:menu_link_format], HashDelegator.safeval(@delegate_object[mo])) }
1093
+ item_back = fdo.call(:menu_option_back_name)
1094
+ item_edit = fdo.call(:menu_option_edit_name)
1095
+ item_history = fdo.call(:menu_option_history_name)
1096
+ item_load = fdo.call(:menu_option_load_name)
1097
+ item_save = fdo.call(:menu_option_save_name)
1098
+ item_shell = fdo.call(:menu_option_shell_name)
1099
+ item_view = fdo.call(:menu_option_view_name)
1126
1100
 
1127
1101
  @run_state.batch_random = Random.new.rand
1128
1102
  @run_state.batch_index = 0
@@ -1136,6 +1110,12 @@ module MarkdownExec
1136
1110
  # puts "@ - parse document #{data}"
1137
1111
  inpseq_parse_document(data)
1138
1112
 
1113
+ if @delegate_object[:menu_for_history]
1114
+ history_files.tap do |files|
1115
+ menu_enable_option(item_history, files.count, 'files', menu_state: MenuState::HISTORY) if files.count.positive?
1116
+ end
1117
+ end
1118
+
1139
1119
  if @delegate_object[:menu_for_saved_lines] && @delegate_object[:document_saved_lines_glob].present?
1140
1120
 
1141
1121
  sf = document_name_in_glob_as_file_name(@dml_link_state.document_filename, @delegate_object[:document_saved_lines_glob])
@@ -1146,11 +1126,11 @@ module MarkdownExec
1146
1126
 
1147
1127
  # add menu items (glob, load, save) and enable selectively
1148
1128
  menu_add_disabled_option(sf) if files.count.positive? || lines_count.positive?
1149
- menu_enable_option(format(@delegate_object[:menu_link_format], HashDelegator.safeval(@delegate_object[:menu_option_load_name])), files.count, 'files', menu_state: MenuState::LOAD) if files.count.positive?
1150
- menu_enable_option(format(@delegate_object[:menu_link_format], HashDelegator.safeval(@delegate_object[:menu_option_edit_name])), lines_count, 'lines', menu_state: MenuState::EDIT) if lines_count.positive?
1151
- menu_enable_option(format(@delegate_object[:menu_link_format], HashDelegator.safeval(@delegate_object[:menu_option_save_name])), 1, '', menu_state: MenuState::SAVE) if lines_count.positive?
1152
- menu_enable_option(format(@delegate_object[:menu_link_format], HashDelegator.safeval(@delegate_object[:menu_option_view_name])), 1, '', menu_state: MenuState::VIEW) if lines_count.positive?
1153
- menu_enable_option(format(@delegate_object[:menu_link_format], HashDelegator.safeval(@delegate_object[:menu_option_shell_name])), 1, '', menu_state: MenuState::SHELL) if @delegate_object[:menu_with_shell]
1129
+ menu_enable_option(item_load, files.count, 'files', menu_state: MenuState::LOAD) if files.count.positive?
1130
+ menu_enable_option(item_edit, lines_count, 'lines', menu_state: MenuState::EDIT) if lines_count.positive?
1131
+ menu_enable_option(item_save, 1, '', menu_state: MenuState::SAVE) if lines_count.positive?
1132
+ menu_enable_option(item_view, 1, '', menu_state: MenuState::VIEW) if lines_count.positive?
1133
+ menu_enable_option(item_shell, 1, '', menu_state: MenuState::SHELL) if @delegate_object[:menu_with_shell]
1154
1134
  end
1155
1135
 
1156
1136
  when :display_menu
@@ -1195,6 +1175,42 @@ module MarkdownExec
1195
1175
  debounce_reset
1196
1176
  edited = edit_text(@dml_link_state.inherited_lines.join("\n"))
1197
1177
  @dml_link_state.inherited_lines = edited.split("\n") if edited
1178
+
1179
+ return :break if pause_user_exit
1180
+
1181
+ InputSequencer.next_link_state(prior_block_was_link: true)
1182
+
1183
+ when item_history
1184
+ debounce_reset
1185
+ files = history_files
1186
+ files_table_rows = files.map do |file|
1187
+ if Regexp.new(@delegate_object[:saved_asset_match]) =~ file
1188
+ OpenStruct.new(file: file, row: [$~[:time], $~[:blockname], $~[:exts]].join(' '))
1189
+ else
1190
+ warn "Cannot parse name: #{file}"
1191
+ next
1192
+ end
1193
+ end.compact
1194
+
1195
+ case (name = prompt_select_code_filename(
1196
+ [@delegate_object[:prompt_filespec_back]] +
1197
+ files_table_rows.map(&:row),
1198
+ string: @delegate_object[:prompt_select_history_file],
1199
+ color_sym: :prompt_color_after_script_execution
1200
+ ))
1201
+ when @delegate_object[:prompt_filespec_back]
1202
+ # do nothing
1203
+ else
1204
+ file = files_table_rows.select { |ftr| ftr.row == name }&.first
1205
+ info = file_info(file.file)
1206
+ warn "#{file.file} - #{info[:lines]} lines / #{info[:size]} bytes"
1207
+ warn(File.readlines(file.file, chomp: false).map.with_index do |line, ind|
1208
+ format(' %s. %s', format('% 4d', ind).violet, line)
1209
+ end)
1210
+ end
1211
+
1212
+ return :break if pause_user_exit
1213
+
1198
1214
  InputSequencer.next_link_state(prior_block_was_link: true)
1199
1215
 
1200
1216
  when item_load
@@ -1205,6 +1221,9 @@ module MarkdownExec
1205
1221
  @dml_link_state.inherited_lines ||= []
1206
1222
  @dml_link_state.inherited_lines += File.readlines(load_filespec, chomp: true)
1207
1223
  end
1224
+
1225
+ return :break if pause_user_exit
1226
+
1208
1227
  InputSequencer.next_link_state(prior_block_was_link: true)
1209
1228
 
1210
1229
  when item_save
@@ -1218,6 +1237,7 @@ module MarkdownExec
1218
1237
  return :break
1219
1238
 
1220
1239
  end
1240
+
1221
1241
  InputSequencer.next_link_state(prior_block_was_link: true)
1222
1242
 
1223
1243
  when item_shell
@@ -1236,11 +1256,17 @@ module MarkdownExec
1236
1256
  warn "#{'ERR'.bred} #{exit_status}"
1237
1257
  end
1238
1258
  end
1259
+
1260
+ return :break if pause_user_exit
1261
+
1239
1262
  InputSequencer.next_link_state(prior_block_was_link: true)
1240
1263
 
1241
1264
  when item_view
1242
1265
  debounce_reset
1243
1266
  warn @dml_link_state.inherited_lines.join("\n")
1267
+
1268
+ return :break if pause_user_exit
1269
+
1244
1270
  InputSequencer.next_link_state(prior_block_was_link: true)
1245
1271
 
1246
1272
  else
@@ -1558,6 +1584,21 @@ module MarkdownExec
1558
1584
  string_send_color(data_string, color_sym)
1559
1585
  end
1560
1586
 
1587
+ # size of a file in bytes and the number of lines
1588
+ def file_info(file_path)
1589
+ file_size = 0
1590
+ line_count = 0
1591
+
1592
+ File.open(file_path, 'r') do |file|
1593
+ file.each_line do |_line|
1594
+ line_count += 1
1595
+ end
1596
+ file_size = file.size
1597
+ end
1598
+
1599
+ { size: file_size, lines: line_count }
1600
+ end
1601
+
1561
1602
  def format_and_execute_command(code_lines:)
1562
1603
  formatted_command = code_lines.flatten.join("\n")
1563
1604
  @fout.fout fetch_color(data_sym: :script_execution_head,
@@ -1654,7 +1695,7 @@ module MarkdownExec
1654
1695
  Thread.new do
1655
1696
  stream.each_line do |line|
1656
1697
  line.strip!
1657
- @run_state.files[file_type] << line if @run_state.files
1698
+ @run_state.files.append_stream_line(file_type, line) if @run_state.files.streams
1658
1699
 
1659
1700
  if @delegate_object[:output_stdout]
1660
1701
  # print line
@@ -1671,6 +1712,16 @@ module MarkdownExec
1671
1712
  end
1672
1713
  end
1673
1714
 
1715
+ def history_files
1716
+ Dir.glob(
1717
+ File.join(
1718
+ @delegate_object[:saved_script_folder],
1719
+ SavedAsset.new(filename: @delegate_object[:filename],
1720
+ saved_asset_format: @delegate_object[:saved_asset_format]).generate_name
1721
+ )
1722
+ )
1723
+ end
1724
+
1674
1725
  # Initializes variables for regex and other states
1675
1726
  def initial_state
1676
1727
  {
@@ -1752,7 +1803,7 @@ module MarkdownExec
1752
1803
  file.rewind
1753
1804
 
1754
1805
  if link_block_data.fetch(LinkKeys::EXEC, false)
1755
- run_state_reset_stream_logs
1806
+ @run_state.files = StreamsOut.new
1756
1807
  execute_command_with_streams([cmd]) do |_stdin, stdout, stderr, _thread|
1757
1808
  line = stdout || stderr
1758
1809
  output_lines.push(line) if line
@@ -1876,6 +1927,7 @@ module MarkdownExec
1876
1927
  expanded_expression
1877
1928
  end
1878
1929
  end
1930
+
1879
1931
  # Handle expression with wildcard characters
1880
1932
  def load_filespec_wildcard_expansion(expr, auto_load_single: false)
1881
1933
  files = find_files(expr)
@@ -1886,7 +1938,11 @@ module MarkdownExec
1886
1938
  else
1887
1939
  ## user selects from existing files or other
1888
1940
  #
1889
- case (name = prompt_select_code_filename([@delegate_object[:prompt_filespec_back]] + files))
1941
+ case (name = prompt_select_code_filename(
1942
+ [@delegate_object[:prompt_filespec_back]] + files,
1943
+ string: @delegate_object[:prompt_select_code_file],
1944
+ color_sym: :prompt_color_after_script_execution
1945
+ ))
1890
1946
  when @delegate_object[:prompt_filespec_back]
1891
1947
  # do nothing
1892
1948
  else
@@ -2053,16 +2109,16 @@ module MarkdownExec
2053
2109
  def output_execution_summary
2054
2110
  return unless @delegate_object[:output_execution_summary]
2055
2111
 
2056
- fout_section 'summary', {
2112
+ @fout.fout_section 'summary', {
2057
2113
  execute_aborted_at: @run_state.aborted_at,
2058
2114
  execute_completed_at: @run_state.completed_at,
2059
2115
  execute_error: @run_state.error,
2060
2116
  execute_error_message: @run_state.error_message,
2061
- execute_files: @run_state.files,
2062
2117
  execute_options: @run_state.options,
2063
2118
  execute_started_at: @run_state.started_at,
2119
+ saved_filespec: @run_state.saved_filespec,
2064
2120
  script_block_name: @run_state.script_block_name,
2065
- saved_filespec: @run_state.saved_filespec
2121
+ streamed_lines: @run_state.files.streams
2066
2122
  }
2067
2123
  end
2068
2124
 
@@ -2075,6 +2131,11 @@ module MarkdownExec
2075
2131
  ), level: level
2076
2132
  end
2077
2133
 
2134
+ def pause_user_exit
2135
+ @delegate_object[:pause_after_script_execution] &&
2136
+ prompt_select_continue == MenuState::EXIT
2137
+ end
2138
+
2078
2139
  def pop_add_current_code_to_head_and_trigger_load(link_state, block_names, code_lines,
2079
2140
  dependencies, selected, next_block_name: nil)
2080
2141
  pop = @link_history.pop # updatable
@@ -2301,10 +2362,9 @@ module MarkdownExec
2301
2362
 
2302
2363
  # public
2303
2364
 
2304
- def prompt_select_code_filename(filenames)
2365
+ def prompt_select_code_filename(filenames, string: @delegate_object[:prompt_select_code_file], color_sym: :prompt_color_after_script_execution)
2305
2366
  @prompt.select(
2306
- string_send_color(@delegate_object[:prompt_select_code_file],
2307
- :prompt_color_after_script_execution),
2367
+ string_send_color(string, color_sym),
2308
2368
  filter: true,
2309
2369
  quiet: true
2310
2370
  ) do |menu|
@@ -2445,7 +2505,7 @@ module MarkdownExec
2445
2505
  end
2446
2506
 
2447
2507
  # Registers console attributes by modifying the options hash.
2448
- # This method handles terminal resizing and adjusts the console dimensions
2508
+ # This method handles terminal resizing and adjusts the console dimensions
2449
2509
  # and pagination settings based on the current terminal size.
2450
2510
  #
2451
2511
  # @param opts [Hash] a hash containing various options for the console settings.
@@ -2462,19 +2522,15 @@ module MarkdownExec
2462
2522
  # register_console_attributes(opts)
2463
2523
  # # opts will be updated with the current console dimensions and pagination settings.
2464
2524
  def register_console_attributes(opts)
2465
- begin
2466
- if (resized = @delegate_object[:menu_resize_terminal])
2467
- resize_terminal
2468
- end
2525
+ if (resized = @delegate_object[:menu_resize_terminal])
2526
+ resize_terminal
2527
+ end
2469
2528
 
2470
- if resized || !opts[:console_width]
2471
- opts[:console_height], opts[:console_width] = opts[:console_winsize] = IO.console.winsize
2472
- end
2529
+ opts[:console_height], opts[:console_width] = opts[:console_winsize] = IO.console.winsize if resized || !opts[:console_width]
2473
2530
 
2474
- opts[:per_page] = opts[:select_page_height] = [opts[:console_height] - 3, 4].max unless opts[:select_page_height]&.positive?
2475
- rescue StandardError
2476
- HashDelegator.error_handler('register_console_attributes', { abort: true })
2477
- end
2531
+ opts[:per_page] = opts[:select_page_height] = [opts[:console_height] - 3, 4].max unless opts[:select_page_height]&.positive?
2532
+ rescue StandardError
2533
+ HashDelegator.error_handler('register_console_attributes', { abort: true })
2478
2534
  end
2479
2535
 
2480
2536
  # Check if the delegate object responds to a given method.
@@ -2493,13 +2549,6 @@ module MarkdownExec
2493
2549
  end
2494
2550
  end
2495
2551
 
2496
- def run_state_reset_stream_logs
2497
- @run_state.files = Hash.new()
2498
- @run_state.files[ExecutionStreams::STD_ERR] = []
2499
- @run_state.files[ExecutionStreams::STD_IN] = []
2500
- @run_state.files[ExecutionStreams::STD_OUT] = []
2501
- end
2502
-
2503
2552
  def runtime_exception(exception_sym, name, items)
2504
2553
  if @delegate_object[exception_sym] != 0
2505
2554
  data = { name: name, detail: items.join(', ') }
@@ -2543,8 +2592,11 @@ module MarkdownExec
2543
2592
  ## user selects from existing files or other
2544
2593
  # input into path with wildcard for easy entry
2545
2594
  #
2546
- name = prompt_select_code_filename([@delegate_object[:prompt_filespec_back], @delegate_object[:prompt_filespec_other]] + files)
2547
- case name
2595
+ case (name = prompt_select_code_filename(
2596
+ [@delegate_object[:prompt_filespec_back], @delegate_object[:prompt_filespec_other]] + files,
2597
+ string: @delegate_object[:prompt_select_code_file],
2598
+ color_sym: :prompt_color_after_script_execution
2599
+ ))
2548
2600
  when @delegate_object[:prompt_filespec_back]
2549
2601
  # do nothing
2550
2602
  when @delegate_object[:prompt_filespec_other]
@@ -2811,12 +2863,12 @@ module MarkdownExec
2811
2863
 
2812
2864
  time_now = Time.now.utc
2813
2865
  @run_state.saved_script_filename =
2814
- SavedAsset.script_name(
2815
- blockname: selected.pub_name,
2816
- filename: @delegate_object[:filename],
2817
- prefix: @delegate_object[:saved_script_filename_prefix],
2818
- time: time_now
2819
- )
2866
+ SavedAsset.new(blockname: selected.pub_name,
2867
+ exts: '.sh',
2868
+ filename: @delegate_object[:filename],
2869
+ prefix: @delegate_object[:saved_script_filename_prefix],
2870
+ saved_asset_format: @delegate_object[:saved_asset_format],
2871
+ time: time_now).generate_name
2820
2872
  @run_state.saved_filespec =
2821
2873
  File.join(@delegate_object[:saved_script_folder],
2822
2874
  @run_state.saved_script_filename)
@@ -3416,25 +3468,27 @@ module MarkdownExec
3416
3468
  @hd.instance_variable_set(:@run_state, mock('run_state'))
3417
3469
  end
3418
3470
 
3419
- def test_format_execution_streams_with_valid_key
3420
- result = HashDelegator.format_execution_streams(ExecutionStreams::STD_OUT,
3421
- { stdout: %w[output1 output2] })
3471
+ def test_format_execution_stream_with_valid_key
3472
+ result = HashDelegator.format_execution_stream(
3473
+ { stdout: %w[output1 output2] },
3474
+ ExecutionStreams::STD_OUT
3475
+ )
3422
3476
 
3423
- assert_equal 'output1output2', result
3477
+ assert_equal "output1\noutput2", result
3424
3478
  end
3425
3479
 
3426
- def test_format_execution_streams_with_empty_key
3480
+ def test_format_execution_stream_with_empty_key
3427
3481
  @hd.instance_variable_get(:@run_state).stubs(:files).returns({})
3428
3482
 
3429
- result = HashDelegator.format_execution_streams(ExecutionStreams::STD_ERR)
3483
+ result = HashDelegator.format_execution_stream(nil, ExecutionStreams::STD_ERR)
3430
3484
 
3431
3485
  assert_equal '', result
3432
3486
  end
3433
3487
 
3434
- def test_format_execution_streams_with_nil_files
3488
+ def test_format_execution_stream_with_nil_files
3435
3489
  @hd.instance_variable_get(:@run_state).stubs(:files).returns(nil)
3436
3490
 
3437
- result = HashDelegator.format_execution_streams(:stdin)
3491
+ result = HashDelegator.format_execution_stream(nil, :stdin)
3438
3492
 
3439
3493
  assert_equal '', result
3440
3494
  end
@@ -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.8.4'
10
+ VERSION = '2.1.0'
11
11
  end
data/lib/menu.src.yml CHANGED
@@ -127,6 +127,13 @@
127
127
  :opt_name: menu_for_saved_lines
128
128
  :procname: val_as_bool
129
129
 
130
+ - :arg_name: BOOL
131
+ :default: true
132
+ :description: Add menu options for history
133
+ :env_var: MDE_menu_for_history
134
+ :opt_name: menu_for_history
135
+ :procname: val_as_bool
136
+
130
137
  - :arg_name: BOOL
131
138
  :default: false
132
139
  :description: Dump @delegate_object
@@ -643,8 +650,8 @@
643
650
  :opt_name: menu_note_format
644
651
  :procname: val_as_str
645
652
 
646
- ## all lines that do not start with "/ " are notes
647
- - :default: "^(?<line>(?!/ )(?<indent>[ \t]*)(?<text>.*?)(?<trailing>[ \t]*))?$"
653
+ ## lines that start with "/" are comments (hidden), not notes (visible)
654
+ - :default: "^(?<line>(?!/)(?<indent>[ \t]*)(?<text>.*?)(?<trailing>[ \t]*))?$"
648
655
  :description: Pattern for notes in block selection menu
649
656
  :env_var: MDE_MENU_NOTE_MATCH
650
657
  :opt_name: menu_note_match
@@ -671,6 +678,13 @@
671
678
  :opt_name: menu_option_exit_name
672
679
  :procname: val_as_str
673
680
 
681
+ - :default:
682
+ :line: "* History"
683
+ :description: Text for History option
684
+ :env_var: MDE_MENU_OPTION_HISTORY_NAME
685
+ :opt_name: menu_option_history_name
686
+ :procname: val_as_str
687
+
674
688
  - :default:
675
689
  :line: "* Load"
676
690
  :description: Text for Load option
@@ -992,6 +1006,12 @@
992
1006
  :opt_name: prompt_select_code_file
993
1007
  :procname: val_as_str
994
1008
 
1009
+ - :default: "\nView file:"
1010
+ :description: Prompt to select a saved asset
1011
+ :env_var: MDE_PROMPT_SELECT_HISTORY_FILE
1012
+ :opt_name: prompt_select_history_file
1013
+ :procname: val_as_str
1014
+
995
1015
  - :default: "\nChoose a file:"
996
1016
  :description: Prompt to select a markdown document
997
1017
  :env_var: MDE_PROMPT_SELECT_MD
@@ -1038,6 +1058,18 @@
1038
1058
  :opt_name: runtime_exception_error_level
1039
1059
  :procname: val_as_int
1040
1060
 
1061
+ - :default: '%{prefix}%{join}%{time}%{join}%{filename}%{join}%{mark}%{join}%{blockname}%{join}%{exts}'
1062
+ :description: saved_asset_format
1063
+ :env_var: MDE_SAVED_ASSET_FORMAT
1064
+ :opt_name: saved_asset_format
1065
+ :procname: val_as_str
1066
+
1067
+ - :default: "^(?<prefix>.+)(?<join>_)(?<time>[0-9\\-]+)\\g'join'(?<filename>.+)\\g'join'(?<mark>~)\\g'join'(?<blockname>.+)\\g'join'(?<exts>\\..+)$"
1068
+ :description: saved_asset_match
1069
+ :env_var: MDE_SAVED_ASSET_MATCH
1070
+ :opt_name: saved_asset_match
1071
+ :procname: val_as_str
1072
+
1041
1073
  - :arg_name: BOOL
1042
1074
  :default: false
1043
1075
  :description: Whether to save an executed script
data/lib/menu.yml CHANGED
@@ -106,6 +106,12 @@
106
106
  :env_var: MDE_MENU_FOR_SAVED_LINES
107
107
  :opt_name: menu_for_saved_lines
108
108
  :procname: val_as_bool
109
+ - :arg_name: BOOL
110
+ :default: true
111
+ :description: Add menu options for history
112
+ :env_var: MDE_menu_for_history
113
+ :opt_name: menu_for_history
114
+ :procname: val_as_bool
109
115
  - :arg_name: BOOL
110
116
  :default: false
111
117
  :description: Dump @delegate_object
@@ -542,7 +548,7 @@
542
548
  :env_var: MDE_MENU_NOTE_FORMAT
543
549
  :opt_name: menu_note_format
544
550
  :procname: val_as_str
545
- - :default: "^(?<line>(?!/ )(?<indent>[ \t]*)(?<text>.*?)(?<trailing>[ \t]*))?$"
551
+ - :default: "^(?<line>(?!/)(?<indent>[ \t]*)(?<text>.*?)(?<trailing>[ \t]*))?$"
546
552
  :description: Pattern for notes in block selection menu
547
553
  :env_var: MDE_MENU_NOTE_MATCH
548
554
  :opt_name: menu_note_match
@@ -565,6 +571,12 @@
565
571
  :env_var: MDE_MENU_OPTION_EXIT_NAME
566
572
  :opt_name: menu_option_exit_name
567
573
  :procname: val_as_str
574
+ - :default:
575
+ :line: "* History"
576
+ :description: Text for History option
577
+ :env_var: MDE_MENU_OPTION_HISTORY_NAME
578
+ :opt_name: menu_option_history_name
579
+ :procname: val_as_str
568
580
  - :default:
569
581
  :line: "* Load"
570
582
  :description: Text for Load option
@@ -848,6 +860,13 @@
848
860
  :procname: val_as_str
849
861
  - :default: |2-
850
862
 
863
+ View file:
864
+ :description: Prompt to select a saved asset
865
+ :env_var: MDE_PROMPT_SELECT_HISTORY_FILE
866
+ :opt_name: prompt_select_history_file
867
+ :procname: val_as_str
868
+ - :default: |2-
869
+
851
870
  Choose a file:
852
871
  :description: Prompt to select a markdown document
853
872
  :env_var: MDE_PROMPT_SELECT_MD
@@ -889,6 +908,16 @@
889
908
  :env_var: MDE_RUNTIME_EXCEPTION_ERROR_LEVEL
890
909
  :opt_name: runtime_exception_error_level
891
910
  :procname: val_as_int
911
+ - :default: "%{prefix}%{join}%{time}%{join}%{filename}%{join}%{mark}%{join}%{blockname}%{join}%{exts}"
912
+ :description: saved_asset_format
913
+ :env_var: MDE_SAVED_ASSET_FORMAT
914
+ :opt_name: saved_asset_format
915
+ :procname: val_as_str
916
+ - :default: "^(?<prefix>.+)(?<join>_)(?<time>[0-9\\-]+)\\g'join'(?<filename>.+)\\g'join'(?<mark>~)\\g'join'(?<blockname>.+)\\g'join'(?<exts>\\..+)$"
917
+ :description: saved_asset_match
918
+ :env_var: MDE_SAVED_ASSET_MATCH
919
+ :opt_name: saved_asset_match
920
+ :procname: val_as_str
892
921
  - :arg_name: BOOL
893
922
  :default: false
894
923
  :description: Whether to save an executed script
data/lib/saved_assets.rb CHANGED
@@ -12,23 +12,57 @@ module MarkdownExec
12
12
  # method derives a name for stdout redirection.
13
13
  #
14
14
  class SavedAsset
15
- FNR11 = %r{[^!#%&()\+,\-0-9=A-Z_a-z~]}.freeze
15
+ FNR11 = %r{[^!#%\+\-0-9=@A-Z_a-z]}.freeze # characters than can be used in a file name without quotes or escaping
16
+ # except '.', ',', '~' reserved for tokenization
16
17
  # / !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
17
18
  FNR12 = '_'
18
19
  DEFAULT_FTIME = '%F-%H-%M-%S'
20
+ FILE_BLOCK_SEP = ','
21
+ JOIN_STR = '_'
22
+ MARK_STR = '~'
19
23
 
20
- # Generates a formatted script name based on the provided parameters.
21
- def self.script_name(filename:, prefix:, time:, blockname:, ftime: DEFAULT_FTIME, join_str: '_', pattern: FNR11, replace: FNR12, exts: '.sh')
22
- fne = filename.gsub(pattern, replace)
23
- bne = blockname.gsub(pattern, replace)
24
- "#{[prefix, time.strftime(ftime), fne, ',', bne].join(join_str)}#{exts}"
24
+ # @param filename [String] the name of the file
25
+ # @param prefix [String] the prefix to use
26
+ # @param time [Time] the time object for formatting
27
+ # @param blockname [String] the block name to include
28
+ # @param ftime [String] the time format (default: DEFAULT_FTIME)
29
+ # @param pattern [Regexp] the pattern to search (default: FNR11)
30
+ # @param replace [String] the string to replace the pattern (default: FNR12)
31
+ # @param exts [String] the extension to append (default: '.sh')
32
+ def initialize(
33
+ saved_asset_format:, filename: nil, prefix: nil, time: nil, blockname: nil,
34
+ ftime: DEFAULT_FTIME, pattern: FNR11, replace: FNR12, exts: nil,
35
+ mark: nil, join_str: nil
36
+ )
37
+ @filename = filename ? filename.gsub(pattern, replace) : '*' # [String] the name of the file
38
+ @prefix = prefix || '*' # [String] the prefix to use
39
+ @time = time ? time.strftime(ftime) : '*' # [Time] the time object for formatting
40
+ @blockname = blockname ? blockname.gsub(pattern, replace) : '*' # [String] the block name to include
41
+ # @ftime = ftime # [String] the time format (default: DEFAULT_FTIME)
42
+ # @pattern = pattern # [Regexp] the pattern to search (default: FNR11)
43
+ # @replace = replace # [String] the string to replace the pattern (default: FNR12)
44
+ @exts = exts || '.*' # [String] the extension to append (default: '.sh')
45
+ @mark = mark || MARK_STR
46
+ @join_str = join_str || JOIN_STR
47
+ @saved_asset_format = saved_asset_format
25
48
  end
26
49
 
27
- # Generates a formatted stdout name based on the provided parameters.
28
- def self.stdout_name(filename:, prefix:, time:, blockname:, ftime: DEFAULT_FTIME, join_str: '_', pattern: FNR11, replace: FNR12, exts: '.out.txt')
29
- fne = filename.gsub(pattern, replace)
30
- bne = blockname.gsub(pattern, replace)
31
- "#{[prefix, time.strftime(ftime), fne, ',', bne].join(join_str)}#{exts}"
50
+ # Generates a formatted name based on the provided parameters.
51
+ #
52
+ # @return [String] the generated formatted name
53
+ def generate_name
54
+ format(
55
+ @saved_asset_format,
56
+ {
57
+ blockname: @blockname,
58
+ exts: @exts,
59
+ filename: @filename,
60
+ join: @join_str,
61
+ mark: @mark,
62
+ prefix: @prefix,
63
+ time: @time
64
+ }
65
+ )
32
66
  end
33
67
  end
34
68
  end
@@ -61,4 +95,76 @@ class SavedAssetTest < Minitest::Test
61
95
  filename: filename, prefix: prefix, time: time, blockname: blockname
62
96
  )
63
97
  end
98
+
99
+ def test_wildcard_name_with_all_parameters
100
+ filename = 'sample.txt'
101
+ prefix = 'test'
102
+ time = Time.new(2023, 1, 1, 12, 0, 0)
103
+ blockname = 'block/1:2'
104
+ expected_wildcard = 'test_2023-01-01-12-00-00_sample_txt_,_block_1_2.sh'
105
+
106
+ assert_equal expected_wildcard, MarkdownExec::SavedAsset.wildcard_name(
107
+ filename: filename, prefix: prefix, time: time, blockname: blockname
108
+ )
109
+ end
110
+
111
+ def test_wildcard_name_with_missing_time
112
+ filename = 'sample.txt'
113
+ prefix = 'test'
114
+ time = nil
115
+ blockname = 'block/1:2'
116
+ expected_wildcard = 'test_*_sample_txt_,_block_1_2.sh'
117
+
118
+ assert_equal expected_wildcard, MarkdownExec::SavedAsset.wildcard_name(
119
+ filename: filename, prefix: prefix, time: time, blockname: blockname
120
+ )
121
+ end
122
+
123
+ def test_wildcard_name_with_missing_filename
124
+ filename = nil
125
+ prefix = 'test'
126
+ time = Time.new(2023, 1, 1, 12, 0, 0)
127
+ blockname = 'block/1:2'
128
+ expected_wildcard = 'test_2023-01-01-12-00-00_*_,_block_1_2.sh'
129
+
130
+ assert_equal expected_wildcard, MarkdownExec::SavedAsset.wildcard_name(
131
+ filename: filename, prefix: prefix, time: time, blockname: blockname
132
+ )
133
+ end
134
+
135
+ def test_wildcard_name_with_missing_prefix
136
+ filename = 'sample.txt'
137
+ prefix = nil
138
+ time = Time.new(2023, 1, 1, 12, 0, 0)
139
+ blockname = 'block/1:2'
140
+ expected_wildcard = '*_2023-01-01-12-00-00_sample_txt_,_block_1_2.sh'
141
+
142
+ assert_equal expected_wildcard, MarkdownExec::SavedAsset.wildcard_name(
143
+ filename: filename, prefix: prefix, time: time, blockname: blockname
144
+ )
145
+ end
146
+
147
+ def test_wildcard_name_with_missing_blockname
148
+ filename = 'sample.txt'
149
+ prefix = 'test'
150
+ time = Time.new(2023, 1, 1, 12, 0, 0)
151
+ blockname = nil
152
+ expected_wildcard = 'test_2023-01-01-12-00-00_sample_txt_,_*.sh'
153
+
154
+ assert_equal expected_wildcard, MarkdownExec::SavedAsset.wildcard_name(
155
+ filename: filename, prefix: prefix, time: time, blockname: blockname
156
+ )
157
+ end
158
+
159
+ def test_wildcard_name_with_all_missing
160
+ filename = nil
161
+ prefix = nil
162
+ time = nil
163
+ blockname = nil
164
+ expected_wildcard = '*_*_*_,_*.sh'
165
+
166
+ assert_equal expected_wildcard, MarkdownExec::SavedAsset.wildcard_name(
167
+ filename: filename, prefix: prefix, time: time, blockname: blockname
168
+ )
169
+ end
64
170
  end
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # encoding=utf-8
5
+
6
+ class StreamsOut
7
+ attr_accessor :streams
8
+
9
+ def initialize
10
+ @streams = []
11
+ end
12
+
13
+ def append_stream_line(stream, line)
14
+ @streams << { stream: stream, line: line, timestamp: Time.now }
15
+ end
16
+
17
+ def write_execution_output_to_file(filespec)
18
+ FileUtils.mkdir_p File.dirname(filespec)
19
+
20
+ output = @streams.map do |entry|
21
+ case entry[:stream]
22
+ when ExecutionStreams::STD_OUT
23
+ entry[:line]
24
+ # "OUT: #{entry[:line]}"
25
+ when ExecutionStreams::STD_ERR
26
+ entry[:line]
27
+ # "ERR: #{entry[:line]}"
28
+ when ExecutionStreams::STD_IN
29
+ entry[:line]
30
+ # " IN: #{entry[:line]}"
31
+ end
32
+ end.join("\n")
33
+
34
+ File.write(filespec, output)
35
+ end
36
+ 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.8.4
4
+ version: 2.1.0
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-06-24 00:00:00.000000000 Z
11
+ date: 2024-07-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: clipboard
@@ -115,6 +115,7 @@ files:
115
115
  - bin/tab_completion.sh.erb
116
116
  - examples/block_names.md
117
117
  - examples/colors.md
118
+ - examples/data-files.md
118
119
  - examples/document_options.md
119
120
  - examples/duplicate_block.md
120
121
  - examples/import0.md
@@ -135,10 +136,12 @@ files:
135
136
  - examples/load_code.md
136
137
  - examples/nickname.md
137
138
  - examples/opts.md
139
+ - examples/opts_output_execution.md
138
140
  - examples/pass-through.md
139
141
  - examples/pause-after-execution.md
140
142
  - examples/plant.md
141
143
  - examples/port.md
144
+ - examples/save.md
142
145
  - examples/search.md
143
146
  - examples/vars.md
144
147
  - examples/wrap.md
@@ -179,6 +182,7 @@ files:
179
182
  - lib/saved_files_matcher.rb
180
183
  - lib/shared.rb
181
184
  - lib/std_out_err_logger.rb
185
+ - lib/streams_out.rb
182
186
  - lib/string_util.rb
183
187
  - lib/tap.rb
184
188
  homepage: https://rubygems.org/gems/markdown_exec