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.
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: "^:::(?<line>(?<indent>[ \t]*)(?<text>.*?)(?<trailing>[ \t]*))?$"
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
- ## all lines that do not start with "/ " are notes
647
- - :default: "^(?<line>(?!/ )(?<indent>[ \t]*)(?<text>.*?)(?<trailing>[ \t]*))?$"
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: Quit prompt
955
- :env_var: MDE_PROMPT_FILESPEC_OTHER
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: Prompt for a custom file name
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: Gem home folder
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: "^:::(?<line>(?<indent>[ \t]*)(?<text>.*?)(?<trailing>[ \t]*))?$"
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>(?!/ )(?<indent>[ \t]*)(?<text>.*?)(?<trailing>[ \t]*))?$"
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: Quit prompt
812
- :env_var: MDE_PROMPT_FILESPEC_OTHER
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: Prompt for a custom file name
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: Gem home folder
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