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
@@ -1,14 +1,23 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
require 'cliqr/
|
3
|
+
require 'cliqr/command/color'
|
4
|
+
require 'cliqr/command/argument_operator_context'
|
5
|
+
require 'cliqr/events/invoker'
|
4
6
|
|
5
7
|
module Cliqr
|
6
8
|
# Definition and builder for command context
|
7
|
-
module
|
9
|
+
module Command
|
8
10
|
# Manages things like arguments and input/output for a command
|
9
11
|
#
|
10
12
|
# @api private
|
11
13
|
class CommandContext
|
14
|
+
include Cliqr::Command::Color
|
15
|
+
|
16
|
+
# Base command name
|
17
|
+
#
|
18
|
+
# @return [String]
|
19
|
+
attr_accessor :base_command
|
20
|
+
|
12
21
|
# Command name
|
13
22
|
#
|
14
23
|
# @return [String]
|
@@ -24,29 +33,37 @@ module Cliqr
|
|
24
33
|
# @return [String]
|
25
34
|
attr_accessor :action_name
|
26
35
|
|
36
|
+
# Environment type
|
37
|
+
#
|
38
|
+
# @return [String]
|
39
|
+
attr_reader :environment
|
40
|
+
|
27
41
|
# Build a instance of command context based on the parsed set of arguments
|
28
42
|
#
|
29
|
-
# @param [Cliqr::
|
43
|
+
# @param [Cliqr::Config::Command] config The configuration settings
|
30
44
|
# @param [Cliqr::Parser::ParsedInput] parsed_input Parsed input object
|
31
45
|
# @param [Hash] options Options for command execution
|
32
46
|
# @param [Proc] executor Executes forwarded commands
|
33
47
|
#
|
34
|
-
# @return [Cliqr::
|
48
|
+
# @return [Cliqr::Command::CommandContext]
|
35
49
|
def self.build(config, parsed_input, options, &executor)
|
36
50
|
CommandContextBuilder.new(config, parsed_input, options, executor).build
|
37
51
|
end
|
38
52
|
|
39
53
|
# Initialize the command context (called by the CommandContextBuilder)
|
40
54
|
#
|
41
|
-
# @return [Cliqr::
|
55
|
+
# @return [Cliqr::Command::CommandContext]
|
42
56
|
def initialize(config, options, arguments, environment, executor)
|
57
|
+
super(config)
|
58
|
+
|
43
59
|
@config = config
|
60
|
+
@base_command = config.root.name
|
44
61
|
@command = config.command
|
45
62
|
@arguments = arguments
|
46
63
|
@action_name = config.name
|
47
|
-
@context = self
|
48
64
|
@environment = environment
|
49
65
|
@executor = executor
|
66
|
+
@event_invoker = Events::Invoker.new(config, self)
|
50
67
|
|
51
68
|
# make option map from array
|
52
69
|
@options = Hash[*options.collect { |option| [option.name, option] }.flatten]
|
@@ -54,22 +71,22 @@ module Cliqr
|
|
54
71
|
|
55
72
|
# List of parsed options
|
56
73
|
#
|
57
|
-
# @return [Array<Cliqr::
|
74
|
+
# @return [Array<Cliqr::Command::CommandOption>]
|
58
75
|
def options
|
59
76
|
@options.values
|
60
77
|
end
|
61
78
|
|
62
|
-
# Get
|
79
|
+
# Get an option by name
|
63
80
|
#
|
64
81
|
# @param [String] name Name of the option
|
65
82
|
#
|
66
|
-
# @return [Cliqr::
|
83
|
+
# @return [Cliqr::Command::CommandOption] Instance of CommandOption for option
|
67
84
|
def option(name)
|
68
85
|
return @options[name] if option?(name)
|
69
86
|
default(name)
|
70
87
|
end
|
71
88
|
|
72
|
-
# Check if
|
89
|
+
# Check if an option with a specified name has been passed
|
73
90
|
#
|
74
91
|
# @param [String] name Name of the option
|
75
92
|
#
|
@@ -78,10 +95,17 @@ module Cliqr
|
|
78
95
|
@options.key?(name)
|
79
96
|
end
|
80
97
|
|
81
|
-
# Check whether
|
98
|
+
# Check whether a action is valid in current context
|
99
|
+
#
|
100
|
+
# @param [String] name Name of the action to check
|
82
101
|
#
|
83
|
-
# @return [Boolean] <tt>true</tt> if this context
|
84
|
-
def action?
|
102
|
+
# @return [Boolean] <tt>true</tt> if this context has the requested action
|
103
|
+
def action?(name)
|
104
|
+
@config.action?(name)
|
105
|
+
end
|
106
|
+
|
107
|
+
# Check if the current context if for a action
|
108
|
+
def action_type?
|
85
109
|
@config.parent?
|
86
110
|
end
|
87
111
|
|
@@ -92,10 +116,24 @@ module Cliqr
|
|
92
116
|
@executor.call(args, options)
|
93
117
|
end
|
94
118
|
|
119
|
+
# Invoke an event
|
120
|
+
#
|
121
|
+
# @return [Boolean] <tt>true</tt> if the event was handled by any event handler
|
122
|
+
def invoke(event_name, *args)
|
123
|
+
@event_invoker.invoke(event_name, nil, *args)
|
124
|
+
end
|
125
|
+
|
95
126
|
# Handle the case when a method is invoked to get an option value
|
96
127
|
#
|
97
128
|
# @return [Object] Option's value
|
98
129
|
def method_missing(name, *_args, &_block)
|
130
|
+
get_or_check_option(name)
|
131
|
+
end
|
132
|
+
|
133
|
+
# Get option value or check if it exists
|
134
|
+
#
|
135
|
+
# @return [Object]
|
136
|
+
def get_or_check_option(name)
|
99
137
|
option_name = name.to_s.chomp('?')
|
100
138
|
existence_check = name.to_s.end_with?('?')
|
101
139
|
existence_check ? option?(option_name) : option(option_name).value \
|
@@ -114,7 +152,17 @@ module Cliqr
|
|
114
152
|
#
|
115
153
|
# @return [Boolean]
|
116
154
|
def bash?
|
117
|
-
@environment == :
|
155
|
+
@environment == :cli
|
156
|
+
end
|
157
|
+
|
158
|
+
# Transform this context to the root context
|
159
|
+
#
|
160
|
+
# @param [Symbol] environment_type Optional environment type
|
161
|
+
#
|
162
|
+
# @return [Cliqr::Command::CommandContext]
|
163
|
+
def root(environment_type = nil)
|
164
|
+
environment_type = @environment if environment_type.nil?
|
165
|
+
CommandContext.new(@config.root, [], [], environment_type, @executor)
|
118
166
|
end
|
119
167
|
|
120
168
|
private :initialize, :default
|
@@ -128,12 +176,12 @@ module Cliqr
|
|
128
176
|
class CommandContextBuilder
|
129
177
|
# Initialize builder for CommandContext
|
130
178
|
#
|
131
|
-
# @param [Cliqr::
|
179
|
+
# @param [Cliqr::Command::Config] config The configuration settings
|
132
180
|
# @param [Cliqr::Parser::ParsedInput] parsed_input Parsed and validated command line arguments
|
133
181
|
# @param [Hash] options Options for command execution
|
134
182
|
# @param [Proc] executor Executes forwarded commands
|
135
183
|
#
|
136
|
-
# @return [Cliqr::
|
184
|
+
# @return [Cliqr::Command::CommandContextBuilder]
|
137
185
|
def initialize(config, parsed_input, options, executor)
|
138
186
|
@config = config
|
139
187
|
@parsed_input = parsed_input
|
@@ -143,7 +191,7 @@ module Cliqr
|
|
143
191
|
|
144
192
|
# Build a new instance of CommandContext
|
145
193
|
#
|
146
|
-
# @return [Cliqr::
|
194
|
+
# @return [Cliqr::Command::CommandContext] A newly created CommandContext instance
|
147
195
|
def build
|
148
196
|
option_contexts = @parsed_input.options.map do |option|
|
149
197
|
CommandOption.new(option, @config.option(option.first))
|
@@ -174,9 +222,9 @@ module Cliqr
|
|
174
222
|
# Create a new command line option instance
|
175
223
|
#
|
176
224
|
# @param [Array] option Parsed arguments for creating a command line option
|
177
|
-
# @param [Cliqr::
|
225
|
+
# @param [Cliqr::Config::Option] option_config Option's config settings
|
178
226
|
#
|
179
|
-
# @return [Cliqr::
|
227
|
+
# @return [Cliqr::Command::CommandContext] A new CommandOption object
|
180
228
|
def initialize(option, option_config)
|
181
229
|
@value = run_value_operator(option.pop, option_config.operator)
|
182
230
|
@name = option.pop
|
@@ -189,7 +237,7 @@ module Cliqr
|
|
189
237
|
# @return [Nothing]
|
190
238
|
def run_value_operator(value, operator)
|
191
239
|
if operator.is_a?(Proc)
|
192
|
-
ArgumentOperatorContext.new(value).instance_eval(&operator)
|
240
|
+
Command::ArgumentOperatorContext.new(value).instance_eval(&operator)
|
193
241
|
else
|
194
242
|
operator.operate(value)
|
195
243
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Cliqr
|
4
|
+
module Command
|
5
|
+
# Used to build a banner string for shell
|
6
|
+
#
|
7
|
+
# @api private
|
8
|
+
class ShellBannerBuilder
|
9
|
+
# Build the banner based on current context
|
10
|
+
#
|
11
|
+
# @return [String]
|
12
|
+
def build(context)
|
13
|
+
"Starting shell for command \"#{context.command}\""
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Cliqr
|
4
|
+
# @api private
|
5
|
+
module Command
|
6
|
+
# The default command executed to run a shell action
|
7
|
+
#
|
8
|
+
# @api private
|
9
|
+
class ShellCommand < Cliqr::Command::BaseCommand
|
10
|
+
# Create a new shell command handler
|
11
|
+
def initialize(shell_config)
|
12
|
+
@shell_config = shell_config
|
13
|
+
end
|
14
|
+
|
15
|
+
# Start a shell in the context of some other command
|
16
|
+
#
|
17
|
+
# @return [Integer] Exit code
|
18
|
+
def execute(context)
|
19
|
+
validate_environment(context)
|
20
|
+
|
21
|
+
root_context = context.root(:shell)
|
22
|
+
|
23
|
+
puts banner(root_context, build_proc(@shell_config.banner))
|
24
|
+
|
25
|
+
context.invoke(:shell_start)
|
26
|
+
exit_code = build_runner(context, root_context).run
|
27
|
+
context.invoke(:shell_stop)
|
28
|
+
puts "shell exited with code #{exit_code}"
|
29
|
+
exit_code
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
# Build an instance of the ShellRunner
|
35
|
+
#
|
36
|
+
# @return [Cliqr::Command::ShellRunner]
|
37
|
+
def build_runner(context, root_context)
|
38
|
+
ShellRunner.new(context.base_command,
|
39
|
+
root_context,
|
40
|
+
build_proc(@shell_config.prompt))
|
41
|
+
end
|
42
|
+
|
43
|
+
# Make sure a shell cannot be run inside an already running shell
|
44
|
+
#
|
45
|
+
# @return Nothing
|
46
|
+
def validate_environment(context)
|
47
|
+
fail(Cliqr::Error::IllegalCommandError,
|
48
|
+
'Cannot run another shell within an already running shell') unless context.bash?
|
49
|
+
end
|
50
|
+
|
51
|
+
# Banner string for current command
|
52
|
+
#
|
53
|
+
# @return [String]
|
54
|
+
def banner(context, block)
|
55
|
+
context.instance_eval(&block)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Build an anonymous method to wrap an attribute value
|
59
|
+
#
|
60
|
+
# @return [Proc]
|
61
|
+
def build_proc(value)
|
62
|
+
if value.is_a?(String)
|
63
|
+
proc { value }
|
64
|
+
elsif value.is_a?(Proc)
|
65
|
+
return value
|
66
|
+
else
|
67
|
+
builder = value
|
68
|
+
builder = value.new if value.is_a?(Class)
|
69
|
+
proc do
|
70
|
+
builder.build(self)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
# The runner for shell command
|
79
|
+
class ShellRunner
|
80
|
+
# Create the runner instance
|
81
|
+
def initialize(base_command, context, prompt)
|
82
|
+
@base_command = base_command
|
83
|
+
@context = context
|
84
|
+
@prompt = prompt
|
85
|
+
end
|
86
|
+
|
87
|
+
# Start shell
|
88
|
+
#
|
89
|
+
# @return [Integer] Exit code
|
90
|
+
def run
|
91
|
+
loop do
|
92
|
+
command = prompt
|
93
|
+
execute(command) unless command == 'exit'
|
94
|
+
break if command == 'exit'
|
95
|
+
end
|
96
|
+
0
|
97
|
+
end
|
98
|
+
|
99
|
+
private
|
100
|
+
|
101
|
+
# Execute a shell command
|
102
|
+
#
|
103
|
+
# @return [Integer] Exit code of the command executed
|
104
|
+
def execute(command)
|
105
|
+
return if command.empty?
|
106
|
+
action_name = command.split(' ').first
|
107
|
+
unless @context.action?(action_name)
|
108
|
+
puts "unknown action \"#{action_name}\""
|
109
|
+
return Cliqr::Executor::ExitCode.code(nil)
|
110
|
+
end
|
111
|
+
@context.forward("#{@base_command} #{command}", :environment => @context.environment)
|
112
|
+
rescue StandardError => e
|
113
|
+
puts e.message
|
114
|
+
end
|
115
|
+
|
116
|
+
# Show a prompt and ask for input
|
117
|
+
#
|
118
|
+
# @return [String]
|
119
|
+
def prompt
|
120
|
+
print @context.instance_eval(&@prompt)
|
121
|
+
$stdin.gets.chomp
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Cliqr
|
4
|
+
module Command
|
5
|
+
# Builds a shell prompt
|
6
|
+
#
|
7
|
+
# @api private
|
8
|
+
class ShellPromptBuilder
|
9
|
+
include Cliqr::Command::Color
|
10
|
+
|
11
|
+
# Create a new shell prompt builder with optional command config
|
12
|
+
def initialize(config = nil)
|
13
|
+
super
|
14
|
+
@count = 0
|
15
|
+
end
|
16
|
+
|
17
|
+
# Build a prompt for current command
|
18
|
+
#
|
19
|
+
# @return [String]
|
20
|
+
def build(context)
|
21
|
+
@count += 1
|
22
|
+
"[#{cyan(context.command)}][#{@count}] #{bold('$')} "
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,226 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'cliqr/util'
|
4
|
+
require 'cliqr/command/base_command'
|
5
|
+
require 'cliqr/config/base'
|
6
|
+
require 'cliqr/config/option_based'
|
7
|
+
|
8
|
+
module Cliqr
|
9
|
+
module Config
|
10
|
+
# Configuration setting for an action
|
11
|
+
#
|
12
|
+
# @api private
|
13
|
+
class Action < Cliqr::Config::OptionBased
|
14
|
+
# Command handler for the base command
|
15
|
+
#
|
16
|
+
# @return [Class<Cliqr::Command::BaseCommand>]
|
17
|
+
attr_accessor :handler
|
18
|
+
validates :handler,
|
19
|
+
one_of: [
|
20
|
+
{ extend: Cliqr::Command::BaseCommand },
|
21
|
+
{ type_of: Proc }
|
22
|
+
]
|
23
|
+
|
24
|
+
# Dictates whether this command can take arbitrary arguments (optional)
|
25
|
+
#
|
26
|
+
# @return [Symbol] Either <tt>#ENABLE_CONFIG</tt> or <tt>#DISABLE_CONFIG</tt>
|
27
|
+
attr_accessor :arguments
|
28
|
+
validates :arguments,
|
29
|
+
inclusion: [ENABLE_CONFIG, DISABLE_CONFIG]
|
30
|
+
|
31
|
+
# Array of children action configs for this action
|
32
|
+
#
|
33
|
+
# @return [Array<Cliqr::CLI::Config>]
|
34
|
+
attr_accessor :actions
|
35
|
+
validates :actions,
|
36
|
+
collection: true
|
37
|
+
|
38
|
+
# Enable or disable help command and option
|
39
|
+
#
|
40
|
+
# @return [Symbol] Either <tt>#ENABLE_CONFIG</tt> or <tt>#DISABLE_CONFIG</tt>
|
41
|
+
attr_accessor :help
|
42
|
+
validates :help,
|
43
|
+
inclusion: [ENABLE_CONFIG, DISABLE_CONFIG]
|
44
|
+
|
45
|
+
# Parent configuration
|
46
|
+
#
|
47
|
+
# @return [Cliqr::Config::CommandConfig]
|
48
|
+
attr_accessor :parent
|
49
|
+
|
50
|
+
# New config instance with all attributes set as UNSET
|
51
|
+
def initialize
|
52
|
+
super
|
53
|
+
|
54
|
+
@handler = UNSET
|
55
|
+
@arguments = UNSET
|
56
|
+
@help = UNSET
|
57
|
+
|
58
|
+
@actions = []
|
59
|
+
@action_index = {}
|
60
|
+
end
|
61
|
+
|
62
|
+
# Finalize config by adding default values for unset values
|
63
|
+
#
|
64
|
+
# @return [Cliqr::Config::Action]
|
65
|
+
def finalize
|
66
|
+
super
|
67
|
+
|
68
|
+
@handler = Util.ensure_instance(Config.get_if_unset(@handler, nil))
|
69
|
+
@arguments = Config.get_if_unset(@arguments, ENABLE_CONFIG)
|
70
|
+
@help = Config.get_if_unset(@help, ENABLE_CONFIG)
|
71
|
+
|
72
|
+
self
|
73
|
+
end
|
74
|
+
|
75
|
+
# Set up default attributes for this configuration
|
76
|
+
#
|
77
|
+
# @return [Cliqr::Config::Command] Update config
|
78
|
+
def setup_defaults
|
79
|
+
add_help
|
80
|
+
@handler = Cliqr::Util.forward_to_help_handler if @handler.nil? && help? && actions?
|
81
|
+
@actions.each(&:setup_defaults)
|
82
|
+
end
|
83
|
+
|
84
|
+
# Set value for a config option
|
85
|
+
#
|
86
|
+
# @param [Symbol] name Name of the config parameter
|
87
|
+
# @param [Object] value Value for the config parameter
|
88
|
+
# @param [Proc] block Function which populates configuration for a sub-attribute
|
89
|
+
#
|
90
|
+
# @return [Object] if setting a attribute's value
|
91
|
+
# @return [Cliqr::Config::Base] if adding a new action or option
|
92
|
+
def set_config(name, value, *args, &block)
|
93
|
+
case name
|
94
|
+
when :action
|
95
|
+
handle_action(value, &block) # value is action's name
|
96
|
+
else
|
97
|
+
super
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# Check if particular action exists
|
102
|
+
#
|
103
|
+
# @param [String] name Name of the action to check
|
104
|
+
#
|
105
|
+
# @return [Boolean] <tt>true</tt> if the action exists in the configuration
|
106
|
+
def action?(name)
|
107
|
+
return false if name.nil?
|
108
|
+
@action_index.key?(name.to_sym)
|
109
|
+
end
|
110
|
+
|
111
|
+
# Check if this config has sub actions
|
112
|
+
#
|
113
|
+
# @return [Boolean]
|
114
|
+
def actions?
|
115
|
+
!@actions.empty?
|
116
|
+
end
|
117
|
+
|
118
|
+
# Get action config by name
|
119
|
+
#
|
120
|
+
# @param [String] name Name of the action
|
121
|
+
#
|
122
|
+
# @return [Cliqr::Config::Action] Configuration of the action
|
123
|
+
def action(name)
|
124
|
+
@action_index[name.to_sym]
|
125
|
+
end
|
126
|
+
|
127
|
+
# Check if arguments are enabled for this configuration
|
128
|
+
#
|
129
|
+
# @return [Boolean] <tt>true</tt> if arguments are enabled
|
130
|
+
def arguments?
|
131
|
+
@arguments == ENABLE_CONFIG
|
132
|
+
end
|
133
|
+
|
134
|
+
# Get name of the command along with the action upto this config
|
135
|
+
#
|
136
|
+
# @return [String] Serialized command name
|
137
|
+
def command
|
138
|
+
return name unless parent?
|
139
|
+
"#{@parent.command} #{name}"
|
140
|
+
end
|
141
|
+
|
142
|
+
# Check if this config has a parent config
|
143
|
+
#
|
144
|
+
# @return [Boolean] <tt>true</tt> if there exists a parent action for this action
|
145
|
+
def parent?
|
146
|
+
!@parent.nil?
|
147
|
+
end
|
148
|
+
|
149
|
+
# Check if help is enabled for this command
|
150
|
+
#
|
151
|
+
# @return [Boolean] <tt>true</tt> if help is enabled
|
152
|
+
def help?
|
153
|
+
@help == ENABLE_CONFIG
|
154
|
+
end
|
155
|
+
|
156
|
+
# The root of action config is itself unless otherwise configured
|
157
|
+
#
|
158
|
+
# @return [Cliqr::Config::Action]
|
159
|
+
def root
|
160
|
+
self
|
161
|
+
end
|
162
|
+
|
163
|
+
# Check if this action is the root
|
164
|
+
def root?
|
165
|
+
self == root
|
166
|
+
end
|
167
|
+
|
168
|
+
private
|
169
|
+
|
170
|
+
# Handle configuration for a new action
|
171
|
+
#
|
172
|
+
# @param [String] name Name of the action
|
173
|
+
# @param [Function] block The block which configures this action
|
174
|
+
#
|
175
|
+
# @return [Cliqr::Config::Action] The newly configured action
|
176
|
+
def handle_action(name, &block)
|
177
|
+
action_config = Action.build(&block)
|
178
|
+
action_config.name = name
|
179
|
+
add_action(action_config)
|
180
|
+
end
|
181
|
+
|
182
|
+
# Add a new action
|
183
|
+
#
|
184
|
+
# @return [Cliqr::Config::Action] The newly added action
|
185
|
+
def add_action(action_config)
|
186
|
+
parent = self
|
187
|
+
action_config.parent = parent
|
188
|
+
action_config.instance_eval do
|
189
|
+
def root
|
190
|
+
parent.root
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
validate_action_name(action_config)
|
195
|
+
|
196
|
+
@actions.push(action_config)
|
197
|
+
@action_index[action_config.name.to_sym] = action_config \
|
198
|
+
unless action_config.name.nil?
|
199
|
+
|
200
|
+
action_config
|
201
|
+
end
|
202
|
+
|
203
|
+
# Make sure that the action's name is unique
|
204
|
+
#
|
205
|
+
# @param [Cliqr::Config::Action] action_config Config for this particular action
|
206
|
+
#
|
207
|
+
# @return [Cliqr::Config::Action] Validated action's Config instance
|
208
|
+
def validate_action_name(action_config)
|
209
|
+
fail Cliqr::Error::DuplicateActions,
|
210
|
+
"multiple actions named \"#{action_config.name}\"" \
|
211
|
+
if action?(action_config.name)
|
212
|
+
|
213
|
+
action_config
|
214
|
+
end
|
215
|
+
|
216
|
+
# Add help command and option to this config
|
217
|
+
#
|
218
|
+
# @return [Cliqr::Config::Base] Updated config
|
219
|
+
def add_help
|
220
|
+
return self unless help?
|
221
|
+
add_action(Cliqr::Util.build_help_action(self)) unless action?('help')
|
222
|
+
add_option(Cliqr::Util.build_help_option(self)) unless option?('help')
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|