Skip to content

Commit

Permalink
Only ask to create config files the first time nu is started (#13857)
Browse files Browse the repository at this point in the history
# Description

Implements #13669

When nu is started for the first time, the directory represented by
`$nu.default-config-dir` typically will not exist. In this case, Nushell
will create the directory. It will then detect that either or both
`config.nu`/`env.nu` don't exist and offer to create them.

(Existing behavior) If the user declines, the directory will still be
created (since the history file lives there as well). The
`default_config.nu` and `default_env.nu` will be loaded.

On subsequent launches, as long as the config directory continues to
exist, the user will not be prompted to recreate the config files.
Nushell will behave as if the user answered "N" to the prompt in that
`default_config.nu` and `default_env.nu` will be used.

The user can still create a `config.nu` or `env.nu` at any point, and
that will be used. In that case, `default_config.nu` and/or
`default_env.nu` will no longer be loaded (unless and until #13671 is
implemented).

# User-Facing Changes

User will no longer be prompted to create config files if they are
missing so long as the config directory exists.

## Before this change:

1. Nushell starts for the first time
2. The directory where config files are stored does not exist
3. The config files do not exist
   * User is asked whether they want to create `env.nu`
- User says, "Y", `default_env.nu` is copied to the directory as
`env.nu` (and directory is created if needed)
- User says, "n", `default_env.nu` is loaded, but no file on the
filesystem is created.
 
   * User is asked whether they want to create `config.nu`
- User says, "Y", `default_config.nu` is copied to the directory as
`config.nu` (and directory is created if needed)
- User says, "n", `default_config.nu` is loaded, but no file on the
filesystem is created.

4. The next time `nu` is run, if either file is missing, the user will
be prompted again for that file.

## After this change:

Steps 1 - 3 remains the same.

4. The next time `nu` is run, we check if the directory exists.  If so:
5. Do not prompt user to create any missing files **(New Behavior)**
6. `$nu.default-config-dir/env.nu` exists?
   * Yes? Use it. (Normal behavior)
   * No?  Evaluate `default_env.nu`.  (Normal behavior)
   * No file is created on the filesystem

7. `$nu.default-config-dir/config.nu` exists?
   * Yes? Use it. (Normal behavior)
   * No?  Evaluate `default_config.nu` (Normal behavior)
   * No file is created on the filesystem

# Tests + Formatting

- 🟢 `toolkit fmt`
- 🟢 `toolkit clippy`
- 🟢 `toolkit test`
- 🟢 `toolkit test stdlib`

# After Submitting

This behavior isn't currently mentioned in the configuration doc. I'll
probably hold off on changing anything in the doc until #13671 is
implemented. Regardless, given the timing, this won't make it into a
release for at least 4 weeks.
  • Loading branch information
NotTheDr01ds authored Sep 26, 2024
1 parent 0c72f88 commit d68c3ec
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 20 deletions.
54 changes: 38 additions & 16 deletions src/config_files.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ pub(crate) fn read_config_file(
stack: &mut Stack,
config_file: Option<Spanned<String>>,
is_env_config: bool,
ask_to_create: bool,
) {
warn!(
"read_config_file() config_file_specified: {:?}, is_env_config: {is_env_config}",
Expand Down Expand Up @@ -66,26 +67,34 @@ pub(crate) fn read_config_file(
} else {
"config"
};
println!(
"No {} file found at {}",
file_msg,
config_path.to_string_lossy()
);
println!("Would you like to create one with defaults (Y/n): ");

let mut answer = String::new();
std::io::stdin()
.read_line(&mut answer)
.expect("Failed to read user input");

let will_create_file = match ask_to_create {
true => {
println!(
"No {} file found at {}",
file_msg,
config_path.to_string_lossy()
);
println!("Would you like to create one with defaults (Y/n): ");

let mut answer = String::new();
std::io::stdin()
.read_line(&mut answer)
.expect("Failed to read user input");

matches!(answer.trim(), "y" | "Y" | "")
}
_ => false,
};

let config_file = if is_env_config {
get_default_env()
} else {
get_default_config()
};

match answer.trim() {
"y" | "Y" | "" => {
match will_create_file {
true => {
if let Ok(mut output) = File::create(&config_path) {
if write!(output, "{config_file}").is_ok() {
let config_type = if is_env_config {
Expand Down Expand Up @@ -226,7 +235,6 @@ fn eval_default_config(
"eval_default_config() config_file_specified: {:?}, is_env_config: {}",
&config_file, is_env_config
);
println!("Continuing without config file");
// Just use the contents of "default_config.nu" or "default_env.nu"
eval_source(
engine_state,
Expand Down Expand Up @@ -259,12 +267,26 @@ pub(crate) fn setup_config(
"setup_config() config_file_specified: {:?}, env_file_specified: {:?}, login: {}",
&config_file, &env_file, is_login_shell
);

let ask_to_create_config = if let Some(mut config_path) = nu_path::config_dir() {
config_path.push(NUSHELL_FOLDER);
!config_path.exists()
} else {
false
};

let result = catch_unwind(AssertUnwindSafe(|| {
#[cfg(feature = "plugin")]
read_plugin_file(engine_state, plugin_file, NUSHELL_FOLDER);

read_config_file(engine_state, stack, env_file, true);
read_config_file(engine_state, stack, config_file, false);
read_config_file(engine_state, stack, env_file, true, ask_to_create_config);
read_config_file(
engine_state,
stack,
config_file,
false,
ask_to_create_config,
);

if is_login_shell {
read_loginshell_file(engine_state, stack);
Expand Down
30 changes: 26 additions & 4 deletions src/run.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
#[cfg(feature = "plugin")]
use crate::config_files::NUSHELL_FOLDER;
use crate::{
command,
config_files::{self, setup_config},
config_files::{self, setup_config, NUSHELL_FOLDER},
};
use log::trace;
#[cfg(feature = "plugin")]
Expand All @@ -26,6 +24,13 @@ pub(crate) fn run_commands(
let mut stack = Stack::new();
let start_time = std::time::Instant::now();

let ask_to_create_config = if let Some(mut config_path) = nu_path::config_dir() {
config_path.push(NUSHELL_FOLDER);
!config_path.exists()
} else {
false
};

if stack.has_env_var(engine_state, "NU_DISABLE_IR") {
stack.use_ir = false;
}
Expand All @@ -49,6 +54,7 @@ pub(crate) fn run_commands(
&mut stack,
parsed_nu_cli_args.env_file,
true,
ask_to_create_config,
);
} else {
config_files::read_default_env_file(engine_state, &mut stack)
Expand All @@ -57,13 +63,21 @@ pub(crate) fn run_commands(
perf!("read env.nu", start_time, use_color);

let start_time = std::time::Instant::now();
let ask_to_create_config = if let Some(mut config_path) = nu_path::config_dir() {
config_path.push(config_files::NUSHELL_FOLDER);
!config_path.exists()
} else {
false
};

// If we have a config file parameter *OR* we have a login shell parameter, read the config file
if parsed_nu_cli_args.config_file.is_some() || parsed_nu_cli_args.login_shell.is_some() {
config_files::read_config_file(
engine_state,
&mut stack,
parsed_nu_cli_args.config_file,
false,
ask_to_create_config,
);
}

Expand Down Expand Up @@ -126,6 +140,12 @@ pub(crate) fn run_file(
// if the --no-config-file(-n) flag is passed, do not load plugin, env, or config files
if parsed_nu_cli_args.no_config_file.is_none() {
let start_time = std::time::Instant::now();
let ask_to_create_config = if let Some(mut config_path) = nu_path::config_dir() {
config_path.push(config_files::NUSHELL_FOLDER);
!config_path.exists()
} else {
false
};
#[cfg(feature = "plugin")]
read_plugin_file(engine_state, parsed_nu_cli_args.plugin_file, NUSHELL_FOLDER);
perf!("read plugins", start_time, use_color);
Expand All @@ -138,6 +158,7 @@ pub(crate) fn run_file(
&mut stack,
parsed_nu_cli_args.env_file,
true,
ask_to_create_config,
);
} else {
config_files::read_default_env_file(engine_state, &mut stack)
Expand All @@ -151,6 +172,7 @@ pub(crate) fn run_file(
&mut stack,
parsed_nu_cli_args.config_file,
false,
ask_to_create_config,
);
}
perf!("read config.nu", start_time, use_color);
Expand Down Expand Up @@ -208,7 +230,7 @@ pub(crate) fn run_repl(
let ret_val = evaluate_repl(
engine_state,
stack,
config_files::NUSHELL_FOLDER,
NUSHELL_FOLDER,
parsed_nu_cli_args.execute,
parsed_nu_cli_args.no_std_lib,
entire_start_time,
Expand Down

0 comments on commit d68c3ec

Please sign in to comment.