clue 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.travis.yml +11 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +32 -0
- data/LICENCE.md +7 -0
- data/README.md +79 -0
- data/Rakefile +15 -0
- data/clue.gemspec +21 -0
- data/lib/clue.rb +32 -0
- data/lib/clue/arguments.rb +41 -0
- data/lib/clue/cli.rb +50 -0
- data/lib/clue/options.rb +70 -0
- data/lib/clue/streams.rb +40 -0
- data/lib/clue/version.rb +3 -0
- data/spec/arguments_spec.rb +60 -0
- data/spec/cli_spec.rb +61 -0
- data/spec/options_spec.rb +71 -0
- data/spec/spec_helper.rb +17 -0
- data/spec/streams_spec.rb +46 -0
- metadata +103 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: adc1f6e8d6b476ddecc339386015e71bab4d4c0d
|
4
|
+
data.tar.gz: 2f5bd6a517174c7c8cc43d2e332b19b37810ca16
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 24232473b4740567d10ec39695048b28b4361d5842ecdb31e2228bdca093d51ef184621d2f43f43c2429f93960b5fa585f48aa9d3129d9759964cbe0ed16b239
|
7
|
+
data.tar.gz: dae14fdd4fe484416e2c5991428ebe8208d24cdcc65bf73b9ab86d333d886003f58493ff926e16c50fb3dbf47b80da5bb86560c72925a5563c81c867a211e5d7
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
clue (1.0.0)
|
5
|
+
activesupport
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
activesupport (3.2.13)
|
11
|
+
i18n (= 0.6.1)
|
12
|
+
multi_json (~> 1.0)
|
13
|
+
diff-lcs (1.2.1)
|
14
|
+
i18n (0.6.1)
|
15
|
+
multi_json (1.7.1)
|
16
|
+
rake (10.0.3)
|
17
|
+
rspec (2.13.0)
|
18
|
+
rspec-core (~> 2.13.0)
|
19
|
+
rspec-expectations (~> 2.13.0)
|
20
|
+
rspec-mocks (~> 2.13.0)
|
21
|
+
rspec-core (2.13.0)
|
22
|
+
rspec-expectations (2.13.0)
|
23
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
24
|
+
rspec-mocks (2.13.0)
|
25
|
+
|
26
|
+
PLATFORMS
|
27
|
+
ruby
|
28
|
+
|
29
|
+
DEPENDENCIES
|
30
|
+
clue!
|
31
|
+
rake
|
32
|
+
rspec
|
data/LICENCE.md
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
Copyright (c) 2013 Novelys
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
4
|
+
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
6
|
+
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
# Clue
|
2
|
+
|
3
|
+
Clue is an oriented-object wrapper around command line utilities.
|
4
|
+
It allows you to execute complex shell commands without the harass of building the string manually.
|
5
|
+
The use-case in mind when creating this gem was rake tasks/capistrano recipes involving third party tools.
|
6
|
+
|
7
|
+
## Prerequisites
|
8
|
+
|
9
|
+
This gem depends only on activesupport. It is tested agains many rubies: 1.8.7, 1.9.3, 2.0.0, jruby-18, jruby-19, rubinius-18, rubinius-19, thanks to travis-ci.
|
10
|
+
|
11
|
+
While it is tested against Ruby 1.8, we do not garanty support in future releases, as it is approaching end of life.
|
12
|
+
|
13
|
+
## Installation
|
14
|
+
|
15
|
+
Directly : `gem install clue`
|
16
|
+
|
17
|
+
Gemfile : `gem 'clue'`
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
There is only one class, `Clue`. First, instantiate the object, then invoke `call` without arguments on it. In most cases, the only difference of usage will be the options passed to the constructor, though you can set them later.
|
22
|
+
|
23
|
+
### Example
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
clue = Clue.new 'mytool', :options => [:drop, {:depth => 1}], :arguments => '~/.hidden', :stdout => '~/not_hidden'
|
27
|
+
clue.call
|
28
|
+
|
29
|
+
# Will execute:
|
30
|
+
# mytool --depth '1' --drop ~/.hidden > '~/not_hidden'
|
31
|
+
```
|
32
|
+
|
33
|
+
### Command name
|
34
|
+
|
35
|
+
The command name can be supplied when initializing the object, as done above, or at a later point, by setting `command` to some value.
|
36
|
+
Calling `call` will raise an exception if `command` is not present.
|
37
|
+
|
38
|
+
### Options
|
39
|
+
|
40
|
+
`Clue` accepts options when initializing, as in `clue = Clue.new(options: [:first, :second, {third: :value}])`.
|
41
|
+
|
42
|
+
You must supply "singular" (options without value) first, and "valued" options as a trailing hash, as shown above.
|
43
|
+
You can add options at a later point use `add_singular_option`, `add_singular_options`, `add_option`, and `add_options`.
|
44
|
+
|
45
|
+
### Arguments
|
46
|
+
|
47
|
+
`Clue` accepts arguments when initializing, as in `clue = Clue.new(arguments: 'path/to/file')`.
|
48
|
+
While in most of the case a single argument will be passed, you can pass an array as well.
|
49
|
+
|
50
|
+
### Streams
|
51
|
+
|
52
|
+
`Clue` handles `stdin`, `stdout`, and `stderr` when initializing, as in `clue = Clue.new(stdout: 'path/to/file')`. Only strings will be recognized.
|
53
|
+
|
54
|
+
### Verbose/dry-run
|
55
|
+
|
56
|
+
Clue can run in `verbose` or `dry_run` mode. The first prints the command before running, the latter only prints it.
|
57
|
+
You can activate those modes when initializing, by supplying `verbose: true` or `dry_run: true`, or by setting the values at a later point.
|
58
|
+
Both of them are false by default.
|
59
|
+
|
60
|
+
### Hooks
|
61
|
+
|
62
|
+
There is two type of hooks, running at two points: `before`/`after` `initialize`/`call`. They allow you to print extra data or to execute specific manipulation when subclassing `Clue`.
|
63
|
+
|
64
|
+
One use case is in `novelys/gomon`, where `after_initialize` is used to parse & split the `uri` option, and `before/after_call` are used to inform of what is happening.
|
65
|
+
|
66
|
+
## Validations
|
67
|
+
|
68
|
+
There is no mecanisme built-in for validating the presence/format of arguments, as we feel there is not a great need for it. However, if you come with an elegant and tested solution, we'll consider merging it.
|
69
|
+
|
70
|
+
## Contributions
|
71
|
+
|
72
|
+
1. Check for open issues or open a fresh issue to start a discussion around a feature idea or a bug. In the first case, please include a use-case.
|
73
|
+
2. Fork the repository on Github, make a feature branch, work on this branch.
|
74
|
+
3. If necessary, write a test which shows that the bug was fixed or that the feature works as expected.
|
75
|
+
4. Send a pull request and annoy us until we notice it. :)
|
76
|
+
|
77
|
+
## Changelog
|
78
|
+
|
79
|
+
* `1.0.0`: First version.
|
data/Rakefile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'rake'
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'bundler/setup'
|
5
|
+
Bundler::GemHelper.install_tasks
|
6
|
+
rescue LoadError
|
7
|
+
puts 'although not required, bundler is recommened for running the tests'
|
8
|
+
end
|
9
|
+
|
10
|
+
task :default => :spec
|
11
|
+
|
12
|
+
require 'rspec/core/rake_task'
|
13
|
+
RSpec::Core::RakeTask.new do |t|
|
14
|
+
t.rspec_opts = ["--color", '--format doc']
|
15
|
+
end
|
data/clue.gemspec
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
$:.unshift File.expand_path('../lib', __FILE__)
|
2
|
+
require 'clue/version'
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "clue"
|
6
|
+
s.version = Clue::VERSION
|
7
|
+
s.platform = Gem::Platform::RUBY
|
8
|
+
s.authors = ["Kevin Soltysiak"]
|
9
|
+
s.email = ["contact@novelys.com"]
|
10
|
+
s.homepage = "http://github.com/novelys/clue"
|
11
|
+
s.summary = "Ruby OO Layer around cli tools"
|
12
|
+
s.description = "Ease up interactions with CLI tools by wrapping them in objects"
|
13
|
+
s.rubyforge_project = s.name
|
14
|
+
s.required_rubygems_version = ">= 1.3.6"
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.require_path = 'lib'
|
17
|
+
|
18
|
+
s.add_dependency('activesupport')
|
19
|
+
s.add_development_dependency('rake')
|
20
|
+
s.add_development_dependency('rspec')
|
21
|
+
end
|
data/lib/clue.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
class Clue; end
|
2
|
+
|
3
|
+
require 'clue/arguments'
|
4
|
+
require 'clue/cli'
|
5
|
+
require 'clue/options'
|
6
|
+
require 'clue/streams'
|
7
|
+
require 'clue/version'
|
8
|
+
|
9
|
+
class Clue
|
10
|
+
include Arguments
|
11
|
+
include CLI
|
12
|
+
include Options
|
13
|
+
include Streams
|
14
|
+
|
15
|
+
# Store command name, parse & store args
|
16
|
+
def initialize(*args)
|
17
|
+
hsh = args.last.kind_of?(Hash) && args.pop || {}
|
18
|
+
raise ArgumentError, 'there should be at most one command' unless args.size <= 1
|
19
|
+
self.command = args.pop
|
20
|
+
|
21
|
+
before_initialize(command, hsh) if self.respond_to?(:before_initialize)
|
22
|
+
|
23
|
+
self.verbose = hsh.delete(:verbose)
|
24
|
+
self.dry_run = hsh.delete(:dry_run)
|
25
|
+
|
26
|
+
init_options hsh[:options]
|
27
|
+
init_arguments hsh[:arguments]
|
28
|
+
init_streams hsh
|
29
|
+
|
30
|
+
after_initialize(command, hsh) if self.respond_to?(:after_initialize)
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Clue::Arguments
|
2
|
+
attr_reader :arguments
|
3
|
+
|
4
|
+
# Initialize arguments ivars
|
5
|
+
def init_arguments(args = nil)
|
6
|
+
@arguments = []
|
7
|
+
|
8
|
+
parse_arguments(args)
|
9
|
+
end
|
10
|
+
|
11
|
+
# Parse "classic" arguments
|
12
|
+
def parse_arguments(value = [])
|
13
|
+
return unless value
|
14
|
+
|
15
|
+
if value.kind_of?(String) || value.kind_of?(Symbol)
|
16
|
+
value = [value]
|
17
|
+
end
|
18
|
+
|
19
|
+
@arguments = value
|
20
|
+
end
|
21
|
+
|
22
|
+
# Add one argument
|
23
|
+
def add_argument(arg)
|
24
|
+
@arguments << arg
|
25
|
+
@arguments.uniq!
|
26
|
+
end
|
27
|
+
|
28
|
+
# Add many arguemnts
|
29
|
+
def add_arguments(args)
|
30
|
+
return unless args
|
31
|
+
args = args.split(' ') if args.is_a?(String)
|
32
|
+
|
33
|
+
@arguments += args.map(&:to_s)
|
34
|
+
@arguments.uniq!
|
35
|
+
end
|
36
|
+
|
37
|
+
# Returns a string or arguments suitable for cli use
|
38
|
+
def cli_arguments
|
39
|
+
@arguments.join(' ')
|
40
|
+
end
|
41
|
+
end
|
data/lib/clue/cli.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'active_support/core_ext/enumerable'
|
2
|
+
|
3
|
+
module Clue::CLI
|
4
|
+
attr_accessor :command
|
5
|
+
|
6
|
+
# Verbose, dry run readers & aliases
|
7
|
+
attr_reader :verbose, :dry_run
|
8
|
+
|
9
|
+
alias :dry_run? :dry_run
|
10
|
+
alias :verbose? :verbose
|
11
|
+
|
12
|
+
# Set the tool as verbose
|
13
|
+
def verbose=(input)
|
14
|
+
@verbose = !!input
|
15
|
+
end
|
16
|
+
|
17
|
+
# Set the tool as dry running
|
18
|
+
def dry_run=(input)
|
19
|
+
@dry_run = !!input
|
20
|
+
end
|
21
|
+
|
22
|
+
# Command as an array
|
23
|
+
def cli_command_array
|
24
|
+
[@command, cli_options, cli_arguments, cli_streams].each_with_object([]) do |string, memo|
|
25
|
+
memo << string if string && string != ''
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Command as a string
|
30
|
+
def cli_command
|
31
|
+
cli_command_array.join(' ')
|
32
|
+
end
|
33
|
+
|
34
|
+
# Print command
|
35
|
+
def print
|
36
|
+
puts cli_command
|
37
|
+
end
|
38
|
+
|
39
|
+
# Print and/or execute command
|
40
|
+
def call
|
41
|
+
raise ArgumentError, 'a command is expected' unless @command
|
42
|
+
|
43
|
+
before_call if self.respond_to?(:before_call)
|
44
|
+
|
45
|
+
print if dry_run? || verbose?
|
46
|
+
system(cli_command) unless dry_run?
|
47
|
+
|
48
|
+
after_call if self.respond_to?(:after_call)
|
49
|
+
end
|
50
|
+
end
|
data/lib/clue/options.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'active_support/core_ext/enumerable'
|
2
|
+
|
3
|
+
module Clue::Options
|
4
|
+
attr_reader :options, :singular_options
|
5
|
+
|
6
|
+
# Initialize options ivars
|
7
|
+
def init_options(options = nil)
|
8
|
+
@options = {}
|
9
|
+
@singular_options = []
|
10
|
+
|
11
|
+
parse_options(options) if options
|
12
|
+
end
|
13
|
+
|
14
|
+
# Separate simple options from valued ones.
|
15
|
+
def parse_options(options)
|
16
|
+
if options.kind_of?(Hash)
|
17
|
+
@options = options
|
18
|
+
elsif options.kind_of?(Array)
|
19
|
+
@singular_options = options
|
20
|
+
@options = @singular_options.pop if @singular_options.last.kind_of?(Hash)
|
21
|
+
elsif options.kind_of?(String) || options.kind_of?(Symbol)
|
22
|
+
@singular_options = [options.to_sym]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Add a singular option
|
27
|
+
def add_singular_option(option)
|
28
|
+
@singular_options << option.to_s
|
29
|
+
@singular_options.uniq!
|
30
|
+
end
|
31
|
+
|
32
|
+
# Add many singular options
|
33
|
+
def add_singular_options(options)
|
34
|
+
return unless options
|
35
|
+
options = options.split(' ') if options.is_a?(String)
|
36
|
+
|
37
|
+
@singular_options += options.map(&:to_s)
|
38
|
+
@singular_options.uniq!
|
39
|
+
end
|
40
|
+
|
41
|
+
# Add a single options
|
42
|
+
def add_option(key, value)
|
43
|
+
@options[key.to_sym] = value.to_s
|
44
|
+
end
|
45
|
+
|
46
|
+
# Add many options
|
47
|
+
def add_options(opts = {})
|
48
|
+
opts.each { |key, value| add_option key, value }
|
49
|
+
end
|
50
|
+
|
51
|
+
# Returns the options string
|
52
|
+
def cli_options
|
53
|
+
options_as_array.join(' ')
|
54
|
+
end
|
55
|
+
|
56
|
+
# Returns options as an array
|
57
|
+
def options_as_array
|
58
|
+
# Valued options
|
59
|
+
ary = @options.each_with_object([]) do |(key, value), memo|
|
60
|
+
memo << "--#{key.to_s} '#{value.to_s}'"
|
61
|
+
end
|
62
|
+
|
63
|
+
# Singular options
|
64
|
+
ary = @singular_options.each_with_object(ary) do |opt, memo|
|
65
|
+
memo << "--#{opt.to_s}"
|
66
|
+
end
|
67
|
+
|
68
|
+
ary
|
69
|
+
end
|
70
|
+
end
|
data/lib/clue/streams.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'active_support/core_ext/enumerable'
|
2
|
+
require 'active_support/core_ext/hash/slice'
|
3
|
+
|
4
|
+
module Clue::Streams
|
5
|
+
STREAMS_SYMBOLS = {
|
6
|
+
:stdin => '<',
|
7
|
+
:stdout => '>',
|
8
|
+
:stderr => '2>'
|
9
|
+
}
|
10
|
+
RECOGNIZED_STREAMS = STREAMS_SYMBOLS.keys
|
11
|
+
|
12
|
+
attr_reader :stdin, :stdout, :stderr
|
13
|
+
|
14
|
+
# Initialize streams ivars
|
15
|
+
def init_streams(args = nil)
|
16
|
+
set_streams(args.slice(*RECOGNIZED_STREAMS)) if args
|
17
|
+
end
|
18
|
+
|
19
|
+
# set a stream
|
20
|
+
def set_stream(stream, value)
|
21
|
+
instance_variable_set "@#{stream.to_s}", value
|
22
|
+
end
|
23
|
+
|
24
|
+
# Add many arguemnts
|
25
|
+
def set_streams(streams)
|
26
|
+
return unless streams && streams.kind_of?(Hash)
|
27
|
+
|
28
|
+
streams.each { |stream, value| set_stream stream, value }
|
29
|
+
end
|
30
|
+
|
31
|
+
# Returns a string of streams suitable for cli use
|
32
|
+
def cli_streams
|
33
|
+
ary = STREAMS_SYMBOLS.each_with_object([]) do |(key, value), memo|
|
34
|
+
ivar = instance_variable_get "@#{key}"
|
35
|
+
memo << "#{value} '#{ivar}'" if ivar
|
36
|
+
end
|
37
|
+
|
38
|
+
ary.join(' ')
|
39
|
+
end
|
40
|
+
end
|
data/lib/clue/version.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'clue'
|
2
|
+
|
3
|
+
describe "Arguments" do
|
4
|
+
subject { Clue.new 'commandname'}
|
5
|
+
let(:arguments) { subject.instance_variable_get :@arguments }
|
6
|
+
|
7
|
+
it 'should add one argument' do
|
8
|
+
subject.add_argument 'value'
|
9
|
+
expect(arguments).to include 'value'
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should add several arguments' do
|
13
|
+
subject.add_arguments 'rocky balboa'
|
14
|
+
expect(arguments).to include 'rocky', 'balboa'
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should add several arguments given as string' do
|
18
|
+
subject.add_arguments 'rocky balboa'
|
19
|
+
expect(arguments).to include 'rocky', 'balboa'
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should add several arguments given as array' do
|
23
|
+
subject.add_arguments ['rocky', 'balboa']
|
24
|
+
expect(arguments).to include 'rocky', 'balboa'
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should not add many times the same argument' do
|
28
|
+
subject.add_arguments ['rocky', 'rocky']
|
29
|
+
expect(arguments).to include 'rocky'
|
30
|
+
expect(arguments.size).to eq 1
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'can merge arguments into a string' do
|
34
|
+
subject.add_arguments %w(john jim jones)
|
35
|
+
|
36
|
+
expect(subject.cli_arguments).to include "john"
|
37
|
+
expect(subject.cli_arguments).to include "jim"
|
38
|
+
expect(subject.cli_arguments).to include "jones"
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should recognize one argument given during initialization' do
|
42
|
+
clue = Clue.new 'commandname', :arguments => 'john'
|
43
|
+
args = clue.instance_variable_get :@arguments
|
44
|
+
expect(args).to include 'john'
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should recognize many arguments given during initialization' do
|
48
|
+
clue = Clue.new 'commandname', :arguments => ['john', 'mcclane']
|
49
|
+
args = clue.instance_variable_get :@arguments
|
50
|
+
expect(args).to include 'john'
|
51
|
+
expect(args).to include 'mcclane'
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'can merge arguments into a string' do
|
55
|
+
subject.add_arguments %w(john jim)
|
56
|
+
|
57
|
+
expect(subject.cli_arguments).to include "john"
|
58
|
+
expect(subject.cli_arguments).to include "jim"
|
59
|
+
end
|
60
|
+
end
|
data/spec/cli_spec.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'clue'
|
2
|
+
|
3
|
+
describe "CLI" do
|
4
|
+
subject { Clue.new 'commandname'}
|
5
|
+
|
6
|
+
it 'should not raise an error when given one argument or none' do
|
7
|
+
p = Proc.new { Clue.new 'john' }
|
8
|
+
expect(p).not_to raise_error
|
9
|
+
|
10
|
+
p = Proc.new { Clue.new }
|
11
|
+
expect(p).not_to raise_error
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should raise an error when more than one argument' do
|
15
|
+
p = Proc.new { Clue.new 'john', 'doe' }
|
16
|
+
expect(p).to raise_error ArgumentError
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should accept options' do
|
20
|
+
p = Proc.new { Clue.new 'john', :wayne => 'lala' }
|
21
|
+
expect(p).not_to raise_error
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should recognize "verbose" option' do
|
25
|
+
c = Clue.new 'john', :verbose => true
|
26
|
+
expect(c.verbose).to be_true
|
27
|
+
|
28
|
+
c = Clue.new 'john', :verbose => 'something truthy'
|
29
|
+
expect(c.verbose).to be_true
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'should not be "verbose" by default' do
|
33
|
+
c = Clue.new 'john'
|
34
|
+
expect(c.verbose).to be_false
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should recognize "dry run" option' do
|
38
|
+
c = Clue.new 'john', :dry_run => true
|
39
|
+
expect(c.dry_run).to be_true
|
40
|
+
|
41
|
+
c = Clue.new 'john', :dry_run => 'something truthy'
|
42
|
+
expect(c.dry_run).to be_true
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should not be a "dry run" by default' do
|
46
|
+
c = Clue.new 'john'
|
47
|
+
expect(c.dry_run).to be_false
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'should have a command string' do
|
51
|
+
clue = Clue.new 'commandname', :options => [:drop, {:depth => 1}], :arguments => '~/.hidden', :stdout => '~/not_hidden'
|
52
|
+
|
53
|
+
expect(clue.cli_command).to include clue.cli_options
|
54
|
+
expect(clue.cli_command).to include clue.cli_arguments
|
55
|
+
expect(clue.cli_command).to include clue.cli_streams
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'should raise an exception when called without a command name' do
|
59
|
+
expect(Clue.new).to raise_error ArgumentError
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'clue'
|
2
|
+
|
3
|
+
describe "Options" do
|
4
|
+
subject { Clue.new 'commandname'}
|
5
|
+
let(:options) { subject.instance_variable_get :@options }
|
6
|
+
let(:singular) { subject.instance_variable_get :@singular_options }
|
7
|
+
|
8
|
+
it 'should add one option' do
|
9
|
+
subject.add_option :key, 'value'
|
10
|
+
expect(options[:key]).to eq 'value'
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should add several options' do
|
14
|
+
subject.add_options :key1 => 'value1', :key2 => 'value2'
|
15
|
+
expect(options[:key1]).to eq 'value1'
|
16
|
+
expect(options[:key2]).to eq 'value2'
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should add options with symbols as keys' do
|
20
|
+
subject.add_options 'key' => 'value'
|
21
|
+
expect(options[:key]).to eq 'value'
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should add one singular option' do
|
25
|
+
subject.add_singular_option 'hank'
|
26
|
+
expect(singular).to include 'hank'
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should add several singular options given as string' do
|
30
|
+
subject.add_singular_options 'rocky balboa'
|
31
|
+
expect(singular).to include 'rocky', 'balboa'
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should add several singular options given as array' do
|
35
|
+
subject.add_singular_options ['rocky', 'balboa']
|
36
|
+
expect(singular).to include 'rocky', 'balboa'
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'can override previous keys' do
|
40
|
+
subject.add_option :key, 'value'
|
41
|
+
expect(options[:key]).to eq 'value'
|
42
|
+
subject.add_option :key, 'new_value'
|
43
|
+
expect(options[:key]).to eq 'new_value'
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should not add many times the same singular option' do
|
47
|
+
subject.add_singular_options ['rocky', 'rocky']
|
48
|
+
expect(singular).to include 'rocky'
|
49
|
+
expect(singular.size).to eq 1
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'can merge options into a string' do
|
53
|
+
subject.add_options :key1 => 'value1', :key2 => 'value2'
|
54
|
+
subject.add_singular_options %w(john jim jones)
|
55
|
+
|
56
|
+
expect(subject.cli_options).to include "--key1 'value1'"
|
57
|
+
expect(subject.cli_options).to include "--key2 'value2'"
|
58
|
+
expect(subject.cli_options).to include "--john"
|
59
|
+
expect(subject.cli_options).to include "--jim"
|
60
|
+
expect(subject.cli_options).to include "--jones"
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'should recognize options given during initialization' do
|
64
|
+
clue = Clue.new 'commandname', :options => ['john', 'mcclane', {:is => 'a killer'}]
|
65
|
+
opts = clue.instance_variable_get :@options
|
66
|
+
sing = clue.instance_variable_get :@singular_options
|
67
|
+
expect(opts[:is]).to eq 'a killer'
|
68
|
+
expect(sing).to include 'john'
|
69
|
+
expect(sing).to include 'mcclane'
|
70
|
+
end
|
71
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
2
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
3
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
4
|
+
# loaded once.
|
5
|
+
#
|
6
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
7
|
+
RSpec.configure do |config|
|
8
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
9
|
+
config.run_all_when_everything_filtered = true
|
10
|
+
config.filter_run :focus
|
11
|
+
|
12
|
+
# Run specs in random order to surface order dependencies. If you find an
|
13
|
+
# order dependency and want to debug it, you can fix the order by providing
|
14
|
+
# the seed, which is printed after each run.
|
15
|
+
# --seed 1234
|
16
|
+
config.order = 'random'
|
17
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'clue'
|
2
|
+
|
3
|
+
describe "Streams" do
|
4
|
+
subject { Clue.new 'commandname'}
|
5
|
+
|
6
|
+
let(:stdin) { subject.stdin }
|
7
|
+
let(:stdout) { subject.stdout }
|
8
|
+
let(:stderr) { subject.stderr }
|
9
|
+
|
10
|
+
it 'should set stdin' do
|
11
|
+
subject.set_stream :stdin, 'value'
|
12
|
+
expect(stdin).to eq 'value'
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should set stdout' do
|
16
|
+
subject.set_stream :stdout, 'value'
|
17
|
+
expect(stdout).to eq 'value'
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should set stderr' do
|
21
|
+
subject.set_stream :stderr, 'value'
|
22
|
+
expect(stderr).to eq 'value'
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should add several streams' do
|
26
|
+
subject.set_streams :stdin => 'value', :stdout => 'value2', :stderr => 'val3'
|
27
|
+
expect(stdin).to eq 'value'
|
28
|
+
expect(stdout).to eq 'value2'
|
29
|
+
expect(stderr).to eq 'val3'
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'should recognize streams given during initialization' do
|
33
|
+
clue = Clue.new 'commandname', :stdin => 'john', :stderr => 'james', :stdout => 'jim'
|
34
|
+
expect(clue.stdin).to eq 'john'
|
35
|
+
expect(clue.stdout).to eq 'jim'
|
36
|
+
expect(clue.stderr).to eq 'james'
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'can merge streams into a string' do
|
40
|
+
subject.set_streams :stdin => 'value', :stdout => 'value2', :stderr => 'val3'
|
41
|
+
|
42
|
+
expect(subject.cli_streams).to include "> 'value2'"
|
43
|
+
expect(subject.cli_streams).to include "< 'value'"
|
44
|
+
expect(subject.cli_streams).to include "2> 'val3'"
|
45
|
+
end
|
46
|
+
end
|
metadata
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: clue
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Kevin Soltysiak
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-04-03 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: Ease up interactions with CLI tools by wrapping them in objects
|
56
|
+
email:
|
57
|
+
- contact@novelys.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- .travis.yml
|
63
|
+
- Gemfile
|
64
|
+
- Gemfile.lock
|
65
|
+
- LICENCE.md
|
66
|
+
- README.md
|
67
|
+
- Rakefile
|
68
|
+
- clue.gemspec
|
69
|
+
- lib/clue.rb
|
70
|
+
- lib/clue/arguments.rb
|
71
|
+
- lib/clue/cli.rb
|
72
|
+
- lib/clue/options.rb
|
73
|
+
- lib/clue/streams.rb
|
74
|
+
- lib/clue/version.rb
|
75
|
+
- spec/arguments_spec.rb
|
76
|
+
- spec/cli_spec.rb
|
77
|
+
- spec/options_spec.rb
|
78
|
+
- spec/spec_helper.rb
|
79
|
+
- spec/streams_spec.rb
|
80
|
+
homepage: http://github.com/novelys/clue
|
81
|
+
licenses: []
|
82
|
+
metadata: {}
|
83
|
+
post_install_message:
|
84
|
+
rdoc_options: []
|
85
|
+
require_paths:
|
86
|
+
- lib
|
87
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - '>='
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '0'
|
92
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 1.3.6
|
97
|
+
requirements: []
|
98
|
+
rubyforge_project: clue
|
99
|
+
rubygems_version: 2.0.3
|
100
|
+
signing_key:
|
101
|
+
specification_version: 4
|
102
|
+
summary: Ruby OO Layer around cli tools
|
103
|
+
test_files: []
|