Basically, we have many modules under the Config:: namespace out on CPAN, many of which serve different purposes and most of which have totally different interfaces. For the sake of the examples, I'll use the package name CFI (Config File Interface). The idea is to build a DBI-like abstraction layer where the programmer provides a format name, and can easily support or convert between any number of different formats. They would all support some common functions and could easily implement extended functionality as well.
An example for use with Config::IniFiles:ServerRoot "d:/wamp/apache2" Timeout 300 Alias /icons/ "d:/wamp/Apache2/icons/" <Directory "d:/wamp/Apache2/icons"> Options Indexes MultiViews AllowOverride None Order allow,deny Allow from all </Directory> Alias /manual/ "d:/wamp/Apache2/htdocs/manual/" <Directory "d:/wamp/Apache2/htdocs/manual"> Options Indexes AllowOverride None Order allow,deny Allow from all <Files *.html> SetHandler type-map </Files> SetEnvIf Request_URI ^/manual/(de|en|es|fr|ja|ko|ru)/ prefer-langu +age=$1 RedirectMatch 301 ^/manual(?:/(de|en|es|fr|ja|ko|ru)){2,}(/.*)?$ / +manual/$1$2 </Directory> ScriptAlias /cgi-bin/ "d:/wamp/Apache2/cgi-bin/" <Directory "d:/wamp/apache2/cgi-bin"> AllowOverride None Options None Order allow,deny Allow from all </Directory>
An example for use with YAML:security = user workgroup = WORKGROUP [homes] comment = Home Directories browseable = no writable = yes readonly = no available = yes public = no
--- name: ingy age: old weight: heavy # I should comment that I also like pink, but don't tell anybody. favorite colors: - red - green - blue
For existing Config:: modules, someone (the original authors, if they'd like to) would write a wrapper specifically for this interface, such as CFD::General for the existing Config::General (again following the DBI/DBD example). And any new formats could be implemented directly under the standard interface. They would all implement a set of common accessor functions, up to the level of complexity that the file format supports. They should all have a way to read (and most should have a way to write) config files:use CFI; # OBJECT = new( FORMAT ); # FORMAT - scalar string denoting the file format to use # note that the case of the format wouldn't matter..."inifiles" and "I +niFiles" would be equivalent my $config_general = new CFI('general'); my $config_inifiles = new CFI('inifiles'); my $config_yaml = new CFI('yaml');
The programmer should be able to access deeply nested structures just as easily as flat or shallow structures. There would be at least three logical seperations of data...parameters, blocks, and attributes:# BOOLEAN = ->read_config( SOURCE, OPTIONS ); # SOURCE - scalar containing filename, scalar ref containing file c +ontents, or filehandle to read from # OPTIONS - hash reference containing any driver-specific options $config_general->read_config(\*CONFIG_FILE, { -AllowMultiOptions => 1, + -AutoTrue => 1 }); $config_inifiles->read_config('./test.ini', { -nocase => 1, -allowcont +inue => 1, -commentchar => ';' }); $config_yaml->read_config(\$default_values); # BOOLEAN = ->write_config( DESTINATION, OPTIONS ); # DESTINATION - scalar containing filename, or scalar ref to assign +contents to, or filehandle to write to # OPTIONS - hash reference containing any driver-specific option +s $config_general->write(\*CONFIG_OUTPUT); $config_yaml->write('~/test.yml');
So thats the initial concept, it would become trivial to write an application that accepts multiple config file formats or converts from one format to another. Even just migrating an existing application from one format to another would be much easier. There will be issues, of course, since all possible config formats may not fit within this scheme, but I'm sure it could be improved.# VALUE = ->param( BLOCKS, FIELD ); # BLOCKS - name(s) of any number of logical blocks (or a single unde +f to use default (root) block) # FIELD - name of field to retrieve (or undef to retrieve all field +names in given block) # parameters are name:value pairs. if undef is passed as a parameter, + return a list of all parameters in current block $config_general->param('Directory','d:/wamp/Apache2/htdocs/manual','Fi +les','*.html','SetHandler'); # returns 'type-map' $config_inifiles->param('homes',undef); # returns array ('comment','br +owseable','writable','readonly','available','public') $config_yaml->param('favorite colors'); # returns ['red','green','blue +'] # VALUE = ->block( BLOCKS ); # BLOCKS - name(s) of any number of logical blocks (or a single unde +f to use default (root) block) # blocks are groups or sections that contain parameters $config_general->block('Directory'); # returns ('d:/wamp/Apache2/icons +','d:/wamp/Apache2/htdocs/manual','d:/wamp/apache2/cgi-bin') $config_inifiles->block(); # returns ('homes') $config_yaml->block(); # returns ('name','age','weight','favorite colo +rs') # HASHREF = ->export(); # this exports the entire configuration as a hashref structure. usefu +l for converting one format to another # BOOLEAN = ->import( CONFIG ); # CONFIG - hash reference containing an entire configuration # this takes a structure of anonymous hashes and arrays and interprets + it as a config structure. $config_general->import( $config_yaml->export() );
Suggestions, comments, admonishments? I'm eager for feedback, positive or negative, but please, if you downvote me for this, at least tell me why :)
Update: cleaned up the (admittedly) convoluted code examples a bit, in response to chromatic's reply
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: RFC: Standard configuration interface...
by LTjake (Prior) on Feb 19, 2007 at 01:42 UTC | |
by EvanK (Chaplain) on Feb 20, 2007 at 16:55 UTC | |
|
Re: RFC: Standard configuration interface...
by chromatic (Archbishop) on Feb 18, 2007 at 21:46 UTC | |
|
Re: RFC: Standard configuration interface...
by Herkum (Parson) on Feb 20, 2007 at 19:19 UTC | |
by EvanK (Chaplain) on Feb 20, 2007 at 21:15 UTC | |
|
Re: RFC: Standard configuration interface...
by ides (Deacon) on Feb 21, 2007 at 22:20 UTC |