cliqr 0.0.3 → 0.0.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f3005b3bec4c39c0af0006b3da4be666c2c0f0b2
4
- data.tar.gz: 11a692aba415f994a5b3f26857c5d025371a1bd6
3
+ metadata.gz: 8b1c3a47c4045454a48b832cc443ea735fe538ae
4
+ data.tar.gz: 4b919b535387086386da176acc4a470b8cf597e6
5
5
  SHA512:
6
- metadata.gz: b0504ab87aafe19c34dff996cb9eb8b5499b2b242a4f8e2973afb643c32d98aff0959fd85d24dd8dd297bc818a0b27247e576be8d6e0a4a8fa2ddc9ddf6ce902
7
- data.tar.gz: 7c61a612684c2a33f3db3cca0525134d0e3cb7621ef43a92c657c51865732b7e716c247f88aecaac94fc3b8c437969ce92b6aff50467d3dda604ceea2c07ecd9
6
+ metadata.gz: 88d7eeb4ca572c3dfb8715611b2f3c5355ef9a5f5cee2c40497d485bc190c1869e57d8e4780f9507de91ad41fd15cebd44066bb28afd0ff68f6c081d67ecd1df
7
+ data.tar.gz: bf965708a3fbb48c021875fd87dfb51f417fe3f73c2e85d8053e5ec449942b0ffb62461ede244f2b48297880acc0aa7160bc1c0db23c510f128a3e61a969588b
data/CHANGELOG.md CHANGED
@@ -1,4 +1,23 @@
1
1
 
2
+ 0.0.4 / 2015-05-11
3
+ ==================
4
+
5
+ * bring document coverage to 100%
6
+ * improve documentation
7
+ * fix minor style error in rake tasks
8
+ * don't execute specs twice
9
+ * add support for command options
10
+ * improve dsl framework by completely hiding dsl methods
11
+ * add method_missing to proxy all dsl methods
12
+ * add example for router in readme
13
+ * ignore document files
14
+ * add command router
15
+ * use a template to build usage
16
+ * move builder spec in its own folder
17
+ * add command usage section
18
+ * change usage information builder
19
+ * show total downloads in readme
20
+
2
21
  0.0.3 / 2015-05-08
3
22
  ==================
4
23
 
data/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
  [![Inline docs](http://inch-ci.org/github/anshulverma/cliqr.svg)](http://inch-ci.org/github/anshulverma/cliqr)
8
8
 
9
9
  [![Version](http://img.shields.io/gem/v/cliqr.svg?style=flat-square)](https://rubygems.org/gems/cliqr)
10
- [![Downloads](http://img.shields.io/gem/dtv/cliqr.svg?style=flat-square)](https://rubygems.org/gems/cliqr)
10
+ [![Downloads](http://img.shields.io/gem/dt/cliqr.svg?style=flat-square)](https://rubygems.org/gems/cliqr)
11
11
 
12
12
  <!-- markdown-toc start - Don't edit this section. Run M-x markdown-toc/generate-toc again -->
13
13
  **Table of Contents**
@@ -15,7 +15,7 @@
15
15
  - [cliqr](#cliqr)
16
16
  - [Summary](#summary)
17
17
  - [Examples](#examples)
18
- - [Simple CLI app with basename and description](#simple-cli-app-with-basename-and-description)
18
+ - [Simple CLI app example](#simple-cli-app-example)
19
19
  - [Installation](#installation)
20
20
  - [Building](#building)
21
21
  - [Contributing](#contributing)
@@ -38,15 +38,43 @@ line application. Features include:
38
38
  The DSL provides several helper methods to build interfaces of different
39
39
  styles. Here are some examples.
40
40
 
41
- ### Simple CLI app with basename and description
41
+ ### Simple CLI app example
42
42
 
43
43
  Here is a simple hello-world example for using Cliqr.
44
44
 
45
45
  ``` ruby
46
+ require 'cliqr'
47
+
48
+ # a custom command handler
49
+ class MyCommandHandler < Cliqr.command
50
+ def execute
51
+ puts 'executing my awesome command'
52
+ end
53
+ end
54
+
46
55
  cli = Cliqr.interface do
47
56
  basename 'my-command'
57
+ description 'this is an awesome command...try it out'
58
+ handler MyCommandHandler
59
+
60
+ option 'an-option' do
61
+ short 'a'
62
+ description 'this is a option'
63
+ end
48
64
  end
65
+
49
66
  puts cli.usage
67
+ #> my-command -- this is an awesome command...try it out
68
+ #>
69
+ #> USAGE:
70
+ #> my-command
71
+ #>
72
+ #> Available options:
73
+ #>
74
+ #> --an-option, -a : this is a option
75
+
76
+ cli.execute
77
+ #> executing my awesome command
50
78
  ```
51
79
 
52
80
  This should print
data/Rakefile CHANGED
@@ -17,7 +17,7 @@ task :coverage do
17
17
  end
18
18
 
19
19
  desc 'default rake task'
20
- task default: [:clean, :spec, :rubocop, :coverage, :verify_measurements, :yardstick_measure]
20
+ task default: [:clean, :coverage, :rubocop, :verify_measurements, :yardstick_measure]
21
21
 
22
22
  desc 'run CI tasks'
23
23
  task :ci do
data/lib/cliqr.rb CHANGED
@@ -5,19 +5,44 @@ require 'cliqr/error'
5
5
 
6
6
  require 'cliqr/cli/config'
7
7
  require 'cliqr/cli/builder'
8
+ require 'cliqr/cli/command'
8
9
 
9
10
  # Top level namespace for the Cliqr gem
11
+ #
12
+ # @api public
10
13
  module Cliqr
11
14
  class << self
12
- # Invokes the CLI::Config builder DSL to prepare config for command line
13
- # application. Then uses that config to build a instance of type Cliqr::CLI
15
+ # Start building a cli interface
16
+ #
17
+ # @example
18
+ # Cliqr.interface do
19
+ # basename 'my-command' # name of the command
20
+ # description 'command description in a few words' # long description
21
+ # handler MyCommandHandler # command's handler class
22
+ #
23
+ # option
24
+ # end
14
25
  #
15
26
  # @return [Cliqr::CLI]
16
27
  #
17
28
  # @api public
18
29
  def interface(&block)
19
30
  config = CLI::Config.build(&block)
20
- CLI::Builder.new(config)
31
+ CLI::Builder.new(config).build
32
+ end
33
+
34
+ # All cliqr commands should extend from this. Here is an example:
35
+ #
36
+ # @example
37
+ # class MyCommand < Cliqr.command
38
+ # def execute
39
+ # # execute the command
40
+ # end
41
+ # end
42
+ #
43
+ # @return [CLI::Command]
44
+ def command
45
+ CLI::Command
21
46
  end
22
47
  end
23
48
  end
@@ -1,32 +1,30 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  require 'cliqr/cli/validator'
4
+ require 'cliqr/cli/interface'
4
5
 
5
6
  module Cliqr
6
7
  module CLI
7
8
  # Builds usage information from [CLI::Config]
9
+ #
10
+ # @api private
8
11
  class Builder
9
12
  # Start building a command line interface
10
13
  #
11
- # @param [Hash] config
12
- # the configuration options for the interface (validated using
13
- # CLI::Validator)
14
+ # @param [Cliqr::CLI::Config] config the configuration options for the
15
+ # interface (validated using CLI::Validator)
14
16
  #
15
17
  # @return [Cliqr::CLI::Builder]
16
18
  def initialize(config)
17
- CLI::Validator.validate config
18
- @basename = config[:basename]
19
+ @config = config
19
20
  end
20
21
 
21
- # Get usage information of this command line interface instance
22
+ # Validate and build a cli interface based on the configuration options
22
23
  #
23
- # @return [String]
24
- #
25
- # @api public
26
- def usage
27
- <<-EOS
28
- USAGE: #{@basename}
29
- EOS
24
+ # @return [Cliqr::CLI::Interface]
25
+ def build
26
+ CLI::Validator.validate @config
27
+ Interface.new(@config)
30
28
  end
31
29
  end
32
30
  end
@@ -0,0 +1,17 @@
1
+ # encoding: utf-8
2
+
3
+ module Cliqr
4
+ module CLI
5
+ # Base class for all commands to extend from
6
+ #
7
+ # @api private
8
+ class Command
9
+ # Execute the command
10
+ #
11
+ # @return [Integer] Exit status of the command execution
12
+ def execute
13
+ 0
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,66 @@
1
+ # encoding: utf-8
2
+
3
+ require 'stringio'
4
+
5
+ module Cliqr
6
+ module CLI
7
+ # Factory class to get instance of CommandRunner based on input options
8
+ #
9
+ # @api private
10
+ class CommandRunnerFactory
11
+ # Get a instance of command runner based on options
12
+ #
13
+ # @param [Hash] options Used to build a command runner instance
14
+ #
15
+ # @return [Cliqr::CLI::StandardCommandRunner] If default output is require from command
16
+ # @return [Cliqr::CLI::BufferedCommandRunner] If command's output needs to be buffered
17
+ def self.get(**options)
18
+ case options[:output]
19
+ when :default
20
+ StandardCommandRunner.new
21
+ when :buffer
22
+ BufferedCommandRunner.new
23
+ else
24
+ fail Cliqr::Error::UnknownCommandRunnerException,
25
+ 'cannot find a command runner for the given options'
26
+ end
27
+ end
28
+ end
29
+
30
+ # A standard implementation for command runner used for most commands
31
+ #
32
+ # @api private
33
+ class StandardCommandRunner
34
+ # simply execute the command handler
35
+ #
36
+ # @return [Integer] Exit status of the command
37
+ def run
38
+ yield
39
+ end
40
+ end
41
+
42
+ # Used to buffer command output
43
+ #
44
+ # @api private
45
+ class BufferedCommandRunner
46
+ # Run the command handler but redirect stdout to a buffer
47
+ #
48
+ # @return [Hash] The hash contains :stdout, :stderr and :status of the command
49
+ def run
50
+ old_stdout = $stdout
51
+ old_stderr = $stderr
52
+ $stdout = StringIO.new('', 'w')
53
+ $stderr = StringIO.new('', 'w')
54
+ yield
55
+ {
56
+ :stdout => $stdout.string,
57
+ :stderr => $stderr.string,
58
+ :status => 0
59
+ }
60
+ ensure
61
+ $stdout = old_stdout
62
+ $stderr = old_stderr
63
+ end
64
+ end
65
+ end
66
+ end
@@ -3,46 +3,166 @@
3
3
  require 'cliqr/dsl'
4
4
 
5
5
  module Cliqr
6
+ # A extension for CLI module to group all config classes
6
7
  module CLI
8
+ # A value to initialize configuration attributes with
9
+ UNSET = Object.new
10
+
7
11
  # The configuration setting to build a cli application with its own dsl
12
+ #
13
+ # @api private
8
14
  class Config
9
15
  extend Cliqr::DSL
10
16
 
17
+ # Base name of the command
18
+ #
19
+ # @return [String]
20
+ attr_accessor :basename
21
+
22
+ # Description for the base command
23
+ #
24
+ # @return [String]
25
+ attr_accessor :description
26
+
27
+ # Command handler for the base command
28
+ #
29
+ # @return [Class]
30
+ attr_accessor :handler
31
+
32
+ # Array of options applied to the base command
33
+ #
34
+ # @return [Array<OptionConfig>]
35
+ attr_accessor :options
36
+
37
+ # New config instance with all attributes set as UNSET
11
38
  def initialize
12
- @config = {}
39
+ @basename = UNSET
40
+ @description = UNSET
41
+ @handler = UNSET
42
+ @options = UNSET
43
+ end
44
+
45
+ # Finalize config by adding default values for unset values
46
+ #
47
+ # @return [Cliqr::CLI::Config]
48
+ def finalize
49
+ @basename = '' if @basename == UNSET
50
+ @description = '' if @description == UNSET
51
+ @handler = nil if @handler == UNSET
52
+ @options = [] if @options == UNSET
53
+
54
+ self
13
55
  end
14
56
 
15
57
  # Set value for a config option
16
58
  #
17
- # @param name
18
- # name of the config parameter
59
+ # @param [Symbol] name Name of the config parameter
19
60
  #
20
- # @param value
21
- # value for the config parameter
61
+ # @param [Object] value Value for the config parameter
22
62
  #
23
- # @return [String] value that was set for the parameter
24
- def set_config(name, value)
25
- @config[name.to_sym] = value
63
+ # @param [Funciton] block Function which populates configuration for a sub-attribute
64
+ #
65
+ # @return [Object] If setting a attribute's value
66
+ # @return [Cliqr::CLI::OptionConfig] If adding a new option
67
+ def set_config(name, value, &block)
68
+ case name
69
+ when :option
70
+ handle_option value, &block # value is the long name for the option
71
+ else
72
+ handle_config name, value
73
+ end
74
+ end
75
+
76
+ private
77
+
78
+ # Set value for config option without evaluating a block
79
+ #
80
+ # @param [Symbol] name Name of the config option
81
+ # @param [Object] value Value for the config option
82
+ #
83
+ # @return [Object] Value that was assigned to attribute
84
+ def handle_config(name, value)
85
+ public_send("#{name}=", value)
86
+ value
87
+ end
88
+
89
+ # Add a new option for the command
90
+ #
91
+ # @param [Symbol] name Long name of the option
92
+ #
93
+ # @param [Function] block Populate the option's config in this funciton block
94
+ #
95
+ # @return [Cliqr::CLI::OptionConfig] Newly created option's config
96
+ def handle_option(name, &block)
97
+ option_config = OptionConfig.build(&block)
98
+ option_config.name = name
99
+ @options = [] if @options == UNSET
100
+ @options.push option_config
101
+ option_config
102
+ end
103
+ end
104
+
105
+ # Config attributes for a command's option
106
+ #
107
+ # @api private
108
+ class OptionConfig
109
+ extend Cliqr::DSL
110
+
111
+ # Long option name
112
+ #
113
+ # @return [String]
114
+ attr_accessor :name
115
+
116
+ # Optional short name for the option
117
+ #
118
+ # @return [String]
119
+ attr_accessor :short
120
+
121
+ # A description string for the option
122
+ #
123
+ # @return [String]
124
+ attr_accessor :description
125
+
126
+ # Initialize a new config instance for an option with UNSET attribute values
127
+ def initialize
128
+ @name = UNSET
129
+ @short = UNSET
130
+ @description = UNSET
26
131
  end
27
132
 
28
- # Finalize config by adding default values for unset values.
133
+ # Finalize option's config by adding default values for unset values
29
134
  #
30
- # @return [Hash]
135
+ # @return [Cliqr::CLI::OptionConfig]
31
136
  def finalize
32
- {
33
- basename: ''
34
- }.merge(@config)
35
- end
36
-
37
- # dsl methods
38
- dsl do
39
- # Set basename for the command line interface
40
- #
41
- # @param [String] basename
42
- # name of the top level command
43
- def basename(basename)
44
- set_config :basename, basename
45
- end
137
+ @name = '' if @name == UNSET
138
+ @short = '' if @short == UNSET
139
+ @description = '' if @description == UNSET
140
+
141
+ self
142
+ end
143
+
144
+ # Set value for command option's attribute
145
+ #
146
+ # @param [Symbol] name Name of the attribute
147
+ #
148
+ # @param [Object] value Value for the attribute
149
+ #
150
+ # @return [Object] Value that was set for the attribute
151
+ def set_config(name, value)
152
+ handle_option_config name, value
153
+ end
154
+
155
+ private
156
+
157
+ # Set value for config option without evaluating a block
158
+ #
159
+ # @param [Symbol] name Name of the config option
160
+ # @param [Object] value Value for the config option
161
+ #
162
+ # @return [Object]
163
+ def handle_option_config(name, value)
164
+ public_send("#{name}=", value)
165
+ value
46
166
  end
47
167
  end
48
168
  end
@@ -0,0 +1,51 @@
1
+ # encoding: utf-8
2
+
3
+ require 'cliqr/error'
4
+
5
+ require 'cliqr/cli/router'
6
+ require 'cliqr/cli/command_runner_factory'
7
+
8
+ module Cliqr
9
+ module CLI
10
+ # A CLI interface instance which is the entry point for all CLI commands.
11
+ #
12
+ # @api private
13
+ class Interface
14
+ # Create a new interface instance with a config
15
+ #
16
+ # @param [Cliqr::CLI::Config] config Config used to create this interface
17
+ def initialize(config)
18
+ @config = config
19
+ end
20
+
21
+ # Get usage information of this command line interface instance
22
+ #
23
+ # @return [String] Defines usage of this interface
24
+ def usage
25
+ template_file_path = File.expand_path('../../../../templates/usage.erb', __FILE__)
26
+ template = ERB.new(File.new(template_file_path).read, nil, '%')
27
+ result = template.result(@config.instance_eval { binding })
28
+
29
+ # remove multiple newlines from the end of usage
30
+ "#{result.strip}\n"
31
+ end
32
+
33
+ # Execute a command
34
+ #
35
+ # @param [Symbol] output Either :default or :buffer
36
+ #
37
+ # @return [Integer] Exit code of the command execution
38
+ def execute(output: :default)
39
+ handler = @config.handler.new
40
+ begin
41
+ runner = CommandRunnerFactory.get(output: output)
42
+ runner.run do
43
+ handler.execute
44
+ end
45
+ rescue StandardError => e
46
+ raise Cliqr::Error::CommandRuntimeException.new "command '#{@config.basename}' failed", e
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,11 @@
1
+ # encoding: utf-8
2
+
3
+ module Cliqr
4
+ module CLI
5
+ # Used for routing the command to the appropriate command handler based on the interface config
6
+ #
7
+ # @api private
8
+ class Router
9
+ end
10
+ end
11
+ end
@@ -5,9 +5,26 @@ require 'cliqr/error'
5
5
  module Cliqr
6
6
  module CLI
7
7
  # Validator for the command line interface configuration
8
+ #
9
+ # @api private
8
10
  class Validator
11
+ # Validates the config to make sure all the options are correctly set
12
+ #
13
+ # @param [Cliqr::CLI::Config] config Settings for building command line interface
14
+ #
15
+ # @return [Cliqr::CLI::Config] Validated config object
9
16
  def self.validate(config)
10
17
  fail Cliqr::Error::ConfigNotFound, 'config is nil' if config.nil?
18
+ fail Cliqr::Error::BasenameNotDefined, 'basename is not defined' if config.basename.empty?
19
+
20
+ fail Cliqr::Error::HandlerNotDefined, 'command handler not defined' if config.handler.nil?
21
+ fail Cliqr::Error::InvalidCommandHandler,
22
+ 'command handler must extend from Cliqr::CLI::Command' unless config.handler < Command
23
+
24
+ fail Cliqr::Error::OptionsNotDefinedException,
25
+ 'options cannot be nil' if config.options.nil?
26
+
27
+ config
11
28
  end
12
29
  end
13
30
  end
data/lib/cliqr/dsl.rb CHANGED
@@ -6,56 +6,54 @@ module Cliqr
6
6
  # Used to separate all dsl methods in a separate block, thus allowing
7
7
  # separation of concerns between non-dsl methods with dsl methods which
8
8
  # improves maintainability.
9
+ #
10
+ # @api private
9
11
  module DSL
10
12
  # Entry point for invoking dsl methods
11
13
  #
12
- # @param args Arguments to be used to build the DSL instance
14
+ # @param [Hash] args Arguments to be used to build the DSL instance
13
15
  #
14
- # @param block The block to evaluate the DSL
16
+ # @param [Function] block The block to evaluate the DSL
15
17
  #
16
18
  # @return [Cliqr::DSL]
17
19
  def build(*args, &block)
18
20
  base = new(*args)
19
21
  if block_given?
20
- delegator_klass = const_get('DSLDelegator')
21
- delegator = delegator_klass.new(base)
22
+ delegator = DSLDelegator.new(base)
22
23
  delegator.instance_eval(&block)
23
24
  end
24
25
  base.finalize
26
+ base
25
27
  end
26
28
 
27
29
  # Delegates all DSL methods to the base class. Can be used to keep DSL
28
- # methods separate from non-dsl methods.
29
- #
30
- # @param block Block containing all dsl methods
31
- #
32
- # Allows separating dsl methods as:
30
+ # methods separate from non-dsl methods. All implementing subclasses will
31
+ # have to implement a set_config method as described below
33
32
  #
34
33
  # class MyDSLClass
35
34
  # extends Cliqr::DSL
36
35
  #
37
- # def set_value(value)
38
- # @value = value
39
- # end
40
- #
41
- # # ... other non-dsl methods ...
42
- #
43
- # dsl do
44
- # def value(value)
45
- # set_value value
46
- # end
36
+ # def set_config(name, value, &block)
37
+ # # handle config value for attribute "name"
47
38
  # end
48
- #
49
39
  # end
50
40
  #
51
41
  # This will be invoked as:
52
42
  #
53
- # MyDSLClass.build do
54
- # value 'some-value'
55
- # end
56
- def dsl(&block)
57
- delegator_klass = Class.new(SimpleDelegator, &block)
58
- const_set('DSLDelegator', delegator_klass)
43
+ # MyDSLClass.build do
44
+ # attribute 'some-value'
45
+ # end
46
+ class DSLDelegator < SimpleDelegator
47
+ # All dsl methods are handled dynamically by proxying through #set_config
48
+ #
49
+ # @param [Symbol] name Name of the method
50
+ # @param [Array] args Method arguments
51
+ # @param [Function] block A function to evaluate in the context of the method's arguments
52
+ #
53
+ # @return [Object] The return value of the proxied method
54
+ def method_missing(name, *args, &block)
55
+ __getobj__.set_config name, args[0], &block
56
+ end
59
57
  end
60
58
  end
61
59
  end
data/lib/cliqr/error.rb CHANGED
@@ -2,6 +2,41 @@
2
2
 
3
3
  module Cliqr
4
4
  module Error
5
+ # Base error class that others error types extend from
6
+ #
7
+ # @api private
8
+ class CliqrError < StandardError
9
+ # Set up the error to wrap another error's trace
10
+ def initialize(error_message, e = nil)
11
+ super e
12
+
13
+ # Preserve the original exception's data if provided
14
+ return unless e && e.is_a?(Exception)
15
+
16
+ set_backtrace e.backtrace
17
+ message.prepend "#{error_message}\n\nCause:\n#{e.class}: "
18
+ end
19
+ end
20
+
21
+ # Raised when the config parameter is nil
5
22
  class ConfigNotFound < StandardError; end
23
+
24
+ # Raised when basename is not defined
25
+ class BasenameNotDefined < StandardError; end
26
+
27
+ # Raised when a command handler is not defined
28
+ class HandlerNotDefined < StandardError; end
29
+
30
+ # Raised if command handler does not extend from Cliqr::CLI::Command
31
+ class InvalidCommandHandler < StandardError; end
32
+
33
+ # Encapsulates the error that gets thrown during a command execution
34
+ class CommandRuntimeException < CliqrError; end
35
+
36
+ # Error to signify that a command's runner is not available
37
+ class UnknownCommandRunnerException < CliqrError; end
38
+
39
+ # Raised if config's option array is nil
40
+ class OptionsNotDefinedException < CliqrError; end
6
41
  end
7
42
  end
data/lib/cliqr/version.rb CHANGED
@@ -2,5 +2,5 @@
2
2
 
3
3
  # Versioned gem
4
4
  module Cliqr
5
- VERSION = '0.0.3'
5
+ VERSION = '0.0.4'
6
6
  end
@@ -0,0 +1,14 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Cliqr::CLI::Config do
6
+ it 'sets proper defaults for unset values' do
7
+ config = Cliqr::CLI::Config.new
8
+ config.finalize
9
+ expect(config.basename).to eq('')
10
+ expect(config.description).to eq('')
11
+ expect(config.handler).to eq(nil)
12
+ expect(config.options).to eq([])
13
+ end
14
+ end
@@ -0,0 +1,40 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Cliqr::CLI::Validator do
6
+ it 'does not allow empty config' do
7
+ expect { Cliqr::CLI::Builder.new(nil).build }.to raise_error(Cliqr::Error::ConfigNotFound)
8
+ end
9
+
10
+ it 'does not allow empty basename' do
11
+ config = Cliqr::CLI::Config.new
12
+ config.basename = ''
13
+ config.finalize
14
+ expect { Cliqr::CLI::Builder.new(config).build }.to raise_error(Cliqr::Error::BasenameNotDefined)
15
+ end
16
+
17
+ it 'does not allow command handler to be null' do
18
+ config = Cliqr::CLI::Config.new
19
+ config.basename = 'my-command'
20
+ config.finalize
21
+ expect { Cliqr::CLI::Builder.new(config).build }.to raise_error(Cliqr::Error::HandlerNotDefined)
22
+ end
23
+
24
+ it 'only accepts command handler that extend from Cliqr::CLI::Command' do
25
+ config = Cliqr::CLI::Config.new
26
+ config.basename = 'my-command'
27
+ config.handler = Object
28
+ config.finalize
29
+ expect { Cliqr::CLI::Builder.new(config).build }.to raise_error(Cliqr::Error::InvalidCommandHandler)
30
+ end
31
+
32
+ it 'expects that config options should not be nil' do
33
+ config = Cliqr::CLI::Config.new
34
+ config.basename = 'my-command'
35
+ config.handler = TestCommand
36
+ config.options = nil
37
+ config.finalize
38
+ expect { Cliqr::CLI::Builder.new(config).build }.to raise_error(Cliqr::Error::OptionsNotDefinedException)
39
+ end
40
+ end
@@ -2,14 +2,80 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- describe Cliqr do
5
+ require 'executor/fixtures/test_command'
6
+
7
+ describe Cliqr::CLI::Interface do
6
8
  it 'builds a base command with name' do
7
9
  cli = Cliqr.interface do
8
- basename 'tinbox'
10
+ basename 'my-command'
11
+ description 'a command used to test cliqr'
12
+ handler TestCommand
13
+ end
14
+
15
+ expect(cli.usage).to eq <<-EOS
16
+ my-command -- a command used to test cliqr
17
+
18
+ USAGE:
19
+ my-command
20
+ EOS
21
+ end
22
+
23
+ it 'only makes basename and handler to be required' do
24
+ cli = Cliqr.interface do
25
+ basename 'my-command'
26
+ handler TestCommand
9
27
  end
10
28
 
11
29
  expect(cli.usage).to eq <<-EOS
12
- USAGE: tinbox
30
+ my-command
31
+
32
+ USAGE:
33
+ my-command
13
34
  EOS
14
35
  end
36
+
37
+ it 'allows options for a command' do
38
+ cli = Cliqr.interface do
39
+ basename 'my-command'
40
+ description 'a command used to test cliqr'
41
+ handler TestCommand
42
+
43
+ option 'option-1' do
44
+ short 'p'
45
+ description 'a nice option to have'
46
+ end
47
+ end
48
+
49
+ expect(cli.usage).to eq <<-EOS
50
+ my-command -- a command used to test cliqr
51
+
52
+ USAGE:
53
+ my-command [options]
54
+
55
+ Available options:
56
+
57
+ --option-1, -p : a nice option to have
58
+ EOS
59
+ end
60
+
61
+ it 'allows command options to optionally have description and short name' do
62
+ cli = Cliqr.interface do
63
+ basename 'my-command'
64
+ description 'a command used to test cliqr'
65
+ handler TestCommand
66
+
67
+ option 'option-1'
68
+ end
69
+
70
+ expect(cli.usage).to eq <<-EOS
71
+ my-command -- a command used to test cliqr
72
+
73
+ USAGE:
74
+ my-command [options]
75
+
76
+ Available options:
77
+
78
+ --option-1
79
+ EOS
80
+ end
15
81
  end
@@ -0,0 +1,25 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Cliqr::CLI::CommandRunnerFactory do
6
+ it 'returns standard runner for default output' do
7
+ runner = Cliqr::CLI::CommandRunnerFactory.get(output: :default)
8
+ expect(runner).to be_kind_of(Cliqr::CLI::StandardCommandRunner)
9
+ end
10
+
11
+ it 'returns buffered runner for buffer output' do
12
+ runner = Cliqr::CLI::CommandRunnerFactory.get(output: :buffer)
13
+ expect(runner).to be_kind_of(Cliqr::CLI::BufferedCommandRunner)
14
+ end
15
+
16
+ it 'throws error for default output type' do
17
+ expect { Cliqr::CLI::CommandRunnerFactory.get(output: :unknown) }.to(
18
+ raise_error(be_kind_of(Cliqr::Error::UnknownCommandRunnerException))
19
+ )
20
+ end
21
+
22
+ it 'returns code 0 for default command runner' do
23
+ expect(Cliqr.command.new.execute).to eq(0)
24
+ end
25
+ end
@@ -0,0 +1,8 @@
1
+ # encoding: utf-8
2
+
3
+ # A command that always throws an error
4
+ class AlwaysErrorCommand < Cliqr.command
5
+ def execute
6
+ fail StandardError, 'I always throw an error'
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ # encoding: utf-8
2
+
3
+ # Test command for the router_spec
4
+ class TestCommand < Cliqr.command
5
+ def execute
6
+ puts 'test command executed'
7
+ end
8
+ end
@@ -0,0 +1,25 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ require 'executor/fixtures/test_command'
6
+ require 'executor/fixtures/always_error_command'
7
+
8
+ describe Cliqr::CLI::Router do
9
+ it 'routes base command with no arguments' do
10
+ cli = Cliqr.interface do
11
+ basename 'my-command'
12
+ handler TestCommand
13
+ end
14
+ result = cli.execute output: :buffer
15
+ expect(result[:stdout]).to eq "test command executed\n"
16
+ end
17
+
18
+ it 'handles error appropriately' do
19
+ cli = Cliqr.interface do
20
+ basename 'my-command'
21
+ handler AlwaysErrorCommand
22
+ end
23
+ expect { cli.execute }.to raise_error(Cliqr::Error::CommandRuntimeException)
24
+ end
25
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cliqr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anshul Verma
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-05-09 00:00:00.000000000 Z
11
+ date: 2015-05-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: log4r
@@ -56,13 +56,22 @@ files:
56
56
  - Rakefile
57
57
  - lib/cliqr.rb
58
58
  - lib/cliqr/cli/builder.rb
59
+ - lib/cliqr/cli/command.rb
60
+ - lib/cliqr/cli/command_runner_factory.rb
59
61
  - lib/cliqr/cli/config.rb
62
+ - lib/cliqr/cli/interface.rb
63
+ - lib/cliqr/cli/router.rb
60
64
  - lib/cliqr/cli/validator.rb
61
65
  - lib/cliqr/dsl.rb
62
66
  - lib/cliqr/error.rb
63
67
  - lib/cliqr/version.rb
64
- - spec/dsl/interface_builder_spec.rb
68
+ - spec/config/config_finalize_spec.rb
69
+ - spec/config/config_validator_spec.rb
65
70
  - spec/dsl/interface_spec.rb
71
+ - spec/executor/command_runner_spec.rb
72
+ - spec/executor/fixtures/always_error_command.rb
73
+ - spec/executor/fixtures/test_command.rb
74
+ - spec/executor/router_spec.rb
66
75
  - spec/spec_helper.rb
67
76
  homepage: https://github.com/anshulverma/cliqr
68
77
  licenses:
@@ -89,7 +98,12 @@ signing_key:
89
98
  specification_version: 4
90
99
  summary: A framework and DSL for defining CLI interface
91
100
  test_files:
92
- - spec/dsl/interface_builder_spec.rb
101
+ - spec/config/config_finalize_spec.rb
102
+ - spec/config/config_validator_spec.rb
93
103
  - spec/dsl/interface_spec.rb
104
+ - spec/executor/command_runner_spec.rb
105
+ - spec/executor/fixtures/always_error_command.rb
106
+ - spec/executor/fixtures/test_command.rb
107
+ - spec/executor/router_spec.rb
94
108
  - spec/spec_helper.rb
95
109
  has_rdoc:
@@ -1,9 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require 'spec_helper'
4
-
5
- describe Cliqr::CLI::Builder do
6
- it 'does not allow empty config' do
7
- expect { Cliqr::CLI::Builder.new(nil) }.to raise_error(Cliqr::Error::ConfigNotFound)
8
- end
9
- end