1Curv has an optional user-defined configuration file, which the `curv`
2command reads during startup.
3
4The configuration file provides default values for -O options which are
5given on the command line.
6
7Loading the Config File
8-----------------------
9$XDG_CONFIG_HOME defines the base directory relative to which the Curv
10config file is stored. If $XDG_CONFIG_HOME is either not set or empty,
11it defaults to "$HOME/.config", unless $HOME is either not set or empty,
12in which case there is no Curv config file.
13
14There are two possible names for the Curv user configuration file.
15First, we try "$XDG_CONFIG_HOME/curv.curv".
16If this file exists, we evaluate it as a Curv syntax source file,
17and the result must be a record value.
18Otherwise, if the directory $XDG_CONFIG_HOME/curv exists, we evaluate it
19using directory syntax.
20
21Update: At present, I just import $XDG_CONFIG_HOME/curv using either file
22syntax or directory syntax.
23
24Accessing Configuration
25-----------------------
26In libcurv, Curv configuration is stored in System::config_,
27as a value of type Shared<const Record>. Not implemented yet; don't need it.
28So far config is only used to provide defaults for export parameters in the
29Curv program, and libcurv knows nothing about this.
30
31Idea: `config` is a builtin binding.
32It sounds cool, but why do I need it? What are the use cases?
33Curv is a file format for sharing geometric models, and it's not obviously
34good for shared models to depend on config. So I've leave this feature out
35until required.
36
37The Config Namespace
38--------------------
39Here's the current CLI -O configuration:
40  mesh (STL, OBJ, X3D)
41    vsize, jit, adaptive,
42  mesh (X3D)
43    colour
44  viewer, GPU (aka Frag options)
45    aa, taa, fdur, bg
46  PNG
47    xsize, ysize, fstart, animate, + the Frag options
48
49I could just put all these names at the top level of the config record.
50
51However, I might want different Frag options for PNG export vs the Viewer
52(eg, high quality for PNG export, higher performance for the Viewer).
53So then I need a 2-level namespace, eg like:
54  config
55    mesh
56      vsize, jit, adaptive, colour
57    view
58      aa, taa, fdur, bg
59    image
60      xsize, ysize, fstart, animate, + the Frag options
61I like this one better:
62  config
63    export
64    viewer
65    repl
66
67Command Line Overrides
68----------------------
69All of the -O options can be given default values in the config file.
70Which means all -O option values are Curv values.
71What about '-O colour=face|vertex' for -o x3d?
72'face' and 'vertex' need to either be strings, or symbols.
73See <language/Symbols> proposal.
74Depending on the outcome of this proposal, we will use one of the following:
75    -O colour='"vertex"'   -- in bash
76    -O "colour=""vertex""" -- in cmd.exe, but for caveats see (*)
77    -O colour=#vertex
78(*) https://stackoverflow.com/questions/562038/escaping-double-quotes-in-batch-script
79
80All configuration can be overidden on the command line.
81Currently, all of the relevant command line options are -O options.
82
83Algorithm for parsing configuration and -O options.
84* error checking: I want to report invalid -O options, and invalid config
85  settings.
86* For each internal options structure, like io::Frag_Export, there is a
87  Parse_Opt function that validates a specific name/value pair,
88  modelled after parse_frag_opt(). This validates a name/value pair from
89  either the config, or from a -O option.
90* template<T> typedef bool (*Parse_Opt)(
91
92Let's say there is a flat config namespace, and we ignore names not relevant
93to the current export context.
94 1. An option structure like Frag_Export is default initialized.
95 2. config values with matching names are copied into the option struct,
96    unknown names are ignored. curv::Values are converted to the correct type.
97 3. All of the -O options are processed. Bad names are reported as an error.
98    Strings are evaluated as Curv values, then converted to the correct type.
99What API do we use?
100
101I could extend the Export_Param::Map to contain a string field (for the -O
102value) and a Value field (for the config value). Load the config record into
103the Export_Param::Map. Then, the current API is mostly unaffected and only
104the internal implementation of Export_Params needs to change.
105
106A Map item now contains a string `opt` and an Value `config`, both nullable.
107How do we evaluate it?
108* Currently we build a Param_Prog pp(*this, p), then we use pp.eval()
109  and At_Program(pp) as an error context.
110* If the parameter has no opt string, only a config value, then we still
111  need a Context for reporting a type or range error on the config value.
112* The minimum config context is the pathname of the root config file and
113  the data path of the config field.
114* Alternatively, we need the 'Program' for the config source file.
115  The important part is the Location. But, what if the config file
116  is a directory tree containing multiple *.curv files?
117  The config value containing the error could come from multiple sources.
118  Tracking this is tricky. In theory, this information can be reconstructed
119  from the minimum config context.
120
121At_Param cx(*this, p);
122cx.eval(deflval)
123
124Lighting Models
125---------------
126There is a default lighting model, which has two attributes, background_colour
127and contrast. The user can override either or both of these attributes,
128and can also replace the default lighting model with another,
129perhaps user-defined lighting model.
130
131Perhaps user-defined lighting models can provide additional parameters that
132can be selectively overridden using the config file or the command line.
133
134In 3D, these config variables are called
135    viewer.lighting
136    viewer.lighting.background_colour
137    viewer.lighting.contrast
138
139In 2D, there is still a background colour, but there is no lighting model.
140What is it called? Currently it is called -Obg=.
141