How to use imports to inherit settings, then override values (like default_flags)?
I'm creating an issue for this question, as requested at https://github.com/Canop/broot/issues/152#issuecomment-1185176610.
I have a general/common broot config file (conf.hjson), and then some smaller configs that I'd like to apply on top during some invocations, adding and/or replacing values from conf.hjson.
For example, sometimes I want to use broot to select a folder to cd into (in the shell), and in that case I only want to see folders, not files.
conf.hjson includes default_flags: igs. I then have select-folder.hjson:
{
imports: [
conf.hjson
]
default_flags: igf
verbs: [
{
apply_to: "directory"
internal: ":print_path"
key: "enter"
leave_broot: true
}
{
apply_to: "file"
cmd: ":focus;:print_path"
key: "enter"
leave_broot: true
}
]
}
I invoke broot with this config in Zsh by hitting alt+down, and the following Zsh loaded:
.zle_redraw-prompt () {
# Credit: romkatv/z4h
emulate -L zsh
for 1 ( chpwd $chpwd_functions precmd $precmd_functions ) {
if (( $+functions[$1] )) $1 &>/dev/null
}
zle .reset-prompt
zle -R
}
.zle_cd-broot () {
echoti rmkx
cd "$(broot --color yes --conf ~/.config/broot/select-folder.hjson)"
.zle_redraw-prompt
}
zle -N .zle_cd-broot
bindkey '^[[1;3B' .zle_cd-broot # alt+down
I am surprised by the result: files as well as folders are shown, not only folders.
How can I get the value of default_flags defined in select-folder.hjson to apply, when using imports to combine config files?
When file A imports file B, the settings of file B override the ones of file A.
Here are two solutions I see for your problem:
Solution 1: remove the default_flags entry in the main conf.hjson
This way the setings you put in select-folder.hjson won't be overridden.
Solution 2: give the two files to --conf
You can specify several paths, and they're applied in order. So you could launch broot with
cd "$(broot --color yes --conf ~/.config/broot/conf.hjson;~/.config/broot/select-folder.hjson)"
Please confirm this solves your problem.
When file A imports file B, the settings of file B override the ones of file A.
I would expect later settings in a file to override earlier imports, and it doesn't seem true in the case of verbs, where the select-folder assignments for the Enter key do seem to override the common setting for Enter.
There's no order among root properties of a file. Changing the position of the imports in a file changes nothing. It's not an include.
Ok but why is the verb set for Enter in select-folder already overriding that in the imported conf?
There's no "overriding" for verbs. It's a list. When executing a key shortcut, or looking for the verb matching a command, all verbs are tried in order until one of them matches (the built-in verbs are "loaded" after the configuration verbs).
I have Enter defined in both. So is this right?
When importing:
- an imported config takes precedence for everything except verbs
- multiple imports have some non-guaranteed or undefined precedence
- verbs defined in the immediate file take precedence over any conflicting imported verbs
Oh I'm not at a computer but if it makes a difference that other Enter definition may be in a file imported by the common conf.
At the macro level, you have to understand the order of file reading:
- when file A imports file B, file B is "read" just after file A
- the root files are read in order of the "--conf" argument
When a file is "read":
- arrays are concatenated, the new items being added after the old items: Verbs are added to the previous list
- for maps, if a key is common, the new value replaces the old ones (for example the "special paths"
- other properties are replaced (you can consider a file as a map)
This is all defined in this simple function: https://github.com/Canop/broot/blob/master/src/conf/conf.rs#L166-L186
(self is the "current" config while conf is the newly read file).
But your description of the sequence when a file is "read" does not apply when providing configs as ;-delimited paths, right?
I've now fixed the behavior with the setup in this (recently edited) comment. I stopped using imports for this purpose, and need to put the small specific configs like select-folder first in the ;-delimited list.
I guess you're saying that list is an application order, which is not the same as the read order?
I'm sorry, I'm still confused about this. Without using imports, if I have a conf for a specific task which I want to override settings of a general conf, I can specify:
--conf "<specific-conf>;<general-conf>"
In this case the verbs/bindings will be correct, but the default_flags will be wrong.
Or
--conf "<general-conf>;<specific-conf>"
In this case the verbs/bindings will be wrong, but the default_flags will be correct.
I think the best solution for me for now is to use
--conf "<specific-conf>;<general-conf>"
and in specific-conf, omit the default_flags setting, but include a comment suggesting flags to be used on the command line in any defined function that uses specific-conf.