linen 0.3.1 → 0.3.2
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.
- 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
|