ConfigLoader
============
:Author: ct
:Date: 2008-08-07

link:Lumiera/ConfigLoader[] is a brainstorming about our configuration file loader.

Table of Contents
-----------------

. xref:anchor_api[API]
 .. xref:anchor_config[lumiera_configfile]
 .. xref:anchor_types[provided TYPES]
 .. xref:anchor_syntax[Syntax/Semantics]
   * xref:anchor_proposal[Syntax Proposal by cehteh]
 .. xref:anchor_links[links]
 .. xref:anchor_internals[internals/implementation sketch]
. xref:anchor_discussion[Discussion on IRC]
. xref:anchor_brainstorm[Brainstorming]


anchor:anchor_api[]API
----------------------

* Namespace is lumiera_config_*
* `struct lumiera_config_struct` for the config system, only one object needed
* `lumiera_config_init (...)`
  - does only initialize the variables, so that they get valid values, but does not allocate them as they will be allocated before as they are singleton.
  - lumiera_config_init (const char* searchpath) searchpath is a buildin-default, can be changed via configure and can be appended and overridden by using a flag, e.g. `--config-path-append=""` or `--config-path=""`

* `lumiera_config_destroy(...)`
  - frees all space allocated by the link:ConfigLoader[].

* `lumiera_config_load(...)`
  - reads *one* single configuration file that will include all settings from other files.
  - does not read itself but give delegates reading. The actual reading and parsing will be done in configfile object. s.later.

* `lumiera_config_save(...)`
  - saves all the changed settings to user's configuration files, but recognizes where settings came from and will write them to an appropriate named file. Example: *changed* values from  `'/usr/local/share/lumiera/plugins/blur.conf'` will be saved into `'~/.lumiera/plugins/blur.conf'`
  - finds out which files are dirty and which settings have to be written to user's config files.
  - does initiate the actual saving procedure by delegating the save to the actual configfile objects, see below.
  - empty user configuration files in RAM will be deleted from disk on write.
  - checks whether the file has changed since last read, and will print out an error if necessary instead of overriding it without notification.
+
`lumiera_config_save () { LLIST_FOREACH(config_singleton.files, f) { LumieraFile file = (LumieraFile) f; if(lumiera_configfile_isdirty (file)) lumiera_configfile_save(file); } }`

* `lumiera_config_purge(const char* filename)` removes all configs loaded from filename

* `lumiera_config_get(...)`
  - get a value by key
  - handles internally everything as string:string key:value pair.
  - lowlevel function
  - lumiera_config_integer_get (const char* key, int *value) will return integers instead of strings and return 0 if succeeded and -1 if it failed.

  - 'int lumiera_config_TYPE_get(const char* key, TYPE* value, const char* default)'
    High level config interface for different types.
    if default is given (!NULL) then value is set to default in case key was not found or any other error occured.
    error code is still set and -1 (fail) is returned in case of an error, but it might be cleared with no ill effects.
    NOTE: errors are persistent in our error handler, they must still be cleared, even when ignored.
          if default is given then `KEY_NOT_FOUND` is not a error here, if default is NULL then it is
    NOTE2: default values are given as strings, the config loader remembers a given default value and checks if it got changed
           when it is _set(). Thus a default value can be suppressed when set/written

* `lumiera_config_set(...)`
  - set a value by key
  - handles internally everything as string:string key:value pair.
  - lowlevel function
  - tag file as dirty
  - set will create a new user configuration file if it does not exist yet or will append a line to the existing one in RAM. These  files, tagged as \'dirty', will be only written if save() is called.
  - `lumiera_config_TYPE_set (const char* key, TYPE*value, const char* fmt)`
    Highlevel interface for different types, fmt is a printf format specifier for the desired format, when NULL, defaults apply.

* `lumiera_config_reset(...)`
  - reset a value by key to the system default values, thus removes a user's configuration line.

* `lumiera_config_info (const char* key, const char** filename, unsigned* line)`
  - Find exact place of a setting.

[NOTE]
=======================================
* multiple config items with the same key stack (to allow undo/removing custom configs)
* same keys in the same file stack also, the _get api returns the last value the _set api sets the last value
* we might need to implement some cursor api to retrieve all values with the same key, this should allow to filter keys from single files!
* if one queries a setting with a default, this default should be stored in the configuration system without an backing file on disk. Rationale is, that when one later _set's a value and this value is found to be equivalent to the default, this _set option is a no-op
=======================================

.foo.bar
=======================================
`integer_set("foo.bar", 123)`
looks up "foo.bar"
this returns as well file and line
it will be decided whether it's a system file or a user's config file.
if systemfile: loop for user's config file, if necessary create it in our RAM but not yet on disk
set the value in the line.
=======================================


anchor:anchor_config[]lumiera_configfile
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

* `lumiera_configfile_struct`
  - contains a `llist` with all lines stored as `lumiera_configline_struct`
  - contains an integer that indicates how \'dirty' the file is, i.e. how many settings were changed. (one increment per _set() call)
  - contains a stat struct for comparison while saving if the file was altered since last read

* `lumiera_configline_struct`
  - stores the line exactly as read from file, but holds as well pointers to the key and the value.

* lumiera_configfile_load
* lumiera_configfile_save
* lumiera_configfile_new
* lumiera_configfile_delete
* lumiera_configfile_init
* lumiera_configfile_destroy



anchor:anchor_types[]provided TYPES
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

[grid="all"]
`--------------.--------------------------------------'------------------------------------------------------------
config type     C type					semantic (example)
-------------------------------------------------------------------------------------------------------------------
number		signed long long			also hex and octal (foo.bar = 12345 #comment)
real		long double				differerent formats as well (foo.bar=1.2345 #comment) 
string		const char*				optionaly quoted string (foo.bar="this string" #this not)
word		const char*				first optionaly quoted word of the config (foo.bar= first this # not)
bool		int					common representations for bools (0,1,true,false,yes,no,on,off,set,clear) 
-------------------------------------------------------------------------------------------------------------------

... add more types on demand (ichthyo mentioned a tuple type for color triples etc.)

config files/strings are utf-8!


anchor:anchor_syntax[]Syntax/Semantics
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

...to be defined...

in short:

* configfiles allow comments,
* some kind of include directive
* includes happen only \'once', its impossible to create include recursions
* config settings are key:value pairs where the key is a hierachical string as in "foo.bar.baz"


anchor:anchor_proposal[]Syntax Proposal by cehteh
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

simple example:

------------------------------------------------------------
@directive options
key = value
[prefix]
[prefix suffix]
------------------------------------------------------------

ebnf:

------------------------------------------------------------
configline ::= [ whitespace ] , { comment | directive | configentry | section } , ? end of line ? ;

whitespace ::= ? one to many tab or blank ? ;

comment ::= "#" , ? arbitary text ? ;

directive ::= "@", ? commandword ? , whitespace, ? arguments ? ;

configentry ::= key, { whitespace } , assignop, value ;

key ::= ? lowercase characters and _ ? , [ "." , key ] ;

assignop ::=  " " | ":" | "=" ;

value ::= ? arbitary text ? ;

section ::= "link:, [ whitespace ] , prefix, [ whitespace, suffix ] , [ whitespace ] []" | emptysection ;

emptysection ::= "[]" ;
prefix ::= key ;
suffix ::= key ;
------------------------------------------------------------

semantics notes:

* The format is strictly line-based
* directives inside non empty sections are not yet defined
* sections can't nest so far (idea: thinking about `[ .extend.with.leading.dot ]`)
* section semantics: a key inside a section `[foo bar]` as in `key=value` is treated as `foo.key.bar=value`


anchor:anchor_links[]links
~~~~~~~~~~~~~~~~~~~~~~~~~~

http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html[]


anchor:anchor_internals[]internals/implementation sketch
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

* `config` *singleton*
  - has a cuckoo hash for lookups
  - holds many `configfile` in a linked list

* `configfile` is a `configitem`
  - holds `lines` as `section` or `directive` starting with the empty section
  - there is one special unnamed (non-disk) file for _defaults_

* `configitem`
  - just an abstraction, we prolly dont need an implementation

* `section` is a `line`
  - parses prefix/suffix
  - holds list of childs of `configline` or `other` lines

* `line` is a `configitem`
  - holds the allocated string (char*)
  - backpointer to parent item (section or file)
  - 2 pointers+length to parsed data, key/value for `configline`, prefix/suffix for `section`

* `configline` is a `line`
  - parses key/value as raw strings
  - maintains lookup hash in ctor/dtor

* `other` is a `line`
  - comment or empty line, just preserved nothing special

* `directive` is a `line`
  - must appear in a empty section, else this is an error


anchor:anchor_discussion[]discussion on irc
-------------------------------------------

------------------------------------------------------------
[01:21] <cehteh> joelholdsworth_: you seen the upcoming config interface i planned with simav?
[01:21] <mno> what about using ardours icons to start with?
[01:21] <joelholdsworth_> *least
[01:22] <joelholdsworth_> cehteh: not yeat, can I see
[01:22] <joelholdsworth_> mno: ardour icons arn't that useful
[01:22] <joelholdsworth_> there aren't that many
[01:22] <cehteh> http://www.pipapo.org/pipawiki/Lumiera/ConfigLoader[]
[01:22] <cehteh> question for you: do you need any more 'types'
[01:22] <joelholdsworth_> and those that are there are probably among the gtk stock set anywhere
[01:22] <cehteh> ichthyo suggested color triples
[01:23] <cehteh> anythinfg you have in mind, just suggest it
[01:23] <joelholdsworth_> so is the this structured like an ini file
[01:23] <joelholdsworth_> sections and keys?
[01:23] <joelholdsworth_> or is it treelike?
[01:24] <cehteh> little unordered, you basically just need to care for lumiera_config_TYPE_get ... and *_set
[01:24] <cehteh> like ini, not nested
[01:24] <joelholdsworth_> flat is good
[01:24] <joelholdsworth_> simple
[01:24] <cehteh> the namespaces are nested
[01:24] <cehteh> but the sectioning is not
[01:24] <cehteh> you can have
[01:24] <cehteh> [gui]
[01:24] <__nasa__> Have you all see Agave (for colorscheme generation)?
[01:24] <cehteh>  foo = bar
[01:25] <cehteh> [gui.baz]
[01:25] <cehteh>  barf= 123
[01:25] <cehteh> its not exactly ini style but close
[01:25] <joelholdsworth_> cehteh: ooh - does mean we can levarge an ini parser?
[01:25] <joelholdsworth_> that would save some work and maintenance effore
[01:25] <cehteh> hey simav want to write the parser himself :P
[01:25] <joelholdsworth_> __nasa__: agave: interesting
[01:26] <joelholdsworth_> cehteh: would he though
[01:26] <cehteh> well i think thats fun to do by ourself :)
[01:26] <joelholdsworth_> it is just like ini
[01:26] <joelholdsworth_> yeah
[01:26] <cehteh> and i plan some special things
[01:26] <joelholdsworth_> but reduction of volume is good
[01:26] <cehteh> like for example setting values from the gui preserves the rest of the data
[01:26] <cehteh> when you have
[01:26] <__nasa__> cehteh: suffixes?
[01:27] <cehteh> [gui.foo bar]
[01:27] <cehteh>  dada = 1234 #comment
[01:27] <__nasa__> I just saw the bottom...
[01:27] <cehteh> that is    gui.foo.dada.bar = 1234 # comment
[01:27] <cehteh> see suffix
[01:28] <cehteh> more in a moment
[01:28] <joelholdsworth_> still an ini parser would be happy with that
[01:28] <cehteh> what i want to tell to joel
[01:28] <joelholdsworth_> of course you have to add some extra code to the end to make the tree
[01:28] <joelholdsworth_> but that would make our lives simpler
[01:29] <cehteh> when you now have a gui which does gui_config_number_set ("gui.foo.dada.bar", 6666)
[01:29] <cehteh> then
[01:29] <cehteh> [gui.foo bar]
[01:29] <cehteh>  dada = 6666 #comment
[01:29] <cehteh> appears in the configfile
[01:29] <joelholdsworth_> did you mean...
[01:29] <cehteh> meaning preserving everything manually set up
[01:29] <joelholdsworth_> [gui.foo.dada]
[01:29] <__nasa__> cehteh: How does it know not to do
[01:29] <joelholdsworth_> bar = 6666 #comment
[01:29] <joelholdsworth_> ?
[01:30] <__nasa__> [gui dada.bar]
[01:30] <__nasa__> foo = 6666 #comment
[01:30] <__nasa__> joelholdsworth_: that works as well :)
[01:31] <cehteh> it just selects best fit sections which already exist
[01:31] <joelholdsworth_> but isn't it supposed to be this way...
[01:31] <cehteh> best fit .. first prefix, then suffix
[01:31] <joelholdsworth_> so [foo.bar] is different from [bar.foo]
[01:31] <__nasa__> Ok.
[01:31] <cehteh> if nothing fits then it places it at a non sectioned part in verbose way
[01:31] <cehteh> joelholdsworth_: yes
[01:31] <__nasa__> (I just wanted to make sure we had a decision on that, as I agree that is the best way)
[01:31] <cehteh> so rationale about sections:
[01:32] <cehteh> rather rarely used but you can do things like
[01:32] <cehteh> [plugin radius]
[01:32] <cehteh>  blur = 1
[01:32] <cehteh>  sharpen = 2
[01:33] <cehteh> or same for key shortcuts what simav initiall intended
[01:33] <joelholdsworth_> wouldn't it be simpler to have simpler systaxx
[01:34] <joelholdsworth_> and have it always with dots or with spaces
[01:34] <cehteh> well the prefix stuff is completely optinal
[01:34] <joelholdsworth_> that way you can't have 1 section in twice
[01:34] <cehteh> eh?
[01:34] <joelholdsworth_> well is [plugin radius] the same as [plugin.radius] ?
[01:34] <cehteh> no
[01:35] <joelholdsworth_> good
[01:35] <joelholdsworth_> ok
[01:35] <cehteh> [plugin radius]  would be suffix prefix
[01:35] <joelholdsworth_> seems overkill to me
[01:35] <cehteh> err opposite
[01:35] <joelholdsworth_> I'd just stick with one or the other
[01:35] <cehteh> <tired
[01:36] <cehteh> [plugin radius]  would be prefix suffix
[01:36] <cehteh> [plugin.radius]  is just prefix
[01:36] <mno> i'm trying to understand all this hehe
[01:37] <cehteh> the idea is that with just prefix you have to settle with a quite rigid hierachy where you know that things will always be ordered by the leaves
[01:37] <cehteh> that doesnt fit for everyone
[01:38] <joelholdsworth_> "ordered by the leaves" ?
[01:38] <cehteh> one might want to configure his plugins one affter each other
[01:38] <__nasa__> Here is what I think is cool about the setup: it means that we can treat builtins and plugins the same.
[01:38] <cehteh> imagine we have    blur and sharben
[01:38] <cehteh> sharpen
[01:38] <__nasa__> [plugin radius]
[01:39] <__nasa__> cinelerra.sharpen = 3
[01:39] <cehteh> both have a radius and a algorihtm. lets say horizontal or vertical
[01:39] <__nasa__> rotate = 2
[01:39] <cehteh> so then you can either first configure blur
[01:39] <cehteh> [plugin.blur]
[01:39] <cehteh>   radius = 1
[01:39] <cehteh>   algo = horiz
[01:40] <joelholdsworth_> oooh! - have you thought of simply using libconfig?
[01:40] <cehteh> # and then sharpen
[01:40] <cehteh> [plugin.sharpen]
[01:40] <cehteh>   radius = 2
[01:40] <cehteh>   algo = horiz
[01:40] <cehteh> ..
[01:40] <__nasa__> joelholdsworth_: that format looks a little painful, but it could work.
[01:41] <joelholdsworth_> it's like JSON I think
[01:41] <cehteh> hey so far thats just like ini
[01:41] <cehteh> well now about suffix
[01:41] <joelholdsworth_> ok
[01:41] <cehteh> imagine you want to configure things by 'topics' ..
[01:42] <cehteh> # first define radius for our plugins
[01:42] <cehteh> [plugin radius]
[01:42] <cehteh>   blur = 1
[01:42] <cehteh>   sharpen = 2
[01:42] <cehteh> # then algo
[01:43] <cehteh> [plugin algo]
[01:43] <joelholdsworth_> yes that's quite clever
[01:43] <cehteh>   sharpen = horiz
[01:43] <cehteh>   blur = horiz
[01:43] <joelholdsworth_> but still it seems overkill
[01:43] <__nasa__> joelholdsworth_: It does look similar to JSON, but more C-like. For example, there are semi-colons instead of commas at the ends of single values.
[01:43] <cehteh> well its completely optional and we can leave it out
[01:43] <joelholdsworth_> these files are not primarily for humans
[01:44] <cehteh> yeah
[01:44] <joelholdsworth_> and also that prefix thing while clever is quite non obvious when you first see it in the file
[01:44] <__nasa__> Yes, but I am a big proponent of trying to make things human readable
[01:44] <cehteh> git works the same way
[01:44] <joelholdsworth_> sure it should be human readable
[01:44] <cehteh> .git/config
[01:44] <__nasa__> So if anything does go wrong, the user can fix it.
[01:45] <joelholdsworth_> well I'm not sure the prefixes thing is obvious enough
[01:45] <cehteh> well and we will have plenty of values which dont need a gui
[01:45] <cehteh> see about:config for firefox
[01:45] <__nasa__> I think that INI is much easier to read than libconfig, even though I have been programming in C for years and I have never edited a windows INI file.
[01:46] <joelholdsworth_> I think I agree
[01:46] <cehteh> they have all defaults and only when altered they are recorded to a config file but they dont need any special gui
[01:46] <__nasa__> about:config is so nasty.
[01:46] <cehteh> well its mighty
[01:46] <joelholdsworth_> but yes all of about:config could be stored in ini format
[01:46] <joelholdsworth_> [accessibility.typeaheadfind]
[01:46] <cehteh> and anything which is commonly changed should have a preferences gui
[01:46] <joelholdsworth_> linksonly=false
[01:47] <cehteh> btw our configs are not enumerateable
[01:47] <cehteh> i dont want the rest of the system to register there, that will be pita
[01:47] <cehteh> you can freely introduce configs (within your namespace)
[01:48] <-- benG has quit (Remote closed the connection)
[01:48] <cehteh> i'd rather make a grep script which goes through the sources and searched for   lumiera_config_.*_get (".*", .*)
[01:49] <joelholdsworth_> yeah that's ok
[01:49] <cehteh> to have some idea what configs are actually used
[01:49] <joelholdsworth_> well maybe we can use libini
[01:49] <cehteh> so a about:config like ui wont be possible
[01:49] <__nasa__> which libini? There are quite a few.
[01:49] <joelholdsworth_> ahh
[01:49] <joelholdsworth_> that's a shame
[01:49] <cehteh> he forget about some libs .. thats so trivial to write by ourself :P
[01:49] <__nasa__> I assume the SF one is the best, as it is GPL.
[01:50] <cehteh> and simav wants to do something :P
[01:50] <joelholdsworth_> yeah
[01:50] <joelholdsworth_> anyway... time for bed for me
[01:50] <cehteh> well and what i rate high is that one can retrieve typed values  and that one can add/set values
[01:51] <cehteh> and this setting should not destroy the existing file structure
[01:51] <joelholdsworth_> yeah
[01:51] <cehteh> just read and write values is no magic .. but preserving human structured files is
[01:52] <joelholdsworth_> that is hard, yes
[01:52] <joelholdsworth_> anyway... got to go
[01:52] <__nasa__> Bye!
[01:52] <cehteh> n8 :)
[01:52] <-- joelholdsworth_ has quit ("Ex-Chat")
[01:52] <__nasa__> It looks like libini uses [plugin/blur] instead, but that is an easy fix.
[01:52] <cehteh> url?
[01:52] <__nasa__> Or we just let simav do the whole thing
[01:53] <cehteh> well i dont know how much time he has
[01:53] <__nasa__> http://sourceforge.net/project/showfiles.php?group_id=25464[]
[01:54] <cehteh> last change 3 year ago :P
[01:56] * cehteh looks at the source
[01:57] <cehteh> fails standard C++ conformance :P
[01:58] <cehteh> and no @include like directive
[01:58] * __nasa__ thinks we should look elsewhere...
[01:58] * cehteh things we should just do ourself :P
[01:58] * __nasa__ agrees.
[01:59] <cehteh> the syntax i typed there is not very special and can be replaced
[01:59] <cehteh> but some other features are important
[01:59] * __nasa__ thinks it should PRE. That way we don't have to totally agree.
[01:59] <cehteh> pre?
[01:59] <__nasa__> (On syntax)
[01:59] <cehteh> no suffix?
[02:00] <cehteh> well as saied its just an idea and completely optional, we can leave it out
[02:00] <__nasa__> sorry -- PCRE.
[02:00] <cehteh> ah
[02:00] <cehteh> i dont see how PCRE helps for a syntax
[02:00] <__nasa__> I always think of it as "Perl Regular Expressions" and forget the "Compatible"
[02:01] <cehteh> anyways: features matter
[02:01] <__nasa__> I was thinking in terms of plugins/blend vs. plugins.blend.
[02:01] <cehteh> that is @include which follows some LUMIERA_CONFIG_PATH
[02:02] <__nasa__> We should have some way to only include certain sections.
[02:02] <__nasa__> Like have the default config be
[02:02] <cehteh> yes
[02:02] <__nasa__> [lumiera.core]
[02:02] <__nasa__> ...
[02:02] <__nasa__> then
[02:02] <cehteh> but thats setup by the administrator/user
[02:02] <__nasa__> @include<plugin> ~/.lumi/plugins/
[02:02] <cehteh> if the user changes lumiera.core.somevalue
[02:03] <cehteh> it will find the file where it is already defined
[02:03] <__nasa__> and it adds all preferences for plugins from <dir>
[02:03] <cehteh> then check if thats a file in the users config space (~/.lumiera/*)
[02:03] <cehteh> and edit it there
[02:03] <__nasa__> Ok.
[02:04] <cehteh> if it is a system wide file it will place a correspondending file in the users config space
[02:04] <cehteh> if the value is not configured already it will search for [lumiera.core] and then [lumiera] and then []
[02:04] <cehteh> best fit the section where it would apply
[02:05] <cehteh> and then do the same write or create into correspondending user config
[02:05] <cehteh> thats why i saied 'features matter'
[02:06] <__nasa__> There should be a callback for a plugin to add a config file for that plugin.
[02:06] <__nasa__> Ooh
[02:06] <__nasa__> cool idea
[02:06] <cehteh> this is not really complicated to do but would give a big usage experience link:JustWorks[][TM]
[02:06] <__nasa__> ~/.lumi/config is the main configuration directory
[02:06] <__nasa__> inside, there is a ~/.lumi/config/config.ini which is main configuration
[02:07] <cehteh> no callbacks .. the idea is that the config system is independent and nothing else need to register there, that makes it much easier
[02:07] <__nasa__> Then, for example accessing plugin.shade.
[02:07] <cehteh> if you install a plugin this plugin should come with a system config file
[02:07] <cehteh> that can be a empty one
[02:07] <__nasa__> either find it in ~/.lumi/config/config.ini or ~/.lumi/config/plugin/config.ini.
[02:08] <cehteh>  /usr/local/share/lumiera/plugin/shade
[02:08] <cehteh> containing just
[02:08] <cehteh> [plugin.shade]
[02:08] <cehteh> when the user edits some value
[02:09] <cehteh> plugin.shade.transparency = 209
[02:09] <cehteh> then this will automatically create a correspondending ~/.lumiera/plugin/shade  in the user config space
[02:09] <__nasa__> yeah, so what I am saying is that instead of [plugin.shade] only [] is needed
[02:10] <cehteh> using the system one as template
[02:10] <cehteh> well if its []
[02:10] <__nasa__> since the file is already in config/PLUGIN/SHADE
[02:10] <cehteh> or that
[02:10] <cehteh> this is not yet decided
[02:10] <cehteh> we can do that too
[02:10] <__nasa__> so automatically add [plugin.shade] to the prefix of files in config/plugin/shade, etc
[02:11] <cehteh> but i would be careful to tie filenames and internal namespaces together
[02:11] <cehteh> yes doable
[02:11] <cehteh> well should still have [plugin.shade]
[02:12] <cehteh> else we have a nested section mess and files loose their identity
[02:12] <__nasa__> Yeah, I just realized it would be a pain to have default configs
[02:12] <__nasa__> Since where does the file go? you have to look inside to see if it had [plugin.shade], tec
[02:12] <__nasa__> etc*
[02:12] <cehteh> anyways nothing is etched in stone yet, we are just brainstorming
[02:13] <cehteh> most important thing is the interface the applciation can use
[02:13] <cehteh> then we can make a mockup for that which only returns defaults
[02:13] <cehteh> then we can use it already even when the config loader isnt finished
[02:14] <__nasa__> We could have a warning if a file in e.g. config/plugin/blur had a section that was [plugin.shade] or something
[02:14] <cehteh> actually the inital plan was to bootstrap the config system by one single site config file
[02:14] <__nasa__> to prevent hackery
[02:14] <cehteh> but plugins are a good point .. they might have their own configs
[02:15] <cehteh> which is not @included by the site config
[02:15] <__nasa__> lumiera_config_t *plugin_shade.request_default_config() or something
[02:15] <cehteh> but the plugin itself loads it when the plugin is used
[02:15] <__nasa__> Yeah
[02:16] <cehteh> nah
[02:16] <cehteh> lumiera_config is just singleton
[02:16] <cehteh> after you loaded plugin.shade it becomes visible there
[02:16] <cehteh> thats way easier
[02:16] <__nasa__> that is lumiera_config_struct
[02:16] <__nasa__> ok
[02:16] <cehteh> not even the struct
[02:17] <cehteh> thats an implementation detail
[02:17] <__nasa__> yeah -- to deal with later
[02:17] <cehteh> the programmers use only   lumiera_coonfig_TYPE_get   or _set
[02:17] <cehteh> where TYPE is to be defined .. see my notes
[02:18] <cehteh> number real string word ... and whatever else we need
[02:19] <cehteh> so you get typed data back .. when you provide a default then you can be even sure that it is always valid
[02:19] <__nasa__> Yeah, I do like that structure.
[02:19] <__nasa__> It also makes mass configuration setup very easy.
[02:21] <cehteh> btw file must have identity ...
[02:21] <__nasa__> meaning?
[02:21] <__nasa__> like they are not all config.ini?
[02:22] <cehteh> i mean a config file has to define for what kinds of values it applies
[02:22] <cehteh> [plugin.shade]    for the plugin/shade file
[02:22] <__nasa__> Ok, I see.
[02:22] <cehteh> then changing a values there will create the correspondending user file
[02:23] <cehteh> *thinking*
[02:23] <cehteh> the user could write  [plugin.shade]
[02:23] <cehteh> into some other config file which then becomes target for that
[02:23] <cehteh> (best fit)
[02:24] <cehteh> just wondering if the user just writes [pluin]
[02:24] <cehteh> [plugin]
[02:24] <cehteh> well i am sure we solve that
[02:25] <__nasa__> [plugin]
[02:26] <__nasa__> shade.radius = 3
[02:26] <__nasa__> in like the plugin/blur folder?
[02:28] <cehteh> no in the users config somewher
[02:28] <__nasa__> oh
[02:28] <cehteh> ~/.lumiera/myconfig
[02:29] <cehteh> shall it pick and mirror /usr/share/lumiera/plugin/blur to the user config space
[02:29] <cehteh> or write it to the [plugin] section in myconfig
[02:30] <cehteh> well maybe we add a   [plugin*]    syntax which hints the best fit
[02:30] <__nasa__> I would think it makes more sense to add a plugin/blur folder
[02:30] <__nasa__> or else lumiera/myconfig would be huge after configuring one project ;-)
[02:30] <cehteh> yes .. thats what you think .. i just wondering how to give the user the control to fit it to his needs
[02:31] <cehteh> ~/.lumiera/all_my_pluginmyconfig
[02:31] <cehteh> [plugin*]
[02:31] <cehteh> hints the best fit algo
[02:32] <cehteh> well just thinking about optional things
[02:32] <__nasa__> I think I am confused -- how is [plugin*] different from [plugin]
[02:33] <cehteh> when you change plugin.blur.radius   then the best fit algo will search the section which covers it best
[02:33] <cehteh> that would be [plugin.blur] in  /usr/share/lumiera/plugin/blur
[02:33] <__nasa__> Oh, unless you have [plugin*]
[02:34] <cehteh> so it will create a correspondending ~/.lumiera/plugin/blur  file for you
[02:34] <cehteh> yes exactly
[02:34] <__nasa__> Ok, that makes sense. Good idea!
[02:34] <cehteh> [plugin*] will take precedence
[02:34] <cehteh> when you have that then you can hint it not to create many tiny files
[02:35] <__nasa__> so that way the config is in one file
[02:35] <__nasa__> yeah
[02:35] <cehteh> hehe the suffux thing comes in mind here
[02:35] <cehteh> [plugin* radius]     in ~/.lumiera/plugin_radius_conf
[02:35] <__nasa__> I was thinking suffixed are only allowed at the e.g. plugin/ level if they effect multiple plugins.
[02:35] <cehteh> well or as trivial as
[02:36] <__nasa__> Ok.
[02:36] <cehteh> [plugin* enable]     in ~/.lumiera/plugins_enabled
[02:36] <__nasa__> Fun!
[02:36] <cehteh>  blur = on
[02:36] <cehteh>  sharpen = off
[02:36] <cehteh> ah .. we need a bool TYPE
[02:36] <cehteh> *blink*
[02:37] <__nasa__> on/off or true/false?
[02:37] <__nasa__> Well, either way.
[02:38] <cehteh> bool
[02:38] <cehteh>
[02:38] <cehteh> int
[02:38] <cehteh>
[02:38] <cehteh> common representations for bools (0,1,yes,no,on,off,set,clear)
[02:38] <cehteh> we can add more
[02:38] <__nasa__> It should be reasonably good at guessing
[02:40] <cehteh> yeah .. i would like to make this little intelligent
[02:40] <cehteh> for example when you want to set something it might look at the existing thing before doing so and then flavor the set with that
[02:41] <cehteh> when a string was quoted, the new one will be quoted to
[02:41] <__nasa__> "Weaken the blur effect"
[02:41] <cehteh> if there was a bool with 'yes' then it will choose 'no' ..
[02:41] <cehteh> and so on
[02:42] <cehteh> this are generally just a few extra lines of code, nothing dramatic .. but that makes it much nicer in detail
[02:43] <__nasa__> Yeah, I think that it will improve the user experience
[02:43] <cehteh> ok i add this irclog to the wiki
[02:43] <__nasa__> for most people, editing a config file is scary
[02:43] <__nasa__> so making it as easy and friendly as possible is good
[02:44] <__nasa__> All right
------------------------------------------------------------



anchor:anchor_brainstorm[]Brainstorming
---------------------------------------

 * support for successive dereferencing foo.bar > baz.barf > blah.boo = final value
 * support for alternatives, query a set of keys, return the first existing
 * provide a @readonly directive which marks a file to be handled readonly (even if writing would be permitted)
