Add env.nu file for environment config (#5099)

* Add env.nu file for environment config

* Add missing flag

* Add $nu.env-path variable

Prints `env.nu` path

* Add example of adding entries to PATH
This commit is contained in:
Jakub Žádník 2022-04-06 20:11:51 +03:00 committed by GitHub
parent c3bed1352a
commit 12d3e4e424
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 126 additions and 76 deletions

View File

@ -1142,6 +1142,7 @@ pub fn eval_variable(
if let Some(mut config_path) = nu_path::config_dir() { if let Some(mut config_path) = nu_path::config_dir() {
config_path.push("nushell"); config_path.push("nushell");
let mut env_config_path = config_path.clone();
let mut history_path = config_path.clone(); let mut history_path = config_path.clone();
@ -1160,6 +1161,14 @@ pub fn eval_variable(
val: config_path.to_string_lossy().to_string(), val: config_path.to_string_lossy().to_string(),
span, span,
}); });
env_config_path.push("env.nu");
output_cols.push("env-path".into());
output_vals.push(Value::String {
val: env_config_path.to_string_lossy().to_string(),
span,
});
} }
#[cfg(feature = "plugin")] #[cfg(feature = "plugin")]

View File

@ -1,59 +1,5 @@
# Nushell Config File # Nushell Config File
def create_left_prompt [] {
let path_segment = ($env.PWD)
$path_segment
}
def create_right_prompt [] {
let time_segment = ([
(date now | date format '%m/%d/%Y %r')
] | str collect)
$time_segment
}
# Use nushell functions to define your right and left prompt
let-env PROMPT_COMMAND = { create_left_prompt }
let-env PROMPT_COMMAND_RIGHT = { create_right_prompt }
# The prompt indicators are environmental variables that represent
# the state of the prompt
let-env PROMPT_INDICATOR = { "〉" }
let-env PROMPT_INDICATOR_VI_INSERT = { ": " }
let-env PROMPT_INDICATOR_VI_NORMAL = { "〉" }
let-env PROMPT_MULTILINE_INDICATOR = { "::: " }
# Specifies how environment variables are:
# - converted from a string to a value on Nushell startup (from_string)
# - converted from a value back to a string when running external commands (to_string)
# Note: The conversions happen *after* config.nu is loaded
let-env ENV_CONVERSIONS = {
"PATH": {
from_string: { |s| $s | split row (char esep) }
to_string: { |v| $v | str collect (char esep) }
}
"Path": {
from_string: { |s| $s | split row (char esep) }
to_string: { |v| $v | str collect (char esep) }
}
}
# Directories to search for scripts when calling source or use
#
# By default, <nushell-config-dir>/scripts is added
let-env NU_LIB_DIRS = [
($nu.config-path | path dirname | path join 'scripts')
]
# Directories to search for plugin binaries when calling register
#
# By default, <nushell-config-dir>/plugins is added
let-env NU_PLUGIN_DIRS = [
($nu.config-path | path dirname | path join 'plugins')
]
module completions { module completions {
# Custom completions for external commands (those outside of Nushell) # Custom completions for external commands (those outside of Nushell)
# Each completions has two parts: the form of the external command, including its flags and parameters # Each completions has two parts: the form of the external command, including its flags and parameters

View File

@ -0,0 +1,58 @@
# Nushell Environment Config File
def create_left_prompt [] {
let path_segment = ($env.PWD)
$path_segment
}
def create_right_prompt [] {
let time_segment = ([
(date now | date format '%m/%d/%Y %r')
] | str collect)
$time_segment
}
# Use nushell functions to define your right and left prompt
let-env PROMPT_COMMAND = { create_left_prompt }
let-env PROMPT_COMMAND_RIGHT = { create_right_prompt }
# The prompt indicators are environmental variables that represent
# the state of the prompt
let-env PROMPT_INDICATOR = { "〉" }
let-env PROMPT_INDICATOR_VI_INSERT = { ": " }
let-env PROMPT_INDICATOR_VI_NORMAL = { "〉" }
let-env PROMPT_MULTILINE_INDICATOR = { "::: " }
# Specifies how environment variables are:
# - converted from a string to a value on Nushell startup (from_string)
# - converted from a value back to a string when running external commands (to_string)
# Note: The conversions happen *after* config.nu is loaded
let-env ENV_CONVERSIONS = {
"PATH": {
from_string: { |s| $s | split row (char esep) }
to_string: { |v| $v | str collect (char esep) }
}
"Path": {
from_string: { |s| $s | split row (char esep) }
to_string: { |v| $v | str collect (char esep) }
}
}
# Directories to search for scripts when calling source or use
#
# By default, <nushell-config-dir>/scripts is added
let-env NU_LIB_DIRS = [
($nu.config-path | path dirname | path join 'scripts')
]
# Directories to search for plugin binaries when calling register
#
# By default, <nushell-config-dir>/plugins is added
let-env NU_PLUGIN_DIRS = [
($nu.config-path | path dirname | path join 'plugins')
]
# To add entries to PATH (on Windows you might use Path), you can use the following pattern:
# let-env PATH = ($env.PATH | prepend '/some/path')

View File

@ -10,6 +10,7 @@ use std::path::PathBuf;
pub(crate) const NUSHELL_FOLDER: &str = "nushell"; pub(crate) const NUSHELL_FOLDER: &str = "nushell";
const CONFIG_FILE: &str = "config.nu"; const CONFIG_FILE: &str = "config.nu";
const ENV_FILE: &str = "env.nu";
const HISTORY_FILE: &str = "history.txt"; const HISTORY_FILE: &str = "history.txt";
pub(crate) fn read_config_file( pub(crate) fn read_config_file(
@ -17,6 +18,7 @@ pub(crate) fn read_config_file(
stack: &mut Stack, stack: &mut Stack,
config_file: Option<Spanned<String>>, config_file: Option<Spanned<String>>,
is_perf_true: bool, is_perf_true: bool,
is_env_config: bool,
) { ) {
// Load config startup file // Load config startup file
if let Some(file) = config_file { if let Some(file) = config_file {
@ -43,10 +45,19 @@ pub(crate) fn read_config_file(
} }
} }
config_path.push(CONFIG_FILE); config_path.push(if is_env_config { ENV_FILE } else { CONFIG_FILE });
if !config_path.exists() { if !config_path.exists() {
println!("No config file found at {}", config_path.to_string_lossy()); let file_msg = if is_env_config {
"environment config"
} 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): "); println!("Would you like to create one with defaults (Y/n): ");
let mut answer = String::new(); let mut answer = String::new();
@ -54,7 +65,11 @@ pub(crate) fn read_config_file(
.read_line(&mut answer) .read_line(&mut answer)
.expect("Failed to read user input"); .expect("Failed to read user input");
let config_file = include_str!("../docs/sample_config/default_config.nu"); let config_file = if is_env_config {
include_str!("../docs/sample_config/default_env.nu")
} else {
include_str!("../docs/sample_config/default_config.nu")
};
match answer.to_lowercase().trim() { match answer.to_lowercase().trim() {
"y" | "" => { "y" | "" => {
@ -64,12 +79,16 @@ pub(crate) fn read_config_file(
} }
_ => { _ => {
println!("Continuing without config file"); println!("Continuing without config file");
// Just use the contents of "default_config.nu" // Just use the contents of "default_config.nu" or "default_env.nu"
eval_source( eval_source(
engine_state, engine_state,
stack, stack,
config_file.as_bytes(), config_file.as_bytes(),
"default_config.nu", if is_env_config {
"default_env.nu"
} else {
"default_config.nu"
},
PipelineData::new(Span::new(0, 0)), PipelineData::new(Span::new(0, 0)),
); );
return; return;

View File

@ -101,6 +101,7 @@ fn main() -> Result<()> {
|| arg == "--testbin" || arg == "--testbin"
|| arg == "--log-level" || arg == "--log-level"
|| arg == "--config" || arg == "--config"
|| arg == "--env-config"
|| arg == "--threads" || arg == "--threads"
|| arg == "-t" || arg == "-t"
{ {
@ -249,7 +250,12 @@ fn main() -> Result<()> {
ret_val ret_val
} else { } else {
setup_config(&mut engine_state, &mut stack, binary_args.config_file); setup_config(
&mut engine_state,
&mut stack,
binary_args.config_file,
binary_args.env_file,
);
let history_path = config_files::create_history_path(); let history_path = config_files::create_history_path();
let ret_val = let ret_val =
@ -269,6 +275,7 @@ fn setup_config(
engine_state: &mut EngineState, engine_state: &mut EngineState,
stack: &mut Stack, stack: &mut Stack,
config_file: Option<Spanned<String>>, config_file: Option<Spanned<String>>,
env_file: Option<Spanned<String>>,
) { ) {
#[cfg(feature = "plugin")] #[cfg(feature = "plugin")]
read_plugin_file(engine_state, stack, NUSHELL_FOLDER, is_perf_true()); read_plugin_file(engine_state, stack, NUSHELL_FOLDER, is_perf_true());
@ -277,7 +284,8 @@ fn setup_config(
info!("read_config_file {}:{}:{}", file!(), line!(), column!()); info!("read_config_file {}:{}:{}", file!(), line!(), column!());
} }
config_files::read_config_file(engine_state, stack, config_file, is_perf_true()); config_files::read_config_file(engine_state, stack, env_file, is_perf_true(), true);
config_files::read_config_file(engine_state, stack, config_file, is_perf_true(), false);
} }
fn parse_commandline_args( fn parse_commandline_args(
@ -332,6 +340,7 @@ fn parse_commandline_args(
let testbin: Option<Expression> = call.get_flag_expr("testbin"); let testbin: Option<Expression> = call.get_flag_expr("testbin");
let perf = call.has_flag("perf"); let perf = call.has_flag("perf");
let config_file: Option<Expression> = call.get_flag_expr("config"); let config_file: Option<Expression> = call.get_flag_expr("config");
let env_file: Option<Expression> = call.get_flag_expr("env-config");
let log_level: Option<Expression> = call.get_flag_expr("log-level"); let log_level: Option<Expression> = call.get_flag_expr("log-level");
let threads: Option<Value> = call.get_flag(engine_state, &mut stack, "threads")?; let threads: Option<Value> = call.get_flag(engine_state, &mut stack, "threads")?;
@ -352,6 +361,7 @@ fn parse_commandline_args(
let commands = extract_contents(commands, engine_state); let commands = extract_contents(commands, engine_state);
let testbin = extract_contents(testbin, engine_state); let testbin = extract_contents(testbin, engine_state);
let config_file = extract_contents(config_file, engine_state); let config_file = extract_contents(config_file, engine_state);
let env_file = extract_contents(env_file, engine_state);
let log_level = extract_contents(log_level, engine_state); let log_level = extract_contents(log_level, engine_state);
let help = call.has_flag("help"); let help = call.has_flag("help");
@ -387,6 +397,7 @@ fn parse_commandline_args(
commands, commands,
testbin, testbin,
config_file, config_file,
env_file,
log_level, log_level,
perf, perf,
threads, threads,
@ -408,6 +419,7 @@ struct NushellCliArgs {
commands: Option<Spanned<String>>, commands: Option<Spanned<String>>,
testbin: Option<Spanned<String>>, testbin: Option<Spanned<String>>,
config_file: Option<Spanned<String>>, config_file: Option<Spanned<String>>,
env_file: Option<Spanned<String>>,
log_level: Option<Spanned<String>>, log_level: Option<Spanned<String>>,
perf: bool, perf: bool,
threads: Option<Value>, threads: Option<Value>,
@ -451,6 +463,12 @@ impl Command for Nu {
"start with an alternate config file", "start with an alternate config file",
None, None,
) )
.named(
"env-config",
SyntaxShape::String,
"start with an alternate environment config file",
None,
)
.named( .named(
"log-level", "log-level",
SyntaxShape::String, SyntaxShape::String,