ctioga2 0.4 → 0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. data/Changelog +16 -0
  2. data/lib/ctioga2/commands/arguments.rb +5 -2
  3. data/lib/ctioga2/commands/commands.rb +45 -13
  4. data/lib/ctioga2/commands/context.rb +9 -1
  5. data/lib/ctioga2/commands/doc/help.rb +2 -2
  6. data/lib/ctioga2/commands/doc/html.rb +8 -8
  7. data/lib/ctioga2/commands/doc/introspection.rb +7 -5
  8. data/lib/ctioga2/commands/parsers/file.rb +123 -120
  9. data/lib/ctioga2/commands/parsers/old-file.rb +191 -0
  10. data/lib/ctioga2/commands/strings.rb +2 -2
  11. data/lib/ctioga2/data/datacolumn.rb +5 -2
  12. data/lib/ctioga2/data/dataset.rb +3 -13
  13. data/lib/ctioga2/data/indexed-dtable.rb +43 -11
  14. data/lib/ctioga2/data/stack.rb +65 -8
  15. data/lib/ctioga2/graphics/elements.rb +2 -1
  16. data/lib/ctioga2/graphics/elements/containers.rb +22 -3
  17. data/lib/ctioga2/graphics/elements/primitive.rb +5 -5
  18. data/lib/ctioga2/graphics/elements/xyz-contour.rb +123 -0
  19. data/lib/ctioga2/graphics/generator.rb +31 -5
  20. data/lib/ctioga2/graphics/legends.rb +44 -3
  21. data/lib/ctioga2/graphics/legends/area.rb +28 -9
  22. data/lib/ctioga2/graphics/legends/items.rb +34 -23
  23. data/lib/ctioga2/graphics/legends/multicols.rb +132 -0
  24. data/lib/ctioga2/graphics/styles.rb +3 -1
  25. data/lib/ctioga2/graphics/styles/axes.rb +10 -4
  26. data/lib/ctioga2/graphics/styles/base.rb +65 -11
  27. data/lib/ctioga2/graphics/styles/colormap.rb +2 -1
  28. data/lib/ctioga2/graphics/styles/contour.rb +141 -0
  29. data/lib/ctioga2/graphics/styles/curve.rb +49 -67
  30. data/lib/ctioga2/graphics/styles/drawable.rb +17 -8
  31. data/lib/ctioga2/graphics/styles/factory.rb +79 -38
  32. data/lib/ctioga2/graphics/styles/legend.rb +49 -6
  33. data/lib/ctioga2/graphics/styles/plot.rb +10 -9
  34. data/lib/ctioga2/graphics/styles/sheet.rb +11 -11
  35. data/lib/ctioga2/graphics/styles/texts.rb +38 -9
  36. data/lib/ctioga2/graphics/types.rb +20 -1
  37. data/lib/ctioga2/graphics/types/dimensions.rb +7 -1
  38. data/lib/ctioga2/metabuilder/types/lists.rb +4 -4
  39. data/lib/ctioga2/metabuilder/types/numbers.rb +3 -3
  40. data/lib/ctioga2/metabuilder/types/styles.rb +2 -2
  41. data/lib/ctioga2/plotmaker.rb +12 -1
  42. data/lib/ctioga2/utils.rb +27 -3
  43. metadata +8 -4
data/Changelog CHANGED
@@ -1,3 +1,19 @@
1
+ ctioga2 (0.5)
2
+
3
+ * Choose the side of axis ticks
4
+ * Multicolumn legends
5
+ * Much more control about the details of the legends
6
+ * A drop command to remove datasets from the stack
7
+ * A much simpler format for command files
8
+ * Improved error detection/report (including now LaTeX errors, with
9
+ Tioga version 1.16)
10
+ * Real contour plots
11
+ * Specify text size/shift with real dimensions
12
+ * Many bug fixes
13
+ * Default size of tick labels is now larger
14
+
15
+ -- Vincent <vincent.fourmond@9online.fr> Mon 26 Aug 22:04:05 CEST 2013
16
+
1
17
  ctioga2 (0.4)
2
18
 
3
19
  * Fixed a bug in /which (dataset) options
@@ -16,7 +16,7 @@ require 'ctioga2/commands/type'
16
16
 
17
17
  module CTioga2
18
18
 
19
- Version::register_svn_info('$Revision: 355 $', '$Date: 2012-12-26 00:19:04 +0100 (Wed, 26 Dec 2012) $')
19
+ Version::register_svn_info('$Revision: 383 $', '$Date: 2013-03-11 21:57:53 +0100 (Mon, 11 Mar 2013) $')
20
20
 
21
21
  module Commands
22
22
 
@@ -42,7 +42,10 @@ module CTioga2
42
42
  # name
43
43
  attr_accessor :option_target
44
44
 
45
- # Whether or not the option is deprecated
45
+ # Whether or not the option is deprecated.
46
+ #
47
+ # If evaluates as true and different from _true_, is converted
48
+ # into a string used as an explanation to the user
46
49
  attr_accessor :option_deprecated
47
50
 
48
51
  # _type_ is a named CommandType
@@ -17,7 +17,7 @@ require 'ctioga2/commands/groups'
17
17
 
18
18
  module CTioga2
19
19
 
20
- Version::register_svn_info('$Revision: 355 $', '$Date: 2012-12-26 00:19:04 +0100 (Wed, 26 Dec 2012) $')
20
+ Version::register_svn_info('$Revision: 430 $', '$Date: 2013-08-23 14:23:52 +0200 (Fri, 23 Aug 2013) $')
21
21
 
22
22
  module Commands
23
23
 
@@ -90,6 +90,14 @@ module CTioga2
90
90
  # The context of definition [file, line]
91
91
  attr_accessor :context
92
92
 
93
+ # The context of the documentation
94
+ attr_accessor :documentation_context
95
+
96
+ def self.get_calling_context(id=2)
97
+ caller[id].gsub(/.*\/ctioga2\//, 'lib/ctioga2/') =~ /(.*):(\d+)/
98
+ return [$1, $2.to_i]
99
+ end
100
+
93
101
  # Creates a Command, with all attributes set up. The code can be
94
102
  # set using #set_code.
95
103
  #
@@ -109,8 +117,7 @@ module CTioga2
109
117
  @code = code
110
118
  self.describe(d_short, d_long, group)
111
119
 
112
- caller[1].gsub(/.*\/ctioga2\//, 'lib/ctioga2/') =~ /(.*):(\d+)/
113
- @context = [$1, $2.to_i]
120
+ @context = Command.get_calling_context
114
121
 
115
122
  # Registers automatically the command
116
123
  if register
@@ -132,6 +139,7 @@ module CTioga2
132
139
  # Sets the descriptions of the command. If the long description
133
140
  # is ommitted, the short is reused.
134
141
  def describe(short, long = nil, group = nil)
142
+ @documentation_context = Command.get_calling_context(1)
135
143
  @short_description = short
136
144
  @long_description = long || short
137
145
  if(group)
@@ -140,6 +148,15 @@ module CTioga2
140
148
  end
141
149
  end
142
150
 
151
+ # Sets the long documentation of the given command
152
+ def self.document_command(cmd, desc)
153
+ tg = Commands::Interpreter.command(cmd)
154
+ if tg
155
+ tg.documentation_context = Command.get_calling_context(1)
156
+ tg.long_description = desc
157
+ end
158
+ end
159
+
143
160
  # Returns a list of three strings:
144
161
  # * the short option
145
162
  # * the long option with arguments
@@ -210,19 +227,24 @@ module CTioga2
210
227
  # instance for the OptionParser with boolean options)
211
228
  def convert_options(options)
212
229
  target_options = {}
230
+ conv = target_option_names()
213
231
  for k,v in options
214
- if ! @optional_arguments.key? k
232
+ kn = normalize_option_name(k)
233
+ if ! conv.key? kn
215
234
  raise CommandOptionUnkown, "Unkown option #{k} for command #{@name}"
216
235
  end
217
- opt = @optional_arguments[k]
236
+ opt = @optional_arguments[conv[kn]]
218
237
  if v.is_a? String
219
238
  v = opt.type.string_to_type(v)
220
239
  end
221
- target = opt.option_target || k
240
+ target = opt.option_target || conv[kn]
222
241
  if opt.option_deprecated
223
242
  expl = ""
224
243
  if opt.option_target
225
244
  expl = " -- please use #{opt.option_target} instead"
245
+ elsif opt.option_deprecated != true # Ie more than plain
246
+ # true/false
247
+ expl = " -- #{opt.option_deprecated}"
226
248
  end
227
249
  Log::warn { "Deprecated option #{k}#{expl}" }
228
250
  end
@@ -232,15 +254,25 @@ module CTioga2
232
254
  return target_options
233
255
  end
234
256
 
257
+ # Returns a hash "normalized option names" => 'real option name'
258
+ def target_option_names
259
+ return @tg_op_names if @tg_op_names
260
+
261
+ @tg_op_names = {}
262
+ for k in @optional_arguments.keys
263
+ @tg_op_names[normalize_option_name(k)] = k
264
+ end
265
+ return @tg_op_names
266
+ end
267
+
268
+ # Returns a lowercase
269
+ def normalize_option_name(opt)
270
+ return opt.gsub(/_/,"-").downcase
271
+ end
272
+
235
273
  # Whether the Command accepts the named _option_.
236
- #
237
- # \todo Several conversions could be used, to facilitate the
238
- # writing of options:
239
- #
240
- # * convert everything to lowercase .
241
- # * ignore the difference between _ and - (a bit delicate).
242
274
  def has_option?(option)
243
- return @optional_arguments.key? option
275
+ return target_option_names.key?(normalize_option_name(option))
244
276
  end
245
277
 
246
278
  # Whether the Command accepts any option at all ?
@@ -41,7 +41,15 @@ module CTioga2
41
41
  if @option
42
42
  "option #{@option} (##{@number})"
43
43
  else
44
- "command #{@command} in file #{@file} line #{@number}"
44
+ file = @file.inspect
45
+ if @file.respond_to?(:path)
46
+ file = @file.path
47
+ end
48
+ if @command
49
+ "command #{@command} in file '#{file}' line #{@number}"
50
+ else
51
+ "line #{@number} in file '#{file}'"
52
+ end
45
53
  end
46
54
  end
47
55
 
@@ -18,7 +18,7 @@ require 'ctioga2/commands/doc/wordwrap'
18
18
 
19
19
  module CTioga2
20
20
 
21
- Version::register_svn_info('$Revision: 132 $', '$Date: 2010-01-14 23:18:19 +0100 (Thu, 14 Jan 2010) $')
21
+ Version::register_svn_info('$Revision: 409 $', '$Date: 2013-08-22 21:23:51 +0200 (Thu, 22 Aug 2013) $')
22
22
 
23
23
  module Commands
24
24
 
@@ -154,7 +154,7 @@ module CTioga2
154
154
  if cmd.has_options?
155
155
  op_start = ' options: '
156
156
  options = cmd.optional_arguments.
157
- keys.sort.map { |x| "/#{x}"}.join(' ')
157
+ keys.sort.map { |x| "/#{cmd.normalize_option_name(x)}"}.join(' ')
158
158
  opts_lines = WordWrapper.wrap(options, size - op_start.size)
159
159
  str += "\n#{total_leading_spaces}#{style(op_start,'switch')}" +
160
160
  style(opts_lines.join("\n#{total_leading_spaces}#{' ' * op_start.size}"), 'options')
@@ -16,7 +16,7 @@ require 'ctioga2/commands/commands'
16
16
 
17
17
  module CTioga2
18
18
 
19
- Version::register_svn_info('$Revision: 216 $', '$Date: 2010-12-31 16:18:17 +0100 (Fri, 31 Dec 2010) $')
19
+ Version::register_svn_info('$Revision: 409 $', '$Date: 2013-08-22 21:23:51 +0200 (Thu, 22 Aug 2013) $')
20
20
 
21
21
  module Commands
22
22
 
@@ -169,23 +169,23 @@ module CTioga2
169
169
  str << "<p class='synopsis'>\n<span class='bold'>Synopsis (file)</span>\n"
170
170
 
171
171
  str << "</p>\n<pre class='examples-cmdfile'>"
172
- str << "<span class='cmd'>#{cmd.name}("
172
+ str << "<span class='cmd'>#{cmd.name} "
173
173
  str << cmd.arguments.map { |arg|
174
174
  "<a class='argument' href='#{@types_url}#type-#{arg.type.name}'>#{arg.displayed_name}</a>"
175
- }.join(',')
175
+ }.join(' ')
176
176
  if cmd.has_options?
177
177
  if(cmd.arguments.size > 0)
178
- str << ", "
178
+ str << " "
179
179
  end
180
- str << "option=..."
180
+ str << "/option=..."
181
181
  end
182
- str << ")</span>\n"
182
+ str << "</span>\n"
183
183
  str << "</pre>\n"
184
184
 
185
185
  # Command-line file synopsis
186
186
  str << "<p class='synopsis'>\n<span class='bold'>Synopsis (command-line)</span>\n"
187
187
  args = cmd.arguments.map { |arg|
188
- "<a class='argument' href='#{@types_url}#type-#{arg.type.name}'>#{arg.displayed_name.upcase}</a>"
188
+ "<a class='argument' href='#{@types_url}#type-#{arg.type.name}'>#{arg.displayed_name}</a>"
189
189
  }.join(' ')
190
190
  if cmd.has_options?
191
191
  args << " /option=..."
@@ -204,7 +204,7 @@ module CTioga2
204
204
  if cmd.has_options?
205
205
  str << "<p class='synopsis'><span class='bold'>Available options</span>:\n"
206
206
  opts = cmd.optional_arguments.sort.map do |k,arg|
207
- "<a href='#{@types_url}#type-#{arg.type.name}'><code>#{k}</code></a>\n"
207
+ "<a href='#{@types_url}#type-#{arg.type.name}'><code>#{cmd.normalize_option_name(k)}</code></a>\n"
208
208
  end
209
209
  str << opts.join(' ')
210
210
  str << "</p>"
@@ -16,7 +16,7 @@ require 'ctioga2/commands/commands'
16
16
 
17
17
  module CTioga2
18
18
 
19
- Version::register_svn_info('$Revision: 336 $', '$Date: 2012-12-23 00:29:48 +0100 (Sun, 23 Dec 2012) $')
19
+ Version::register_svn_info('$Revision: 430 $', '$Date: 2013-08-23 14:23:52 +0200 (Fri, 23 Aug 2013) $')
20
20
 
21
21
  module Commands
22
22
 
@@ -106,10 +106,11 @@ module CTioga2
106
106
  end
107
107
 
108
108
  # Lauches an editor to edit the given command:
109
- def edit_command(cmd)
109
+ def edit_command(cmd, doc)
110
110
  cmd = Interpreter::command(cmd)
111
111
  if cmd
112
- edit_file(*cmd.context)
112
+ cntx = doc ? cmd.documentation_context : cmd.context
113
+ edit_file(*cntx)
113
114
  end
114
115
  end
115
116
 
@@ -205,8 +206,9 @@ EOH
205
206
 
206
207
  EditCommandCmd =
207
208
  Cmd.new('edit-command', nil, '--edit-command',
208
- [ CmdArg.new('text')]) do |plotmaker, cmd|
209
- Introspection.new.edit_command(cmd)
209
+ [ CmdArg.new('text')],
210
+ {'doc' => CmdArg.new('boolean')}) do |plotmaker, cmd, opts|
211
+ Introspection.new.edit_command(cmd, opts['doc'])
210
212
  end
211
213
 
212
214
  EditCommandCmd.describe("Edit the command",
@@ -1,5 +1,5 @@
1
- # file.rb: a file parser for ctioga2
2
- # copyright (c) 2009 by Vincent Fourmond
1
+ # file.rb: new style file parser for ctioga2
2
+ # copyright (c) 2013 by Vincent Fourmond
3
3
 
4
4
  # This program is free software; you can redistribute it and/or modify
5
5
  # it under the terms of the GNU General Public License as published by
@@ -11,38 +11,28 @@
11
11
  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
12
  # GNU General Public License for more details (in the COPYING file).
13
13
 
14
- require 'stringio'
14
+
15
15
  require 'ctioga2/utils'
16
16
  require 'ctioga2/log'
17
17
  require 'ctioga2/commands/commands'
18
18
  require 'ctioga2/commands/strings'
19
+ require 'ctioga2/commands/parsers/old-file'
19
20
 
20
21
  module CTioga2
21
22
 
22
- Version::register_svn_info('$Revision: 327 $', '$Date: 2012-11-28 14:47:52 +0100 (Wed, 28 Nov 2012) $')
23
+ Version::register_svn_info('$Revision: 420 $', '$Date: 2013-08-23 01:05:44 +0200 (Fri, 23 Aug 2013) $')
23
24
 
24
25
  module Commands
25
26
 
26
27
  module Parsers
27
28
 
28
- # Raised when EOF is encountered during a symbol parsing
29
- class UnterminatedSymbol < Exception
30
- end
31
-
32
- # Unexepected character.
33
- class UnexpectedCharacter < Exception
34
- end
35
-
36
- # Syntax error
37
- class ParserSyntaxError < Exception
38
- end
39
-
40
- # This class is in charge of parsing a command-line against a list
41
- # of known commands.
29
+ # This class parses a "new style" command file, delegating
42
30
  class FileParser
43
31
 
44
32
  include Log
45
33
 
34
+
35
+
46
36
  # Runs a command file targeting the given _interpreter_.
47
37
  def self.run_command_file(file, interpreter)
48
38
  FileParser.new.run_command_file(file, interpreter)
@@ -68,122 +58,135 @@ module CTioga2
68
58
  # Parses a given _io_ object, sending commands/variable
69
59
  # definitions to the given _interpreter_.
70
60
  def parse_io_object(io, interpreter)
71
- # The process is simple: we look for symbols and
72
- # corresponding syntax element: parentheses or assignments
73
-
74
- ## @todo It would be really great if assignments could be
75
- ## made conditional (a bit like in makefiles)
76
- while(1)
77
- symbol = up_to_next_symbol(io)
78
- break if not symbol
61
+
62
+ # We first split everything into lines
63
+ lines = io.readlines
64
+
65
+ # First, we look for old-style commands to see if we
66
+ # delegate to the other parser. In any case, we build up a
67
+ # list of "unsplit" lines (ie gather lines that end with \)
68
+
69
+ parsed_lines = []
70
+ cur = nil
71
+
72
+ lines_indices = []
73
+ idx = 0
74
+
75
+
76
+ ## @todo line counting ?
77
+ for l in lines
78
+ idx += 1
79
+ # If we find something that looks like a command at the
80
+ # beginning of a line, we say this is an old style file.
81
+
82
+ ## @todo Find a way to disable this compatibility stuff --
83
+ ## or make it more accurate ? The problem is that in a
84
+ ## large command file, there may be things that look like
85
+ ## old style commands ?
79
86
 
80
- while(1)
81
- c = io.getc
82
- if ! c # EOF
83
- raise ParserSyntaxError, "Expecting something after symbol #{symbol}"
84
- end
85
- ch = c.chr
86
- if ch =~ /\s/ # blank...
87
- next
88
- elsif ch == '(' # beginning of a function call
89
- # Parse string:
90
- str = InterpreterString.parse_until_unquoted(io,")")
91
- # Now, we need to split str.
92
- args = str.expand_and_split(/\s*,\s*/, interpreter)
93
-
94
- cmd = interpreter.get_command(symbol)
95
- real_args = args.slice!(0, cmd.argument_number)
96
- # And now the options:
97
- options = {}
98
-
99
- # Problem: the space on the right of the = sign is
100
- # *significant*.
101
- for o in args
102
- if o =~ /^\s*\/?([\w-]+)\s*=(.*)/
103
- if cmd.has_option? $1
104
- options[$1] = $2
105
- else
106
- error {
107
- "Command #{cmd.name} does not take option #{$1}"
108
- }
109
- end
110
- end
111
- end
87
+ if l =~ /^([a-z0-9-]+)\(/
88
+ path = io.respond_to?(:path) ? io.path : io.to_s
89
+ warn { "Found old style (deprecated) commands in '#{path}', using old style parser"}
90
+ return OldFileParser.new.
91
+ run_commands(lines.join(""), interpreter)
92
+ end
93
+ if cur
94
+ cur << l
95
+ else
96
+ cur = l
97
+ end
112
98
 
113
- interpreter.context.parsing_file(symbol, io) # Missing line number
114
- interpreter.run_command(cmd, real_args, options)
115
- io.getc # Slurp up the )
116
- break
117
- elsif ch == ':' # Assignment
118
- c = io.getc
119
- if ! c # EOF
120
- raise ParserSyntaxError, "Expecting = after :"
121
- end
122
- ch = c.chr
123
- if ch != '='
124
- raise ParserSyntaxError, "Expecting = after :"
125
- end
126
- str = InterpreterString.parse_until_unquoted(io,"\n", false)
127
- interpreter.variables.define_variable(symbol, str,
128
- interpreter)
129
- break
130
- elsif ch == '='
131
- str = InterpreterString.parse_until_unquoted(io,"\n", false)
132
- interpreter.variables.define_variable(symbol, str, nil)
133
- break
134
- else
135
- raise UnexpectedCharacter, "Did not expect #{ch} after #{symbol}"
136
- end
99
+ if cur =~ /\\$/
100
+ cur.gsub!(/\\$/,'')
101
+ cur.chomp!
102
+ else
103
+ # Strip all white space at the end of unfinished lines.
104
+ parsed_lines << cur.gsub(/\s+$/,"\n")
105
+ lines_indices << idx
106
+ cur = nil
137
107
  end
108
+
138
109
  end
139
- end
140
110
 
141
- protected
111
+ # Flush any pending unfinished line
112
+ parsed_lines << cur if cur
113
+ lines_indices << idx if cur
114
+
115
+ # Now, we rearrange the lines...
116
+ idx = -1
117
+ for l in parsed_lines
118
+ idx += 1
119
+ interpreter.context.parsing_file(nil, io, lines_indices[idx])
120
+ if l =~ /^\s*([a-zA-Z0-9_-]+)\s*(=|:=)\s*(.*)/
121
+ symbol = $1
122
+ value = InterpreterString.parse_until_unquoted(StringIO.new($3),"\n", false)
123
+ rec = (($2 == "=") ? nil : interpreter)
124
+
125
+ interpreter.variables.define_variable(symbol, value, rec)
126
+ elsif l =~ /^\s*#/
127
+ # comment...
128
+ else
129
+ l += "\n"
130
+ str = InterpreterString.parse_until_unquoted(StringIO.new(l),"\n")
131
+ words = str.expand_and_split(/\s+/, interpreter)
142
132
 
143
- SYMBOL_CHAR_REGEX = /[a-zA-Z0-9_-]/
144
-
145
- # Parses the _io_ stream up to and including the next
146
- # symbol. Only white space or comments may be found on the
147
- # way. This function returns the symbol.
148
- #
149
- # Symbols are composed of the alphabet SYMBOL_CHAR_REGEX.
150
- def up_to_next_symbol(io)
151
-
152
- symbol = nil # As long as no symbol as been started
153
- # it will stay nil.
154
- while(1)
155
- c = io.getc
156
- if ! c # EOF
157
- if symbol
158
- raise UnterminatedSymbol, "EOF reached during symbol parsing"
159
- else
160
- # File is finished and we didn't meet any symbol.
161
- # Nothing to do !
162
- return nil
133
+ # Take care of strings starting with spaces...
134
+
135
+ if words.size == 0
136
+ next
163
137
  end
138
+
139
+ symbol = words[0]
140
+ all_args = words[1..-1]
141
+
142
+ cmd = interpreter.get_command(symbol)
143
+
144
+ args, opts = parse_args_and_opts(cmd, all_args)
145
+
146
+ interpreter.context.parsing_file(symbol, io, lines_indices[idx]) # Missing line number
147
+ interpreter.run_command(cmd, args, opts)
164
148
  end
165
- ch = c.chr
166
- if symbol # We have started
167
- if ch =~ SYMBOL_CHAR_REGEX
168
- symbol += ch
149
+ end
150
+ end
151
+
152
+ protected
153
+
154
+
155
+ # Parses the all_args into arguments and options.
156
+ def parse_args_and_opts(cmd, all_args)
157
+
158
+ opts = {}
159
+ args = []
160
+ while all_args.size > 0
161
+ a = all_args.shift
162
+ if a =~ /^\/([a-zA-Z0-9_-]+)(=(.*))?$/
163
+ o = $1
164
+ if cmd.has_option?(o)
165
+ if $2
166
+ if $3
167
+ opts[o] = $3
168
+ else
169
+ opts[o] = all_args.shift
170
+ end
171
+ else
172
+ nxt = all_args.shift
173
+ if nxt =~ /^\s*=\s*$/
174
+ opts[o] = all_args.shift
175
+ else
176
+ opts[o] = nxt.gsub(/^\s*=/,'')
177
+ end
178
+ end
169
179
  else
170
- io.ungetc(c)
171
- return symbol
180
+ warn { "#{o} looks like an option, but command #{cmd.name} does not have such an option" }
181
+ args << a
172
182
  end
173
183
  else
174
- if ch =~ SYMBOL_CHAR_REGEX
175
- symbol = ch
176
- elsif ch =~ /\s/
177
- # Nothing
178
- elsif ch == '#'
179
- io.gets
180
- else
181
- raise UnexpectedCharacter, "Unexpected character: #{ch}, when looking for a symbol"
182
- end
184
+ args << a
183
185
  end
184
186
  end
185
- end
186
187
 
188
+ return [args, opts]
189
+ end
187
190
  end
188
191
 
189
192
  end