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 +4 -4
- data/CHANGELOG.md +18 -9
- data/Gemfile.lock +1 -1
- data/bin/tab_completion.sh +2 -2
- data/examples/data-files.md +50 -0
- data/examples/opts_output_execution.md +46 -0
- data/examples/save.md +7 -0
- data/lib/constants.rb +1 -0
- data/lib/hash_delegator.rb +153 -99
- data/lib/markdown_exec/version.rb +1 -1
- data/lib/menu.src.yml +34 -2
- data/lib/menu.yml +30 -1
- data/lib/saved_assets.rb +117 -11
- data/lib/streams_out.rb +36 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f49177c09809e5635f448181166f2fe60dffe9b942f1c23eeb29b2ecd43b55a8
|
4
|
+
data.tar.gz: 43488e384c44c757e1c7b95ad68e755a60a5bd617f3532c4e3213604984097e5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9c923456c84259f80f53a839d48d4ed54c91f3bdc3ddb06fb96a1014b79a4640f21eed0bdb1f58635869fa70a5fb786259745a6e2a46cba2780a0093b81bc3e9
|
7
|
+
data.tar.gz: fbccdda04147b4a9ac0c9dd31bff501a626c60112fd70d0554aa89d2e005494e755abc0f63714c417e25461da23de3a960478cc1dd65fef9c126e927b6bbf037
|
data/CHANGELOG.md
CHANGED
@@ -1,14 +1,23 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
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
data/bin/tab_completion.sh
CHANGED
@@ -13,7 +13,7 @@ __filedirs_all()
|
|
13
13
|
}
|
14
14
|
|
15
15
|
_mde_echo_version() {
|
16
|
-
echo "2.0
|
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-
|
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
data/lib/constants.rb
CHANGED
data/lib/hash_delegator.rb
CHANGED
@@ -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.
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
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
|
-
|
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
|
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
|
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
|
-
|
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
|
-
|
1121
|
-
|
1122
|
-
|
1123
|
-
|
1124
|
-
|
1125
|
-
|
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(
|
1150
|
-
menu_enable_option(
|
1151
|
-
menu_enable_option(
|
1152
|
-
menu_enable_option(
|
1153
|
-
menu_enable_option(
|
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
|
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
|
-
|
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(
|
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
|
-
|
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(
|
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
|
-
|
2466
|
-
|
2467
|
-
|
2468
|
-
end
|
2525
|
+
if (resized = @delegate_object[:menu_resize_terminal])
|
2526
|
+
resize_terminal
|
2527
|
+
end
|
2469
2528
|
|
2470
|
-
|
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
|
-
|
2475
|
-
|
2476
|
-
|
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(
|
2547
|
-
|
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.
|
2815
|
-
|
2816
|
-
|
2817
|
-
|
2818
|
-
|
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
|
3420
|
-
result = HashDelegator.
|
3421
|
-
|
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
|
3477
|
+
assert_equal "output1\noutput2", result
|
3424
3478
|
end
|
3425
3479
|
|
3426
|
-
def
|
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.
|
3483
|
+
result = HashDelegator.format_execution_stream(nil, ExecutionStreams::STD_ERR)
|
3430
3484
|
|
3431
3485
|
assert_equal '', result
|
3432
3486
|
end
|
3433
3487
|
|
3434
|
-
def
|
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.
|
3491
|
+
result = HashDelegator.format_execution_stream(nil, :stdin)
|
3438
3492
|
|
3439
3493
|
assert_equal '', result
|
3440
3494
|
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
|
-
##
|
647
|
-
- :default: "^(?<line>(?!/
|
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>(?!/
|
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{[
|
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
|
-
#
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
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
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
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
|
data/lib/streams_out.rb
ADDED
@@ -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
|
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-
|
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
|