J
John W. Long
------=_NextPart_000_0020_01C3C4E8.FCD59B60
Content-Type: text/plain;
charset="Windows-1252"
Content-Transfer-Encoding: 7bit
A while back someone submitted some code to this list for evaluating
Configuration files in the style of:
% cat test.config
editor.spacespertab = 4
toolbar.visible = true
statusbar.visible = false
. . .
One of the great things about their code was that it enabled you to use ruby
code within your configuration file so you could do things like this:
%cat test2.config
timer.alarm = 30 * 60 # set the timer to go off in 30 min
Their implementation was pretty simple. Mainly they created a hash,
splitting each line on /=/, and evaled the right side and stored the result
in the hash with a key of the left side.
I like this concept, but I wanted a better implementation. So I set to work
and created the attached files. The attached now enables you to do this:
%cat myprog.rb
require 'config'
$conf = Config.new
# set up the default values and configuration structure:
$conf.define %{
editor.spacespertab = 8
toolbar.visible = false
toolbar.caption = "Tools"
statusbar.visible = true
copyright = "Copyright © 2003, John W. Long"
}
$conf.read File.new('test.config', 'r').read
# you can even read multi line ruby snippets:
$conf.read %{
copyright = "Copyright © 2003, John W. Long
All Rights Reserved"
alarm = 30 * 60 #seconds
}
# now for getting the values, note the object hierarchy
toolbar.caption = $conf.toolbar.caption.value
toolbar.show if $conf.toolbar.visible.value
aboutbox.copyright = $conf.copyright.value
. . .
You get the idea.
A couple of advantages that this has over the previous concept:
-- You define the default values and create the config structure at the same
time
-- Because you define a config structure if someone makes a typo in the
config file misspelling "toolbar" as "tolbar" an error will be thrown
(eventually it will even tell you what line the error was on)
-- You access the values from the config file in almost the same way that
they are written into the config file on your Config object
I didn't attach the unit tests of this version because the code still
relatively crude. Once I get things worked out a bit I may post it on
RubyForge.
Feedback is appreciated.
___________________
John Long
www.wiseheartdesign.com
------=_NextPart_000_0020_01C3C4E8.FCD59B60
Content-Type: application/octet-stream;
name="cleanobject.rb"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename="cleanobject.rb"
class CleanObject=0A=
alias :__extend__ :extend=0A=
alias :__instance_eval__ :instance_eval=0A=
def initialize=0A=
methods.each { |s|=0A=
symbol =3D s.intern=0A=
next if s =3D~ /^__.*__$/=0A=
next if [:instance_eval].include?(symbol)=0A=
instance_eval %{ undef :#{symbol.to_s} }=0A=
}=0A=
instance_eval %{ undef :instance_eval }=0A=
end=0A=
end=0A=
------=_NextPart_000_0020_01C3C4E8.FCD59B60
Content-Type: application/octet-stream;
name="config.rb"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename="config.rb"
require "cleanobject"=0A=
=0A=
class Config=0A=
module Node=0A=
attr_accessor :__defining__, :__children__, :value=0A=
def __defining__=3D(value)=0A=
@__children__ ||=3D Hash.new=0A=
@__children__.each{ |s, v|=0A=
v.__defining__ =3D value=0A=
}=0A=
@__defining__ =3D value=0A=
end=0A=
def method_missing(symbol, *args)=0A=
@__children__ ||=3D Hash.new=0A=
if @__defining__ =0A=
s =3D symbol.to_s=0A=
s =3D $1 if s =3D~ /(.*)=3D$/=0A=
__instance_eval__ <<-CODE=0A=
def #{s}=3D(value)=0A=
unless @__children__.has_key?#{s})=0A=
n =3D CleanObject.new=0A=
n.__extend__(Node)=0A=
n.__defining__ =3D true=0A=
@__children__[:#{s}] =3D n=0A=
end=0A=
@__children__[:#{s}].value =3D value=0A=
end=0A=
def #{s}=0A=
unless @__children__.has_key?#{s})=0A=
n =3D CleanObject.new=0A=
n.__extend__(Node)=0A=
n.__defining__ =3D true=0A=
@__children__[:#{s}] =3D n=0A=
end=0A=
@__children__[:#{s}]=0A=
end=0A=
CODE=0A=
__send__ symbol, *args=0A=
else=0A=
raise NoMethodError, "undefined method `#{symbol}'"=0A=
end=0A=
end=0A=
end=0A=
=0A=
def initialize=0A=
@root =3D CleanObject.new=0A=
@root.__extend__(Node)=0A=
end=0A=
=0A=
def define(object)=0A=
@root.__defining__ =3D true=0A=
@root.__instance_eval__(prep(object.to_s))=0A=
@root.__defining__ =3D false=0A=
end=0A=
=0A=
def read(object)=0A=
@root.__instance_eval__(prep(object.to_s))=0A=
end=0A=
=0A=
def prep(string)=0A=
code =3D ""=0A=
string.each { |line|=0A=
c =3D line.strip=0A=
c =3D "self.#{c}" unless c =3D~ /^self\./ or c !~ /=3D/=0A=
code << "#{c}\n"=0A=
}=0A=
code=0A=
end=0A=
=0A=
def method_missing(symbol, *args)=0A=
@root.__send__ symbol, *args=0A=
end=0A=
end=0A=
------=_NextPart_000_0020_01C3C4E8.FCD59B60--
Content-Type: text/plain;
charset="Windows-1252"
Content-Transfer-Encoding: 7bit
A while back someone submitted some code to this list for evaluating
Configuration files in the style of:
% cat test.config
editor.spacespertab = 4
toolbar.visible = true
statusbar.visible = false
. . .
One of the great things about their code was that it enabled you to use ruby
code within your configuration file so you could do things like this:
%cat test2.config
timer.alarm = 30 * 60 # set the timer to go off in 30 min
Their implementation was pretty simple. Mainly they created a hash,
splitting each line on /=/, and evaled the right side and stored the result
in the hash with a key of the left side.
I like this concept, but I wanted a better implementation. So I set to work
and created the attached files. The attached now enables you to do this:
%cat myprog.rb
require 'config'
$conf = Config.new
# set up the default values and configuration structure:
$conf.define %{
editor.spacespertab = 8
toolbar.visible = false
toolbar.caption = "Tools"
statusbar.visible = true
copyright = "Copyright © 2003, John W. Long"
}
$conf.read File.new('test.config', 'r').read
# you can even read multi line ruby snippets:
$conf.read %{
copyright = "Copyright © 2003, John W. Long
All Rights Reserved"
alarm = 30 * 60 #seconds
}
# now for getting the values, note the object hierarchy
toolbar.caption = $conf.toolbar.caption.value
toolbar.show if $conf.toolbar.visible.value
aboutbox.copyright = $conf.copyright.value
. . .
You get the idea.
A couple of advantages that this has over the previous concept:
-- You define the default values and create the config structure at the same
time
-- Because you define a config structure if someone makes a typo in the
config file misspelling "toolbar" as "tolbar" an error will be thrown
(eventually it will even tell you what line the error was on)
-- You access the values from the config file in almost the same way that
they are written into the config file on your Config object
I didn't attach the unit tests of this version because the code still
relatively crude. Once I get things worked out a bit I may post it on
RubyForge.
Feedback is appreciated.
___________________
John Long
www.wiseheartdesign.com
------=_NextPart_000_0020_01C3C4E8.FCD59B60
Content-Type: application/octet-stream;
name="cleanobject.rb"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename="cleanobject.rb"
class CleanObject=0A=
alias :__extend__ :extend=0A=
alias :__instance_eval__ :instance_eval=0A=
def initialize=0A=
methods.each { |s|=0A=
symbol =3D s.intern=0A=
next if s =3D~ /^__.*__$/=0A=
next if [:instance_eval].include?(symbol)=0A=
instance_eval %{ undef :#{symbol.to_s} }=0A=
}=0A=
instance_eval %{ undef :instance_eval }=0A=
end=0A=
end=0A=
------=_NextPart_000_0020_01C3C4E8.FCD59B60
Content-Type: application/octet-stream;
name="config.rb"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename="config.rb"
require "cleanobject"=0A=
=0A=
class Config=0A=
module Node=0A=
attr_accessor :__defining__, :__children__, :value=0A=
def __defining__=3D(value)=0A=
@__children__ ||=3D Hash.new=0A=
@__children__.each{ |s, v|=0A=
v.__defining__ =3D value=0A=
}=0A=
@__defining__ =3D value=0A=
end=0A=
def method_missing(symbol, *args)=0A=
@__children__ ||=3D Hash.new=0A=
if @__defining__ =0A=
s =3D symbol.to_s=0A=
s =3D $1 if s =3D~ /(.*)=3D$/=0A=
__instance_eval__ <<-CODE=0A=
def #{s}=3D(value)=0A=
unless @__children__.has_key?#{s})=0A=
n =3D CleanObject.new=0A=
n.__extend__(Node)=0A=
n.__defining__ =3D true=0A=
@__children__[:#{s}] =3D n=0A=
end=0A=
@__children__[:#{s}].value =3D value=0A=
end=0A=
def #{s}=0A=
unless @__children__.has_key?#{s})=0A=
n =3D CleanObject.new=0A=
n.__extend__(Node)=0A=
n.__defining__ =3D true=0A=
@__children__[:#{s}] =3D n=0A=
end=0A=
@__children__[:#{s}]=0A=
end=0A=
CODE=0A=
__send__ symbol, *args=0A=
else=0A=
raise NoMethodError, "undefined method `#{symbol}'"=0A=
end=0A=
end=0A=
end=0A=
=0A=
def initialize=0A=
@root =3D CleanObject.new=0A=
@root.__extend__(Node)=0A=
end=0A=
=0A=
def define(object)=0A=
@root.__defining__ =3D true=0A=
@root.__instance_eval__(prep(object.to_s))=0A=
@root.__defining__ =3D false=0A=
end=0A=
=0A=
def read(object)=0A=
@root.__instance_eval__(prep(object.to_s))=0A=
end=0A=
=0A=
def prep(string)=0A=
code =3D ""=0A=
string.each { |line|=0A=
c =3D line.strip=0A=
c =3D "self.#{c}" unless c =3D~ /^self\./ or c !~ /=3D/=0A=
code << "#{c}\n"=0A=
}=0A=
code=0A=
end=0A=
=0A=
def method_missing(symbol, *args)=0A=
@root.__send__ symbol, *args=0A=
end=0A=
end=0A=
------=_NextPart_000_0020_01C3C4E8.FCD59B60--