summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/puppet/string.rb8
-rw-r--r--lib/puppet/string/action.rb32
-rw-r--r--lib/puppet/string/action_builder.rb11
-rw-r--r--lib/puppet/string/action_manager.rb10
-rw-r--r--lib/puppet/string/option.rb24
-rw-r--r--lib/puppet/string/option_builder.rb25
-rw-r--r--lib/puppet/string/option_manager.rb46
7 files changed, 138 insertions, 18 deletions
diff --git a/lib/puppet/string.rb b/lib/puppet/string.rb
index 04db1f33b..517cf4506 100644
--- a/lib/puppet/string.rb
+++ b/lib/puppet/string.rb
@@ -2,12 +2,16 @@ require 'puppet'
require 'puppet/util/autoload'
class Puppet::String
- require 'puppet/string/action_manager'
require 'puppet/string/string_collection'
+ require 'puppet/string/action_manager'
include Puppet::String::ActionManager
extend Puppet::String::ActionManager
+ require 'puppet/string/option_manager'
+ include Puppet::String::OptionManager
+ extend Puppet::String::OptionManager
+
include Puppet::Util
class << self
@@ -58,7 +62,7 @@ class Puppet::String
def initialize(name, version, &block)
unless Puppet::String::StringCollection.validate_version(version)
- raise ArgumentError, "Cannot create string with invalid version number '#{version}'!"
+ raise ArgumentError, "Cannot create string #{name.inspect} with invalid version number '#{version}'!"
end
@name = Puppet::String::StringCollection.underscorize(name)
diff --git a/lib/puppet/string/action.rb b/lib/puppet/string/action.rb
index 5a7f3f203..4219aca0a 100644
--- a/lib/puppet/string/action.rb
+++ b/lib/puppet/string/action.rb
@@ -1,4 +1,5 @@
require 'puppet/string'
+require 'puppet/string/option'
class Puppet::String::Action
attr_reader :name
@@ -8,11 +9,10 @@ class Puppet::String::Action
end
def initialize(string, name, attrs = {})
- name = name.to_s
- raise "'#{name}' is an invalid action name" unless name =~ /^[a-z]\w*$/
-
- @string = string
- @name = name
+ raise "#{name.inspect} is an invalid action name" unless name.to_s =~ /^[a-z]\w*$/
+ @string = string
+ @name = name.to_sym
+ @options = {}
attrs.each do |k,v| send("#{k}=", v) end
end
@@ -27,4 +27,26 @@ class Puppet::String::Action
@string.meta_def(@name, &block)
end
end
+
+ def add_option(option)
+ if option? option.name then
+ raise ArgumentError, "#{option.name} duplicates an existing option on #{self}"
+ elsif @string.option? option.name then
+ raise ArgumentError, "#{option.name} duplicates an existing option on #{@string}"
+ end
+
+ @options[option.name] = option
+ end
+
+ def option?(name)
+ @options.include? name.to_sym
+ end
+
+ def options
+ (@options.keys + @string.options).sort
+ end
+
+ def get_option(name)
+ @options[name.to_sym] || @string.get_option(name)
+ end
end
diff --git a/lib/puppet/string/action_builder.rb b/lib/puppet/string/action_builder.rb
index b3db51104..fb2a749ae 100644
--- a/lib/puppet/string/action_builder.rb
+++ b/lib/puppet/string/action_builder.rb
@@ -5,10 +5,8 @@ class Puppet::String::ActionBuilder
attr_reader :action
def self.build(string, name, &block)
- name = name.to_s
- raise "Action '#{name}' must specify a block" unless block
- builder = new(string, name, &block)
- builder.action
+ raise "Action #{name.inspect} must specify a block" unless block
+ new(string, name, &block).action
end
def initialize(string, name, &block)
@@ -24,4 +22,9 @@ class Puppet::String::ActionBuilder
raise "Invoke called on an ActionBuilder with no corresponding Action" unless @action
@action.invoke = block
end
+
+ def option(name, attrs = {}, &block)
+ option = Puppet::String::OptionBuilder.build(@action, name, attrs, &block)
+ @action.add_option(option)
+ end
end
diff --git a/lib/puppet/string/action_manager.rb b/lib/puppet/string/action_manager.rb
index c29dbf454..c980142ce 100644
--- a/lib/puppet/string/action_manager.rb
+++ b/lib/puppet/string/action_manager.rb
@@ -5,20 +5,15 @@ module Puppet::String::ActionManager
# the code to do so.
def action(name, &block)
@actions ||= {}
- name = name.to_s.downcase.to_sym
-
raise "Action #{name} already defined for #{self}" if action?(name)
-
action = Puppet::String::ActionBuilder.build(self, name, &block)
-
- @actions[name] = action
+ @actions[action.name] = action
end
# This is the short-form of an action definition; it doesn't use the
# builder, just creates the action directly from the block.
def script(name, &block)
@actions ||= {}
- name = name.to_s.downcase.to_sym
raise "Action #{name} already defined for #{self}" if action?(name)
@actions[name] = Puppet::String::Action.new(self, name, :invoke => block)
end
@@ -36,7 +31,8 @@ module Puppet::String::ActionManager
end
def get_action(name)
- @actions[name].dup
+ @actions ||= {}
+ @actions[name.to_sym]
end
def action?(name)
diff --git a/lib/puppet/string/option.rb b/lib/puppet/string/option.rb
new file mode 100644
index 000000000..bdc3e07c5
--- /dev/null
+++ b/lib/puppet/string/option.rb
@@ -0,0 +1,24 @@
+class Puppet::String::Option
+ attr_reader :name, :string
+
+ def initialize(string, name, attrs = {})
+ raise "#{name.inspect} is an invalid option name" unless name.to_s =~ /^[a-z]\w*$/
+ @string = string
+ @name = name.to_sym
+ attrs.each do |k,v| send("#{k}=", v) end
+ end
+
+ def to_s
+ @name.to_s.tr('_', '-')
+ end
+
+ Types = [:boolean, :string]
+ def type
+ @type ||= :boolean
+ end
+ def type=(input)
+ value = begin input.to_sym rescue nil end
+ Types.include?(value) or raise ArgumentError, "#{input.inspect} is not a valid type"
+ @type = value
+ end
+end
diff --git a/lib/puppet/string/option_builder.rb b/lib/puppet/string/option_builder.rb
new file mode 100644
index 000000000..2087cbc99
--- /dev/null
+++ b/lib/puppet/string/option_builder.rb
@@ -0,0 +1,25 @@
+require 'puppet/string/option'
+
+class Puppet::String::OptionBuilder
+ attr_reader :option
+
+ def self.build(string, name, attrs = {}, &block)
+ new(string, name, attrs, &block).option
+ end
+
+ private
+ def initialize(string, name, attrs, &block)
+ @string = string
+ @option = Puppet::String::Option.new(string, name, attrs)
+ block and instance_eval(&block)
+ @option
+ end
+
+ # Metaprogram the simple DSL from the option class.
+ Puppet::String::Option.instance_methods.grep(/=$/).each do |setter|
+ next if setter =~ /^=/ # special case, darn it...
+
+ dsl = setter.sub(/=$/, '')
+ define_method(dsl) do |value| @option.send(setter, value) end
+ end
+end
diff --git a/lib/puppet/string/option_manager.rb b/lib/puppet/string/option_manager.rb
new file mode 100644
index 000000000..df3ae6b4b
--- /dev/null
+++ b/lib/puppet/string/option_manager.rb
@@ -0,0 +1,46 @@
+require 'puppet/string/option_builder'
+
+module Puppet::String::OptionManager
+ # Declare that this app can take a specific option, and provide
+ # the code to do so.
+ def option(name, attrs = {}, &block)
+ @options ||= {}
+ raise ArgumentError, "Option #{name} already defined for #{self}" if option?(name)
+ actions.each do |action|
+ if get_action(action).option?(name) then
+ raise ArgumentError, "Option #{name} already defined on action #{action} for #{self}"
+ end
+ end
+ option = Puppet::String::OptionBuilder.build(self, name, &block)
+ @options[option.name] = option
+ end
+
+ def options
+ @options ||= {}
+ result = @options.keys
+
+ if self.is_a?(Class) and superclass.respond_to?(:options)
+ result += superclass.options
+ elsif self.class.respond_to?(:options)
+ result += self.class.options
+ end
+ result.sort
+ end
+
+ def get_option(name)
+ @options ||= {}
+ result = @options[name.to_sym]
+ unless result then
+ if self.is_a?(Class) and superclass.respond_to?(:get_option)
+ result = superclass.get_option(name)
+ elsif self.class.respond_to?(:get_option)
+ result = self.class.get_option(name)
+ end
+ end
+ return result
+ end
+
+ def option?(name)
+ options.include? name.to_sym
+ end
+end