benry-cmdapp 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,185 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'oktest'
4
+
5
+ require 'benry/cmdapp'
6
+ require_relative './shared'
7
+
8
+
9
+ Oktest.scope do
10
+
11
+
12
+ topic Benry::CmdApp::ActionIndex do
13
+ include CommonTestingHelper
14
+
15
+ class IndexTestAction < Benry::CmdApp::ActionScope
16
+ @action.("lookup test #1")
17
+ @option.(:repeat, "-r <N>", "repeat", type: Integer)
18
+ def lookup1(user="world", repeat: nil); end
19
+ #
20
+ @action.("lookup test #2")
21
+ def lookup2(); end
22
+ #
23
+ private
24
+ @action.("lookup test #3") # hidden
25
+ def lookup3(); end
26
+ end
27
+
28
+ Benry::CmdApp.action_alias("findxx", "lookup2")
29
+
30
+
31
+ topic '.lookup_action()' do
32
+
33
+ spec "[!vivoa] returns action metadata object." do
34
+ x = Benry::CmdApp::INDEX.lookup_action("lookup1")
35
+ ok {x} != nil
36
+ ok {x}.is_a?(Benry::CmdApp::ActionMetadata)
37
+ ok {x.name} == "lookup1"
38
+ ok {x.klass} == IndexTestAction
39
+ ok {x.method} == :lookup1
40
+ end
41
+
42
+ spec "[!tnwq0] supports alias name." do
43
+ x = Benry::CmdApp::INDEX.lookup_action("findxx")
44
+ ok {x} != nil
45
+ ok {x}.is_a?(Benry::CmdApp::ActionMetadata)
46
+ ok {x.name} == "lookup2"
47
+ ok {x.klass} == IndexTestAction
48
+ ok {x.method} == :lookup2
49
+ end
50
+
51
+ spec "[!z15vu] returns ActionWithArgs object if alias has args and/or kwargs." do
52
+ Benry::CmdApp.action_alias("findyy1", "lookup1", "Alice", "-r3")
53
+ x = Benry::CmdApp::INDEX.lookup_action("findyy1")
54
+ ok {x} != nil
55
+ ok {x}.is_a?(Benry::CmdApp::ActionWithArgs)
56
+ ok {x.args} == ["Alice"]
57
+ ok {x.kwargs} == {repeat: 3}
58
+ ok {x.name} == "lookup1"
59
+ ok {x.klass} == IndexTestAction
60
+ ok {x.method} == :lookup1
61
+ end
62
+
63
+ end
64
+
65
+
66
+ topic '.each_action_name_and_desc()' do
67
+
68
+ before do
69
+ clear_index_except(IndexTestAction)
70
+ end
71
+
72
+ after do
73
+ restore_index()
74
+ end
75
+
76
+ spec "[!5lahm] yields action name, description, and important flag." do
77
+ arr = []
78
+ Benry::CmdApp::INDEX.each_action_name_and_desc(false) {|a| arr << a }
79
+ ok {arr} == [
80
+ ["lookup1", "lookup test #1", nil],
81
+ ["lookup2", "lookup test #2", nil],
82
+ ]
83
+ #
84
+ with_important("lookup1"=>true, "lookup2"=>false) do
85
+ arr = []
86
+ Benry::CmdApp::INDEX.each_action_name_and_desc(false) {|a| arr << a }
87
+ ok {arr} == [
88
+ ["lookup1", "lookup test #1", true],
89
+ ["lookup2", "lookup test #2", false],
90
+ ]
91
+ end
92
+ end
93
+
94
+ spec "[!27j8b] includes alias names when the first arg is true." do
95
+ arr = []
96
+ Benry::CmdApp::INDEX.each_action_name_and_desc(true) {|a| arr << a }
97
+ ok {arr} == [
98
+ ["findxx", "alias of 'lookup2' action", nil],
99
+ ["findyy1", "alias of 'lookup1 Alice -r3'", nil],
100
+ ["lookup1", "lookup test #1", nil],
101
+ ["lookup2", "lookup test #2", nil],
102
+ ]
103
+ end
104
+
105
+ spec "[!8xt8s] rejects hidden actions if 'all: false' kwarg specified." do
106
+ arr = []
107
+ Benry::CmdApp::INDEX.each_action_name_and_desc(false, all: false) {|a| arr << a }
108
+ ok {arr} == [
109
+ ["lookup1", "lookup test #1", nil],
110
+ ["lookup2", "lookup test #2", nil],
111
+ ]
112
+ end
113
+
114
+ spec "[!5h7s5] includes hidden actions if 'all: true' kwarg specified." do
115
+ arr = []
116
+ Benry::CmdApp::INDEX.each_action_name_and_desc(false, all: true) {|a| arr << a }
117
+ ok {arr} == [
118
+ ["lookup1", "lookup test #1", nil],
119
+ ["lookup2", "lookup test #2", nil],
120
+ ["lookup3", "lookup test #3", false], # hidden action
121
+ ]
122
+ end
123
+
124
+ spec "[!arcia] action names are sorted." do
125
+ arr = []
126
+ Benry::CmdApp::INDEX.each_action_name_and_desc(true) {|a| arr << a }
127
+ ok {arr} == arr.sort_by(&:first)
128
+ end
129
+
130
+ end
131
+
132
+
133
+ topic '#delete_action()' do
134
+
135
+ spec "[!08e1s] unregisters action." do
136
+ class DeleteActionTest < Benry::CmdApp::ActionScope
137
+ @action.("test")
138
+ def delaction1(); end
139
+ end
140
+ name = "delaction1"
141
+ ok {Benry::CmdApp::INDEX.action_exist?(name)} == true
142
+ Benry::CmdApp::INDEX.delete_action(name)
143
+ ok {Benry::CmdApp::INDEX.action_exist?(name)} == false
144
+ end
145
+
146
+ spec "[!zjpq0] raises error if action not registered." do
147
+ name = "delaction99"
148
+ ok {Benry::CmdApp::INDEX.action_exist?(name)} == false
149
+ pr = proc { Benry::CmdApp::INDEX.delete_action(name) }
150
+ ok {pr}.raise?(Benry::CmdApp::ActionNotFoundError,
151
+ "delete_action(\"delaction99\"): Action not found.")
152
+ end
153
+
154
+ end
155
+
156
+
157
+ topic '#delete_alias()' do
158
+
159
+ spec "[!8ls45] unregisters alias." do
160
+ class DeleteAliasTest < Benry::CmdApp::ActionScope
161
+ @action.("test")
162
+ def delalias1(); end
163
+ end
164
+ Benry::CmdApp.action_alias("delali1", "delalias1")
165
+ name = "delali1"
166
+ ok {Benry::CmdApp::INDEX.alias_exist?(name)} == true
167
+ Benry::CmdApp::INDEX.delete_alias(name)
168
+ ok {Benry::CmdApp::INDEX.alias_exist?(name)} == false
169
+ end
170
+
171
+ spec "[!fdfyq] raises error if alias not registered." do
172
+ name = "delalias99"
173
+ ok {Benry::CmdApp::INDEX.alias_exist?(name)} == false
174
+ pr = proc { Benry::CmdApp::INDEX.delete_alias(name) }
175
+ ok {pr}.raise?(Benry::CmdApp::ActionNotFoundError,
176
+ "delete_alias(\"delalias99\"): Alias not found.")
177
+ end
178
+
179
+ end
180
+
181
+
182
+ end
183
+
184
+
185
+ end
data/test/run_all.rb ADDED
@@ -0,0 +1,7 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+
4
+ Dir.glob(File.dirname(__FILE__) + '/*.rb').each do |filename|
5
+ #$stderr.puts "\033[0;31m*** debug: filename=#{filename.inspect}\033[0m"
6
+ require_relative File.basename(filename)
7
+ end
data/test/shared.rb ADDED
@@ -0,0 +1,75 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+
4
+ module CommonTestingHelper
5
+
6
+ def uncolorize(str)
7
+ return str.gsub(/\e\[.*?m/, '')
8
+ end
9
+
10
+ def without_tty(&block)
11
+ result = nil
12
+ capture_sio(tty: false) { result = yield }
13
+ return result
14
+ end
15
+
16
+ def with_tty(&block)
17
+ result = nil
18
+ capture_sio(tty: true) { result = yield }
19
+ return result
20
+ end
21
+
22
+ def with_important(keyval={}, &block)
23
+ bkup = {}
24
+ keyval.each do |name, val|
25
+ action = Benry::CmdApp::INDEX.get_action(name)
26
+ bkup[name] = action.important
27
+ action.instance_variable_set('@important', val)
28
+ end
29
+ begin
30
+ yield
31
+ ensure
32
+ bkup.each do |name, val|
33
+ action = Benry::CmdApp::INDEX.get_action(name)
34
+ action.instance_variable_set('@important', val)
35
+ end
36
+ end
37
+ end
38
+
39
+ module_function
40
+
41
+ def clear_index_except(klass)
42
+ actions = Benry::CmdApp::INDEX.instance_variable_get('@actions')
43
+ aliases = Benry::CmdApp::INDEX.instance_variable_get('@aliases')
44
+ @_bkup_actions = actions.dup()
45
+ actions.delete_if {|_, x| x.klass != klass }
46
+ anames = actions.keys()
47
+ @_bkup_aliases = aliases.dup()
48
+ aliases.delete_if {|_, x| ! anames.include?(x.action_name) }
49
+ end
50
+
51
+ def restore_index()
52
+ actions = Benry::CmdApp::INDEX.instance_variable_get('@actions')
53
+ aliases = Benry::CmdApp::INDEX.instance_variable_get('@aliases')
54
+ actions.update(@_bkup_actions)
55
+ aliases.update(@_bkup_aliases)
56
+ end
57
+
58
+ end
59
+
60
+
61
+ module ActionMetadataTestingHelper
62
+ include CommonTestingHelper
63
+
64
+ def new_schema(lang: true)
65
+ schema = Benry::Cmdopt::Schema.new
66
+ schema.add(:lang, "-l, --lang=<en|fr|it>", "language") if lang
67
+ return schema
68
+ end
69
+
70
+ def new_metadata(schema, meth=:halo1, **kwargs)
71
+ metadata = Benry::CmdApp::ActionMetadata.new(meth.to_s, MetadataTestAction, meth, "greeting", schema, **kwargs)
72
+ return metadata
73
+ end
74
+
75
+ end
data/test/util_test.rb ADDED
@@ -0,0 +1,189 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'oktest'
4
+
5
+ require 'benry/cmdapp'
6
+ require_relative './shared'
7
+
8
+
9
+ Oktest.scope do
10
+
11
+
12
+ topic Benry::CmdApp::Util do
13
+
14
+
15
+ topic '.hidden_name?()' do
16
+
17
+ spec "[!fcfic] returns true if name is '_foo'." do
18
+ ok {Benry::CmdApp::Util.hidden_name?("_foo")} == true
19
+ end
20
+
21
+ spec "[!po5co] returns true if name is '_foo:bar'." do
22
+ ok {Benry::CmdApp::Util.hidden_name?("_foo:bar")} == true
23
+ end
24
+
25
+ spec "[!9iqz3] returns true if name is 'foo:_bar'." do
26
+ ok {Benry::CmdApp::Util.hidden_name?("foo:_bar")} == true
27
+ end
28
+
29
+ spec "[!mjjbg] returns false if else." do
30
+ ok {Benry::CmdApp::Util.hidden_name?("foo")} == false
31
+ ok {Benry::CmdApp::Util.hidden_name?("foo_")} == false
32
+ ok {Benry::CmdApp::Util.hidden_name?("foo_:bar")} == false
33
+ ok {Benry::CmdApp::Util.hidden_name?("foo:bar_")} == false
34
+ end
35
+
36
+ end
37
+
38
+
39
+ topic '.schema_empty?()' do
40
+
41
+ spec "[!8t5ju] returns true if schema empty." do
42
+ sc = Benry::CmdOpt::Schema.new
43
+ ok {Benry::CmdApp::Util.schema_empty?(sc)} == true
44
+ sc.add(:help, "-h", "help")
45
+ ok {Benry::CmdApp::Util.schema_empty?(sc)} == false
46
+ end
47
+
48
+ spec "[!c4ljy] returns true if schema contains only private (hidden) options." do
49
+ sc = Benry::CmdOpt::Schema.new
50
+ sc.add(:_help, "-h", "help")
51
+ ok {Benry::CmdApp::Util.schema_empty?(sc)} == true
52
+ sc.add(:version, "-V", "version")
53
+ ok {Benry::CmdApp::Util.schema_empty?(sc)} == false
54
+ end
55
+
56
+ end
57
+
58
+
59
+ topic '.method2action()' do
60
+
61
+ spec "[!801f9] converts action name 'aa_bb_cc_' into 'aa_bb_cc'." do
62
+ ok {Benry::CmdApp::Util.method2action("aa_")} == "aa"
63
+ ok {Benry::CmdApp::Util.method2action("_aa_")} == "_aa"
64
+ end
65
+
66
+ spec "[!9pahu] converts action name 'aa__bb__cc' into 'aa:bb:cc'." do
67
+ ok {Benry::CmdApp::Util.method2action("aa__bb__cc")} == "aa:bb:cc"
68
+ end
69
+
70
+ spec "[!7a1s7] converts action name 'aa_bb:_cc_dd' into 'aa-bb:_cc-dd'." do
71
+ ok {Benry::CmdApp::Util.method2action("aa_bb:cc_dd")} == "aa-bb:cc-dd"
72
+ ok {Benry::CmdApp::Util.method2action("aa_bb:_cc_dd")} == "aa-bb:_cc-dd"
73
+ ok {Benry::CmdApp::Util.method2action("aa___bb")} == "aa:_bb"
74
+ end
75
+
76
+ end
77
+
78
+
79
+ topic '.colorize?()' do
80
+
81
+ spec "[!801y1] returns $COLOR_MODE value if it is not nil." do
82
+ bkup = $COLOR_MODE
83
+ begin
84
+ $COLOR_MODE = true
85
+ ok {Benry::CmdApp::Util.colorize?()} == true
86
+ $COLOR_MODE = false
87
+ ok {Benry::CmdApp::Util.colorize?()} == false
88
+ ensure
89
+ $COLOR_MODE = bkup
90
+ end
91
+ end
92
+
93
+ spec "[!0harg] returns true if stdout is a tty." do
94
+ capture_sio(tty: true) {
95
+ ok {Benry::CmdApp::Util.colorize?()} == true
96
+ }
97
+ end
98
+
99
+ spec "[!u1j1x] returns false if stdout is not a tty." do
100
+ capture_sio(tty: false) {
101
+ ok {Benry::CmdApp::Util.colorize?()} == false
102
+ }
103
+ end
104
+
105
+ end
106
+
107
+
108
+ topic '.del_escape_seq()' do
109
+
110
+ spec "[!wgp2b] deletes escape sequence." do
111
+ s = " \e[1m%-18s\e[0m : %s"
112
+ ok {Benry::CmdApp::Util.del_escape_seq(s)} == " %-18s : %s"
113
+ end
114
+
115
+ end
116
+
117
+
118
+ topic '._important?()' do
119
+
120
+ spec "[!0yz2h] returns nil if tag == nil." do
121
+ ok {Benry::CmdApp::Util._important?(nil)} == nil
122
+ end
123
+
124
+ spec "[!h5pid] returns true if tag == :important." do
125
+ ok {Benry::CmdApp::Util._important?(:important)} == true
126
+ ok {Benry::CmdApp::Util._important?("important")} == true
127
+ end
128
+
129
+ spec "[!7zval] returns false if tag == :unimportant." do
130
+ ok {Benry::CmdApp::Util._important?(:unimportant)} == false
131
+ ok {Benry::CmdApp::Util._important?("unimportant")} == false
132
+ end
133
+
134
+ spec "[!z1ygi] supports nested tag." do
135
+ ok {Benry::CmdApp::Util._important?([:important, :foo])} == true
136
+ ok {Benry::CmdApp::Util._important?([:bar, :unimportant])} == false
137
+ end
138
+
139
+ end
140
+
141
+
142
+ topic '.format_help_line()' do
143
+
144
+ fixture :format do
145
+ " [[%-10s]] : %s"
146
+ end
147
+
148
+ spec "[!xx1vj] if `important == nil` then format help line with no decoration." do
149
+ |format|
150
+ s = Benry::CmdApp::Util.format_help_line(format, "<action>", "<desc>", nil)
151
+ ok {s} == " [[<action> ]] : <desc>"
152
+ end
153
+
154
+ spec "[!oaxp1] if `important == true` then format help line with strong decoration." do
155
+ |format|
156
+ s = Benry::CmdApp::Util.format_help_line(format, "<action>", "<desc>", true)
157
+ ok {s} == " [[\e[4m<action>\e[0m ]] : <desc>"
158
+ end
159
+
160
+ spec "[!bdhh6] if `important == false` then format help line with weak decoration." do
161
+ |format|
162
+ s = Benry::CmdApp::Util.format_help_line(format, "<action>", "<desc>", false)
163
+ ok {s} == " [[\e[2m<action>\e[0m ]] : <desc>"
164
+ end
165
+
166
+ end
167
+
168
+
169
+ topic '.fill_with_decoration()' do
170
+
171
+ spec "[!udrbj] returns decorated string with padding by white spaces." do
172
+ format = " [[%-10s]] : %s"
173
+ s = Benry::CmdApp::Util.fill_with_decoration(format, "<action>") {|s| "\e[1m#{s}\e[0m" }
174
+ ok {s} == "\e[1m<action>\e[0m "
175
+ end
176
+
177
+ spec "[!7bl2b] considers minus sign in format." do
178
+ format = " [[%10s]] : %s"
179
+ s = Benry::CmdApp::Util.fill_with_decoration(format, "<action>") {|s| "\e[1m#{s}\e[0m" }
180
+ ok {s} == " \e[1m<action>\e[0m"
181
+ end
182
+
183
+ end
184
+
185
+
186
+ end
187
+
188
+
189
+ end
metadata ADDED
@@ -0,0 +1,98 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: benry-cmdapp
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - kwatch
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-10-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: benry-cmdopt
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: oktest
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1'
41
+ description: |
42
+ Benry-CmdApp is a framework to create command-line application
43
+ like `git`, `docker`, or `npm` commands.
44
+
45
+ If you want create a command-line application which takes sub-commands,
46
+ Benry-CmdApp is the solution.
47
+
48
+ See https://kwatch.github.io/benry-ruby/benry-cmdapp.html for details.
49
+ email: kwatch@gmail.com
50
+ executables: []
51
+ extensions: []
52
+ extra_rdoc_files: []
53
+ files:
54
+ - CHANGES.md
55
+ - MIT-LICENSE
56
+ - README.md
57
+ - benry-cmdapp.gemspec
58
+ - doc/benry-cmdapp.html
59
+ - doc/css/style.css
60
+ - lib/benry/cmdapp.rb
61
+ - test/action_test.rb
62
+ - test/app_test.rb
63
+ - test/func_test.rb
64
+ - test/help_test.rb
65
+ - test/index_test.rb
66
+ - test/run_all.rb
67
+ - test/shared.rb
68
+ - test/util_test.rb
69
+ homepage: https://kwatch.github.io/benry-ruby/benry-cmdapp.html
70
+ licenses:
71
+ - MIT
72
+ metadata: {}
73
+ post_install_message:
74
+ rdoc_options: []
75
+ require_paths:
76
+ - lib
77
+ required_ruby_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '2.3'
82
+ required_rubygems_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ requirements: []
88
+ rubygems_version: 3.4.10
89
+ signing_key:
90
+ specification_version: 4
91
+ summary: Command-line application framework`
92
+ test_files:
93
+ - test/action_test.rb
94
+ - test/app_test.rb
95
+ - test/func_test.rb
96
+ - test/help_test.rb
97
+ - test/index_test.rb
98
+ - test/util_test.rb