cliqr 1.2.0 → 2.0.0
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/CHANGELOG.md +95 -0
- data/README.md +9 -71
- data/examples/numbers +1 -2
- data/examples/vagrant +0 -3
- data/lib/cliqr.rb +52 -11
- data/lib/cliqr/argument_validation/argument_type_validator.rb +2 -2
- data/lib/cliqr/argument_validation/validator.rb +3 -3
- data/lib/cliqr/{cli → command}/argument_operator.rb +2 -2
- data/lib/cliqr/{cli → command}/argument_operator_context.rb +1 -1
- data/lib/cliqr/{cli/command.rb → command/base_command.rb} +2 -2
- data/lib/cliqr/command/color.rb +174 -0
- data/lib/cliqr/{cli → command}/command_context.rb +68 -20
- data/lib/cliqr/command/shell_banner_builder.rb +17 -0
- data/lib/cliqr/command/shell_command.rb +125 -0
- data/lib/cliqr/command/shell_prompt_builder.rb +26 -0
- data/lib/cliqr/config/action.rb +226 -0
- data/lib/cliqr/config/base.rb +84 -0
- data/lib/cliqr/config/command.rb +137 -0
- data/lib/cliqr/config/dsl.rb +81 -0
- data/lib/cliqr/config/event.rb +43 -0
- data/lib/cliqr/config/event_based.rb +78 -0
- data/lib/cliqr/config/named.rb +55 -0
- data/lib/cliqr/config/option.rb +95 -0
- data/lib/cliqr/config/option_based.rb +130 -0
- data/lib/cliqr/config/shell.rb +87 -0
- data/lib/cliqr/config/validation/validation_set.rb +66 -0
- data/lib/cliqr/config/validation/validator_factory.rb +403 -0
- data/lib/cliqr/config/validation/verifiable.rb +91 -0
- data/lib/cliqr/error.rb +20 -4
- data/lib/cliqr/events/event.rb +56 -0
- data/lib/cliqr/events/event_context.rb +31 -0
- data/lib/cliqr/events/handler.rb +32 -0
- data/lib/cliqr/events/invoker.rb +70 -0
- data/lib/cliqr/{cli → executor}/command_runner_factory.rb +3 -3
- data/lib/cliqr/{cli → executor}/router.rb +4 -4
- data/lib/cliqr/{cli/executor.rb → executor/runner.rb} +25 -10
- data/lib/cliqr/interface.rb +98 -0
- data/lib/cliqr/parser/token_factory.rb +1 -1
- data/lib/cliqr/usage/command_usage_context.rb +94 -0
- data/lib/cliqr/usage/option_usage_context.rb +86 -0
- data/lib/cliqr/usage/templates/partial/action_list.erb +10 -0
- data/lib/cliqr/usage/templates/partial/command_name.erb +3 -0
- data/lib/cliqr/usage/templates/partial/option_list.erb +18 -0
- data/lib/cliqr/usage/templates/partial/usage_info.erb +5 -0
- data/lib/cliqr/usage/templates/usage/cli.erb +4 -0
- data/lib/cliqr/usage/templates/usage/shell.erb +2 -0
- data/lib/cliqr/usage/usage_builder.rb +59 -0
- data/lib/cliqr/util.rb +81 -34
- data/lib/cliqr/version.rb +1 -1
- data/spec/config/action_config_validator_spec.rb +127 -5
- data/spec/config/config_finalize_spec.rb +3 -3
- data/spec/config/config_validator_spec.rb +120 -17
- data/spec/config/option_config_validator_spec.rb +1 -1
- data/spec/dsl/interface_spec.rb +2 -2
- data/spec/dsl/usage_spec.rb +461 -465
- data/spec/executor/action_executor_spec.rb +1 -1
- data/spec/executor/color_executor_spec.rb +125 -0
- data/spec/executor/command_runner_spec.rb +6 -8
- data/spec/executor/event_executor_spec.rb +365 -0
- data/spec/executor/executor_spec.rb +49 -11
- data/spec/executor/help_executor_spec.rb +107 -103
- data/spec/fixtures/action_reader_command.rb +1 -1
- data/spec/fixtures/test_arg_printer_event_handler.rb +9 -0
- data/spec/fixtures/test_color_shell_prompt.rb +13 -0
- data/spec/fixtures/test_empty_event_handler.rb +5 -0
- data/spec/fixtures/test_invoker_event_handler.rb +9 -0
- data/spec/fixtures/test_shell_banner.rb +8 -0
- data/spec/fixtures/test_shell_prompt.rb +13 -0
- data/spec/shell/shell_executor_spec.rb +700 -0
- data/spec/validation/validation_spec.rb +2 -2
- metadata +65 -27
- data/lib/cliqr/cli/config.rb +0 -554
- data/lib/cliqr/cli/interface.rb +0 -107
- data/lib/cliqr/cli/shell_command.rb +0 -69
- data/lib/cliqr/cli/usage_builder.rb +0 -185
- data/lib/cliqr/config_validation/validation_set.rb +0 -48
- data/lib/cliqr/config_validation/validator_factory.rb +0 -319
- data/lib/cliqr/config_validation/verifiable.rb +0 -89
- data/lib/cliqr/dsl.rb +0 -59
- data/spec/executor/shell_executor_spec.rb +0 -233
- data/templates/usage.erb +0 -39
@@ -0,0 +1,91 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'cliqr/validation_errors'
|
4
|
+
require 'cliqr/config/validation/validator_factory'
|
5
|
+
require 'cliqr/config/validation/validation_set'
|
6
|
+
|
7
|
+
module Cliqr
|
8
|
+
module Config
|
9
|
+
# Validation framework for the command line interface config definition adopted from
|
10
|
+
# lotus/validations by @jodosha
|
11
|
+
#
|
12
|
+
# @api private
|
13
|
+
#
|
14
|
+
# @see https://github.com/lotus/validations
|
15
|
+
module Validation
|
16
|
+
# If a class includes this module, we add a few useful methods to that class
|
17
|
+
#
|
18
|
+
# @see http://www.ruby-doc.org/core/Module.html#method-i-included
|
19
|
+
#
|
20
|
+
# @return [Object]
|
21
|
+
def self.included(base)
|
22
|
+
base.class_eval do
|
23
|
+
extend Verifiable
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Check if the class is valid based on the configured attribute validations
|
28
|
+
#
|
29
|
+
# @return [Boolean] <tt>true</tt> if there are no validation errors
|
30
|
+
def valid?
|
31
|
+
validate
|
32
|
+
|
33
|
+
errors.empty?
|
34
|
+
end
|
35
|
+
|
36
|
+
# Run the validation against all attribute values
|
37
|
+
#
|
38
|
+
# @return [Hash] All validated attributed attributes and their values
|
39
|
+
def validate
|
40
|
+
read_attributes.each do |name, value|
|
41
|
+
validations.validate(name, value, errors)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Get the list of validations to be performed
|
46
|
+
#
|
47
|
+
# @return [Hash] A hash of attribute name to its validator
|
48
|
+
def validations
|
49
|
+
self.class.__send__(:validations)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Read current values for all attributes that must be validated
|
53
|
+
#
|
54
|
+
# @return [Hash] All attributes that must be validated along with their current values
|
55
|
+
def read_attributes
|
56
|
+
{}.tap do |attributes|
|
57
|
+
validations.each_key do |attribute|
|
58
|
+
attributes[attribute] = public_send(attribute)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Get a list of errors after validation finishes
|
64
|
+
#
|
65
|
+
# @return [Cliqr::ValidationErrors] A wrapper of all errors
|
66
|
+
def errors
|
67
|
+
@errors ||= ValidationErrors.new
|
68
|
+
end
|
69
|
+
|
70
|
+
# Validations DSL
|
71
|
+
module Verifiable
|
72
|
+
# Add a new validation for a attribute
|
73
|
+
#
|
74
|
+
# @param [Symbol] name Name of the attribute to validate
|
75
|
+
# @param [Object] options Configuration to initialize a attribute validator with
|
76
|
+
#
|
77
|
+
# @return [Cliqr::Config::Validation::ValidationSet]
|
78
|
+
def validates(name, options)
|
79
|
+
validations.add(name, options)
|
80
|
+
end
|
81
|
+
|
82
|
+
# Get or create a new <tt>Cliqr::Config::Validation::ValidationSet</tt>
|
83
|
+
#
|
84
|
+
# @return [Cliqr::Config::Validation::ValidationSet]
|
85
|
+
def validations
|
86
|
+
@validations ||= ValidationSet.new
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
data/lib/cliqr/error.rb
CHANGED
@@ -6,6 +6,15 @@ module Cliqr
|
|
6
6
|
#
|
7
7
|
# @api private
|
8
8
|
class CliqrError < StandardError
|
9
|
+
class << self
|
10
|
+
# The error code based on the error condition
|
11
|
+
#
|
12
|
+
# @return [Integer]
|
13
|
+
attr_accessor :error_code
|
14
|
+
end
|
15
|
+
|
16
|
+
@error_code = 100
|
17
|
+
|
9
18
|
# Set up the error to wrap another error's trace
|
10
19
|
#
|
11
20
|
# @param [String] error_message A short error description
|
@@ -55,7 +64,14 @@ module Cliqr
|
|
55
64
|
class ValidationError < CliqrError; end
|
56
65
|
|
57
66
|
# Encapsulates the error that gets thrown during a command execution
|
58
|
-
class CommandRuntimeError < CliqrError
|
67
|
+
class CommandRuntimeError < CliqrError
|
68
|
+
@error_code = 101
|
69
|
+
end
|
70
|
+
|
71
|
+
# Raised if an argument does not conform to the option's type
|
72
|
+
class IllegalArgumentError < CliqrError
|
73
|
+
@error_code = 102
|
74
|
+
end
|
59
75
|
|
60
76
|
# Error to signify that a command's runner is not available
|
61
77
|
class UnknownCommandRunnerException < CliqrError; end
|
@@ -75,9 +91,6 @@ module Cliqr
|
|
75
91
|
# Raised if multiple actions are defined with same name at the same nesting level
|
76
92
|
class DuplicateActions < CliqrError; end
|
77
93
|
|
78
|
-
# Raised if an argument does not conform to the option's type
|
79
|
-
class IllegalArgumentError < CliqrError; end
|
80
|
-
|
81
94
|
# Indicates that a unknown validator type is being used in a class
|
82
95
|
class UnknownValidatorType < CliqrError; end
|
83
96
|
|
@@ -86,5 +99,8 @@ module Cliqr
|
|
86
99
|
|
87
100
|
# Raised when a command is executed that is not supposed to run
|
88
101
|
class IllegalCommandError < CliqrError; end
|
102
|
+
|
103
|
+
# Raised if event invocation is in invalid state
|
104
|
+
class InvocationError < CliqrError; end
|
89
105
|
end
|
90
106
|
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Cliqr
|
4
|
+
module Events
|
5
|
+
# Defines a event and its properties
|
6
|
+
#
|
7
|
+
# @api private
|
8
|
+
class Event
|
9
|
+
# Event's name
|
10
|
+
#
|
11
|
+
# @return [String]
|
12
|
+
attr_reader :name
|
13
|
+
|
14
|
+
# Command that was first invoked which resulted in this event
|
15
|
+
#
|
16
|
+
# @return [String]
|
17
|
+
attr_reader :command
|
18
|
+
|
19
|
+
# Time when the event was invoked
|
20
|
+
#
|
21
|
+
# @return [Time]
|
22
|
+
attr_reader :timestamp
|
23
|
+
|
24
|
+
# If this event was invoked from another event handler, this will ne non-nil
|
25
|
+
#
|
26
|
+
# @return [Cliqr::Events::Event]
|
27
|
+
attr_reader :parent
|
28
|
+
|
29
|
+
# Create a new event
|
30
|
+
def initialize(name, command, parent)
|
31
|
+
@name = name
|
32
|
+
@command = command
|
33
|
+
@parent = parent
|
34
|
+
@timestamp = Time.now
|
35
|
+
@propagate = true
|
36
|
+
end
|
37
|
+
|
38
|
+
# Check if this event has a parent event
|
39
|
+
def parent?
|
40
|
+
!parent.nil?
|
41
|
+
end
|
42
|
+
|
43
|
+
# Control event propagation
|
44
|
+
def propagate?
|
45
|
+
@propagate
|
46
|
+
end
|
47
|
+
|
48
|
+
# Unset propagation bit
|
49
|
+
#
|
50
|
+
# @return [Boolean]
|
51
|
+
def stop_propagation
|
52
|
+
@propagate = false
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Cliqr
|
4
|
+
module Events
|
5
|
+
# The context in which event handlers are invoked
|
6
|
+
#
|
7
|
+
# @api private
|
8
|
+
class EventContext
|
9
|
+
# Create a new event context to execute events
|
10
|
+
def initialize(invoker, context, event)
|
11
|
+
@invoker = invoker
|
12
|
+
@context = context
|
13
|
+
@event = event
|
14
|
+
end
|
15
|
+
|
16
|
+
# Invoke a event handler chain by name
|
17
|
+
#
|
18
|
+
# @return [Boolean]
|
19
|
+
def invoke(event_name, *args)
|
20
|
+
@invoker.invoke(event_name, @event, *args)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Handle the case when a method is invoked to get an option value
|
24
|
+
#
|
25
|
+
# @return [Object] Option's value
|
26
|
+
def method_missing(name, *_args, &_block)
|
27
|
+
@context.get_or_check_option(name)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Cliqr
|
4
|
+
# Set of classes to manage and facilitate event handling
|
5
|
+
#
|
6
|
+
# @api private
|
7
|
+
module Events
|
8
|
+
# Event handler that all event handlers come from
|
9
|
+
class Handler
|
10
|
+
# Create a instance of event handler
|
11
|
+
def initialize(context)
|
12
|
+
@context = context
|
13
|
+
end
|
14
|
+
|
15
|
+
# Handle a incoming event needs to be implemented in a subclass
|
16
|
+
#
|
17
|
+
# @throws [Cliqr::Error::InvocationError]
|
18
|
+
#
|
19
|
+
# @return [Nothing]
|
20
|
+
def handle(*_args)
|
21
|
+
fail Cliqr::Error::InvocationError, 'handle method not implemented by handler class'
|
22
|
+
end
|
23
|
+
|
24
|
+
# Invoker another event
|
25
|
+
#
|
26
|
+
# @return [Boolean]
|
27
|
+
def invoke(*args)
|
28
|
+
@context.invoke(*args)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'cliqr/events/event'
|
4
|
+
require 'cliqr/events/event_context'
|
5
|
+
|
6
|
+
module Cliqr
|
7
|
+
module Events
|
8
|
+
# Invokes a event and associated event-chain by propagating the event
|
9
|
+
#
|
10
|
+
# @api private
|
11
|
+
class Invoker
|
12
|
+
# Create a new event invoker instance
|
13
|
+
#
|
14
|
+
# @param [Cliqr::Config::Action] config
|
15
|
+
def initialize(config, context)
|
16
|
+
@config = config
|
17
|
+
@context = context
|
18
|
+
end
|
19
|
+
|
20
|
+
# Invoke a event in the context of the configuration set in this invoker
|
21
|
+
#
|
22
|
+
# @return [Boolean] <tt>true</tt> if the event was handled by an associated handler
|
23
|
+
def invoke(event_name, parent_event, *args)
|
24
|
+
handled = false
|
25
|
+
current_config = @config
|
26
|
+
event = build_event(event_name, parent_event)
|
27
|
+
loop do
|
28
|
+
if current_config.handle?(event_name)
|
29
|
+
handle(event, current_config.event(event_name), *args)
|
30
|
+
handled = true
|
31
|
+
break unless event.propagate?
|
32
|
+
end
|
33
|
+
break if current_config.root?
|
34
|
+
current_config = current_config.parent
|
35
|
+
end
|
36
|
+
handled
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
# Build a event by name
|
42
|
+
#
|
43
|
+
# @return [Cliqr::Events::Event]
|
44
|
+
def build_event(name, parent_event)
|
45
|
+
Events::Event.new(name, @config.command, parent_event)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Handle invocation of a event
|
49
|
+
#
|
50
|
+
# @return [Nothing]
|
51
|
+
def handle(event, event_config, *args)
|
52
|
+
context = Events::EventContext.new(self, @context, event)
|
53
|
+
context.instance_exec(event, *args, &wrap(event_config.handler, context))
|
54
|
+
rescue StandardError => e
|
55
|
+
raise Cliqr::Error::InvocationError.new("failed invocation for #{event.name}", e)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Wrap the event invocation handler in a proc
|
59
|
+
#
|
60
|
+
# @return [Proc]
|
61
|
+
def wrap(event_handler, context)
|
62
|
+
return event_handler if event_handler.is_a?(Proc)
|
63
|
+
handler = event_handler.new(context)
|
64
|
+
proc do |*args|
|
65
|
+
handler.handle(*args)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
require 'stringio'
|
4
4
|
|
5
5
|
module Cliqr
|
6
|
-
module
|
6
|
+
module Executor
|
7
7
|
# Factory class to get instance of CommandRunner based on input options
|
8
8
|
#
|
9
9
|
# @api private
|
@@ -12,8 +12,8 @@ module Cliqr
|
|
12
12
|
#
|
13
13
|
# @param [Hash] options Used to build a command runner instance
|
14
14
|
#
|
15
|
-
# @return [Cliqr::
|
16
|
-
# @return [Cliqr::
|
15
|
+
# @return [Cliqr::Executor::StandardCommandRunner] If default output is require from command
|
16
|
+
# @return [Cliqr::Executor::BufferedCommandRunner] If command's output needs to be buffered
|
17
17
|
def self.get(**options)
|
18
18
|
case options[:output]
|
19
19
|
when :default
|
@@ -1,18 +1,18 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
require 'cliqr/
|
3
|
+
require 'cliqr/executor/command_runner_factory'
|
4
4
|
|
5
5
|
module Cliqr
|
6
|
-
module
|
6
|
+
module Executor
|
7
7
|
# Used for routing the command to the appropriate command handler based on the interface config
|
8
8
|
#
|
9
9
|
# @api private
|
10
10
|
class Router
|
11
11
|
# Create a new Router instance
|
12
12
|
#
|
13
|
-
# @param [Cliqr::
|
13
|
+
# @param [Cliqr::Config::Command] config Command line configuration
|
14
14
|
#
|
15
|
-
# @return [Cliqr::
|
15
|
+
# @return [Cliqr::Interface::Router]
|
16
16
|
def initialize(config)
|
17
17
|
@config = config
|
18
18
|
end
|
@@ -1,17 +1,18 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
require 'cliqr/cli/router'
|
4
|
-
require 'cliqr/cli/command_context'
|
5
3
|
require 'cliqr/argument_validation/validator'
|
6
4
|
require 'cliqr/parser/argument_parser'
|
5
|
+
require 'cliqr/command/command_context'
|
6
|
+
require 'cliqr/executor/router'
|
7
7
|
|
8
8
|
module Cliqr
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
9
|
+
# Handles command execution with error handling
|
10
|
+
#
|
11
|
+
# @api private
|
12
|
+
module Executor
|
13
|
+
# The command runner that handles errors as well
|
14
|
+
class Runner
|
15
|
+
# Create a new command runner
|
15
16
|
def initialize(config)
|
16
17
|
@config = config
|
17
18
|
@validator = Cliqr::ArgumentValidation::Validator.new
|
@@ -27,11 +28,11 @@ module Cliqr
|
|
27
28
|
args = Cliqr::Util.sanitize_args(args, @config)
|
28
29
|
action_config, parsed_input = parse(args)
|
29
30
|
begin
|
30
|
-
command_context = CommandContext.build(action_config, parsed_input, options) \
|
31
|
+
command_context = Command::CommandContext.build(action_config, parsed_input, options) \
|
31
32
|
do |forwarded_args, forwarded_options|
|
32
33
|
execute(forwarded_args, options.merge(forwarded_options))
|
33
34
|
end
|
34
|
-
Router.new(action_config).handle(command_context, **options)
|
35
|
+
Executor::Router.new(action_config).handle(command_context, **options)
|
35
36
|
rescue StandardError => e
|
36
37
|
raise Cliqr::Error::CommandRuntimeError.new(
|
37
38
|
"command '#{action_config.command}' failed", e)
|
@@ -55,5 +56,19 @@ module Cliqr
|
|
55
56
|
[action_config, parsed_input]
|
56
57
|
end
|
57
58
|
end
|
59
|
+
|
60
|
+
# Exit code mapper based on error type
|
61
|
+
#
|
62
|
+
# @api private
|
63
|
+
class ExitCode
|
64
|
+
# Get exit code based on type
|
65
|
+
#
|
66
|
+
# @return [Integer]
|
67
|
+
def self.code(type)
|
68
|
+
return 0 if type == :success
|
69
|
+
return type.class.error_code if type.class.respond_to?(:error_code)
|
70
|
+
99
|
71
|
+
end
|
72
|
+
end
|
58
73
|
end
|
59
74
|
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'cliqr/error'
|
4
|
+
require 'cliqr/executor/runner'
|
5
|
+
require 'cliqr/usage/usage_builder'
|
6
|
+
|
7
|
+
# The top level module
|
8
|
+
module Cliqr
|
9
|
+
# The execution interface to a command line application built using Cliqr
|
10
|
+
#
|
11
|
+
# @api private
|
12
|
+
class Interface
|
13
|
+
# Command line interface configuration
|
14
|
+
#
|
15
|
+
# @return [Cliqr::CLI::Config]
|
16
|
+
attr_accessor :config
|
17
|
+
|
18
|
+
# Create a new interface instance with a config
|
19
|
+
#
|
20
|
+
# @param [Cliqr::Config::Command] config Config used to create this interface
|
21
|
+
def initialize(config)
|
22
|
+
@config = config
|
23
|
+
@runner = Executor::Runner.new(config)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Get usage information of this command line interface instance
|
27
|
+
#
|
28
|
+
# @return [String] Defines usage of this interface
|
29
|
+
def usage
|
30
|
+
Usage::UsageBuilder.new(:cli).build(config)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Execute a command
|
34
|
+
#
|
35
|
+
# @param [Array<String>] args Arguments that will be used to execute the command
|
36
|
+
# @param [Hash] options Options for command execution
|
37
|
+
#
|
38
|
+
# @return [Integer] Exit code of the command execution
|
39
|
+
def execute(args = [], **options)
|
40
|
+
execute_internal(args, options)
|
41
|
+
Executor::ExitCode.code(:success)
|
42
|
+
rescue Cliqr::Error::CliqrError => e
|
43
|
+
puts e.message
|
44
|
+
Executor::ExitCode.code(e)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Executes a command without handling error conditions
|
48
|
+
#
|
49
|
+
# @return [Integer] Exit code
|
50
|
+
def execute_internal(args = [], **options)
|
51
|
+
options = {
|
52
|
+
:output => :default,
|
53
|
+
:environment => :cli
|
54
|
+
}.merge(options)
|
55
|
+
@runner.execute(args, options)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Invoke the builder method for [Cliqr::CLI::Interface]
|
59
|
+
#
|
60
|
+
# @param [Cliqr::CLI::Config] config Instance of the command line config
|
61
|
+
#
|
62
|
+
# @return [Cliqr::CLI::Interface]
|
63
|
+
def self.build(config)
|
64
|
+
InterfaceBuilder.new(config).build
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
# Builder for [Cliqr::CLI::Interface]
|
71
|
+
#
|
72
|
+
# @api private
|
73
|
+
class InterfaceBuilder
|
74
|
+
# Start building a command line interface
|
75
|
+
#
|
76
|
+
# @param [Cliqr::CLI::Config] config the configuration options for the
|
77
|
+
# interface (validated using CLI::Validator)
|
78
|
+
#
|
79
|
+
# @return [Cliqr::CLI::ConfigBuilder]
|
80
|
+
def initialize(config)
|
81
|
+
@config = config
|
82
|
+
end
|
83
|
+
|
84
|
+
# Validate and build a cli interface based on the configuration options
|
85
|
+
#
|
86
|
+
# @return [Cliqr::CLI::Interface]
|
87
|
+
#
|
88
|
+
# @throws [Cliqr::Error::ConfigNotFound] if a config is <tt>nil</tt>
|
89
|
+
# @throws [Cliqr::Error::ValidationError] if the validation for config fails
|
90
|
+
def build
|
91
|
+
fail Cliqr::Error::ConfigNotFound, 'a valid config should be defined' if @config.nil?
|
92
|
+
fail Cliqr::Error::ValidationError, \
|
93
|
+
"invalid Cliqr interface configuration - [#{@config.errors}]" unless @config.valid?
|
94
|
+
|
95
|
+
Interface.new(@config)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|