markdown_exec 2.0.8.4 → 2.2.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/.rubocop.yml +3 -2
- data/CHANGELOG.md +32 -10
- data/Gemfile +3 -3
- data/Gemfile.lock +134 -92
- data/README.md +13 -13
- data/bin/tab_completion.sh +14 -3
- data/bin/tab_completion.sh.erb +0 -1
- data/examples/bash-blocks.md +58 -0
- data/examples/block-names.md +27 -0
- data/examples/data-files.md +50 -0
- data/examples/indent.md +43 -2
- data/examples/link-blocks-block.md +5 -0
- data/examples/link-blocks-load-save.md +59 -0
- data/examples/link-blocks-vars.md +56 -0
- data/examples/linked.md +6 -101
- data/examples/opts-blocks-require.md +28 -0
- data/examples/opts_output_execution.md +46 -0
- data/examples/{port.md → port-blocks.md} +18 -9
- data/examples/save.md +79 -0
- data/examples/vars-blocks.md +38 -0
- data/lib/constants.rb +2 -1
- data/lib/fcb.rb +202 -16
- data/lib/filter.rb +12 -12
- data/lib/hash_delegator.rb +751 -371
- data/lib/link_history.rb +34 -1
- data/lib/markdown_exec/version.rb +1 -1
- data/lib/markdown_exec.rb +56 -75
- data/lib/mdoc.rb +112 -57
- data/lib/menu.src.yml +65 -20
- data/lib/menu.yml +57 -17
- data/lib/namer.rb +50 -0
- data/lib/poly.rb +152 -0
- data/lib/saved_assets.rb +112 -13
- data/lib/streams_out.rb +36 -0
- data/lib/string_util.rb +0 -1
- metadata +18 -6
- data/examples/vars.md +0 -20
- /data/examples/{opts.md → opts-blocks.md} +0 -0
- /data/examples/{pass-through.md → pass-through-arguments.md} +0 -0
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
|
@@ -268,8 +275,10 @@
|
|
268
275
|
:default: false
|
269
276
|
:description: Execute script in own window
|
270
277
|
:env_var: MDE_EXECUTE_IN_OWN_WINDOW
|
278
|
+
:long_name: execute_in_own_window
|
271
279
|
:opt_name: execute_in_own_window
|
272
280
|
:procname: val_as_bool
|
281
|
+
:short_name: w
|
273
282
|
|
274
283
|
- :default: fg_rgbh_7f_ff_00
|
275
284
|
:description: execution_report_preview_frame_color
|
@@ -296,13 +305,13 @@
|
|
296
305
|
|
297
306
|
## match fenced code indented by spaces
|
298
307
|
#
|
299
|
-
- :default: "^(?<indent> *)`{3,}"
|
308
|
+
- :default: "^(?<indent>[ \t]*)`{3,}"
|
300
309
|
:description: Matches the start and end of a fenced code block
|
301
310
|
:env_var: MDE_FENCED_START_AND_END_REGEX
|
302
311
|
:opt_name: fenced_start_and_end_regex
|
303
312
|
:procname: val_as_str
|
304
313
|
|
305
|
-
- :default: "^(?<indent> *)`{3,}(?<shell>[^`\\s]*) *(:(?<name>[^\\s]*))? *(?<rest>.*) *$"
|
314
|
+
- :default: "^(?<indent>[ \t]*)`{3,}(?<shell>[^`\\s]*) *(:(?<name>[^\\s]*))? *(?<rest>.*) *$"
|
306
315
|
:description: Match the start of a fenced block
|
307
316
|
:env_var: MDE_FENCED_START_EXTENDED_REGEX
|
308
317
|
:opt_name: fenced_start_extended_regex
|
@@ -373,7 +382,7 @@
|
|
373
382
|
|
374
383
|
- :arg_name: HOW
|
375
384
|
:default: ''
|
376
|
-
:description: Find in YAML configuration options
|
385
|
+
:description: Find keyword in YAML configuration options
|
377
386
|
:long_name: how
|
378
387
|
:procname: how
|
379
388
|
:short_name: "?"
|
@@ -431,6 +440,7 @@
|
|
431
440
|
:long_name: load-code
|
432
441
|
:opt_name: load_code
|
433
442
|
:procname: val_as_str
|
443
|
+
:short_name: l
|
434
444
|
|
435
445
|
- :arg_name: PREFIX
|
436
446
|
:default: mde
|
@@ -500,7 +510,7 @@
|
|
500
510
|
:opt_name: menu_divider_format
|
501
511
|
:procname: val_as_str
|
502
512
|
|
503
|
-
- :default: "
|
513
|
+
- :default: "^(?<indent>[ \t]*):::(?<line>(?<text>.*?)(?<trailing>[ \t]*))?$"
|
504
514
|
:description: Pattern for topics/dividers in block selection menu
|
505
515
|
:env_var: MDE_MENU_DIVIDER_MATCH
|
506
516
|
:opt_name: menu_divider_match
|
@@ -643,8 +653,9 @@
|
|
643
653
|
:opt_name: menu_note_format
|
644
654
|
:procname: val_as_str
|
645
655
|
|
646
|
-
##
|
647
|
-
- :default: "^(?<
|
656
|
+
## lines that start with "/" are comments (hidden), not notes (visible)
|
657
|
+
# - :default: "^(?<indent>[ \t]*)(?<line>(?!/)(?<text>.*?)(?<trailing>[ \t]*))?$"
|
658
|
+
- :default: "^(?<line>(?![ \t]*/)(?<text>.*?)(?<trailing>[ \t]*))?$"
|
648
659
|
:description: Pattern for notes in block selection menu
|
649
660
|
:env_var: MDE_MENU_NOTE_MATCH
|
650
661
|
:opt_name: menu_note_match
|
@@ -671,6 +682,13 @@
|
|
671
682
|
:opt_name: menu_option_exit_name
|
672
683
|
:procname: val_as_str
|
673
684
|
|
685
|
+
- :default:
|
686
|
+
:line: "* History"
|
687
|
+
:description: Text for History option
|
688
|
+
:env_var: MDE_MENU_OPTION_HISTORY_NAME
|
689
|
+
:opt_name: menu_option_history_name
|
690
|
+
:procname: val_as_str
|
691
|
+
|
674
692
|
- :default:
|
675
693
|
:line: "* Load"
|
676
694
|
:description: Text for Load option
|
@@ -951,13 +969,19 @@
|
|
951
969
|
:procname: val_as_str
|
952
970
|
|
953
971
|
- :default: Back
|
954
|
-
:description:
|
955
|
-
:env_var:
|
972
|
+
:description: User wants out of menu
|
973
|
+
:env_var: MDE_PROMPT_FILESPEC_BACK
|
956
974
|
:opt_name: prompt_filespec_back
|
957
975
|
:procname: val_as_str
|
958
976
|
|
977
|
+
- :default: Facet
|
978
|
+
:description: User wants to tailor the menu
|
979
|
+
:env_var: MDE_PROMPT_FILESPEC_FACET
|
980
|
+
:opt_name: prompt_filespec_facet
|
981
|
+
:procname: val_as_str
|
982
|
+
|
959
983
|
- :default: Other
|
960
|
-
:description:
|
984
|
+
:description: User wants a custom file name
|
961
985
|
:env_var: MDE_PROMPT_FILESPEC_OTHER
|
962
986
|
:opt_name: prompt_filespec_other
|
963
987
|
:procname: val_as_str
|
@@ -992,6 +1016,12 @@
|
|
992
1016
|
:opt_name: prompt_select_code_file
|
993
1017
|
:procname: val_as_str
|
994
1018
|
|
1019
|
+
- :default: "\nView file:"
|
1020
|
+
:description: Prompt to select a saved asset
|
1021
|
+
:env_var: MDE_PROMPT_SELECT_HISTORY_FILE
|
1022
|
+
:opt_name: prompt_select_history_file
|
1023
|
+
:procname: val_as_str
|
1024
|
+
|
995
1025
|
- :default: "\nChoose a file:"
|
996
1026
|
:description: Prompt to select a markdown document
|
997
1027
|
:env_var: MDE_PROMPT_SELECT_MD
|
@@ -1022,7 +1052,7 @@
|
|
1022
1052
|
:opt_name: prompt_yes
|
1023
1053
|
:procname: val_as_str
|
1024
1054
|
|
1025
|
-
- :description:
|
1055
|
+
- :description: Print the gem's home directory
|
1026
1056
|
:long_name: pwd
|
1027
1057
|
:opt_name: pwd
|
1028
1058
|
:procname: val_as_bool
|
@@ -1038,6 +1068,18 @@
|
|
1038
1068
|
:opt_name: runtime_exception_error_level
|
1039
1069
|
:procname: val_as_int
|
1040
1070
|
|
1071
|
+
- :default: '%{prefix}%{join}%{time}%{join}%{filename}%{join}%{mark}%{join}%{blockname}%{join}%{exts}'
|
1072
|
+
:description: Format for script and log file names
|
1073
|
+
:env_var: MDE_SAVED_ASSET_FORMAT
|
1074
|
+
:opt_name: saved_asset_format
|
1075
|
+
:procname: val_as_str
|
1076
|
+
|
1077
|
+
- :default: "^(?<prefix>.+)(?<join>_)(?<time>[0-9\\-]+)\\g'join'(?<filename>.+)\\g'join'(?<mark>~)\\g'join'(?<blockname>.+)\\g'join'(?<exts>\\..+)$"
|
1078
|
+
:description: Regexp for script and log file names
|
1079
|
+
:env_var: MDE_SAVED_ASSET_MATCH
|
1080
|
+
:opt_name: saved_asset_match
|
1081
|
+
:procname: val_as_str
|
1082
|
+
|
1041
1083
|
- :arg_name: BOOL
|
1042
1084
|
:default: false
|
1043
1085
|
:description: Whether to save an executed script
|
@@ -1064,6 +1106,12 @@
|
|
1064
1106
|
:opt_name: saved_filename_replacement
|
1065
1107
|
:procname: val_as_str
|
1066
1108
|
|
1109
|
+
- :default: '%{time} %{blockname} %{exts}'
|
1110
|
+
:description: Format for each row displayed in history
|
1111
|
+
:env_var: MDE_SAVED_HISTORY_FORMAT
|
1112
|
+
:opt_name: saved_history_format
|
1113
|
+
:procname: val_as_str
|
1114
|
+
|
1067
1115
|
- :arg_name: INT
|
1068
1116
|
:default: 493
|
1069
1117
|
:description: chmod for saved scripts
|
@@ -1162,16 +1210,6 @@
|
|
1162
1210
|
:opt_name: select_page_height
|
1163
1211
|
:procname: val_as_int
|
1164
1212
|
|
1165
|
-
- :description: Select and execute a recently saved output
|
1166
|
-
:long_name: select-recent-output
|
1167
|
-
:opt_name: select_recent_output
|
1168
|
-
:procname: val_as_bool
|
1169
|
-
|
1170
|
-
- :description: Select and execute a recently saved script
|
1171
|
-
:long_name: select-recent-script
|
1172
|
-
:opt_name: select_recent_script
|
1173
|
-
:procname: val_as_bool
|
1174
|
-
|
1175
1213
|
- :default: "#!/usr/bin/env"
|
1176
1214
|
:description: Shebang for saved scripts
|
1177
1215
|
:env_var: MDE_SHEBANG
|
@@ -1202,6 +1240,13 @@
|
|
1202
1240
|
:opt_name: shell_code_label_time_format
|
1203
1241
|
:procname: val_as_str
|
1204
1242
|
|
1243
|
+
- :arg_name: BOOL
|
1244
|
+
:default: true
|
1245
|
+
:description: Whether saved file names include shell parameter expansion
|
1246
|
+
:env_var: MDE_SHELL_PARAMETER_EXPANSION
|
1247
|
+
:opt_name: shell_parameter_expansion
|
1248
|
+
:procname: val_as_bool
|
1249
|
+
|
1205
1250
|
- :description: List tab completions
|
1206
1251
|
:long_name: tab-completions
|
1207
1252
|
:opt_name: tab_completions
|
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
|
@@ -230,8 +236,10 @@
|
|
230
236
|
:default: false
|
231
237
|
:description: Execute script in own window
|
232
238
|
:env_var: MDE_EXECUTE_IN_OWN_WINDOW
|
239
|
+
:long_name: execute_in_own_window
|
233
240
|
:opt_name: execute_in_own_window
|
234
241
|
:procname: val_as_bool
|
242
|
+
:short_name: w
|
235
243
|
- :default: fg_rgbh_7f_ff_00
|
236
244
|
:description: execution_report_preview_frame_color
|
237
245
|
:env_var: MDE_EXECUTION_REPORT_PREVIEW_FRAME_COLOR
|
@@ -253,12 +261,12 @@
|
|
253
261
|
:long_name: exit
|
254
262
|
:procname: exit
|
255
263
|
:short_name: x
|
256
|
-
- :default: "^(?<indent> *)`{3,}"
|
264
|
+
- :default: "^(?<indent>[ \t]*)`{3,}"
|
257
265
|
:description: Matches the start and end of a fenced code block
|
258
266
|
:env_var: MDE_FENCED_START_AND_END_REGEX
|
259
267
|
:opt_name: fenced_start_and_end_regex
|
260
268
|
:procname: val_as_str
|
261
|
-
- :default: "^(?<indent> *)`{3,}(?<shell>[^`\\s]*) *(:(?<name>[^\\s]*))? *(?<rest>.*)
|
269
|
+
- :default: "^(?<indent>[ \t]*)`{3,}(?<shell>[^`\\s]*) *(:(?<name>[^\\s]*))? *(?<rest>.*)
|
262
270
|
*$"
|
263
271
|
:description: Match the start of a fenced block
|
264
272
|
:env_var: MDE_FENCED_START_EXTENDED_REGEX
|
@@ -319,7 +327,7 @@
|
|
319
327
|
:procname: val_as_str
|
320
328
|
- :arg_name: HOW
|
321
329
|
:default: ''
|
322
|
-
:description: Find in YAML configuration options
|
330
|
+
:description: Find keyword in YAML configuration options
|
323
331
|
:long_name: how
|
324
332
|
:procname: how
|
325
333
|
:short_name: "?"
|
@@ -367,6 +375,7 @@
|
|
367
375
|
:long_name: load-code
|
368
376
|
:opt_name: load_code
|
369
377
|
:procname: val_as_str
|
378
|
+
:short_name: l
|
370
379
|
- :arg_name: PREFIX
|
371
380
|
:default: mde
|
372
381
|
:description: Name prefix for stdout files
|
@@ -425,7 +434,7 @@
|
|
425
434
|
:env_var: MDE_MENU_DIVIDER_FORMAT
|
426
435
|
:opt_name: menu_divider_format
|
427
436
|
:procname: val_as_str
|
428
|
-
- :default: "
|
437
|
+
- :default: "^(?<indent>[ \t]*):::(?<line>(?<text>.*?)(?<trailing>[ \t]*))?$"
|
429
438
|
:description: Pattern for topics/dividers in block selection menu
|
430
439
|
:env_var: MDE_MENU_DIVIDER_MATCH
|
431
440
|
:opt_name: menu_divider_match
|
@@ -542,7 +551,7 @@
|
|
542
551
|
:env_var: MDE_MENU_NOTE_FORMAT
|
543
552
|
:opt_name: menu_note_format
|
544
553
|
:procname: val_as_str
|
545
|
-
- :default: "^(?<line>(
|
554
|
+
- :default: "^(?<line>(?![ \t]*/)(?<text>.*?)(?<trailing>[ \t]*))?$"
|
546
555
|
:description: Pattern for notes in block selection menu
|
547
556
|
:env_var: MDE_MENU_NOTE_MATCH
|
548
557
|
:opt_name: menu_note_match
|
@@ -565,6 +574,12 @@
|
|
565
574
|
:env_var: MDE_MENU_OPTION_EXIT_NAME
|
566
575
|
:opt_name: menu_option_exit_name
|
567
576
|
:procname: val_as_str
|
577
|
+
- :default:
|
578
|
+
:line: "* History"
|
579
|
+
:description: Text for History option
|
580
|
+
:env_var: MDE_MENU_OPTION_HISTORY_NAME
|
581
|
+
:opt_name: menu_option_history_name
|
582
|
+
:procname: val_as_str
|
568
583
|
- :default:
|
569
584
|
:line: "* Load"
|
570
585
|
:description: Text for Load option
|
@@ -808,12 +823,17 @@
|
|
808
823
|
:opt_name: prompt_exit
|
809
824
|
:procname: val_as_str
|
810
825
|
- :default: Back
|
811
|
-
:description:
|
812
|
-
:env_var:
|
826
|
+
:description: User wants out of menu
|
827
|
+
:env_var: MDE_PROMPT_FILESPEC_BACK
|
813
828
|
:opt_name: prompt_filespec_back
|
814
829
|
:procname: val_as_str
|
830
|
+
- :default: Facet
|
831
|
+
:description: User wants to tailor the menu
|
832
|
+
:env_var: MDE_PROMPT_FILESPEC_FACET
|
833
|
+
:opt_name: prompt_filespec_facet
|
834
|
+
:procname: val_as_str
|
815
835
|
- :default: Other
|
816
|
-
:description:
|
836
|
+
:description: User wants a custom file name
|
817
837
|
:env_var: MDE_PROMPT_FILESPEC_OTHER
|
818
838
|
:opt_name: prompt_filespec_other
|
819
839
|
:procname: val_as_str
|
@@ -848,6 +868,13 @@
|
|
848
868
|
:procname: val_as_str
|
849
869
|
- :default: |2-
|
850
870
|
|
871
|
+
View file:
|
872
|
+
:description: Prompt to select a saved asset
|
873
|
+
:env_var: MDE_PROMPT_SELECT_HISTORY_FILE
|
874
|
+
:opt_name: prompt_select_history_file
|
875
|
+
:procname: val_as_str
|
876
|
+
- :default: |2-
|
877
|
+
|
851
878
|
Choose a file:
|
852
879
|
:description: Prompt to select a markdown document
|
853
880
|
:env_var: MDE_PROMPT_SELECT_MD
|
@@ -875,7 +902,7 @@
|
|
875
902
|
:env_var: MDE_PROMPT_YES
|
876
903
|
:opt_name: prompt_yes
|
877
904
|
:procname: val_as_str
|
878
|
-
- :description:
|
905
|
+
- :description: Print the gem's home directory
|
879
906
|
:long_name: pwd
|
880
907
|
:opt_name: pwd
|
881
908
|
:procname: val_as_bool
|
@@ -889,6 +916,16 @@
|
|
889
916
|
:env_var: MDE_RUNTIME_EXCEPTION_ERROR_LEVEL
|
890
917
|
:opt_name: runtime_exception_error_level
|
891
918
|
:procname: val_as_int
|
919
|
+
- :default: "%{prefix}%{join}%{time}%{join}%{filename}%{join}%{mark}%{join}%{blockname}%{join}%{exts}"
|
920
|
+
:description: Format for script and log file names
|
921
|
+
:env_var: MDE_SAVED_ASSET_FORMAT
|
922
|
+
:opt_name: saved_asset_format
|
923
|
+
:procname: val_as_str
|
924
|
+
- :default: "^(?<prefix>.+)(?<join>_)(?<time>[0-9\\-]+)\\g'join'(?<filename>.+)\\g'join'(?<mark>~)\\g'join'(?<blockname>.+)\\g'join'(?<exts>\\..+)$"
|
925
|
+
:description: Regexp for script and log file names
|
926
|
+
:env_var: MDE_SAVED_ASSET_MATCH
|
927
|
+
:opt_name: saved_asset_match
|
928
|
+
:procname: val_as_str
|
892
929
|
- :arg_name: BOOL
|
893
930
|
:default: false
|
894
931
|
:description: Whether to save an executed script
|
@@ -911,6 +948,11 @@
|
|
911
948
|
:env_var: MDE_SAVED_FILENAME_REPLACEMENT
|
912
949
|
:opt_name: saved_filename_replacement
|
913
950
|
:procname: val_as_str
|
951
|
+
- :default: "%{time} %{blockname} %{exts}"
|
952
|
+
:description: Format for each row displayed in history
|
953
|
+
:env_var: MDE_SAVED_HISTORY_FORMAT
|
954
|
+
:opt_name: saved_history_format
|
955
|
+
:procname: val_as_str
|
914
956
|
- :arg_name: INT
|
915
957
|
:default: 493
|
916
958
|
:description: chmod for saved scripts
|
@@ -998,14 +1040,6 @@
|
|
998
1040
|
:env_var: MDE_SELECT_PAGE_HEIGHT
|
999
1041
|
:opt_name: select_page_height
|
1000
1042
|
:procname: val_as_int
|
1001
|
-
- :description: Select and execute a recently saved output
|
1002
|
-
:long_name: select-recent-output
|
1003
|
-
:opt_name: select_recent_output
|
1004
|
-
:procname: val_as_bool
|
1005
|
-
- :description: Select and execute a recently saved script
|
1006
|
-
:long_name: select-recent-script
|
1007
|
-
:opt_name: select_recent_script
|
1008
|
-
:procname: val_as_bool
|
1009
1043
|
- :default: "#!/usr/bin/env"
|
1010
1044
|
:description: Shebang for saved scripts
|
1011
1045
|
:env_var: MDE_SHEBANG
|
@@ -1032,6 +1066,12 @@
|
|
1032
1066
|
:env_var: MDE_SHELL_CODE_LABEL_TIME_FORMAT
|
1033
1067
|
:opt_name: shell_code_label_time_format
|
1034
1068
|
:procname: val_as_str
|
1069
|
+
- :arg_name: BOOL
|
1070
|
+
:default: true
|
1071
|
+
:description: Whether saved file names include shell parameter expansion
|
1072
|
+
:env_var: MDE_SHELL_PARAMETER_EXPANSION
|
1073
|
+
:opt_name: shell_parameter_expansion
|
1074
|
+
:procname: val_as_bool
|
1035
1075
|
- :description: List tab completions
|
1036
1076
|
:long_name: tab-completions
|
1037
1077
|
:opt_name: tab_completions
|
data/lib/namer.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# encoding=utf-8
|
5
|
+
require 'digest'
|
6
|
+
# require_relative 'poly'
|
7
|
+
|
8
|
+
$pd = false unless defined?($pd)
|
9
|
+
|
10
|
+
class Hash
|
11
|
+
# block name in commands and documents
|
12
|
+
def pub_name(**kwargs)
|
13
|
+
full = fetch(:nickname, nil) || fetch(:oname, nil)
|
14
|
+
full&.to_s&.pub_name(**kwargs).tap { |ret| pp [__LINE__, 'Hash.pub_name() ->', ret] if $pd }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class String
|
19
|
+
FN_ID_LEN = 4
|
20
|
+
FN_MAX_LEN = 64
|
21
|
+
FN_PATTERN = %r{[^!#%\+\-0-9=@A-Z_a-z()\[\]{}]}.freeze # characters than can be used in a file name without quotes or escaping
|
22
|
+
# except '.', ',', '~' reserved for tokenization
|
23
|
+
# / !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
|
24
|
+
FN_REPLACEMENT = '_'
|
25
|
+
|
26
|
+
# block name in commands and documents
|
27
|
+
def pub_name(
|
28
|
+
id_len: FN_ID_LEN, max_len: FN_MAX_LEN,
|
29
|
+
pattern: FN_PATTERN, replacement: FN_REPLACEMENT
|
30
|
+
)
|
31
|
+
trimmed = if self[max_len]
|
32
|
+
rand(((10**(id_len - 1)) + 1)..(10**id_len)).to_s
|
33
|
+
dig = Digest::MD5.hexdigest(self)[0, id_len]
|
34
|
+
self[0..max_len - id_len] + dig
|
35
|
+
else
|
36
|
+
self
|
37
|
+
end
|
38
|
+
|
39
|
+
trimmed.gsub(pattern, replacement).tap { |ret| pp [__LINE__, 'String.pub_name() ->', ret] if $pd }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# require 'ostruct'
|
44
|
+
|
45
|
+
# class BlkS < OpenStruct
|
46
|
+
# # Method to fetch the value associated with the attribute :nickname or :oname
|
47
|
+
# def pub_name
|
48
|
+
# self.nickname || self.oname
|
49
|
+
# end
|
50
|
+
# end
|
data/lib/poly.rb
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# encoding=utf-8
|
5
|
+
|
6
|
+
$pd = false
|
7
|
+
|
8
|
+
class Poly
|
9
|
+
# attr_reader :table
|
10
|
+
def initialize(table = {})
|
11
|
+
@table = table.tap{|ret| pp [__LINE__,'Poly.initialize()','table',table.to_yaml] if $pd }
|
12
|
+
end
|
13
|
+
|
14
|
+
def fetch(key, *args)
|
15
|
+
key_sym = key.to_sym
|
16
|
+
if respond_to?("get_#{key}")
|
17
|
+
send("get_#{key}")
|
18
|
+
elsif @table.key?(key_sym)
|
19
|
+
@table[key_sym]
|
20
|
+
elsif block_given?
|
21
|
+
yield key_sym
|
22
|
+
elsif args.count.positive?
|
23
|
+
# binding.irb
|
24
|
+
args.first
|
25
|
+
else
|
26
|
+
binding.irb
|
27
|
+
raise KeyError, "key not found: #{key}"
|
28
|
+
end.tap{|ret| pp([__LINE__,"Poly.fetch #{key} #{args}",'->',ret]) if $pd }
|
29
|
+
end
|
30
|
+
|
31
|
+
def key?(name)
|
32
|
+
@table.key?(name.to_sym).tap{|ret| pp([__LINE__,"Poly.key? #{name}",'->',ret]) if $pd }
|
33
|
+
end
|
34
|
+
|
35
|
+
def method_missing(name, *args)
|
36
|
+
pt = nil
|
37
|
+
if name.to_s.end_with?('=')
|
38
|
+
# Setter method
|
39
|
+
attribute = name.to_s.chomp('=').to_sym
|
40
|
+
value = args.first
|
41
|
+
if respond_to?("set_#{attribute}")
|
42
|
+
pt = 'send set_'
|
43
|
+
send("set_#{attribute}", value)
|
44
|
+
else
|
45
|
+
pt = 'table set'
|
46
|
+
@table[attribute] = value
|
47
|
+
end
|
48
|
+
elsif respond_to?("get_#{name}")
|
49
|
+
pt = 'send get_'
|
50
|
+
# Getter method
|
51
|
+
send("get_#{name}")
|
52
|
+
elsif @table.respond_to?(name)
|
53
|
+
pt = 'send name'
|
54
|
+
@table.send(name, *args)
|
55
|
+
else
|
56
|
+
pt = 'table read'
|
57
|
+
@table[name.to_sym]
|
58
|
+
end.tap{|ret| pp([__LINE__,"Poly.method_missing #{name} #{args.map(&:to_s).join(' ')}",pt,'->',ret]) if $pd }
|
59
|
+
end
|
60
|
+
|
61
|
+
def respond_to_missing?(name, include_private = false)
|
62
|
+
# name.to_s.end_with?('=') || @table.key?(name.to_sym) || @table.respond_to?(name) || super
|
63
|
+
(name.to_s.end_with?('=') || @table.key?(name.to_sym) || @table.respond_to?(name) || super).tap{|ret| pp([__LINE__,"Poly.respond_to_missing? #{name}",'->',ret]) if $pd }
|
64
|
+
end
|
65
|
+
|
66
|
+
def [](key)
|
67
|
+
if respond_to?("get_#{key}")
|
68
|
+
send("get_#{key}")
|
69
|
+
else
|
70
|
+
@table[key.to_sym]
|
71
|
+
end.tap{|ret| pp([__LINE__,"Poly.[] #{key}",'->',ret]) if $pd }
|
72
|
+
end
|
73
|
+
|
74
|
+
def []=(key, value)
|
75
|
+
if respond_to?("set_#{key}")
|
76
|
+
send("set_#{key}", value)
|
77
|
+
else
|
78
|
+
@table[key.to_sym] = value
|
79
|
+
end.tap{|ret| pp([__LINE__,"Poly.[]= #{key} #{value}",'->',ret]) if $pd }
|
80
|
+
end
|
81
|
+
|
82
|
+
# for export to Prompt library
|
83
|
+
# def merge(*args)
|
84
|
+
# Proc.new { |x| @table.merge x }
|
85
|
+
# end
|
86
|
+
def merge(*args)
|
87
|
+
# pp caller
|
88
|
+
# binding.irb
|
89
|
+
@table.merge(*args).tap{|ret| pp([__LINE__,"Poly.merge",'->',ret]) if $pd }
|
90
|
+
end
|
91
|
+
|
92
|
+
# for export to Prompt library
|
93
|
+
def to_h
|
94
|
+
@table.tap{|ret| pp([__LINE__,"Poly.to_h",'->',ret]) if $pd }
|
95
|
+
end
|
96
|
+
|
97
|
+
def to_yaml
|
98
|
+
@table.to_yaml.tap{|ret| pp([__LINE__,"Poly.to_yaml",'->',ret]) if $pd }
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# class CustomStruct < Poly
|
103
|
+
# # Custom setter for virtual attribute :full_name
|
104
|
+
# def set_full_name(value)
|
105
|
+
# names = value.split(' ')
|
106
|
+
# @table[:first_name] = names.first
|
107
|
+
# @table[:last_name] = names.last
|
108
|
+
# end
|
109
|
+
|
110
|
+
# # Custom getter for virtual attribute :full_name
|
111
|
+
# def get_full_name
|
112
|
+
# "#{@table[:first_name]} #{@table[:last_name]}"
|
113
|
+
# end
|
114
|
+
# end
|
115
|
+
|
116
|
+
# # Example usage
|
117
|
+
# person = CustomStruct.new
|
118
|
+
# person.first_name = 'John'
|
119
|
+
# person.last_name = 'Doe'
|
120
|
+
# puts person.first_name # => John
|
121
|
+
# puts person.last_name # => Doe
|
122
|
+
|
123
|
+
# # Setting and getting a virtual attribute
|
124
|
+
# person.full_name = 'Jane Smith'
|
125
|
+
# puts person.first_name # => Jane
|
126
|
+
# puts person.last_name # => Smith
|
127
|
+
# puts person.full_name # => Jane Smith
|
128
|
+
|
129
|
+
# # Setting and getting a regular attribute
|
130
|
+
# person.age = 30
|
131
|
+
# puts person.age # => 30
|
132
|
+
|
133
|
+
# # Using array notation
|
134
|
+
# person[:age] = 35
|
135
|
+
# puts person[:age] # => 35
|
136
|
+
|
137
|
+
# person[:full_name] = 'Alice Johnson'
|
138
|
+
# puts person[:first_name] # => Alice
|
139
|
+
# puts person[:last_name] # => Johnson
|
140
|
+
# puts person[:full_name] # => Alice Johnson
|
141
|
+
|
142
|
+
# # Using fetch method
|
143
|
+
# puts person.fetch(:age) # => 35
|
144
|
+
# puts person.fetch(:nonexistent, 'default') # => default
|
145
|
+
# puts person.fetch(:nonexistent) { |key| "block default for #{key}" } # => block default for nonexistent
|
146
|
+
|
147
|
+
# # This will raise a KeyError
|
148
|
+
# begin
|
149
|
+
# person.fetch(:nonexistent)
|
150
|
+
# rescue KeyError => e
|
151
|
+
# puts e.message # => key not found: nonexistent
|
152
|
+
# end
|