1
# interpreter.rb: the interpreter of commands
2
# copyright (c) 2009 by Vincent Fourmond
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; either version 2 of the License, or
7
# (at your option) any later version.
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
# GNU General Public License for more details (in the COPYING file).
14
require 'ctioga2/utils'
15
require 'ctioga2/commands/commands'
16
require 'ctioga2/commands/variables'
17
require 'ctioga2/commands/strings'
18
require 'ctioga2/commands/parsers/command-line'
19
require 'ctioga2/commands/doc/doc'
23
Version::register_svn_info('$Revision: 155 $', '$Date: 2010-06-21 21:41:32 +0200 (Mon, 21 Jun 2010) $')
25
# This module contains the real core of ctioga2: a set of classes
26
# that implement the concept of commands. Each command translates
27
# into an action (of any kind).
29
# Commands can be specified using several ways: either using command-line
30
# options/arguments or through a commands file.
33
# An exception raised when a command is defined twice
34
class DoubleDefinition < Exception
37
# An exception raised when a command is not known to the interpreter
38
class UnknownCommand < Exception
41
# An exception raised upon invalid names.
42
class InvalidName < Exception
45
# An exception raised when a CommandType is not known
46
class InvalidType < Exception
49
# A CommandGroup#id or Command#name should match this regular
51
NameValidationRE = /^[a-z0-9-]+$/
53
# The core class interpreting all the commands and executing them.
54
# It holds a hash class variable containing all the Command
55
# objects defined so far.
58
# All commands defined so far.
61
# All command groups defined so far.
64
# All types defined so fat
69
# Registers a given command. This is called automatically from
70
# Command.new, so you should not have to do it yourself.
71
def self.register_command(command)
72
if self.command(command.name)
73
raise DoubleDefinition, "Command '#{command.name}' already defined"
75
if command.name =~ NameValidationRE
76
@@commands[command.name] = command
78
raise InvalidName, "Name '#{command.name}' is invalid"
83
# Registers a given group. This is called automatically from
84
# CommandGroup.new, so you should not have to do it yourself.
85
def self.register_group(group)
86
if self.group(group.id)
87
raise DoubleDefinition, "Group '#{group.id}' already defined"
89
if group.id =~ NameValidationRE
90
@@groups[group.id] = group
92
raise InvalidName, "Name '#{group.id}' is invalid"
97
# Registers a given type. This is called automatically from
98
# CommandType.new, so you should not have to do it yourself.
99
def self.register_type(type)
100
if self.type(type.name)
101
raise DoubleDefinition, "Type '#{type.name}' already defined"
103
if type.name =~ NameValidationRE
104
@@types[type.name] = type
106
raise InvalidName, "Name '#{type.name}' is invalid"
112
# Returns the named CommandType
117
# Returns all registered CommandType objects
122
# Deletes a command whose name is given
123
def self.delete_command(cmd)
124
@@commands.delete(cmd)
127
# Returns the command given by its name _cmd_, or nil if none was found.
128
def self.command(cmd)
129
return @@commands[cmd]
132
# Returns the groups given by its _id_, or nil if none was found.
137
# Returns the commands hash
142
# Returns the groups hash
147
# A Variables object holding the ... variables ! (I'm sure you
149
attr_accessor :variables
151
# The PlotMaker object that will receive the commands of the
153
attr_accessor :plotmaker_target
155
# The Parsers::CommandLineParser object used to... parse the command-line.
156
# (surprising, isn't it ??)
157
attr_reader :command_line_parser
159
# The Documentation::Doc object that can interact with documentation
162
# The Parsers::FileParser object used to... parse files ?
163
attr_reader :file_parser
165
# Creates an Interpreter with _target_ as the PlotMaker target
168
# As far as command-line and help is concerned, it takes a
169
# snapshot of the current commands known to the system, so
170
# please instantiate it last.
172
# \todo probably this behavior is not really desired.
174
def initialize(target)
175
@plotmaker_target = target
176
@command_line_parser =
177
Parsers::CommandLineParser.new(@@commands.values,
178
CTioga2::PlotMaker::PlotCommand)
180
@doc = Documentation::Doc.new()
181
@variables = Variables.new
183
@file_parser = Parsers::FileParser.new
187
# Parses and run the given command-line, sending the commands to
188
# the #plotmaker_target.
189
def run_command_line(args)
190
@command_line_parser.parse_command_line(args, self) do |arg|
191
puts "Non-optional argument: #{arg.first}"
195
# Parses and runs the given file. Sets PlotMaker#figure_name to
196
# the base name of the given file if no figure name was
198
def run_command_file(file)
199
@file_parser.run_command_file(file, self)
200
if ! @plotmaker_target.figure_name
201
@plotmaker_target.figure_name = file.gsub(/\.[^.]+$/,'')
205
# Parses and runs the given string.
206
def run_commands(string)
207
@file_parser.run_commands(string, self)
210
# Returns a Command object corresponding to the given _symbol_, or
211
# raises an UnknownCommand exception.
212
def get_command(symbol)
213
if @@commands.key? symbol
214
return @@commands[symbol]
216
raise UnknownCommand, "Unknown command: #{symbol}"
220
# Returns the list of all know command names
222
return @@commands.keys
225
# Runs _command_ with the given _arguments_ and _options_,
226
# converting them as necessary. All the commands ran from this
227
# interpreter should be ran from here.
229
# _command_ can be either a String or a Command
231
# Later, it could be a good idea to add a spying mechanism here.
232
def run_command(command, arguments, options = nil)
233
converted_args = command.convert_arguments(arguments)
235
converted_options = command.convert_options(options)
237
converted_options = nil
239
command.run_command(@plotmaker_target, converted_args,
245
# An alias for Commands::Command
246
Cmd = Commands::Command
248
# An alias for Commands::CommandArgument
249
CmdArg = Commands::CommandArgument
251
# An alias for Commands::CommandGroup
252
CmdGroup = Commands::CommandGroup
254
# An alias for Commands::CommandType
255
CmdType = Commands::CommandType