markdown_exec 2.0.8.4 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|