linen 0.3.1 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/indifferent_hash.rb +9 -9
- data/lib/linen.rb +8 -8
- data/lib/linen/argument.rb +21 -21
- data/lib/linen/cli.rb +214 -214
- data/lib/linen/command.rb +118 -118
- data/lib/linen/exceptions.rb +13 -13
- data/lib/linen/plugin.rb +63 -63
- data/lib/linen/plugin_registry.rb +38 -38
- data/lib/linen/workspace.rb +15 -15
- data/lib/string_extensions.rb +3 -3
- data/test/test_cli.rb +72 -72
- data/test/test_indifferent_hash.rb +26 -26
- data/test/test_plugins.rb +35 -35
- metadata +1 -1
@@ -10,56 +10,56 @@
|
|
10
10
|
require 'singleton'
|
11
11
|
|
12
12
|
class Linen::PluginRegistry
|
13
|
-
|
13
|
+
include Singleton
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
15
|
+
include Enumerable
|
16
|
+
def each
|
17
|
+
### yield the actual plugin object, which knows its own name
|
18
|
+
@plugins.each { |name, plugin| yield plugin }
|
19
|
+
end
|
20
20
|
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
|
22
|
+
def register_plugin( plugin )
|
23
|
+
raise Linen::Plugin::ArgumentError, "Attempted to register something that is not a Linen::Plugin" unless
|
24
|
+
plugin < Linen::Plugin
|
25
25
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
26
|
+
@plugins ||= {}
|
27
|
+
@plugins[ plugin.short_name ] = plugin
|
28
|
+
end
|
29
|
+
alias register register_plugin
|
30
|
+
alias << register_plugin
|
31
31
|
|
32
32
|
|
33
|
-
|
34
|
-
|
35
|
-
|
33
|
+
def size
|
34
|
+
return @plugins.size
|
35
|
+
end
|
36
36
|
|
37
37
|
|
38
|
-
|
39
|
-
|
40
|
-
|
38
|
+
def []( name )
|
39
|
+
return @plugins[ name ]
|
40
|
+
end
|
41
41
|
|
42
42
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
43
|
+
def commands
|
44
|
+
if @commands.nil?
|
45
|
+
### create @commands. Each new key will get an empty array as its default value.
|
46
|
+
@commands = IndifferentHash.new
|
47
47
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
48
|
+
### populates @commands as a hash of arrays. The hash key is the command name (.to_s) and the value
|
49
|
+
### is an array containing each plugin class in which that command is defined.
|
50
|
+
@plugins.each do |name, plugin|
|
51
|
+
plugin.commands.each do |name, cmd|
|
52
|
+
@commands[ name ] ||= []
|
53
|
+
@commands[ name ] << plugin
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
57
|
|
58
|
-
|
59
|
-
|
58
|
+
return @commands
|
59
|
+
end
|
60
60
|
|
61
61
|
|
62
|
-
|
63
|
-
|
64
|
-
|
62
|
+
def find_command( name )
|
63
|
+
return @commands[ name ]
|
64
|
+
end
|
65
65
|
end
|
data/lib/linen/workspace.rb
CHANGED
@@ -8,22 +8,22 @@
|
|
8
8
|
##############################################################
|
9
9
|
|
10
10
|
class Linen::Workspace
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
11
|
+
def set_value( name, value )
|
12
|
+
# add getter
|
13
|
+
(class << self ; self ; end).instance_eval {
|
14
|
+
attr_reader name.to_s.intern
|
15
|
+
}
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
# add ivar
|
18
|
+
instance_variable_set "@#{name}", value
|
19
|
+
end
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
21
|
+
def add_values( hash )
|
22
|
+
raise ArgumentError,
|
23
|
+
"must send a hash" unless hash.is_a? Hash
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
25
|
+
hash.each do |k,v|
|
26
|
+
self.set_value k, v
|
27
|
+
end
|
28
|
+
end
|
29
29
|
end
|
data/lib/string_extensions.rb
CHANGED
@@ -8,8 +8,8 @@
|
|
8
8
|
##############################################################
|
9
9
|
|
10
10
|
class String
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
def wrap(line_width = 72)
|
12
|
+
self.gsub(/\n/, "\n\n").gsub(/(.{1,#{line_width}})(\s+|$)/, "\\1\n").strip
|
13
|
+
end
|
14
14
|
end
|
15
15
|
|
data/test/test_cli.rb
CHANGED
@@ -12,100 +12,100 @@ require 'linen'
|
|
12
12
|
|
13
13
|
class TestCLICommandCompletion < Test::Unit::TestCase
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
################
|
16
|
+
# test plugins #
|
17
|
+
################
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
19
|
+
class ::TestPlugin < Linen::Plugin
|
20
|
+
command :add do;end
|
21
|
+
command :administer do;end
|
22
|
+
command :somethingelse do;end
|
23
|
+
end
|
24
24
|
|
25
25
|
|
26
|
-
|
27
|
-
|
28
|
-
|
26
|
+
class ::TeaPlugin < Linen::Plugin
|
27
|
+
command :foo do;end
|
28
|
+
end
|
29
29
|
|
30
30
|
|
31
|
-
|
32
|
-
|
33
|
-
|
31
|
+
class ::OtherPlugin < Linen::Plugin
|
32
|
+
command :food do;end
|
33
|
+
end
|
34
34
|
|
35
35
|
|
36
|
-
|
37
|
-
|
38
|
-
|
36
|
+
#########
|
37
|
+
# tests #
|
38
|
+
#########
|
39
39
|
|
40
|
-
|
41
|
-
|
40
|
+
def test_plugin_completion
|
41
|
+
all_plugins = Linen.plugins.map {|p| p.short_name}.sort
|
42
42
|
|
43
|
-
|
44
|
-
|
45
|
-
|
43
|
+
assert_raises_plugin_ambiguity_error( all_plugins ) do
|
44
|
+
complete ''
|
45
|
+
end
|
46
46
|
|
47
|
-
|
48
|
-
|
49
|
-
|
47
|
+
assert_raises_plugin_ambiguity_error( all_plugins.select {|p| p =~ /^te/} ) do
|
48
|
+
complete 'te'
|
49
|
+
end
|
50
50
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
51
|
+
assert_nothing_raised do
|
52
|
+
### strip'ing because completion returns it with a trailing space
|
53
|
+
assert_equal "test", complete( 'tes' ).strip
|
54
|
+
end
|
55
|
+
end
|
56
56
|
|
57
57
|
|
58
|
-
|
59
|
-
|
58
|
+
def test_command_completion
|
59
|
+
test_commands = Linen.plugins[ 'test' ].commands.keys.map {|k| k.to_s}.sort
|
60
60
|
|
61
|
-
|
62
|
-
|
63
|
-
|
61
|
+
assert_raises_command_ambiguity_error( test_commands ) do
|
62
|
+
complete 'tes '
|
63
|
+
end
|
64
64
|
|
65
|
-
|
66
|
-
|
67
|
-
|
65
|
+
assert_raises_command_ambiguity_error( test_commands ) do
|
66
|
+
complete 'test '
|
67
|
+
end
|
68
68
|
|
69
|
-
|
69
|
+
starts_with_ad = test_commands.select {|c| c =~ /^ad/}
|
70
70
|
|
71
|
-
|
72
|
-
|
73
|
-
|
71
|
+
assert_raises_command_ambiguity_error( starts_with_ad ) do
|
72
|
+
assert_equal "test ad", complete( 'test ad' )
|
73
|
+
end
|
74
74
|
|
75
|
-
|
76
|
-
|
77
|
-
|
75
|
+
assert_raises_command_ambiguity_error( starts_with_ad ) do
|
76
|
+
assert_equal "test ad", complete( 'tes ad' )
|
77
|
+
end
|
78
78
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
79
|
+
assert_nothing_raised do
|
80
|
+
### strip'ing because completion returns it with a trailing space
|
81
|
+
assert_equal "test administer", complete( 'test adm' ).strip
|
82
|
+
assert_equal "test administer", complete( 'tes adm' ).strip
|
83
|
+
end
|
84
|
+
end
|
85
85
|
|
86
86
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
87
|
+
#######
|
88
|
+
private
|
89
|
+
#######
|
90
|
+
def complete( str )
|
91
|
+
return Linen::CLI.expand_command( str )
|
92
|
+
end
|
93
93
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
94
|
+
def assert_raises_ambiguity_error( exception, candidates, &block )
|
95
|
+
begin
|
96
|
+
block.call
|
97
|
+
rescue exception => e
|
98
|
+
assert_equal candidates, e.candidates
|
99
|
+
else
|
100
|
+
flunk 'no exception raised!'
|
101
|
+
end
|
102
|
+
end
|
103
103
|
|
104
|
-
|
105
|
-
|
106
|
-
|
104
|
+
def assert_raises_plugin_ambiguity_error( candidates, &block )
|
105
|
+
assert_raises_ambiguity_error Linen::CLI::AmbiguousPluginError, candidates, &block
|
106
|
+
end
|
107
107
|
|
108
|
-
|
109
|
-
|
110
|
-
|
108
|
+
def assert_raises_command_ambiguity_error( candidates, &block )
|
109
|
+
assert_raises_ambiguity_error Linen::CLI::AmbiguousCommandError, candidates, &block
|
110
|
+
end
|
111
111
|
end
|
@@ -11,41 +11,41 @@ require 'test/unit'
|
|
11
11
|
require 'indifferent_hash'
|
12
12
|
|
13
13
|
class TestIndifferentHash < Test::Unit::TestCase
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
14
|
+
def setup
|
15
|
+
@rhash = {
|
16
|
+
:symbol => 'regular symbol',
|
17
|
+
'string' => 'regular string'
|
18
|
+
}
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
20
|
+
@ihash = IndifferentHash.new
|
21
|
+
@ihash[ :symbol ] = 'indifferent symbol'
|
22
|
+
@ihash[ 'string' ] = 'indifferent string'
|
23
|
+
end
|
24
24
|
|
25
25
|
|
26
|
-
|
27
|
-
|
26
|
+
def test_string_to_symbol_lookups
|
27
|
+
key = 'symbol'
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
|
29
|
+
assert_nil @rhash[ key ]
|
30
|
+
assert_equal 'indifferent symbol', @ihash[ key ]
|
31
|
+
end
|
32
32
|
|
33
33
|
|
34
|
-
|
35
|
-
|
34
|
+
def test_symbol_to_string_lookups
|
35
|
+
key = :string
|
36
36
|
|
37
|
-
|
38
|
-
|
39
|
-
|
37
|
+
assert_nil @rhash[ key ]
|
38
|
+
assert_equal 'indifferent string', @ihash[ key ]
|
39
|
+
end
|
40
40
|
|
41
41
|
|
42
|
-
|
43
|
-
|
42
|
+
def test_literal_key_priority
|
43
|
+
ihash = IndifferentHash.new
|
44
44
|
|
45
|
-
|
46
|
-
|
45
|
+
ihash[ :key ] = "symbol"
|
46
|
+
ihash[ 'key' ] = "string"
|
47
47
|
|
48
|
-
|
49
|
-
|
50
|
-
|
48
|
+
assert_equal "symbol", ihash[ :key ]
|
49
|
+
assert_equal "string", ihash[ 'key' ]
|
50
|
+
end
|
51
51
|
end
|
data/test/test_plugins.rb
CHANGED
@@ -12,54 +12,54 @@ require 'linen'
|
|
12
12
|
|
13
13
|
### a little helper for later
|
14
14
|
class String
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
def to_regex
|
16
|
+
return /#{self}/
|
17
|
+
end
|
18
18
|
end
|
19
19
|
|
20
20
|
|
21
21
|
class TestPlugins < Test::Unit::TestCase
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
|
23
|
+
########################
|
24
|
+
# "constant" variables #
|
25
|
+
########################
|
26
26
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
27
|
+
@description = "This is some descriptions"
|
28
|
+
@help_msg = "This is some help messagesess"
|
29
|
+
class << self
|
30
|
+
attr_reader :description, :help_msg
|
31
|
+
end
|
32
32
|
|
33
|
-
|
34
|
-
|
35
|
-
|
33
|
+
################
|
34
|
+
# test plugins #
|
35
|
+
################
|
36
36
|
|
37
|
-
|
38
|
-
|
39
|
-
|
37
|
+
class ::HelpfulPlugin < Linen::Plugin
|
38
|
+
puts TestPlugins.description
|
39
|
+
description TestPlugins.description
|
40
40
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
41
|
+
command :test do
|
42
|
+
help_message TestPlugins.help_msg
|
43
|
+
end
|
44
|
+
end
|
45
45
|
|
46
46
|
|
47
|
-
|
48
|
-
|
49
|
-
|
47
|
+
class ::UnhelpfulPlugin < Linen::Plugin
|
48
|
+
command :test do;end
|
49
|
+
end
|
50
50
|
|
51
|
-
|
52
|
-
|
53
|
-
|
51
|
+
#########
|
52
|
+
# tests #
|
53
|
+
#########
|
54
54
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
55
|
+
def test_plugin_help
|
56
|
+
assert HelpfulPlugin.help =~ TestPlugins.description.to_regex
|
57
|
+
assert UnhelpfulPlugin.help =~ /No help for unhelpful/
|
58
|
+
end
|
59
59
|
|
60
60
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
61
|
+
def test_command_help
|
62
|
+
assert HelpfulPlugin.commands[ :test ].help =~ TestPlugins.help_msg.to_regex
|
63
|
+
assert UnhelpfulPlugin.commands[ :test ].help =~ /No help for unhelpful test/
|
64
|
+
end
|
65
65
|
end
|