Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor the default configuration #7371

Open
sophiajt opened this issue Dec 6, 2022 · 12 comments
Open

Refactor the default configuration #7371

sophiajt opened this issue Dec 6, 2022 · 12 comments
Labels
configuration Issue related to nu's configuration enhancement New feature or request

Comments

@sophiajt
Copy link
Member

sophiajt commented Dec 6, 2022

Related problem

Right now we use two configuration files: env.nu for environment and config.nu for configuration.

While this is helpful, it's easy to break between versions. It's also a bit tricky to contribute new completions to the default.

Describe the solution you'd like

One recommendation would be that the default files aren't intended to be edited, but they point to files that are. That way, defaults can be handled by Nushell and we won't overwrite the user's custom settings.

This could be done by the config.nu (or env.nu) importing settings from other files. Say path.nuon which has a list of paths in it that will form the user's PATH/Path.

We could also move completions into their own directory that's a subdirectory of the main nushell configuration directory. Each of these files could be imported by the default configuration. As they don't have an ordering, we could (once we had a mechanism in the language to do it) just let users drop new files into this directory and also pre-populate it from a core set of completions (including things like git completions).

Describe alternatives you've considered

No response

Additional context and details

No response

@sophiajt sophiajt added the enhancement New feature or request label Dec 6, 2022
@stormasm
Copy link
Contributor

stormasm commented Dec 7, 2022

yes, that would be very cool ! the things you are interested in live in a separate spot --- and some how they get merged into the config system or you are alerted as to the change that was made for you [when a config option changes for whatever reason ] --- and then you have the option to get in there and update your "separate stuff"

@rgwood
Copy link
Contributor

rgwood commented Dec 7, 2022

Cool idea. I'm trying to figure out how it might work in practice; is this on the right track?

  1. Nu creates base-config.nu and user-config.nu files when it first starts up
    1. base-config.nu has big screaming "DO NOT EDIT THIS" warning comments at the top
    2. base-config.nu imports the contents of user-config.nu
    3. user-config.nu is empty by default (maybe with some commented-out examples)
  2. If you want to def a custom function you do it in user-config.nu
  3. When a new version of Nu is launched, it overwrites base-config.nu with the latest version

@CAD97
Copy link
Contributor

CAD97 commented Dec 12, 2022

FWIW, I've currently put my completions in $env.NU_LIB_DIRS | path join "completions" (and themes in $env.NU_LIB_DIRS | path join "themes.nu", aliases in $env.NU_LIB_DIRS | path join "aliases.nu") which I then use (source for themes) from config.nu.

Generally, my expected workflow would be for the base defaults to live in the "application directory" (e.g. C:\Program Files\nu on Windows) and not get touched, with the "configuration directory" (e.g. $env.APPDATA\nushell ($nu.config-path) on Windows) to be persistent user configuration not touched by version updates (except perhaps to do automated format migration).

Semantically, I would say nushell should load {nu.app-dir}/config.nu and then {nu.config-dir}/config.nu as if from a synthetic file which just sources the two files in that order. That way the default things are defined by default, but can be overridden by the user configuration. Notably, if the user config does let-env config = { ... }, this would result in the default $env.settings not being available (but the reasonable defaults should be used if unset); the default config should thus probably do an upsert to the existing config rather than overwrite it.

However, a really interesting idea is to treat user configuration uniformly as an overlay, just one that's used by default; e.g. on startup, we'd have an overlay list of [zero, default, user]. I don't know how well overlays support overlaying configuration currently, but this seems on the surface like a very straightforward way to define how the default and user configuration are overlaid.

@sholderbach sholderbach added the configuration Issue related to nu's configuration label Dec 14, 2022
@PerBothner
Copy link
Contributor

Separating user-edited configuration from default configuration (including completions) is important - they should be separate files. However, that is not enough: default configuration should never be in the user's home directory or other user-specific area. You should be able to have a good experience if you run Nu on a read-only file-system or in a guest account. Preferably, no files should be created by default.

Default configuration files and completions should be in a system "resource" area. On Linux system that would probably be /usr/share/nushell.

@stormasm
Copy link
Contributor

@PerBothner

https://hackmd.io/NfBoTWUeQhOTXoeKra437A

We are in the process of attempting to completely re-design how our config system works... The core team has spent the past two meetings allocating quite a bit of time to brainstorming some new ideas...

We are not there yet... But these links should give you some more information...

https://hackmd.io/@nucore

@PerBothner
Copy link
Contributor

In the links I just saw some discussion of config file syntax, but nothing about config file location.

As to syntax, it appears the team does not want JSON for config files. I strongly agree: JSON should not be used for a user-readable/user-editable config file.

JSON is ok for files are machine-generated or that only Nu developers are expected to edit.

Using Nu language syntax for the config files for the Nu languages seems to make most sense. It does have the downside that it is difficult to load it "in pieces" - you need to read and evaluate the whole thing - possibly doing undesirable side-effects and possible malware. Don't know if that is a concern. If it is, perhaps a Nu language "declarative" subset may be an option.

@stormasm
Copy link
Contributor

@PerBothner Thanks for your feedback I attached this issue as a reference section inside the document

https://hackmd.io/NfBoTWUeQhOTXoeKra437A

As for file location of the config files

I see that as a separate issue...

Currently the location of our config files is a function of a crate that we use
(but I can't remember the name of it)
that has the ability to work cross platform... That is currently the main gating factor for where we put them.

We would welcome a new rust crate that manages (cross platform) locations of where you can put your config files... But for now, that is not (I don't think) a high priority since we have something that works / and we don't have to worry about maintaining the code.

@stormasm
Copy link
Contributor

@PerBothner so if you look inside our nu-path crate you will see a reference to the crate
https://crates.io/crates/dirs-next

Ideally we would like a crate like this ----
that gives us more flexibility moving forward on where the config files
can possibly go...

but as noted above --- this would be something that someone else could happily maintain so that we would not have to build this functionality into nushell.

@CAD97
Copy link
Contributor

CAD97 commented Jan 19, 2023

Side note: the dirs crate is maintained again and you might potentially move back to dirs from dirs-next. I've not done an analysis of any divergence, just noted that dirs is again maintained and more recently updated than dirs-next.

As I noted above, you can accomplish this just fine with dirs(-next)... or rather, with the mid-level sister crate, directories(-next). The user configuration goes into the config directory, but the defaults should either be embedded into the app (if maintaining a portable exe distribution) or auxiliary files in the application installation. I believe that the data directory and/or local data directory (there's only a difference on Windows) matches @PerBothner's expectation. But as defaults, I don't think these should be in user directories at all; they're part of the application and should be in the application directory... but I've also not studied exactly what the conventions are.

@stormasm
Copy link
Contributor

@CAD97 thanks for the update on the history of the dirs / dirs-next crates...
good to know that the dirs crate is maintained again...
when I saw how long it had been since dirs-next was modified that is cause for some concern...

@CAD97
Copy link
Contributor

CAD97 commented Jan 19, 2023

The other "competitor" appears to be app_dirs2, though it does also point back at the directories crate. I don't have any insight on which crate(s) to choose, but I will note that the specification(s) for what folder(s) to use are all essentially stable, so it's not necessarily a bad sign for the crate to be "finished" and not have any recent releases, if there's still maintainer responsiveness on the issue tracker.

@texastoland
Copy link
Contributor

texastoland commented Dec 31, 2023

My current workaround is (opposite of the proposal):

  1. Prefix the default env.nu and config.nu filenames with default_
  2. Create a new env.nu and config.nu starting with:
    source default_env.nu # or default_config.nu

I simulated config reset with a custom config update command to automate those steps:

# config.nu
export def update []: nothing -> list<path> {
  let default_paths = [$nu.env-path $nu.config-path] | each {
    path replace stem { $'default_($in)' }
  }
  config env --default | save --force $default_paths.0
  config nu --default | save --force $default_paths.1
  $default_paths
}

def 'path replace' [part: string format: closure]: path -> path {
  let parts = path parse
  let replace = $parts | get $part | do $format
  $parts | update $part $replace | path join
}

One recommendation would be that the default files aren't intended to be edited, but they point to files that are. That way, defaults can be handled by Nushell and we won't overwrite the user's custom settings.

I strongly agree with this but the defaults should be system level configs suggested in #5660.

@sophiajt Is there any way I can help champion your proposal to improve the status quo?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
configuration Issue related to nu's configuration enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

7 participants