## Design Motivation
-LunaConfig is designed to be an improvement over the old-school Kconfig, which in
-particular to address the issue of lacking hierchical representation. This is
-because Kconfig organise options into a big flat list, while the options are
-organised into menu which is hierachical in nature. It is very difficult to
-identify membership of a config without diving into menuconfig.
+LunaConfig is designed as an improvement over the old-school Kconfig,
+particularly to address its lack of hierarchical representation. Kconfig
+organises options into a large, flat list, even though they appear in a
+hierarchical menu structure. As a result, it can be very difficult to
+determine which menu a configuration option belongs to without diving into
+menuconfig.
-## Basic Concepts
+## Basic Constructs
-LunaConfig is presented as a file named `LConfig` and thus limited to one LConfig per directory. This is because LunaConfig enforce user to organise each directory to be a module or logical packaging of set of relavent functionalities.
+LunaConfig is presented as a file named `LConfig` and thus limited to one
+LConfig per directory. This is because LunaConfig enforce user to organise each
+directory to be a module or logical packaging of set of relavent functionalities.
-In each LunaConfig files, these major concepts you will usually seen.
+Each LunaConfig files is comprised by these major constructs:
1. Config Component: `Terms` and `Groups`
2. Config Import
> The logical object that is used to organise the `terms` or other `groups`
-A group is similar to term but without return type indication and return statement
+A group is similar to term but without return type indication and return
+statement
And it is usually nested with other groups or terms.
return True
```
-### LunaConfig Import
+### Import Mechanism
Multiple `LConfig`s may be defined across different sub-directory in large scale
project for better maintainability
-LunaConfig allow you to import content of other LBuild using python's relative import
-feature:
+LunaConfig allow you to import content of other LConfig using python's relative
+import feature:
```py
from . import module
```
This import mechanism works like `#include` directive in C preprocessor,
-the `from . import` construct will automatically intercepted by the LBuild interpreter and
-be replaced with the content from `./module/LConfig`
+the `from . import` construct will be automatically intercepted by the LConfig
+interpreter and be replaced with the content from `./module/LConfig`
-You can also address file in the deeper hierarchy of the directory tree, for example
+You can also address file in the deeper hierarchy of the directory tree, for
+example
```py
from .sub1.sub2 import module
### Native Python
-Native Python code is fully supported in LunaConfig, this include everything like packages import, functions, and class definitions. LunaConfig has the ability to distinguish these code transparently from legitimate config code.
+Native Python code is fully supported in LunaConfig, this include everything
+like packages import, functions, and class definitions. LunaConfig has the
+ability to distinguish these code transparently from legitimate config code.
-However, there is one exception for this ability. Since LunaConfig treat function definition as declaration of config component, to define a python native function you will need to decorate it with `@native`. For example:
+However, there is one exception for this ability. Since LunaConfig treat
+function definition as declaration of config component, to define a python
+native function you will need to decorate it with `@native`. For example:
```py
@native
return add(1, 2)
```
-If a native function is nested in a config component, it will not be affected by the scope and still avaliable globally. But this is not the case if it is nested by another native function.
+If a native function is nested in a config component, it will not be affected
+by the scope and still avaliable globally. But this is not the case if it is
+nested by another native function.
-If a config component is nested in a native function, then it is ignored by LunaConfig
+If a config component is nested in a native function, then it is ignored by
+LunaConfig
## Term Typing
-A config term require it's value type to be specified explicitly. The type can be a literal type, primitive type or composite type
+A config term require it's value type to be specified explicitly. The type can
+be a literal type, primitive type or composite type
### Literal Typing
-A term can take a literal as it's type, doing this will ensure the value taken by the term to be exactly same as the given type
+A term can take a literal as it's type, doing this will ensure the value taken
+by the term to be exactly same as the given type
```py
# OK
### Primitive Typing
-A term can take any python's primitive type, the value taken by the term will be type checked rather than value checked
+A term can take any python's primitive type, the value taken by the term will
+be type checked rather than value checked
```py
# OK
### Composite Typing
-Any literal type or primitive type can be composite together via some structure to form composite type. The checking on these type is depends on the composite structure used.
+Any literal type or primitive type can be composite together via some structure
+to form composite type. The checking on these type is depends on the composite
+structure used.
#### Union Structure
-A Union structure realised through binary disjunctive connector `|`. The term value must satisfy the type check against one of the composite type:
+A Union structure realised through binary disjunctive connector `|`. The term
+value must satisfy the type check against one of the composite type:
```py
-def feature1() -> "a" | "b" | int
+def feature1() -> "a" | "b" | int:
# value can be either:
# "a" or "b" or any integer
return "a"
## Component Attributes
-Each component have set of attributes to modify its behaviour and apperance, these
-attributes are conveyed through decorators
+Each component have set of attributes to modify its behaviour and apperance,
+these attributes are conveyed through decorators
### Labels
> usage: `Groups` and `Terms`
-Label provide a user friendly name for a component, which will be the first choice
-of the name displayed by the interactive configuration tool
+Label provide a user friendly name for a component, which will be the first
+choice of the name displayed by the interactive configuration tool
```py
@"This is feature 1"
> usage: `Terms`
-Marking a term to be readonly prevent explicit value update, that is, manual update by user. Implicit value update initiated by `constrains` (more on this later) is still allowed.
+Marking a term to be readonly prevent explicit value update, that is, manual
+update by user. Implicit value update initiated by `constrains` (more on this
+later) is still allowed.
```py
@readonly
> usage: `Groups` and `Terms`
-A component can be marked to be hidden thus prevent it from displayed by the configuration tool, it does not affect the visibility in the code.
+A component can be marked to be hidden thus prevent it from displayed by the
+configuration tool, it does not affect the visibility in the code.
-If the decorated target is a group, then it is inheritated by all it's subordinates.
+If the decorated target is a group, then it is inherited by all it's
+subordinates.
```py
@hidden
> usage: `Groups` and `Terms`
-Any component can be defined outside of the logical hierachial structure (i.e., the nested function) but still attached to it's physical hierachial structure.
+Any component can be defined outside of the logical hierachial structure (i.e.,
+the nested function) but still attached to it's physical hierachial structure.
```py
@parent := parent_group
return False
```
-This will assigned `feature1` to be a subordinate of `parent_group`. Note that the reference to `parent_group` does not required to be after the declaration.
+This will assigned `feature1` to be a subordinate of `parent_group`. Note that
+the reference to `parent_group` does not required to be after the declaration.
It is equivalent to
> usage: `Groups` and `Terms`
-A help message will provide explainantion or comment of a component, to be used and displayed by the configuration tool.
+A help message will provide explainantion or comment of a component, to be used
+and displayed by the configuration tool.
The form of message is expressed using python's doc-string
> usage: `Groups` and `Terms`
-The dependency between components is described by various `require(...)` directives.
+The dependency between components is described by various `require(...)`
+directives.
-This directive follows the python function call syntax and accept one argument of a boolean expression as depedency predicate.
+This directive follows the python function call syntax and accept one argument
+of a boolean expression as depedency predicate.
-Multiple `require` directives will be chainned together with logical conjunction (i.e., `and`)
+Multiple `require` directives will be chainned together with logical conjunction
+(i.e., `and`)
```py
def feature1() -> bool:
return True
```
-This composition is equivalent to `feature5 and (feature2 or feature3)`, indicate that the `feature1` require presences of both `feature5` and at least one of `feature2` or `feature3`.
+This composition is equivalent to `feature5 and (feature2 or feature3)`,
+indicate that the `feature1` require presences of both `feature5` and at least
+one of `feature2` or `feature3`.
-If a dependency can not be satisfied, then the feature is disabled. This will cause it neither to be shown in configuration tool nor referencable in source code.
+If a dependency can not be satisfied, then the feature is disabled. This will
+cause it neither to be shown in configuration tool nor referencable in source
+code.
-Note that the dependency check only perform on the enablement of the node but not visibility.
+Note that the dependency check only perform on the enablement of the node but
+not visibility.
-### Auto Toggling
+### Constrains (Inverse Dependency)
> usage: `Terms` with `bool` value type
-The `when(...)` directive allow changing the default value based on the predicate evaluation on the value of other terms. Therefore, it can be only used by `Terms` with `bool` as value type.
+The `when(...)` directive allow changing the default value based on the
+predicate evaluation on the value of other terms. Therefore, it can be only
+used by `Terms` with `bool` as value type.
-Similar to `require`, it is based on the function call syntax and takes one argument of conjunctive expression (i.e., boolean expression with only `and` connectors).
+Similar to `require`, it is based on the function call syntax and takes one
+argument of conjunctive expression (i.e., boolean expression with only `and`
+connectors).
Multiple `when` will be chained together using logical disjunction (i.e., `or`)
when (feature3)
```
-Which means `feature1` will takes value of `True` if one of the following is satisfied:
+Which means `feature1` will takes value of `True` if one of the following is
+satisfied:
+ both `feature2` and `feature5` has value of `"value1"`
+ `feature3` has value of True
-Notice that we do not have `return` statement at the end as the precense of `when` will add a return automatically (or replace it if one exists)
+Notice that we do not have `return` statement at the end as the precense of
+`when` will add a return automatically (or replace it if one exists)
## Validation
-For configuration language being a python superset will have a risk of abusing due to the high flexibility. This include complex logic, non-trivial operation being used in a component to derive the final value. Thus shifting the style from declarative to imperative and greatly reduce the overall reability.
+Since the language is based on Python, it's very tempting to pack in advanced
+features or messy logic into the config file, which can make it harder to
+follow—especially as the file grows in size.
-For prevention of this potential drawback, LunaConfig implemented a syntactical validator to identify these possible bad-practice and issue warning (or rise a fatal-error depending on the user setting).
+LunaConfig recognises this issue and includes a built-in linter to help users
+identify such bad practices. It shows warnings by default but can be configured
+to raise errors instead.
-Currently, LunaConfig detect the misuses based on these rule rules:
+Currently, LunaConfig detect the misuses based on these rules:
-+ `dynamic-logic`: The presence of conditional branching that could lead to complex logic. However, pattern matching is allowed.
++ `dynamic-logic`: The presence of conditional branching that could lead to
+ complex logic. However, pattern matching is allowed.
+ `while-loop`, `for-loop`: The presence of any loop structure.
+ `class-def`: The presence of class definition
+ `complex-struct`: The present of complicated data structure such as `dict`.
+ `side-effect`: The presence of dynamic assignment of other config terms value.
-+ `non-trivial-value`: The presence of non-trivial value being used as default value. This include every things other than:
- + constant
- + variable reference
- + comparison between constant or variable
- + single boolean operation
- + ternary operator with constant/refernece and trivial boolean operation
++ `non-trivial-value`: The presence of non-trivial value being used as default
+ value. This include every things **other than**:
+ + literal constant
+ + template literal