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