markdown_exec 2.1.0 → 2.3.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 +5 -1
- data/CHANGELOG.md +23 -1
- 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 +62 -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/{port.md → port-blocks.md} +18 -9
- data/examples/save.md +76 -4
- data/examples/vars-blocks.md +38 -0
- data/lib/colorize.rb +13 -0
- data/lib/constants.rb +1 -1
- data/lib/fcb.rb +202 -16
- data/lib/filter.rb +12 -12
- data/lib/hash_delegator.rb +695 -326
- data/lib/hierarchy_string.rb +133 -0
- data/lib/input_sequencer.rb +4 -2
- data/lib/link_history.rb +34 -1
- data/lib/markdown_exec/version.rb +1 -1
- data/lib/markdown_exec.rb +67 -79
- data/lib/mdoc.rb +122 -60
- data/lib/menu.src.yml +71 -21
- data/lib/menu.yml +59 -19
- data/lib/namer.rb +50 -0
- data/lib/poly.rb +152 -0
- data/lib/saved_assets.rb +4 -11
- data/lib/string_util.rb +0 -1
- data/lib/text_analyzer.rb +100 -0
- metadata +16 -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.yml
CHANGED
@@ -236,8 +236,10 @@
|
|
236
236
|
:default: false
|
237
237
|
:description: Execute script in own window
|
238
238
|
:env_var: MDE_EXECUTE_IN_OWN_WINDOW
|
239
|
+
:long_name: execute_in_own_window
|
239
240
|
:opt_name: execute_in_own_window
|
240
241
|
:procname: val_as_bool
|
242
|
+
:short_name: w
|
241
243
|
- :default: fg_rgbh_7f_ff_00
|
242
244
|
:description: execution_report_preview_frame_color
|
243
245
|
:env_var: MDE_EXECUTION_REPORT_PREVIEW_FRAME_COLOR
|
@@ -259,12 +261,12 @@
|
|
259
261
|
:long_name: exit
|
260
262
|
:procname: exit
|
261
263
|
:short_name: x
|
262
|
-
- :default: "^(?<indent> *)`{3,}"
|
264
|
+
- :default: "^(?<indent>[ \t]*)`{3,}"
|
263
265
|
:description: Matches the start and end of a fenced code block
|
264
266
|
:env_var: MDE_FENCED_START_AND_END_REGEX
|
265
267
|
:opt_name: fenced_start_and_end_regex
|
266
268
|
:procname: val_as_str
|
267
|
-
- :default: "^(?<indent> *)`{3,}(?<shell>[^`\\s]*) *(:(?<name>[^\\s]*))? *(?<rest>.*)
|
269
|
+
- :default: "^(?<indent>[ \t]*)`{3,}(?<shell>[^`\\s]*) *(:(?<name>[^\\s]*))? *(?<rest>.*)
|
268
270
|
*$"
|
269
271
|
:description: Match the start of a fenced block
|
270
272
|
:env_var: MDE_FENCED_START_EXTENDED_REGEX
|
@@ -325,7 +327,7 @@
|
|
325
327
|
:procname: val_as_str
|
326
328
|
- :arg_name: HOW
|
327
329
|
:default: ''
|
328
|
-
:description: Find in YAML configuration options
|
330
|
+
:description: Find keyword in YAML configuration options
|
329
331
|
:long_name: how
|
330
332
|
:procname: how
|
331
333
|
:short_name: "?"
|
@@ -337,6 +339,35 @@
|
|
337
339
|
:env_var: MDE_IMPORT_PATTERN
|
338
340
|
:opt_name: import_pattern
|
339
341
|
:procname: val_as_str
|
342
|
+
- :default:
|
343
|
+
- :color_method: :bold_underline
|
344
|
+
:pattern: "\\*\\*_([^_]{0,64})_\\*\\*"
|
345
|
+
- :color_method: :bold_italic
|
346
|
+
:pattern: "\\*\\*~([^~]{0,64})~\\*\\*"
|
347
|
+
- :color_method: :bold
|
348
|
+
:pattern: "\\*\\*([^*]{0,64})\\*\\*"
|
349
|
+
- :color_method: :bold
|
350
|
+
:pattern: __([^_]{0,64})__
|
351
|
+
- :color_method: :underline
|
352
|
+
:pattern: "\\*([^*]{0,64})\\*"
|
353
|
+
- :color_method: :underline_italic
|
354
|
+
:pattern: _~([^_]{0,64})~_
|
355
|
+
- :color_method: strikethrough
|
356
|
+
:pattern: "~~([^~]{0,64})~~"
|
357
|
+
:description: Line-oriented text decoration (Main)
|
358
|
+
:env_var: MDE_LINE_DECOR_MAIN
|
359
|
+
:opt_name: line_decor_main
|
360
|
+
:procname: val_as_str
|
361
|
+
- :default: []
|
362
|
+
:description: Line-oriented text decoration (Post)
|
363
|
+
:env_var: MDE_LINE_DECOR_POST
|
364
|
+
:opt_name: line_decor_post
|
365
|
+
:procname: val_as_str
|
366
|
+
- :default: []
|
367
|
+
:description: Line-oriented text decoration (Pre)
|
368
|
+
:env_var: MDE_LINE_DECOR_PRE
|
369
|
+
:opt_name: line_decor_pre
|
370
|
+
:procname: val_as_str
|
340
371
|
- :description: List blocks
|
341
372
|
:long_name: list-blocks
|
342
373
|
:opt_name: list_blocks
|
@@ -373,6 +404,7 @@
|
|
373
404
|
:long_name: load-code
|
374
405
|
:opt_name: load_code
|
375
406
|
:procname: val_as_str
|
407
|
+
:short_name: l
|
376
408
|
- :arg_name: PREFIX
|
377
409
|
:default: mde
|
378
410
|
:description: Name prefix for stdout files
|
@@ -431,7 +463,7 @@
|
|
431
463
|
:env_var: MDE_MENU_DIVIDER_FORMAT
|
432
464
|
:opt_name: menu_divider_format
|
433
465
|
:procname: val_as_str
|
434
|
-
- :default: "
|
466
|
+
- :default: "^(?<indent>[ \t]*):::(?<line>(?<text>.*?)(?<trailing>[ \t]*))?$"
|
435
467
|
:description: Pattern for topics/dividers in block selection menu
|
436
468
|
:env_var: MDE_MENU_DIVIDER_MATCH
|
437
469
|
:opt_name: menu_divider_match
|
@@ -548,7 +580,7 @@
|
|
548
580
|
:env_var: MDE_MENU_NOTE_FORMAT
|
549
581
|
:opt_name: menu_note_format
|
550
582
|
:procname: val_as_str
|
551
|
-
- :default: "^(?<line>(
|
583
|
+
- :default: "^(?<line>(?![ \t]*/)(?<text>.*?)(?<trailing>[ \t]*))?$"
|
552
584
|
:description: Pattern for notes in block selection menu
|
553
585
|
:env_var: MDE_MENU_NOTE_MATCH
|
554
586
|
:opt_name: menu_note_match
|
@@ -820,12 +852,17 @@
|
|
820
852
|
:opt_name: prompt_exit
|
821
853
|
:procname: val_as_str
|
822
854
|
- :default: Back
|
823
|
-
:description:
|
824
|
-
:env_var:
|
855
|
+
:description: User wants out of menu
|
856
|
+
:env_var: MDE_PROMPT_FILESPEC_BACK
|
825
857
|
:opt_name: prompt_filespec_back
|
826
858
|
:procname: val_as_str
|
859
|
+
- :default: Facet
|
860
|
+
:description: User wants to tailor the menu
|
861
|
+
:env_var: MDE_PROMPT_FILESPEC_FACET
|
862
|
+
:opt_name: prompt_filespec_facet
|
863
|
+
:procname: val_as_str
|
827
864
|
- :default: Other
|
828
|
-
:description:
|
865
|
+
:description: User wants a custom file name
|
829
866
|
:env_var: MDE_PROMPT_FILESPEC_OTHER
|
830
867
|
:opt_name: prompt_filespec_other
|
831
868
|
:procname: val_as_str
|
@@ -894,7 +931,7 @@
|
|
894
931
|
:env_var: MDE_PROMPT_YES
|
895
932
|
:opt_name: prompt_yes
|
896
933
|
:procname: val_as_str
|
897
|
-
- :description:
|
934
|
+
- :description: Print the gem's home directory
|
898
935
|
:long_name: pwd
|
899
936
|
:opt_name: pwd
|
900
937
|
:procname: val_as_bool
|
@@ -909,12 +946,12 @@
|
|
909
946
|
:opt_name: runtime_exception_error_level
|
910
947
|
:procname: val_as_int
|
911
948
|
- :default: "%{prefix}%{join}%{time}%{join}%{filename}%{join}%{mark}%{join}%{blockname}%{join}%{exts}"
|
912
|
-
:description:
|
949
|
+
:description: Format for script and log file names
|
913
950
|
:env_var: MDE_SAVED_ASSET_FORMAT
|
914
951
|
:opt_name: saved_asset_format
|
915
952
|
:procname: val_as_str
|
916
953
|
- :default: "^(?<prefix>.+)(?<join>_)(?<time>[0-9\\-]+)\\g'join'(?<filename>.+)\\g'join'(?<mark>~)\\g'join'(?<blockname>.+)\\g'join'(?<exts>\\..+)$"
|
917
|
-
:description:
|
954
|
+
:description: Regexp for script and log file names
|
918
955
|
:env_var: MDE_SAVED_ASSET_MATCH
|
919
956
|
:opt_name: saved_asset_match
|
920
957
|
:procname: val_as_str
|
@@ -940,6 +977,11 @@
|
|
940
977
|
:env_var: MDE_SAVED_FILENAME_REPLACEMENT
|
941
978
|
:opt_name: saved_filename_replacement
|
942
979
|
:procname: val_as_str
|
980
|
+
- :default: "%{time} %{blockname} %{exts}"
|
981
|
+
:description: Format for each row displayed in history
|
982
|
+
:env_var: MDE_SAVED_HISTORY_FORMAT
|
983
|
+
:opt_name: saved_history_format
|
984
|
+
:procname: val_as_str
|
943
985
|
- :arg_name: INT
|
944
986
|
:default: 493
|
945
987
|
:description: chmod for saved scripts
|
@@ -1027,14 +1069,6 @@
|
|
1027
1069
|
:env_var: MDE_SELECT_PAGE_HEIGHT
|
1028
1070
|
:opt_name: select_page_height
|
1029
1071
|
:procname: val_as_int
|
1030
|
-
- :description: Select and execute a recently saved output
|
1031
|
-
:long_name: select-recent-output
|
1032
|
-
:opt_name: select_recent_output
|
1033
|
-
:procname: val_as_bool
|
1034
|
-
- :description: Select and execute a recently saved script
|
1035
|
-
:long_name: select-recent-script
|
1036
|
-
:opt_name: select_recent_script
|
1037
|
-
:procname: val_as_bool
|
1038
1072
|
- :default: "#!/usr/bin/env"
|
1039
1073
|
:description: Shebang for saved scripts
|
1040
1074
|
:env_var: MDE_SHEBANG
|
@@ -1061,6 +1095,12 @@
|
|
1061
1095
|
:env_var: MDE_SHELL_CODE_LABEL_TIME_FORMAT
|
1062
1096
|
:opt_name: shell_code_label_time_format
|
1063
1097
|
:procname: val_as_str
|
1098
|
+
- :arg_name: BOOL
|
1099
|
+
:default: true
|
1100
|
+
:description: Whether saved file names include shell parameter expansion
|
1101
|
+
:env_var: MDE_SHELL_PARAMETER_EXPANSION
|
1102
|
+
:opt_name: shell_parameter_expansion
|
1103
|
+
:procname: val_as_bool
|
1064
1104
|
- :description: List tab completions
|
1065
1105
|
:long_name: tab-completions
|
1066
1106
|
: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
|
data/lib/saved_assets.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
# encoding=utf-8
|
5
|
+
require_relative 'namer'
|
5
6
|
|
6
7
|
module MarkdownExec
|
7
8
|
# SavedAsset
|
@@ -12,10 +13,6 @@ module MarkdownExec
|
|
12
13
|
# method derives a name for stdout redirection.
|
13
14
|
#
|
14
15
|
class SavedAsset
|
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
|
17
|
-
# / !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
|
18
|
-
FNR12 = '_'
|
19
16
|
DEFAULT_FTIME = '%F-%H-%M-%S'
|
20
17
|
FILE_BLOCK_SEP = ','
|
21
18
|
JOIN_STR = '_'
|
@@ -26,21 +23,17 @@ module MarkdownExec
|
|
26
23
|
# @param time [Time] the time object for formatting
|
27
24
|
# @param blockname [String] the block name to include
|
28
25
|
# @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
26
|
# @param exts [String] the extension to append (default: '.sh')
|
32
27
|
def initialize(
|
33
28
|
saved_asset_format:, filename: nil, prefix: nil, time: nil, blockname: nil,
|
34
|
-
ftime: DEFAULT_FTIME,
|
29
|
+
ftime: DEFAULT_FTIME, exts: nil,
|
35
30
|
mark: nil, join_str: nil
|
36
31
|
)
|
37
|
-
@filename = filename ? filename.
|
32
|
+
@filename = filename ? filename.pub_name : '*' # [String] the name of the file
|
38
33
|
@prefix = prefix || '*' # [String] the prefix to use
|
39
34
|
@time = time ? time.strftime(ftime) : '*' # [Time] the time object for formatting
|
40
|
-
@blockname = blockname ? blockname.
|
35
|
+
@blockname = blockname ? blockname.pub_name : '*' # [String] the block name to include
|
41
36
|
# @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
37
|
@exts = exts || '.*' # [String] the extension to append (default: '.sh')
|
45
38
|
@mark = mark || MARK_STR
|
46
39
|
@join_str = join_str || JOIN_STR
|
data/lib/string_util.rb
CHANGED
@@ -0,0 +1,100 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TextAnalyzer
|
4
|
+
# Analyzes a hierarchical structure (String or Array) and highlights segments based on the pattern
|
5
|
+
#
|
6
|
+
# @param hierarchy [String, Array] the hierarchical structure to be analyzed
|
7
|
+
# @param pattern [Regexp] the pattern to match against the text
|
8
|
+
# @param default_color [String] the color for non-matching segments
|
9
|
+
# @param match_color [String] the color for matching segments
|
10
|
+
#
|
11
|
+
# @return [Array<Hash>, Array<Array<Hash>>] an array or nested arrays of highlighted segments
|
12
|
+
#
|
13
|
+
# @raise [ArgumentError] if the hierarchy structure is neither a String nor an Array
|
14
|
+
def self.analyze_hierarchy(hierarchy, pattern, default_color, match_color)
|
15
|
+
case hierarchy
|
16
|
+
when String
|
17
|
+
highlight_segments(hierarchy, pattern, default_color, match_color)
|
18
|
+
when Hash
|
19
|
+
decorated = highlight_segments(hierarchy[:text], pattern,
|
20
|
+
hierarchy[:color], match_color)
|
21
|
+
|
22
|
+
case decorated
|
23
|
+
when String
|
24
|
+
hierarchy
|
25
|
+
when Array
|
26
|
+
if decorated.length == 1
|
27
|
+
hierarchy
|
28
|
+
else
|
29
|
+
decorated
|
30
|
+
end
|
31
|
+
else
|
32
|
+
decorated
|
33
|
+
end
|
34
|
+
when Array
|
35
|
+
hierarchy.map do |element|
|
36
|
+
analyze_hierarchy(element, pattern, default_color, match_color)
|
37
|
+
end
|
38
|
+
when HierarchyString
|
39
|
+
|
40
|
+
hierarchy.replace_text! do |substring|
|
41
|
+
substring ### no change
|
42
|
+
end
|
43
|
+
|
44
|
+
else
|
45
|
+
binding.irb
|
46
|
+
raise ArgumentError, 'Invalid hierarchy structure'
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Highlights segments of the text based on the pattern
|
51
|
+
#
|
52
|
+
# @param text [String] the text to be analyzed
|
53
|
+
# @param pattern [Regexp] the pattern to match against the text
|
54
|
+
# @param default_color [String] the color for non-matching segments
|
55
|
+
# @param match_color [String] the color for matching segments
|
56
|
+
#
|
57
|
+
# @return [Array<Hash>] an array of hashes, each containing a segment of text and its corresponding color
|
58
|
+
def self.highlight_segments(text, pattern, default_color, match_color)
|
59
|
+
segments = []
|
60
|
+
|
61
|
+
yield_matches_and_non_matches(text, pattern) do |segment, is_match|
|
62
|
+
segments << if is_match
|
63
|
+
{ text: segment, color: match_color }
|
64
|
+
else
|
65
|
+
{ text: segment, color: default_color }
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
segments
|
70
|
+
end
|
71
|
+
|
72
|
+
# Yields matching and non-matching segments of the text based on the pattern
|
73
|
+
#
|
74
|
+
# @param text [String] the text to be analyzed
|
75
|
+
# @param pattern [Regexp] the pattern to match against the text
|
76
|
+
#
|
77
|
+
# @yieldparam segment [String] a segment of the text
|
78
|
+
# @yieldparam is_match [Boolean] true if the segment matches the pattern, false otherwise
|
79
|
+
def self.yield_matches_and_non_matches(text, pattern)
|
80
|
+
last_end = 0
|
81
|
+
|
82
|
+
text.scan(pattern) do |match|
|
83
|
+
match_start = Regexp.last_match.begin(0)
|
84
|
+
match_end = Regexp.last_match.end(0)
|
85
|
+
|
86
|
+
# Yield the non-matching segment before the match
|
87
|
+
yield text[last_end...match_start], false if match_start > last_end
|
88
|
+
|
89
|
+
# Yield the matching segment
|
90
|
+
yield match.first, true
|
91
|
+
|
92
|
+
last_end = match_end
|
93
|
+
end
|
94
|
+
|
95
|
+
# Yield any remaining non-matching segment after the last match
|
96
|
+
return unless last_end < text.length
|
97
|
+
|
98
|
+
yield text[last_end..-1], false
|
99
|
+
end
|
100
|
+
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.
|
4
|
+
version: 2.3.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-08-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: clipboard
|
@@ -113,6 +113,8 @@ files:
|
|
113
113
|
- bin/setup
|
114
114
|
- bin/tab_completion.sh
|
115
115
|
- bin/tab_completion.sh.erb
|
116
|
+
- examples/bash-blocks.md
|
117
|
+
- examples/block-names.md
|
116
118
|
- examples/block_names.md
|
117
119
|
- examples/colors.md
|
118
120
|
- examples/data-files.md
|
@@ -125,6 +127,9 @@ files:
|
|
125
127
|
- examples/index.md
|
126
128
|
- examples/interrupt.md
|
127
129
|
- examples/line-wrapping.md
|
130
|
+
- examples/link-blocks-block.md
|
131
|
+
- examples/link-blocks-load-save.md
|
132
|
+
- examples/link-blocks-vars.md
|
128
133
|
- examples/linked.md
|
129
134
|
- examples/linked1.md
|
130
135
|
- examples/linked2.md
|
@@ -135,15 +140,16 @@ files:
|
|
135
140
|
- examples/load2.sh
|
136
141
|
- examples/load_code.md
|
137
142
|
- examples/nickname.md
|
138
|
-
- examples/opts.md
|
143
|
+
- examples/opts-blocks-require.md
|
144
|
+
- examples/opts-blocks.md
|
139
145
|
- examples/opts_output_execution.md
|
140
|
-
- examples/pass-through.md
|
146
|
+
- examples/pass-through-arguments.md
|
141
147
|
- examples/pause-after-execution.md
|
142
148
|
- examples/plant.md
|
143
|
-
- examples/port.md
|
149
|
+
- examples/port-blocks.md
|
144
150
|
- examples/save.md
|
145
151
|
- examples/search.md
|
146
|
-
- examples/vars.md
|
152
|
+
- examples/vars-blocks.md
|
147
153
|
- examples/wrap.md
|
148
154
|
- lib/ansi_formatter.rb
|
149
155
|
- lib/array.rb
|
@@ -165,6 +171,7 @@ files:
|
|
165
171
|
- lib/fout.rb
|
166
172
|
- lib/hash.rb
|
167
173
|
- lib/hash_delegator.rb
|
174
|
+
- lib/hierarchy_string.rb
|
168
175
|
- lib/input_sequencer.rb
|
169
176
|
- lib/instance_method_wrapper.rb
|
170
177
|
- lib/link_history.rb
|
@@ -173,8 +180,10 @@ files:
|
|
173
180
|
- lib/mdoc.rb
|
174
181
|
- lib/menu.src.yml
|
175
182
|
- lib/menu.yml
|
183
|
+
- lib/namer.rb
|
176
184
|
- lib/object_present.rb
|
177
185
|
- lib/option_value.rb
|
186
|
+
- lib/poly.rb
|
178
187
|
- lib/regexp.rb
|
179
188
|
- lib/resize_terminal.rb
|
180
189
|
- lib/rspec_helpers.rb
|
@@ -185,6 +194,7 @@ files:
|
|
185
194
|
- lib/streams_out.rb
|
186
195
|
- lib/string_util.rb
|
187
196
|
- lib/tap.rb
|
197
|
+
- lib/text_analyzer.rb
|
188
198
|
homepage: https://rubygems.org/gems/markdown_exec
|
189
199
|
licenses:
|
190
200
|
- MIT
|
data/examples/vars.md
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
```bash :(defaults)
|
2
|
-
: ${VAULT:=default}
|
3
|
-
```
|
4
|
-
```bash :show_vars +(defaults)
|
5
|
-
source bin/colorize_env_vars.sh
|
6
|
-
colorize_env_vars '' VAULT
|
7
|
-
```
|
8
|
-
```vars :set
|
9
|
-
VAULT: 11
|
10
|
-
```
|
11
|
-
```vars :set_with_show +show_vars
|
12
|
-
VAULT: 22
|
13
|
-
```
|
14
|
-
```bash :(hidden)
|
15
|
-
colorize_env_vars '' NOTHING
|
16
|
-
```
|
17
|
-
```bash :show_with_set +set
|
18
|
-
source bin/colorize_env_vars.sh
|
19
|
-
colorize_env_vars '' VAULT
|
20
|
-
```
|
File without changes
|
File without changes
|