markdown_exec 1.3.0 → 1.3.1
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/.reek +3 -0
- data/.rubocop.yml +3 -0
- data/CHANGELOG.md +32 -9
- data/Gemfile +5 -0
- data/Gemfile.lock +15 -13
- data/README.md +56 -0
- data/Rakefile +182 -63
- data/bin/tab_completion.sh +21 -3
- data/bin/tab_completion.sh.erb +23 -0
- data/lib/cli.rb +19 -0
- data/lib/environment_opt_parse.rb +200 -0
- data/lib/markdown_exec/version.rb +1 -1
- data/lib/markdown_exec.rb +222 -139
- data/lib/menu.yml +135 -64
- data/lib/object_present.rb +40 -0
- data/lib/shared.rb +3 -14
- data/lib/tap.rb +76 -21
- metadata +5 -2
data/bin/tab_completion.sh.erb
CHANGED
@@ -30,6 +30,7 @@ _mde() {
|
|
30
30
|
if [[ ${prev} == -* ]] ; then
|
31
31
|
case $prev in
|
32
32
|
<% svhs.each do |svh|
|
33
|
+
|
33
34
|
svn = svh[:long_name]
|
34
35
|
if svn && svh[:arg_name]
|
35
36
|
svn = '--' + svh[:long_name]
|
@@ -43,6 +44,21 @@ _mde() {
|
|
43
44
|
<%= svn + ') COMPREPLY="' + svh[:compreply] + '"; return 0 ;;' %>
|
44
45
|
<% end
|
45
46
|
end
|
47
|
+
|
48
|
+
svn = svh[:short_name]
|
49
|
+
if svn && svh[:arg_name]
|
50
|
+
svn = '-' + svh[:short_name]
|
51
|
+
if svh[:compreply] == false
|
52
|
+
# nothing
|
53
|
+
elsif svh[:compreply].nil? %>
|
54
|
+
<%= svn + ') __filedirs_all; return 0 ;;' %>
|
55
|
+
<% elsif svh[:compreply].empty?
|
56
|
+
# nothing
|
57
|
+
else %>
|
58
|
+
<%= svn + ') COMPREPLY="' + svh[:compreply] + '"; return 0 ;;' %>
|
59
|
+
<% end
|
60
|
+
end
|
61
|
+
|
46
62
|
end %>
|
47
63
|
esac
|
48
64
|
fi
|
@@ -65,11 +81,18 @@ _mde() {
|
|
65
81
|
if [[ -z ${cur} ]] ; then
|
66
82
|
case $prev in
|
67
83
|
<% svhs.each do |svh|
|
84
|
+
|
68
85
|
svn = svh[:long_name]
|
69
86
|
if svn && svh[:arg_name]
|
70
87
|
svn = '--' + svh[:long_name] %>
|
71
88
|
<%= svn + ') COMPREPLY=".' + svh[:arg_name] + '."; return 0 ;;' %>
|
72
89
|
<% end
|
90
|
+
|
91
|
+
svn = svh[:short_name]
|
92
|
+
if svn && svh[:arg_name]
|
93
|
+
svn = '-' + svh[:short_name] %>
|
94
|
+
<%= svn + ') COMPREPLY=".' + svh[:arg_name] + '."; return 0 ;;' %>
|
95
|
+
<% end
|
73
96
|
end %>
|
74
97
|
esac
|
75
98
|
fi
|
data/lib/cli.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# encoding=utf-8
|
4
|
+
|
5
|
+
# utility functions to provide CLI
|
6
|
+
#
|
7
|
+
module CLI
|
8
|
+
# skip :reek:UtilityFunction
|
9
|
+
def value_for_cli(value)
|
10
|
+
case value.class.to_s
|
11
|
+
when 'String'
|
12
|
+
Shellwords.escape value
|
13
|
+
when 'FalseClass', 'TrueClass'
|
14
|
+
value ? '1' : '0'
|
15
|
+
else
|
16
|
+
Shellwords.escape value.to_s
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,200 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# encoding=utf-8
|
4
|
+
|
5
|
+
require 'optparse'
|
6
|
+
require 'yaml'
|
7
|
+
|
8
|
+
require_relative 'object_present'
|
9
|
+
|
10
|
+
class Hash
|
11
|
+
unless defined?(sym_keys)
|
12
|
+
def sym_keys
|
13
|
+
transform_keys(&:to_sym)
|
14
|
+
# map do |key, value|
|
15
|
+
# [key.to_sym, value]
|
16
|
+
# end.to_h
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class EnvironmentOptParse
|
22
|
+
attr_reader :options, :remainder
|
23
|
+
|
24
|
+
# utility functions to create menu
|
25
|
+
#
|
26
|
+
module Menu
|
27
|
+
def menu_all(menu_data, lambdas, config)
|
28
|
+
config.tap_yaml 'config'
|
29
|
+
input_option_values, remainder, = menu_parse(add_proc(menu_data, lambdas))
|
30
|
+
# options = menu_default_option_values(menu_data).merge input_option_values
|
31
|
+
# options = (menu_default_option_values(menu_data)).merge(input_option_values).tap_yaml 'options1'
|
32
|
+
options = menu_default_option_values(menu_data).merge(config).merge(input_option_values) #.tap_yaml 'options2'
|
33
|
+
# options = menu_data.map do |menu_item|
|
34
|
+
# menu_item.tap_inspect 'menu_item'
|
35
|
+
# mion = menu_item[:opt_name]&.to_sym.tap_inspect 'mion'
|
36
|
+
# omion = config[mion].tap_inspect 'omion'
|
37
|
+
# unless omion.nil?
|
38
|
+
# menu_item[:default] = omion
|
39
|
+
# end
|
40
|
+
# menu_item
|
41
|
+
# end,
|
42
|
+
|
43
|
+
[options, remainder]
|
44
|
+
end
|
45
|
+
|
46
|
+
def add_proc(menu_data, lambdas)
|
47
|
+
menu_data.each do |menu_item|
|
48
|
+
menu_item.tap_yaml 'menu_item'
|
49
|
+
procname = menu_item[:procname]
|
50
|
+
next if procname.nil?
|
51
|
+
|
52
|
+
menu_item[:proccode] = lambdas.fetch(procname.to_sym, menu_item[:procname])
|
53
|
+
end.tap_yaml
|
54
|
+
end
|
55
|
+
|
56
|
+
def menu_default_option_values(menu_data)
|
57
|
+
menu_data.map do |item|
|
58
|
+
item_default = item[:default]
|
59
|
+
next if item_default.nil?
|
60
|
+
next unless item[:opt_name].present?
|
61
|
+
|
62
|
+
[item[:opt_name].to_sym, item_default]
|
63
|
+
end.compact.to_h
|
64
|
+
end
|
65
|
+
|
66
|
+
def menu_help(menu_data)
|
67
|
+
options = {}
|
68
|
+
option_parser = OptionParser.new do |opts|
|
69
|
+
opts.banner = [
|
70
|
+
"#{APP_NAME} - #{APP_DESC} (#{VERSION})",
|
71
|
+
"Usage: #{File.basename($PROGRAM_NAME)} [options]"
|
72
|
+
].join("\n")
|
73
|
+
|
74
|
+
menu_data.each do |item|
|
75
|
+
menu_option_append opts, options, item
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
option_parser.help
|
80
|
+
end
|
81
|
+
|
82
|
+
def menu_option_append(opts, options, item)
|
83
|
+
return unless item[:long_name].present? || item[:short_name].present?
|
84
|
+
|
85
|
+
mmoo = [
|
86
|
+
# long name
|
87
|
+
if item[:long_name].present?
|
88
|
+
"--#{item[:long_name]}#{item[:arg_name].present? ? " #{item[:arg_name]}" : ''}"
|
89
|
+
end,
|
90
|
+
|
91
|
+
# short name
|
92
|
+
item[:short_name].present? ? "-#{item[:short_name]}" : nil,
|
93
|
+
|
94
|
+
# description and default
|
95
|
+
[item[:description],
|
96
|
+
item[:default].present? ? "[#{value_for_menu item[:default]}]" : nil].compact.join(' '),
|
97
|
+
|
98
|
+
# apply proccode, if present, to value
|
99
|
+
# save value to options hash if option is named
|
100
|
+
#
|
101
|
+
lambda { |value|
|
102
|
+
(item[:proccode] ? item[:proccode].call(value) : value).tap do |converted|
|
103
|
+
opt_name = item[:opt_name]
|
104
|
+
next if opt_name.nil?
|
105
|
+
|
106
|
+
options[opt_name.to_sym] = converted if item[:opt_name]
|
107
|
+
end
|
108
|
+
}
|
109
|
+
].compact
|
110
|
+
opts.on(*mmoo)
|
111
|
+
end
|
112
|
+
|
113
|
+
def menu_parse(menu_options)
|
114
|
+
options = {}
|
115
|
+
option_parser = OptionParser.new do |opts|
|
116
|
+
menu_options.each do |item|
|
117
|
+
item[:opt_name] = item[:opt_name]&.to_sym
|
118
|
+
menu_option_append opts, options, item
|
119
|
+
end
|
120
|
+
end
|
121
|
+
option_parser.load # filename defaults to basename of the program without suffix in a directory ~/.options
|
122
|
+
option_parser.environment # env defaults to the basename of the program.
|
123
|
+
remainder = option_parser.parse!
|
124
|
+
|
125
|
+
[options, remainder, option_parser.help]
|
126
|
+
end
|
127
|
+
|
128
|
+
# skip :reek:UtilityFunction
|
129
|
+
def value_for_menu(value)
|
130
|
+
case value.class.to_s
|
131
|
+
when 'String'
|
132
|
+
value
|
133
|
+
when 'FalseClass', 'TrueClass'
|
134
|
+
value ? '1' : '0'
|
135
|
+
else
|
136
|
+
value.to_s
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
include Menu
|
142
|
+
|
143
|
+
def initialize(menu: {}, lambdas: nil, options: nil, version: nil)
|
144
|
+
@menu = if menu.class.to_s == 'String'
|
145
|
+
filetext = File.read(menu).tap_yaml 'filetext'
|
146
|
+
fileyaml = YAML.load(filetext)
|
147
|
+
fileyaml.map(&:sym_keys)
|
148
|
+
else
|
149
|
+
menu
|
150
|
+
end.tap_yaml '@menu'
|
151
|
+
@lambdas = lambdas
|
152
|
+
@version = version || '0.1'
|
153
|
+
# @options = {}
|
154
|
+
@options = if options.class.to_s == 'String'
|
155
|
+
YAML.safe_load(File.read(options)).sym_keys.tap_yaml '@options'
|
156
|
+
else
|
157
|
+
{}
|
158
|
+
end #.tap_yaml '@options'
|
159
|
+
|
160
|
+
parse!
|
161
|
+
end
|
162
|
+
|
163
|
+
def parse!
|
164
|
+
@options, @remainder = menu_all(
|
165
|
+
@menu,
|
166
|
+
# @menu.map do |menu_item|
|
167
|
+
# menu_item.tap_inspect 'menu_item'
|
168
|
+
# mion = menu_item[:opt_name]&.to_sym.tap_inspect 'mion'
|
169
|
+
# omion = @options[mion].tap_inspect 'omion'
|
170
|
+
# unless omion.nil?
|
171
|
+
# @options[menu_item[:default]] = omion
|
172
|
+
# end
|
173
|
+
# menu_item
|
174
|
+
# end,
|
175
|
+
{
|
176
|
+
debug: ->(value) { tap_config value: value },
|
177
|
+
|
178
|
+
# stdout_configuration: lambda { |_| self.options.tap_puts 'eop' },
|
179
|
+
# stdout_configuration: (lambda { |options|
|
180
|
+
# lambda { |v| options.tap_puts 'eop_l' }
|
181
|
+
# }).call(@options),
|
182
|
+
|
183
|
+
stdout_defaults: ->(_) { menu_default_option_values(@menu).to_yaml.tap_puts },
|
184
|
+
stdout_help: lambda { |_|
|
185
|
+
menu_help(@menu).tap_puts
|
186
|
+
exit
|
187
|
+
},
|
188
|
+
val_as_bool: ->(value) { value.class.to_s == 'String' ? (value.chomp != '0') : value },
|
189
|
+
val_as_int: ->(value) { value.to_i },
|
190
|
+
val_as_str: ->(value) { value.to_s },
|
191
|
+
version: lambda { |_|
|
192
|
+
@version.tap_puts
|
193
|
+
exit
|
194
|
+
}
|
195
|
+
}.merge(@lambdas || {}),
|
196
|
+
@options
|
197
|
+
)
|
198
|
+
@options #.tap_yaml '@options'
|
199
|
+
end
|
200
|
+
end
|