linen 0.6.4 → 0.7.0

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.
@@ -18,8 +18,8 @@ require 'string_extensions'
18
18
 
19
19
 
20
20
  module Linen
21
- VERSION = "0.6.4"
22
- SVNRev = %q$Rev: 223 $
21
+ VERSION = "0.7.0"
22
+ SVNRev = %q$Rev: 231 $
23
23
 
24
24
 
25
25
  def self::plugins
@@ -13,7 +13,7 @@ class Linen::Plugin::Argument
13
13
  def initialize( plugin, name, opts )
14
14
  @plugin = plugin
15
15
  @name = name
16
- @prompt = opts[ :prompt ] || "Please enter the value for #{@name}"
16
+ @prompt = opts[ :prompt ] || "Please enter the value for #{@name}: "
17
17
  @regex = opts[ :regex ] || //
18
18
  @process = opts[ :process ] || nil
19
19
  end
@@ -32,7 +32,7 @@ class Linen::Plugin::Argument
32
32
  end
33
33
  end
34
34
 
35
- raise Linen::Plugin::ArgumentError, "Invalid entry." unless value =~ @regex
35
+ raise Linen::Plugin::ArgumentError, "The value entered ('#{value}') is not a valid #{@name}." unless value =~ @regex
36
36
  return value unless @process
37
37
 
38
38
  begin
@@ -40,3 +40,5 @@ end
40
40
 
41
41
  class Linen::WorkspaceError < RuntimeError ; end
42
42
  class Linen::HandlerError < RuntimeError ; end
43
+
44
+ class Linen::Abort < RuntimeError ; end
@@ -8,10 +8,17 @@
8
8
  ##############################################################
9
9
 
10
10
  class Linen::Handler
11
- # placeholder. This will eventually become the abstract
12
- # class from which all handlers inherit.
13
-
14
- def self::say( input )
11
+ def self::say( input = '' )
15
12
  raise NotImplementedError, "You must override say() in the handler"
16
13
  end
14
+
15
+
16
+ def self::die( input = '' )
17
+ raise NotImplementedError, "You must override die() in the handler"
18
+ end
19
+
20
+
21
+ def self::history
22
+ raise NotImplementedError, "Handlers must provide a #history method that quacks like an Array"
23
+ end
17
24
  end
@@ -55,6 +55,10 @@ class Linen::CLI < Linen::Handler
55
55
  end
56
56
  elsif plugin.nil? or command.nil?
57
57
  puts "You must enter both a plugin name and a command."
58
+ elsif Linen.plugins[ plugin ].nil?
59
+ puts "Plugin '#{plugin}' not found."
60
+ elsif Linen.plugins[ plugin ].commands[ command ].nil?
61
+ puts "Command '#{command}' not found in '#{plugin}' plugin."
58
62
  else
59
63
  plugin, command, *args = canonicalize( input ).split
60
64
 
@@ -68,26 +72,43 @@ class Linen::CLI < Linen::Handler
68
72
 
69
73
  def self::start
70
74
  loop do
75
+ input = nil
76
+
71
77
  begin
72
78
  input = Readline.readline( @prompt )
73
- rescue Interrupt
74
- puts "\nPlease type 'quit' or 'exit' to quit."
75
- else
76
79
  parse_command input
80
+ rescue Interrupt
81
+ if input
82
+ puts "\nCommand aborted."
83
+ else
84
+ puts "\nPlease type 'quit' or 'exit' to quit."
85
+ end
86
+ rescue Linen::Plugin::ArgumentError => e
87
+ puts e.message
77
88
  end
78
89
 
79
90
  puts # blank line to clean things up
80
91
  end
81
92
  end
93
+
94
+
95
+ def self::history
96
+ return Readline::HISTORY
97
+ end
82
98
 
83
99
 
84
100
  #######
85
101
  private
86
102
  #######
87
103
 
88
- def self::say( input = "" )
104
+ def self::say( input = '' )
89
105
  puts input.wrap
90
106
  end
107
+
108
+
109
+ def self::die( input = '' )
110
+ raise Linen::Abort, input
111
+ end
91
112
 
92
113
 
93
114
  def self::canonicalize( input )
@@ -207,7 +228,7 @@ END
207
228
  end
208
229
 
209
230
 
210
- def self::reprompt( prompt = "Re-enter: " )
231
+ def self::prompt( prompt = "Re-enter: " )
211
232
  old_completion_proc = Readline.completion_proc
212
233
  Readline.completion_proc = proc {}
213
234
 
@@ -104,4 +104,13 @@ class Linen::Plugin
104
104
 
105
105
  @description = input
106
106
  end
107
+
108
+
109
+ ### give validation a way to fail without explicitly raising
110
+ ### an exception in the lambda
111
+ def self::fail( input = nil )
112
+ input ||= "Validation failed."
113
+
114
+ raise Linen::Plugin::ArgumentError, input
115
+ end
107
116
  end
@@ -113,37 +113,35 @@ class Linen::Plugin::SimpleCommand
113
113
  @require_confirmation
114
114
  end
115
115
 
116
- ###########
117
- private #
118
- ###########
116
+ #######
117
+ private
118
+ #######
119
119
 
120
120
  ### FIXME:bbleything
121
121
  ###
122
- ### The reprompting stuff below is going to come back to bite us when we try to
123
- ### add batch mode later... that said, in the interest of getting things out the
124
- ### door, we're going to leave it be for now.
122
+ ### Much of the reprompting stuff is gone, it only exists now to allow us to
123
+ ### prompt when users don't enter anything. We should consider moving the
124
+ ### argument fetching into a separate phase of execution, so as to prevent
125
+ ### the ridiculous duplication of history-manipulation code in the following
126
+ ### two methods (and generally make it clearer how the whole thing works), but
127
+ ### that's probably not going to make it into 0.7.0.
125
128
 
126
129
  def validate_one_of_arguments( arg )
127
130
  results = IndifferentHash.new
128
-
129
- begin
130
- @arguments.each do |arg_name|
131
- argument = @plugin.arguments[ arg_name ]
132
-
133
- results[ arg_name ] = argument.process( arg ) rescue nil
134
- end
135
-
136
- raise Linen::Plugin::ArgumentError,
137
- "The value you entered ('#{arg}') is invalid for all arguments." if
138
- results.values.compact.empty?
139
- rescue Linen::Plugin::ArgumentError => e
140
- puts e.message
141
- arg = Linen::CLI.reprompt.split.first
142
-
143
- retry
131
+
132
+ # put the argument onto the command history if it wasn't already there
133
+ command_line = Linen::Workspace.handler.history.pop.strip
134
+ command_line << " #{arg}" unless command_line =~ /#{arg}$/
135
+ Linen::Workspace.handler.history.push command_line.squeeze( ' ' ).strip
136
+
137
+ @arguments.each do |arg_name|
138
+ argument = @plugin.arguments[ arg_name ]
139
+ results[ arg_name ] = argument.process( arg ) rescue nil
144
140
  end
145
-
146
- return results
141
+
142
+ raise Linen::Plugin::ArgumentError,
143
+ "The value you entered ('#{arg}') is invalid for all arguments." if
144
+ results.values.compact.empty?
147
145
  end
148
146
 
149
147
 
@@ -152,20 +150,17 @@ class Linen::Plugin::SimpleCommand
152
150
 
153
151
  @arguments.each do |arg_name|
154
152
  argument = @plugin.arguments[ arg_name ]
153
+
154
+ # prompt if we don't have the arg on the stack already
155
155
  arg_value = args.shift
156
-
157
- begin
158
- arg_value = Linen::CLI.reprompt( argument.prompt ) if arg_value.nil?
159
-
160
- results[ arg_name ] = argument.process( arg_value )
161
- rescue Linen::Plugin::ArgumentError => e
162
- puts e.message
163
-
164
- # reset arg_value to nil so we get prompted on retry
165
- arg_value = nil
166
-
167
- retry
168
- end
156
+ arg_value ||= Linen::Workspace.handler.prompt( argument.prompt )
157
+
158
+ # put the arg value back onto the command line
159
+ command_line = Linen::Workspace.handler.history.pop
160
+ command_line << " #{arg_value}" unless command_line =~ /#{arg_value}$/
161
+ Linen::Workspace.handler.history.push command_line.squeeze( ' ' ).strip
162
+
163
+ results[ arg_name ] = argument.process( arg_value )
169
164
  end
170
165
 
171
166
  return results
@@ -45,37 +45,6 @@ class Linen::Plugin::TwoPhaseCommand
45
45
  # PLUGIN DEFINITION METHODS #
46
46
  #############################
47
47
 
48
-
49
- # def one_of( *args )
50
- # raise Linen::Plugin::ArgumentError,
51
- # "You may not specify both required and one_of arguments" if @argument_type == :required
52
- #
53
- # @argument_type = :one_of
54
- #
55
- # args.each do |arg|
56
- # raise Linen::Plugin::ArgumentError,
57
- # "Argument '#{arg}' has not been defined" unless @plugin.arguments.include? arg
58
- #
59
- # @arguments << arg
60
- # end
61
- # end
62
- #
63
- #
64
- # def required_arguments( *args )
65
- # raise Linen::Plugin::ArgumentError,
66
- # "You may not specify both required and one_of arguments" if @argument_type == :one_of
67
- #
68
- # @argument_type = :required
69
- #
70
- # args.each do |arg|
71
- # raise Linen::Plugin::ArgumentError,
72
- # "Argument '#{arg}' has not been defined" unless @plugin.arguments.include? arg
73
- #
74
- # @arguments << arg
75
- # end
76
- # end
77
- # alias required_argument required_arguments
78
-
79
48
  def lookup_by( attr_name, &block )
80
49
  @lookup_attr = attr_name
81
50
  @lookup_block = block
@@ -121,27 +90,21 @@ class Linen::Plugin::TwoPhaseCommand
121
90
  argument = @plugin.arguments[ @lookup_attr ]
122
91
  arg_value = input
123
92
 
124
- begin
125
- arg_value = Linen::CLI.reprompt( argument.prompt ) if arg_value.nil?
126
-
127
- processed_argument = argument.process( arg_value )
93
+ # prompt if we didn't get an arg value
94
+ arg_value ||= Linen::CLI.prompt( argument.prompt )
128
95
 
129
- results[ @lookup_attr ] = @lookup_block.call( processed_argument )
130
- rescue Linen::Plugin::ArgumentError => e
131
- # reset arg_value to nil so we get prompted on retry
132
- arg_value = nil
133
-
134
- retry
135
- end
96
+ # put the command back onto the history
97
+ command_line = Linen::Workspace.handler.history.pop
98
+ command_line << " #{arg_value}" unless command_line =~ /#{arg_value}$/
99
+ Linen::Workspace.handler.history.push command_line.squeeze( ' ' ).strip
100
+
101
+ processed_argument = argument.process( arg_value )
102
+ results[ @lookup_attr ] = @lookup_block.call( processed_argument )
136
103
 
137
104
  return results
138
105
  end
139
-
140
- ### FIXME:bbleything
141
- ###
142
- ### The reprompting stuff below is going to come back to bite us when we try to
143
- ### add batch mode later... that said, in the interest of getting things out the
144
- ### door, we're going to leave it be for now.
106
+
107
+
145
108
  def validate_arguments( args )
146
109
  results = IndifferentHash.new
147
110
 
@@ -150,7 +113,7 @@ class Linen::Plugin::TwoPhaseCommand
150
113
  arg_value = args.shift
151
114
 
152
115
  begin
153
- arg_value = Linen::CLI.reprompt( argument.prompt ) if arg_value.nil?
116
+ arg_value = Linen::CLI.prompt( argument.prompt ) if arg_value.nil?
154
117
 
155
118
  result = argument.process( arg_value, :mode => :edit )
156
119
 
@@ -162,6 +125,8 @@ class Linen::Plugin::TwoPhaseCommand
162
125
  results[ arg_name ] = result
163
126
  end
164
127
  rescue Linen::Plugin::ArgumentError => e
128
+ puts e.message
129
+
165
130
  # reset arg_value to nil so we get prompted on retry
166
131
  arg_value = nil ; retry
167
132
  end
@@ -38,4 +38,8 @@ class Linen::Workspace
38
38
  def method_missing( *args )
39
39
  @@handler.send( *args )
40
40
  end
41
+
42
+ def self::handler
43
+ return @@handler
44
+ end
41
45
  end
@@ -9,7 +9,7 @@
9
9
 
10
10
  class String
11
11
  def wrap(line_width = 72)
12
- self.gsub(/\n/, "\n\n").gsub(/(.{1,#{line_width}})(\s+|$)/, "\\1\n").strip
12
+ self.gsub(/\n/, "\n\n").gsub(/(.{1,#{line_width}})(\s+|$)/, "\\1\n").chomp
13
13
  end
14
14
  end
15
15
 
metadata CHANGED
@@ -3,7 +3,7 @@ rubygems_version: 0.9.4
3
3
  specification_version: 1
4
4
  name: linen
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.6.4
6
+ version: 0.7.0
7
7
  date: 2007-09-10 00:00:00 -07:00
8
8
  summary: Linen - A pluggable command-line interface library
9
9
  require_paths: