mamertes 2.4.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.
Files changed (53) hide show
  1. checksums.yaml +15 -0
  2. data/.DS_Store +0 -0
  3. data/.gitignore +6 -0
  4. data/.travis-gemfile +15 -0
  5. data/.travis.yml +10 -0
  6. data/.yardopts +1 -0
  7. data/Gemfile +21 -0
  8. data/README.md +126 -0
  9. data/Rakefile +29 -0
  10. data/doc/Mamertes.html +155 -0
  11. data/doc/Mamertes/Application.html +3057 -0
  12. data/doc/Mamertes/Command.html +7031 -0
  13. data/doc/Mamertes/CommandMethods.html +125 -0
  14. data/doc/Mamertes/CommandMethods/Children.html +1286 -0
  15. data/doc/Mamertes/CommandMethods/Help.html +209 -0
  16. data/doc/Mamertes/Error.html +631 -0
  17. data/doc/Mamertes/Localizer.html +376 -0
  18. data/doc/Mamertes/Option.html +6671 -0
  19. data/doc/Mamertes/Parser.html +276 -0
  20. data/doc/Mamertes/ParserMethods.html +125 -0
  21. data/doc/Mamertes/ParserMethods/General.html +134 -0
  22. data/doc/Mamertes/ParserMethods/General/ClassMethods.html +574 -0
  23. data/doc/Mamertes/Version.html +189 -0
  24. data/doc/_index.html +276 -0
  25. data/doc/class_list.html +54 -0
  26. data/doc/css/common.css +1 -0
  27. data/doc/css/full_list.css +57 -0
  28. data/doc/css/style.css +338 -0
  29. data/doc/file.README.html +198 -0
  30. data/doc/file_list.html +56 -0
  31. data/doc/frames.html +28 -0
  32. data/doc/index.html +198 -0
  33. data/doc/js/app.js +214 -0
  34. data/doc/js/full_list.js +178 -0
  35. data/doc/js/jquery.js +4 -0
  36. data/doc/method_list.html +509 -0
  37. data/doc/top-level-namespace.html +112 -0
  38. data/lib/mamertes.rb +18 -0
  39. data/lib/mamertes/application.rb +206 -0
  40. data/lib/mamertes/command.rb +529 -0
  41. data/lib/mamertes/option.rb +236 -0
  42. data/lib/mamertes/parser.rb +317 -0
  43. data/lib/mamertes/version.rb +24 -0
  44. data/locales/en.yml +40 -0
  45. data/locales/it.yml +40 -0
  46. data/mamertes.gemspec +30 -0
  47. data/spec/coverage_helper.rb +20 -0
  48. data/spec/mamertes/application_spec.rb +181 -0
  49. data/spec/mamertes/command_spec.rb +526 -0
  50. data/spec/mamertes/option_spec.rb +274 -0
  51. data/spec/mamertes/parser_spec.rb +126 -0
  52. data/spec/spec_helper.rb +15 -0
  53. metadata +115 -0
@@ -0,0 +1,24 @@
1
+ # encoding: utf-8
2
+ #
3
+ # This file is part of the mamertes gem. Copyright (C) 2013 and above Shogun <shogun_panda@me.com>.
4
+ # Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
5
+ #
6
+
7
+ module Mamertes
8
+ # The current version of Mamertes, according to semantic versioning.
9
+ #
10
+ # @see http://semver.org
11
+ module Version
12
+ # The major version.
13
+ MAJOR = 2
14
+
15
+ # The minor version.
16
+ MINOR = 4
17
+
18
+ # The patch version.
19
+ PATCH = 1
20
+
21
+ # The current version number of Mamertes.
22
+ STRING = [MAJOR, MINOR, PATCH].compact.join(".")
23
+ end
24
+ end
@@ -0,0 +1,40 @@
1
+ # encoding: utf-8
2
+ #
3
+ # This file is part of the mamertes gem. Copyright (C) 2013 and above Shogun <shogun_panda@me.com>.
4
+ # Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
5
+ #
6
+
7
+ ---
8
+ mamertes:
9
+ default_application_name: "__APPLICATION__"
10
+ ambigous_command: "Command shortcut \"%1\" is ambiguous across commands %2. Please add some other characters."
11
+ needless_argument: "Option %1 does not expects an argument."
12
+ missing_argument: "Option %1 expects an argument."
13
+ invalid_option: "Invalid option %1."
14
+ invalid_integer: "Option %1 expects a valid integer as argument."
15
+ invalid_float: "Option %1 expects a valid floating number as argument."
16
+ conflicting_options: "Options %1 and %2 have conflicting forms."
17
+ missing_option: "Required option %1 is missing."
18
+ invalid_value: "Value of option %1 must be one of these values: %2."
19
+ invalid_for_regexp: "Value of option %1 must match the regular expression: %2."
20
+ help_option_short_form: "-h"
21
+ help_option_long_form: "--help"
22
+ help_message: "Shows this message."
23
+ help_arg: "ARG"
24
+ help_name: "[NAME]"
25
+ help_application_synopsis: "%s [options] %s[command-options] [arguments] "
26
+ help_command_synopsis: "%s [options] %s %s[command-options] [arguments] "
27
+ help_synopsis: "[SYNOPSIS]"
28
+ help_description: "[DESCRIPTION]"
29
+ help_no_description: "*NO DESCRIPTION PROVIDED*"
30
+ help_options: "[OPTIONS]"
31
+ help_global_options: "[GLOBAL OPTIONS]"
32
+ help_commands: "[COMMANDS]"
33
+ help_subcommands: "[SUBCOMMANDS]"
34
+ help_subcommand_invocation: "[command [sub-command ...]] "
35
+ help_subsubcommand_invocation: "[sub-command [sub-sub-command ...]] "
36
+ help_command_description: "Shows a help about a command."
37
+ existing_command: "The command \"%1\" already exists."
38
+ existing_option_global: "The global option \"%1\" already exists."
39
+ existing_option: "The option \"%1\" already exists for the command \"%2\"."
40
+ missing_app_block: "You have to provide a block to Mamertes::App!"
@@ -0,0 +1,40 @@
1
+ # encoding: utf-8
2
+ #
3
+ # This file is part of the mamertes gem. Copyright (C) 2013 and above Shogun <shogun_panda@me.com>.
4
+ # Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
5
+ #
6
+
7
+ ---
8
+ mamertes:
9
+ default_application_name: "__APPLICAZIONE__"
10
+ ambigous_command: "La scorciatoia di comando \"%1\" è ambigua tra i seguenti comandi %2. Per favore aggiungi qualche altro carattere."
11
+ needless_argument: "L'opzione %1 non richiede un argomento."
12
+ missing_argument: "L'opzione %1 richiede un argomento."
13
+ invalid_option: "L'opzione %1 non è valida."
14
+ invalid_integer: "L'opzione %1 richiede un numero intero valido come argomento."
15
+ invalid_float: "L'opzione %1 richiede un numero decimale valido come argomento."
16
+ conflicting_options: "Le opzioni %1 e %2 hanno forme in conflitto."
17
+ missing_option: "L'opzione richiesta %1 è mancante."
18
+ invalid_value: "Il valore dell'opzione %1 deve essere uno dei seguenti valori: %2."
19
+ invalid_for_regexp: "Il valore dell'opzione %1 deve soddisfare questa espressione regolare: %2."
20
+ help_option_short_form: "-h"
21
+ help_option_long_form: "--help"
22
+ help_message: "Mostra questo messaggio."
23
+ help_arg: "ARG"
24
+ help_name: "[NOME]"
25
+ help_application_synopsis: "%s [opzioni] %s[opzioni-comando] [argomenti] "
26
+ help_command_synopsis: "%s [opzioni] %s %s[opzioni-comando] [argomenti] "
27
+ help_synopsis: "[UTILIZZO]"
28
+ help_description: "[DESCRIZIONE]"
29
+ help_no_description: "*NESSUNA DESCRIZIONE FORNITA*"
30
+ help_options: "[OPZIONI]"
31
+ help_global_options: "[OPZIONI GLOBALI]"
32
+ help_commands: "[COMANDI]"
33
+ help_subcommands: "[SOTTOCOMANDI]"
34
+ help_subcommand_invocation: "[comando [sotto-comando ...]] "
35
+ help_subsubcommand_invocation: "[sotto-comando [sotto-sotto-comando ...]] "
36
+ help_command_description: "Mostra aiuto riguardo un comando."
37
+ existing_command: "Il comando \"%1\" è già esistente."
38
+ existing_option_global: "L'opzione globale \"%1\" è già esistente."
39
+ existing_option: "L'opzione \"%1\" è già esistente per il comando \"%2\"."
40
+ missing_app_block: "Devi fornire un blocco per Mamertes::App!"
@@ -0,0 +1,30 @@
1
+ # encoding: utf-8
2
+ #
3
+ # This file is part of the mamertes gem. Copyright (C) 2013 and above Shogun <shogun_panda@me.com>.
4
+ # Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
5
+ #
6
+
7
+ require "./lib/mamertes/version"
8
+
9
+ Gem::Specification.new do |gem|
10
+ gem.name = "mamertes"
11
+ gem.version = Mamertes::Version::STRING
12
+ gem.authors = ["Shogun"]
13
+ gem.email = ["shogun_panda@me.com"]
14
+ gem.homepage = "http://sw.cow.tc/mamertes"
15
+ gem.summary = %q{Yet another command line manager.}
16
+ gem.description = %q{Yet another command line manager.}
17
+
18
+ gem.rubyforge_project = "mamertes"
19
+ gem.files = `git ls-files`.split("\n")
20
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
21
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
22
+ gem.require_paths = ["lib"]
23
+
24
+ gem.required_ruby_version = ">= 1.9.3"
25
+
26
+ gem.add_dependency("bovem", "~> 2.4.0")
27
+ end
28
+
29
+
30
+
@@ -0,0 +1,20 @@
1
+ # encoding: utf-8
2
+ #
3
+ # This file is part of the mamertes gem. Copyright (C) 2013 and above Shogun <shogun_panda@me.com>.
4
+ # Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
5
+ #
6
+
7
+ require "pathname"
8
+ require "simplecov"
9
+ require "coveralls"
10
+
11
+ Coveralls.wear! if ENV["CI"] || ENV["JENKINS_URL"]
12
+
13
+ SimpleCov.start do
14
+ root = Pathname.new(File.dirname(__FILE__)) + ".."
15
+
16
+ add_filter do |src_file|
17
+ path = Pathname.new(src_file.filename).relative_path_from(root).to_s
18
+ path !~ /^(bin|lib)/
19
+ end
20
+ end
@@ -0,0 +1,181 @@
1
+ # encoding: utf-8
2
+ #
3
+ # This file is part of the mamertes gem. Copyright (C) 2013 and above Shogun <shogun_panda@me.com>.
4
+ # Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
5
+ #
6
+
7
+ require "spec_helper"
8
+
9
+ describe Mamertes::Error do
10
+ describe "#initialize" do
11
+ it "copies attributes" do
12
+ error = ::Mamertes::Error.new("A", "B", "C")
13
+ expect(error.target).to eq("A")
14
+ expect(error.reason).to eq("B")
15
+ expect(error.message).to eq("C")
16
+ end
17
+ end
18
+ end
19
+
20
+ describe Mamertes::Application do
21
+ let(:application) { ::Mamertes::Application.new(locale: :en) }
22
+
23
+ describe "#initialize" do
24
+ it "should call the parent constructor" do
25
+ options = {a: :b}
26
+ block = Proc.new {}
27
+
28
+ expect(::Mamertes::Command).to receive(:new).with(options, &block)
29
+ ::Mamertes::Application.new(options, &block)
30
+ end
31
+
32
+ it "should set good defaults" do
33
+ expect(application.shell).to eq(::Bovem::Shell.instance)
34
+ expect(application.console).to eq(application.shell.console)
35
+ expect(application.skip_commands).to be_false
36
+ expect(application.show_commands).to be_false
37
+ expect(application.output_commands).to be_false
38
+ end
39
+ end
40
+
41
+ describe "#version" do
42
+ it "should set and return the version" do
43
+ expect(application.version).to be_nil
44
+ expect(application.version("another")).to eq("another")
45
+ expect(application.version(nil)).to eq("another")
46
+ end
47
+ end
48
+
49
+ describe "#help_option" do
50
+ it "should add a command and a option" do
51
+ expect(application).to receive(:command).with(:help, {description: "Shows a help about a command."})
52
+ expect(application).to receive(:option).with(:help, ["-h", "--help"], {help: "Shows this message."})
53
+ application.help_option
54
+ end
55
+
56
+ it "should execute associated actions" do
57
+ expect(application).to receive(:show_help).exactly(2)
58
+ expect(application).to receive(:command_help)
59
+
60
+ application.execute(["help", "command"])
61
+ application.execute("-h")
62
+ end
63
+ end
64
+
65
+ describe "#executable_name" do
66
+ it "should return executable name" do
67
+ expect(application.executable_name).to eq($0)
68
+ end
69
+ end
70
+
71
+ describe "#command_help" do
72
+ it "should show the help for the command" do
73
+ command = application.command "command"
74
+ subcommand = command.command "subcommand"
75
+
76
+ expect(application).to receive(:show_help)
77
+ application.command_help(application)
78
+
79
+ expect(command).to receive(:show_help)
80
+ application.argument(command.name)
81
+ application.command_help(application)
82
+
83
+ expect(subcommand).to receive(:show_help)
84
+ application.argument(subcommand.name)
85
+ application.command_help(application)
86
+
87
+ expect(subcommand).to receive(:show_help)
88
+ application.argument("foo")
89
+ application.command_help(application)
90
+ end
91
+ end
92
+
93
+ describe "#run" do
94
+ it "should forward to the shell" do
95
+ expect(application.shell).to receive(:run).with("COMMAND", "MESSAGE", true, "A", false, false, "B")
96
+ application.run("COMMAND", "MESSAGE", "A", "B")
97
+
98
+ application.skip_commands = true
99
+ application.output_commands = true
100
+ application.show_commands = true
101
+ expect(application.shell).to receive(:run).with("COMMAND", "MESSAGE", false, "C", true, true, "D")
102
+ application.run("COMMAND", "MESSAGE", "C", "D")
103
+ end
104
+ end
105
+
106
+ describe ".create" do
107
+ it "should complain about a missing block" do
108
+ expect { ::Mamertes::Application.create }.to raise_error(::Mamertes::Error)
109
+ end
110
+
111
+ it "should print errors" do
112
+ allow(::Mamertes::Application).to receive(:create_application).and_raise(ArgumentError.new("ERROR"))
113
+ expect(Kernel).to receive(:puts).with("ERROR")
114
+ expect(Kernel).to receive(:exit).with(1)
115
+ ::Mamertes::Application.create(__args__: []) {}
116
+ end
117
+
118
+ it "should create a default application" do
119
+ expect(::Mamertes::Application).to receive(:new).with({name: "__APPLICATION__", parent: nil, application: nil, locale: :en})
120
+ ::Mamertes::Application.create({locale: :en}) {}
121
+ end
122
+
123
+ it "should create an application with given options and block" do
124
+ options = {name: "OK"}
125
+
126
+ expect(::Mamertes::Application).to receive(:new).with({name: "OK", parent: nil, application: nil})
127
+ application = ::Mamertes::Application.create(options) {}
128
+ end
129
+
130
+ it "should execute the block" do
131
+ allow_any_instance_of(::Bovem::Console).to receive(:write)
132
+ allow(Kernel).to receive(:exit)
133
+ options = {name: "OK", __args__: []}
134
+ check = false
135
+
136
+ application = ::Mamertes::Application.create(options) { check = true }
137
+ expect(check).to be_true
138
+ expect(application.name).to eq("OK")
139
+ end
140
+
141
+ it "should execute the new application" do
142
+ args = []
143
+
144
+ application = ::Mamertes::Application.create do
145
+ option("require", [], {})
146
+ option("format", [], {})
147
+ option("example", [], {})
148
+
149
+ action do |command|
150
+ args = command.arguments.join("-")
151
+ end
152
+ end
153
+
154
+ expect(args).to eq(ARGV.reject {|a| a =~ /^--/ }.join("-"))
155
+ end
156
+
157
+ it "can override arguments" do
158
+ args = []
159
+
160
+ application = ::Mamertes::Application.create({__args__: ["C", "D"]}) do
161
+ action do |command|
162
+ args = command.arguments.join("-")
163
+ end
164
+ end
165
+
166
+ expect(args).to eq("C-D")
167
+ end
168
+
169
+ it "should not execute the application if requested to" do
170
+ args = []
171
+
172
+ application = ::Mamertes::Application.create(run: false) do
173
+ action do |command|
174
+ args = command.arguments.join("-")
175
+ end
176
+ end
177
+
178
+ expect(args).to eq([])
179
+ end
180
+ end
181
+ end
@@ -0,0 +1,526 @@
1
+ # encoding: utf-8
2
+ #
3
+ # This file is part of the mamertes gem. Copyright (C) 2013 and above Shogun <shogun_panda@me.com>.
4
+ # Licensed under the MIT license, which can be found at http://www.opensource.org/licenses/mit-license.php.
5
+ #
6
+
7
+ require "spec_helper"
8
+
9
+ describe Mamertes::Command do
10
+ let(:application) {
11
+ ::Mamertes::Application.new(locale: :en) {
12
+ action {}
13
+ }
14
+ }
15
+
16
+ let(:command) {
17
+ c = ::Mamertes::Command.new(locale: :en)
18
+ c.application = application
19
+ c
20
+ }
21
+
22
+ describe "#initialize" do
23
+ it "should forward to #setup_with" do
24
+ expect(::Mamertes::Command.new(name: "command").name).to eq("command")
25
+ end
26
+
27
+ it "should call the block" do
28
+ count = 0
29
+ ::Mamertes::Command.new(name: "command") { count += 1 }
30
+ expect(count).to eq(1)
31
+ end
32
+ end
33
+
34
+ describe "#name" do
35
+ it "should set and return the name" do
36
+ expect(command.name).to be_nil
37
+ expect(command.name("another")).to eq("another")
38
+ expect(command.name(nil)).to eq("another")
39
+ end
40
+ end
41
+
42
+ describe "#full_name" do
43
+ it "should retrieve the full hierarchy of the name" do
44
+ command.name = "root"
45
+ expect(command.full_name).to eq("root")
46
+
47
+ subcommand = ::Mamertes::Command.new(name: "child")
48
+ subcommand.parent = command
49
+ expect(subcommand.full_name).to eq("root:child")
50
+ expect(subcommand.full_name(nil, " ")).to eq("root child")
51
+ expect(subcommand.full_name("A", " ")).to eq("root child A")
52
+ end
53
+ end
54
+
55
+ describe "#description" do
56
+ it "should set and return the description" do
57
+ expect(command.description).to be_nil
58
+ expect(command.description("another")).to eq("another")
59
+ expect(command.description(nil)).to eq("another")
60
+ end
61
+ end
62
+
63
+ describe "#banner" do
64
+ it "should set and return the banner" do
65
+ expect(command.banner).to be_nil
66
+ expect(command.banner("another")).to eq("another")
67
+ expect(command.banner(nil)).to eq("another")
68
+ end
69
+
70
+ end
71
+
72
+ describe "#synopsis" do
73
+ it "should set and return the synopsis" do
74
+ expect(command.synopsis).to be_nil
75
+ expect(command.synopsis("another")).to eq("another")
76
+ expect(command.synopsis(nil)).to eq("another")
77
+ end
78
+ end
79
+
80
+ describe "#before" do
81
+ it "should set and return the before hook" do
82
+ valid = Proc.new{|a| puts "OK" }
83
+
84
+ expect(command.before).to be_nil
85
+ expect(command.before(1)).to be_nil
86
+ expect(command.before { puts "OK" }).to be_nil
87
+ expect(command.before {|a, b| puts "OK" }).to be_nil
88
+ expect(command.before(:method)).to eq(:method)
89
+ expect(command.action("METHOD")).to eq("METHOD")
90
+ expect(command.before(&valid)).to eq(valid)
91
+ expect(command.before("METHOD", &valid)).to eq("METHOD")
92
+ end
93
+ end
94
+
95
+ describe "#action" do
96
+ it "should set and return the action" do
97
+ valid = Proc.new{|a| puts "OK" }
98
+
99
+ expect(command.action).to be_nil
100
+ expect(command.action(1)).to be_nil
101
+ expect(command.action { puts "OK" }).to be_nil
102
+ expect(command.action {|a, b| puts "OK" }).to be_nil
103
+ expect(command.action(:method)).to eq(:method)
104
+ expect(command.action("METHOD")).to eq("METHOD")
105
+ expect(command.action(&valid)).to eq(valid)
106
+ expect(command.action("METHOD", &valid)).to eq("METHOD")
107
+ end
108
+ end
109
+
110
+ describe "#after" do
111
+ it "should set and return the after hook" do
112
+ valid = Proc.new{|a| puts "OK" }
113
+
114
+ expect(command.after).to be_nil
115
+ expect(command.after(1)).to be_nil
116
+ expect(command.after { puts "OK" }).to be_nil
117
+ expect(command.after {|a, b| puts "OK" }).to be_nil
118
+ expect(command.after(:method)).to eq(:method)
119
+ expect(command.after("METHOD")).to eq("METHOD")
120
+ expect(command.after(&valid)).to eq(valid)
121
+ expect(command.after("METHOD", &valid)).to eq("METHOD")
122
+ end
123
+ end
124
+
125
+ describe "#has_description?" do
126
+ it "should check if the command has a description" do
127
+ expect(::Mamertes::Command.new.has_description?).to be_false
128
+ expect(::Mamertes::Command.new({description: "DESCRIPTION"}).has_description?).to be_true
129
+ end
130
+ end
131
+
132
+ describe "#has_banner?" do
133
+ it "should check if the command has a banner" do
134
+ expect(::Mamertes::Command.new.has_banner?).to be_false
135
+ expect(::Mamertes::Command.new({banner: "BANNER"}).has_banner?).to be_true
136
+ end
137
+ end
138
+
139
+ describe "#command" do
140
+ it "should add a subcommand" do
141
+ command.command("subcommand", {banner: "BANNER"}) do |option|
142
+ description("DESCRIPTION")
143
+ end
144
+
145
+ subcommand = command.commands["subcommand"]
146
+
147
+ expect(subcommand.name).to eq("subcommand")
148
+ expect(subcommand.parent).to be(command)
149
+ expect(subcommand.application).to be(application)
150
+ expect(subcommand.banner).to eq("BANNER")
151
+ expect(subcommand.description).to eq("DESCRIPTION")
152
+ end
153
+
154
+ it "should check for duplicates" do
155
+ command.command("subcommand")
156
+ expect {command.command("subcommand")}.to raise_error(::Mamertes::Error)
157
+ end
158
+ end
159
+
160
+ describe "#option" do
161
+ it "should add a subcommand" do
162
+ command.option("option", ["short", "long"], {type: String, help: "HELP"})
163
+
164
+ option = command.options["option"]
165
+
166
+ expect(option.name).to eq("option")
167
+ expect(option.short).to eq("s")
168
+ expect(option.long).to eq("long")
169
+ expect(option.help).to eq("HELP")
170
+ end
171
+
172
+ it "should check for duplicates" do
173
+ application.option("option")
174
+ command.option("option")
175
+ expect {command.option("option")}.to raise_error(::Mamertes::Error)
176
+ expect {application.option("option")}.to raise_error(::Mamertes::Error)
177
+ end
178
+ end
179
+
180
+ describe "#commands" do
181
+ it "should return the list of commands" do
182
+ expect(command.commands).to eq({})
183
+ command.command("subcommand1")
184
+ command.command("subcommand2")
185
+ expect(command.commands.values.collect(&:name).sort).to eq(["subcommand1", "subcommand2"])
186
+ end
187
+
188
+ it "should let access both with Symbol or String" do
189
+ command.command("subcommand1")
190
+ expect(command.commands).to be_a(HashWithIndifferentAccess)
191
+ expect(command.commands[:subcommand1]).to eq(command.commands["subcommand1"])
192
+ end
193
+ end
194
+
195
+ describe "#clear_commands" do
196
+ it "should remove commands" do
197
+ command.command("subcommand")
198
+ expect(command.commands.length == 1)
199
+ command.clear_commands
200
+ expect(command.commands.length == 0)
201
+ end
202
+ end
203
+
204
+ describe "#has_commands?" do
205
+ it "should check if the command has subcommands" do
206
+ expect(command.has_commands?).to be_false
207
+ command.command("subcommand")
208
+ expect(command.has_commands?).to be_true
209
+ end
210
+ end
211
+
212
+ describe "#clear_options" do
213
+ it "should remove options" do
214
+ command.option("option")
215
+ expect(command.options.length == 1)
216
+ command.clear_options
217
+ expect(command.options.length == 0)
218
+ end
219
+ end
220
+
221
+ describe "#options" do
222
+ it "should return the list of options" do
223
+ expect(command.options).to eq({})
224
+ command.option("option1")
225
+ command.option("option2")
226
+ expect(command.options.values.collect(&:name).sort).to eq(["option1", "option2"])
227
+ end
228
+
229
+ it "should let access both with Symbol or String" do
230
+ command.option("option1")
231
+ expect(command.options).to be_a(HashWithIndifferentAccess)
232
+ expect(command.options[:option1]).to eq(command.options["option1"])
233
+ end
234
+ end
235
+
236
+ describe "#has_options?" do
237
+ it "should check if the command has options" do
238
+ expect(command.has_options?).to be_false
239
+ command.option("option")
240
+ expect(command.has_options?).to be_true
241
+ end
242
+ end
243
+
244
+ describe "#argument" do
245
+ it "should add an argument to the command" do
246
+ expect(command.arguments).to eq([])
247
+ command.argument("A")
248
+ expect(command.arguments).to eq(["A"])
249
+ command.argument("B")
250
+ expect(command.arguments).to eq(["A", "B"])
251
+ end
252
+ end
253
+
254
+ describe "#arguments" do
255
+ it "should return arguments" do
256
+ expect(command.arguments).to eq([])
257
+ command.argument("A")
258
+ expect(command.arguments).to eq(["A"])
259
+ command.argument("B")
260
+ expect(command.arguments).to eq(["A", "B"])
261
+ end
262
+ end
263
+
264
+ describe "#application" do
265
+ it "should return the application" do
266
+ expect(command.application).to be(application)
267
+ expect(application.application).to be(application)
268
+ end
269
+ end
270
+
271
+ describe "#is_application?" do
272
+ it "should check if the command is an application" do
273
+ expect(command.is_application?).to be_false
274
+ expect(application.is_application?).to be_true
275
+ end
276
+ end
277
+
278
+ describe "#setup_with" do
279
+ it "should setup required option by calling proper methods" do
280
+ expect(command).to receive("name").with("new-command")
281
+ expect(command).to receive("application=").with(nil)
282
+ command.setup_with({name: "new-command", application: nil, invalid: false})
283
+ end
284
+ end
285
+
286
+ describe "#execute" do
287
+ it "should parse command line" do
288
+ allow(Kernel).to receive(:exit)
289
+ allow_any_instance_of(::Bovem::Console).to receive(:write)
290
+
291
+ args = ["command"]
292
+ expect(::Mamertes::Parser).to receive(:parse).with(command, args)
293
+ command.execute(args)
294
+ end
295
+
296
+ it "should execute hooks and actions in sequence" do
297
+ check = []
298
+ child = []
299
+ args = ["command"]
300
+
301
+ command.before do |command|
302
+ check << "A"
303
+ end
304
+
305
+ command.action do |command|
306
+ check << "B"
307
+ end
308
+
309
+ command.after do |command|
310
+ check << "C"
311
+ end
312
+
313
+ command.command("subcommand") do
314
+ before do |command|
315
+ check << "D"
316
+ end
317
+
318
+ action do |command|
319
+ check << "E"
320
+ end
321
+
322
+ after do |command|
323
+ check << "F"
324
+ end
325
+ end
326
+
327
+ allow(::Mamertes::Parser).to receive(:parse).and_return(nil)
328
+ command.execute(args)
329
+ expect(check).to eq(["A", "B", "C"])
330
+ end
331
+
332
+ it "should execute the hooks even they are methods" do
333
+ check = []
334
+ child = []
335
+ args = ["command"]
336
+
337
+ allow(command).to receive(:application).and_return(Object.new)
338
+ allow(command.application).to receive(:action_before) { check << "A" }
339
+ allow(command.application).to receive("action_perform") { check << "B" }
340
+ allow(command.application).to receive(:action_after) { check << "C" }
341
+
342
+ command.before(:action_before)
343
+ command.action("action_perform")
344
+ command.after(:action_after)
345
+
346
+ allow(::Mamertes::Parser).to receive(:parse).and_return(nil)
347
+ command.execute(args)
348
+ expect(check).to eq(["A", "B", "C"])
349
+ end
350
+
351
+ it "should skip its actions and hooks and pass control to the subcommand" do
352
+ check = []
353
+ child = []
354
+ args = ["command"]
355
+
356
+ command.before do |command|
357
+ check << "A"
358
+ end
359
+
360
+ command.action do |command|
361
+ check << "B"
362
+ end
363
+
364
+ command.after do |command|
365
+ check << "C"
366
+ end
367
+
368
+ command.command("subcommand") do
369
+ before do |command|
370
+ check << "D"
371
+ end
372
+
373
+ action do |command|
374
+ check << "E"
375
+ end
376
+
377
+ after do |command|
378
+ check << "F"
379
+ end
380
+ end
381
+
382
+ allow(::Mamertes::Parser).to receive(:parse) do |cmd, args|
383
+ cmd == command ? {name: "subcommand", args: args} : nil
384
+ end
385
+ command.execute(args)
386
+ expect(check).to eq(["D", "E", "F"])
387
+ end
388
+
389
+ it "should show help if action is not defined and no subcommand is found" do
390
+ check = []
391
+ child = []
392
+ args = ["command"]
393
+
394
+ command.command("subcommand") do
395
+ before do |command|
396
+ check << "D"
397
+ end
398
+
399
+ action do |command|
400
+ check << "E"
401
+ end
402
+
403
+ after do |command|
404
+ check << "F"
405
+ end
406
+ end
407
+
408
+ allow(::Mamertes::Parser).to receive(:parse).and_return(nil)
409
+ expect(command).to receive(:show_help)
410
+ command.execute(args)
411
+ expect(check).to eq([])
412
+ end
413
+ end
414
+
415
+ describe "#get_options" do
416
+ let(:reference){
417
+ c = ::Mamertes::Command.new("command") do
418
+ option("aaa", [], {type: Integer, default: 456})
419
+ option("bbb", [], {type: String})
420
+ option("ccc", [], {type: Array, default: ["1", "2"]})
421
+ end
422
+
423
+ c.application = ::Mamertes::Application.new do |a|
424
+ option("aaa", [], {type: Integer, default: 123})
425
+ option("ddd", [], {type: Float})
426
+ action {}
427
+ end
428
+
429
+ c
430
+ }
431
+
432
+ it "should return the full list of options" do
433
+ Mamertes::Parser.parse(reference.application, ["--aaa", "111", "--ddd", "2.0"])
434
+ Mamertes::Parser.parse(reference, ["--bbb", "2.0", "--ccc", "A,B,C"])
435
+ expect(reference.get_options.symbolize_keys).to eq({application_aaa: 111, application_ddd: 2.0, aaa: 456, bbb: "2.0", ccc: ["A", "B", "C"]})
436
+ end
437
+
438
+ it "should only return provided options if required to" do
439
+ Mamertes::Parser.parse(reference.application, ["--aaa", "111"])
440
+ Mamertes::Parser.parse(reference, ["--ccc", "2.0"])
441
+ expect(reference.get_options(false).symbolize_keys).to eq({application_aaa: 111, aaa: 456, ccc: ["2.0"]})
442
+ end
443
+
444
+ it "should skip application options if required to" do
445
+ Mamertes::Parser.parse(reference.application, ["--aaa", "111", "--ddd", "2.0"])
446
+ Mamertes::Parser.parse(reference, ["--bbb", "2.0", "--ccc", "A,B,C"])
447
+ expect(reference.get_options(true, false).symbolize_keys).to eq({aaa: 456, bbb: "2.0", ccc: ["A", "B", "C"]})
448
+ expect(reference.get_options(true, nil).symbolize_keys).to eq({aaa: 456, bbb: "2.0", ccc: ["A", "B", "C"]})
449
+ end
450
+
451
+ it "should apply the requested prefix for command options" do
452
+ Mamertes::Parser.parse(reference.application, ["--aaa", "111", "--ddd", "2.0"])
453
+ Mamertes::Parser.parse(reference, ["--bbb", "2.0", "--ccc", "A,B,C"])
454
+ expect(reference.get_options(true, false, "PREFIX").symbolize_keys).to eq({PREFIXaaa: 456, PREFIXbbb: "2.0", PREFIXccc: ["A", "B", "C"]})
455
+ end
456
+
457
+ it "should apply the requested prefix for application options" do
458
+ Mamertes::Parser.parse(reference.application, ["--aaa", "111", "--ddd", "2.0"])
459
+ Mamertes::Parser.parse(reference, ["--bbb", "2.0", "--ccc", "A,B,C"])
460
+ expect(reference.get_options(true, "APP").symbolize_keys).to eq({APPaaa: 111, APPddd: 2.0, aaa: 456, bbb: "2.0", ccc: ["A", "B", "C"]})
461
+ end
462
+
463
+ it "should only return requested options" do
464
+ Mamertes::Parser.parse(reference.application, ["--aaa", "111", "--ddd", "2.0"])
465
+ Mamertes::Parser.parse(reference, ["--bbb", "2.0", "--ccc", "A,B,C"])
466
+ expect(reference.get_options(true, "application_", "", :aaa, :bbb).symbolize_keys).to eq({application_aaa: 111, aaa: 456, bbb: "2.0"})
467
+ end
468
+
469
+ it "should apply higher precedence to command options in case of conflicts" do
470
+ Mamertes::Parser.parse(reference.application, ["--aaa", "111", "--ddd", "2.0"])
471
+ Mamertes::Parser.parse(reference, ["--bbb", "2.0", "--ccc", "A,B,C"])
472
+ expect(reference.get_options(true, "", "").symbolize_keys).to eq({ddd: 2.0, aaa: 456, bbb: "2.0", ccc: ["A", "B", "C"]})
473
+ end
474
+ end
475
+
476
+ describe "#show_help" do
477
+ it "should behave differently for application" do
478
+ allow(Kernel).to receive(:exit).and_return(0)
479
+
480
+ expect(application.console).to receive(:write).with("[NAME]")
481
+ expect(application.console).to receive(:write).at_least(1)
482
+ application.show_help
483
+ end
484
+
485
+ it "should print a banner" do
486
+ allow(Kernel).to receive(:exit).and_return(0)
487
+
488
+ command.banner = "BANNER"
489
+ expect(application.console).to receive(:write).with("[DESCRIPTION]")
490
+ expect(application.console).to receive(:write).at_least(1)
491
+ command.show_help
492
+ end
493
+
494
+ it "should print options" do
495
+ allow(Kernel).to receive(:exit).and_return(0)
496
+
497
+ application.option("global", [], {type: String})
498
+ command.option("local")
499
+
500
+ expect(application.console).to receive(:write).with("[GLOBAL OPTIONS]")
501
+ expect(application.console).to receive(:write).with("[OPTIONS]")
502
+ expect(application.console).to receive(:write).at_least(1)
503
+ application.show_help
504
+ command.show_help
505
+ end
506
+
507
+ it "should print subcommands" do
508
+ allow(Kernel).to receive(:exit).and_return(0)
509
+
510
+ command.command("subcommand")
511
+ expect(application.console).to receive(:write).with("[COMMANDS]")
512
+ expect(application.console).to receive(:write).with("[SUBCOMMANDS]")
513
+ expect(application.console).to receive(:write).at_least(1)
514
+ application.show_help
515
+ command.show_help
516
+ end
517
+
518
+ it "should exit" do
519
+ allow(Kernel).to receive(:puts)
520
+ allow(::Bovem::Console.any_instance).to receive(:write)
521
+
522
+ expect(Kernel).to receive(:exit).with(0).exactly(1)
523
+ application.show_help
524
+ end
525
+ end
526
+ end