broot icon indicating copy to clipboard operation
broot copied to clipboard

How to use imports to inherit settings, then override values (like default_flags)?

Open AndydeCleyre opened this issue 3 years ago • 11 comments

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?

AndydeCleyre avatar Jul 15 '22 15:07 AndydeCleyre

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.

Canop avatar Jul 16 '22 13:07 Canop

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.

AndydeCleyre avatar Jul 16 '22 14:07 AndydeCleyre

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.

Canop avatar Jul 16 '22 14:07 Canop

Ok but why is the verb set for Enter in select-folder already overriding that in the imported conf?

AndydeCleyre avatar Jul 16 '22 14:07 AndydeCleyre

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).

Canop avatar Jul 16 '22 14:07 Canop

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

AndydeCleyre avatar Jul 16 '22 15:07 AndydeCleyre

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.

AndydeCleyre avatar Jul 16 '22 15:07 AndydeCleyre

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).

Canop avatar Jul 16 '22 15:07 Canop

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?

AndydeCleyre avatar Jul 16 '22 18:07 AndydeCleyre

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.

AndydeCleyre avatar Oct 16 '23 18:10 AndydeCleyre

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.

AndydeCleyre avatar Oct 18 '23 04:10 AndydeCleyre