valet 0.0.7 → 0.0.8

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.
@@ -0,0 +1,32 @@
1
+ require 'valet/option/common'
2
+
3
+ module Valet
4
+ module Option
5
+ class Switch < Common
6
+ attr_reader :default, :value
7
+
8
+ def initialize(long_name)
9
+ super
10
+ @default = false
11
+ @value = @default
12
+ end
13
+
14
+ def default=(new_default)
15
+ @default = new_default ? true : false
16
+ @value = @default
17
+ end
18
+
19
+ def switch
20
+ @value = ! @value
21
+ end
22
+
23
+ def long_name_to_s
24
+ if default
25
+ "--no-#{long_name}".gsub(/_/, '-')
26
+ else
27
+ "--#{long_name}".gsub(/_/, '-')
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,31 @@
1
+ require 'set'
2
+
3
+ module Valet
4
+ class Options < Set
5
+ def [](name)
6
+ find_option(name)
7
+ end
8
+
9
+ def method_missing(method_name, *args, &block)
10
+ if (option = find_switch(method_name)) || (option = find_flag(method_name))
11
+ option.value
12
+ else
13
+ super
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def find_option(name)
20
+ self.find { |option| name == option.name }
21
+ end
22
+
23
+ def find_switch(name)
24
+ self.find { |option| name =~ /#{option.name}\?/ if option.switch? }
25
+ end
26
+
27
+ def find_flag(name)
28
+ self.find { |option| name == option.name if option.flag? }
29
+ end
30
+ end
31
+ end
data/lib/valet/version.rb CHANGED
@@ -2,7 +2,7 @@ module Valet
2
2
  module VERSION
3
3
  MAJOR = 0
4
4
  MINOR = 0
5
- BUILD = 7
5
+ BUILD = 8
6
6
  PRE = nil
7
7
 
8
8
  STRING = [MAJOR, MINOR, BUILD, PRE].compact.join('.')
data/spec/spec_helper.rb CHANGED
@@ -15,19 +15,15 @@ Dir[File.expand_path('spec/support/**/*.rb')].each { |file| require file }
15
15
  require 'valet'
16
16
  include Valet
17
17
 
18
- # Capture STDOUT and STDIN in new IO streams
19
- require 'stringio'
20
- $stdout = StringIO.new
21
- $stderr = StringIO.new
22
-
23
- # Reset ARGV to contain no arguments
24
- ARGV.clear
25
-
26
18
  # Configure RSpec
27
19
  RSpec.configure do |config|
20
+ # Ensure usage of RSpec's new expectation syntax
21
+ config.expect_with(:rspec) { |c| c.syntax = :expect }
22
+
23
+ # Metadata keys can be written as ":symbol" instead of "symbol: true"
28
24
  config.treat_symbols_as_metadata_keys_with_true_values = true
29
25
 
30
- # Use a :focus tag for running only specific example(s)
26
+ # Use a ":focus" tag for running only specific example(s)
31
27
  config.filter_run :focus
32
28
  config.run_all_when_everything_filtered = true
33
29
  end
@@ -0,0 +1,54 @@
1
+ shared_examples_for "a common option" do
2
+ subject(:opt) { described_class.new(:format) }
3
+
4
+ its(:long_name) { should be_a(Symbol) }
5
+ its(:short_name) { should be_nil }
6
+ its(:summary) { should be_nil }
7
+ its(:description) { should be_nil }
8
+
9
+ describe "#initialize" do
10
+ context "raises an OptionError" do
11
+ it "if the long name is not a symbol" do
12
+ expect { described_class.new('format') }.to raise_error(OptionError)
13
+ end
14
+
15
+ it "if the long name is only one character long" do
16
+ expect { described_class.new(:f) }.to raise_error(OptionError)
17
+ end
18
+ end
19
+ end
20
+
21
+ describe "attributes" do
22
+ it "can be given a short name" do
23
+ opt.short_name = :f
24
+ expect(opt.short_name).to be(:f)
25
+ end
26
+
27
+ it "can be given a summary" do
28
+ opt.summary = 'Specify a format (Markdown or Textile)'
29
+ expect(opt.summary).to eq('Specify a format (Markdown or Textile)')
30
+ end
31
+
32
+ it "can be given a description" do
33
+ opt.description = 'A longer option description...'
34
+ expect(opt.description).to eq('A longer option description...')
35
+ end
36
+
37
+ context "raises an OptionError" do
38
+ it "if the short name is not a symbol" do
39
+ expect { opt.short_name = 'f' }.to raise_error(OptionError)
40
+ end
41
+
42
+ it "if the short name is longer than one character" do
43
+ expect { opt.short_name = 'format' }.to raise_error(OptionError)
44
+ end
45
+ end
46
+ end
47
+
48
+ describe "#short_name_to_s" do
49
+ it "returns the short name's string representation" do
50
+ opt.short_name = :f
51
+ expect(opt.short_name_to_s).to eq('-f')
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,20 @@
1
+ require 'stringio'
2
+
3
+ RSpec.configure do |config|
4
+ # Clear all remaining arguments in ARGV to make it testable
5
+ config.before(:suite) { ARGV.clear }
6
+
7
+ # Reroute STDOUT, STDERR and STDIN to testable streams
8
+ config.before(:each) do
9
+ $stdout = StringIO.new
10
+ $stderr = StringIO.new
11
+ $stdin = StringIO.new
12
+ end
13
+
14
+ # Set STDOUT, STDERR and STDIN back to default
15
+ config.after(:each) do
16
+ $stdout = STDOUT
17
+ $stderr = STDERR
18
+ $stdin = STDIN
19
+ end
20
+ end
@@ -1,52 +1,82 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Valet::Application do
4
- let(:app) { Application.new }
4
+ subject(:app) { Application.new }
5
5
 
6
- describe "class attributes" do
7
- it "can have a name" do
8
- Application.name = 'Backup'
9
- Application.name.should == 'Backup'
6
+ its(:arguments) { should be(ARGV) }
7
+ its(:options) { should be_an_instance_of(Options) }
8
+ its(:commands) { should be_an_instance_of(Commands) }
9
+
10
+ its(:name) { should be_nil }
11
+ its(:version) { should be_nil }
12
+ its(:authors) { should be_nil }
13
+ its(:email) { should be_nil }
14
+ its(:homepage) { should be_nil }
15
+ its(:copyright) { should be_nil }
16
+ its(:license) { should be_nil }
17
+ its(:summary) { should be_nil }
18
+ its(:description) { should be_nil }
19
+ its(:examples) { should eq([]) }
20
+
21
+ describe "attributes" do
22
+ it "can be given a name" do
23
+ app.name = 'Backup'
24
+ expect(app.name).to eq('Backup')
25
+ end
26
+
27
+ it "can be given a version" do
28
+ app.version = '1.2.3'
29
+ expect(app.version).to eq('1.2.3')
10
30
  end
11
31
 
12
- it "can have a version" do
13
- Application.version = '1.2.3'
14
- Application.version.should == '1.2.3'
32
+ it "can be given authors" do
33
+ app.authors = ['Alexander Baumann', 'Bob the Builder']
34
+ expect(app).to have(2).authors
15
35
  end
16
36
 
17
- it "can have authors" do
18
- Application.authors = ['Alexander Baumann', 'Bob the Builder']
19
- Application.authors.should == ['Alexander Baumann', 'Bob the Builder']
37
+ it "can be given email addresses" do
38
+ app.email = ['alexander.baumann@arclight.ch', 'bob@builder.com']
39
+ expect(app.email).to have(2).emails
20
40
  end
21
41
 
22
- it "can have a copyright notice" do
23
- Application.copyright = 'Copyright (c) 2012 Free Software Foundation, Inc.'
24
- Application.copyright.should == 'Copyright (c) 2012 Free Software Foundation, Inc.'
42
+ it "can be given a homepage" do
43
+ app.homepage = 'http://gitkeeper.github.com/valet'
44
+ expect(app.homepage).to eq('http://gitkeeper.github.com/valet')
25
45
  end
26
46
 
27
- it "can have a license" do
28
- Application.license = <<-LICENSE.gsub(/^ {6}/, '').strip
47
+ it "can be given a copyright notice" do
48
+ app.copyright = 'Copyright (c) 2012 Free Software Foundation, Inc.'
49
+ expect(app.copyright).to eq('Copyright (c) 2012 Free Software Foundation, Inc.')
50
+ end
51
+
52
+ it "can be given a license" do
53
+ app.license = <<-LICENSE.gsub(/^ {8}/, '').strip
29
54
  License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
30
55
  This is free software: You are free to change and redistribute it.
31
56
  There is NO WARRANTY, to the extent permitted by law.
32
57
  LICENSE
33
- Application.license.should include('GNU GPL version 3 or later')
58
+ expect(app.license).to include('GNU GPL version 3 or later')
34
59
  end
35
- end
36
60
 
37
- describe ".start" do
38
- it "passes ARGV as arguments to it's new instance by default" do
39
- app = Application.start
40
- app.args.should == ARGV
61
+ it "can be given a summary" do
62
+ app.summary = 'A framework for creating GNU compliant CLIs.'
63
+ expect(app.summary).to eq('A framework for creating GNU compliant CLIs.')
41
64
  end
42
65
 
43
- it "can pass custom arguments to it's new instance" do
44
- app = Application.start(%w( --custom arguments ))
45
- app.args.should == %w( --custom arguments )
66
+ it "can be given a description" do
67
+ app.description = <<-DESC.gsub(/^ {8}/, '').strip
68
+ Valet helps you write the sophisticated command-line interfaces you're
69
+ so used to from GNU/Linux. It provides a beautiful API, rich template
70
+ support, smart configuration, man page generator, and many other useful
71
+ features. No matter how large or complex your application is, Valet tops
72
+ it off with the command-line interface it deserves.
73
+ DESC
74
+ expect(app.description).to include('provides a beautiful API')
46
75
  end
47
76
 
48
- it "returns the new application" do
49
- Application.start.should be_an_instance_of(Application)
77
+ it "can be given examples" do
78
+ app.examples << ['Generate command files' 'valet generate command backup']
79
+ expect(app.examples).to have(1).example
50
80
  end
51
81
  end
52
82
  end
@@ -0,0 +1,116 @@
1
+ require 'spec_helper'
2
+
3
+ describe Valet::Command do
4
+ subject(:cmd) { Command.new(:backup) }
5
+
6
+ its(:name) { should be_a(Symbol) }
7
+ its(:aliases) { should be_nil }
8
+ its(:action) { should be_nil }
9
+ its(:options) { should be_an_instance_of(Options) }
10
+ its(:commands) { should be_an_instance_of(Commands) }
11
+ its(:syntax) { should be_nil }
12
+ its(:summary) { should be_nil }
13
+ its(:description) { should be_nil }
14
+ its(:examples) { should eq([]) }
15
+
16
+ describe "#initialize" do
17
+ context "raises a CommandError" do
18
+ it "if the name is not a symbol" do
19
+ expect { Command.new('backup') }.to raise_error(CommandError)
20
+ end
21
+ end
22
+ end
23
+
24
+ describe "attributes" do
25
+ it "can be given aliases" do
26
+ cmd.aliases = [:bak, :b]
27
+ expect(cmd.aliases).to eq([:bak, :b])
28
+ end
29
+
30
+ it "can be given options" do
31
+ cmd.options << double("Option")
32
+ expect(cmd.options).to have(1).option
33
+ end
34
+
35
+ it "can be given (sub-)commands" do
36
+ cmd.commands << double("Command")
37
+ expect(cmd.commands).to have(1).command
38
+ end
39
+
40
+ it "can be given a syntax" do
41
+ cmd.syntax = 'backup [OPTION]... SOURCE... DIRECTORY'
42
+ expect(cmd.syntax).to eq('backup [OPTION]... SOURCE... DIRECTORY')
43
+ end
44
+
45
+ it "can be given a summary" do
46
+ cmd.summary = 'Backup compresses and archives your precious data.'
47
+ expect(cmd.summary).to eq('Backup compresses and archives your precious data.')
48
+ end
49
+
50
+ it "can be given a description" do
51
+ description = <<-DESC.gsub(/ {8}/, '')
52
+ Backup tends to your precious data by scheduling cron jobs that
53
+ compress and archive your files efficiently. You can specify one or
54
+ multiple locations to copy your archives to.
55
+ DESC
56
+ cmd.description = description
57
+ expect(cmd.description).to be(description)
58
+ end
59
+
60
+ it "can be given examples" do
61
+ cmd.examples << ['A zipped backup', 'backup --gzip ~/projects ~/backups ']
62
+ expect(cmd.examples).to have(1).example
63
+ end
64
+ end
65
+
66
+ describe "#action" do
67
+ before { cmd.action { 'Backing up...' } }
68
+
69
+ it "attaches a new action if a block is supplied" do
70
+ cmd.action { 'Deleting all backups...' }
71
+ expect(cmd.action.call).to eq('Deleting all backups...')
72
+ end
73
+
74
+ it "attaches actions with one block parameter (options)" do
75
+ expect { cmd.action { |opts| "#{opts}" } }.not_to raise_error
76
+ end
77
+
78
+ it "attaches actions with two block parameters (operands, options)" do
79
+ expect { cmd.action { |args, opts| "#{args} #{opts}" } }.not_to raise_error
80
+ end
81
+
82
+ it "raises a CommandError if more than two block parameters are given" do
83
+ expect { cmd.action { |a, b, c| a + b + c } }.to raise_error(CommandError)
84
+ end
85
+
86
+ it "raises a CommandError if arbitrary number of parameters are given" do
87
+ expect { cmd.action { |*args, opts| "#{args} #{opts}" } }.to raise_error(CommandError)
88
+ end
89
+
90
+ it "returns the action if no block is supplied" do
91
+ expect(cmd.action.call).to eq('Backing up...')
92
+ end
93
+ end
94
+
95
+ describe "#execute" do
96
+ it "can call an action without block parameters" do
97
+ cmd.stub(action: -> { 'Backing up...' })
98
+ expect(cmd.execute).to eq('Backing up...')
99
+ end
100
+
101
+ it "can call an action with one block parameter (options)" do
102
+ cmd.stub(options: double("Options", verbose?: true))
103
+ cmd.stub(action: ->(opts) { 'Backing up...' if opts.verbose? })
104
+
105
+ cmd.options.should_receive(:verbose?)
106
+ cmd.execute
107
+ end
108
+
109
+ it "can call an action with two block parameters (operands, options)" do
110
+ cmd.stub(options: double("Options", verbose?: true))
111
+ cmd.stub(action: ->(args, opts) { args.shift if opts.verbose? })
112
+
113
+ expect(cmd.execute('Backing up...')).to eq('Backing up...')
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe Valet::Commands do
4
+ pending
5
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ describe Valet::Helpers::TypeCast do
4
+ subject(:obj) { Class.new.extend(Helpers::TypeCast) }
5
+
6
+ let(:array) { %w( Bob Alisha Fred ) }
7
+ let(:array_comma) { 'Bob,Alisha,Fred' }
8
+ let(:array_space) { 'Bob Alisha Fred' }
9
+
10
+ let(:hash) { { name: 'Bob', gender: 'male', age: '42' } }
11
+ let(:hash_comma) { 'name:Bob,gender:male,age:42' }
12
+ let(:hash_space) { 'name:Bob gender:male age:42' }
13
+
14
+ let(:time) { Time.parse('11.07.2012 08:00') }
15
+ let(:time_string) { '11.07.2012 08:00'}
16
+
17
+ describe "#string_to" do
18
+ specify { expect(obj.string_to(String, 'Bob')).to eq('Bob') }
19
+ specify { expect(obj.string_to(Integer, '13')).to eq(13) }
20
+ specify { expect(obj.string_to(Float, '13.37')).to eq(13.37) }
21
+ specify { expect(obj.string_to(Array, array_comma)).to eq(array) }
22
+ specify { expect(obj.string_to(Array, array_space)).to eq(array) }
23
+ specify { expect(obj.string_to(Hash, hash_comma)).to eq(hash) }
24
+ specify { expect(obj.string_to(Hash, hash_space)).to eq(hash) }
25
+ specify { expect(obj.string_to(Time, time_string)).to eq(time) }
26
+
27
+ context "it raises a TypeError" do
28
+ it "if the given type is not allowed" do
29
+ expect { obj.string_to(Mutex, 'Bob') }.to raise_error(TypeError)
30
+ end
31
+ end
32
+ end
33
+ end