markdown_exec 2.0.8.4 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +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
|