From 12d3e4e424b089c1d8171a1dda4e12814c91d6ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20=C5=BD=C3=A1dn=C3=ADk?= Date: Wed, 6 Apr 2022 20:11:51 +0300 Subject: [PATCH] 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 --- crates/nu-engine/src/eval.rs | 9 +++ docs/sample_config/default_config.nu | 84 +++++----------------------- docs/sample_config/default_env.nu | 58 +++++++++++++++++++ src/config_files.rs | 29 ++++++++-- src/main.rs | 22 +++++++- 5 files changed, 126 insertions(+), 76 deletions(-) create mode 100644 docs/sample_config/default_env.nu diff --git a/crates/nu-engine/src/eval.rs b/crates/nu-engine/src/eval.rs index a325065059..03116068d3 100644 --- a/crates/nu-engine/src/eval.rs +++ b/crates/nu-engine/src/eval.rs @@ -1142,6 +1142,7 @@ pub fn eval_variable( if let Some(mut config_path) = nu_path::config_dir() { config_path.push("nushell"); + let mut env_config_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(), 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")] diff --git a/docs/sample_config/default_config.nu b/docs/sample_config/default_config.nu index 1a87c81a38..dc0ce241f3 100644 --- a/docs/sample_config/default_config.nu +++ b/docs/sample_config/default_config.nu @@ -1,59 +1,5 @@ # 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, /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, /plugins is added -let-env NU_PLUGIN_DIRS = [ - ($nu.config-path | path dirname | path join 'plugins') -] - module completions { # 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 @@ -259,7 +205,7 @@ let $config = { type: { layout: columnar columns: 4 - col_width: 20 + col_width: 20 col_padding: 2 } style: { @@ -267,9 +213,9 @@ let $config = { selected_text: green_reverse description_text: yellow } - source: { |buffer, position| - $nu.scope.commands - | where command =~ $buffer + source: { |buffer, position| + $nu.scope.commands + | where command =~ $buffer | each { |it| {value: $it.command description: $it.usage} } } } @@ -286,10 +232,10 @@ let $config = { selected_text: green_reverse description_text: yellow } - source: { |buffer, position| - $nu.scope.vars - | where name =~ $buffer - | sort-by name + source: { |buffer, position| + $nu.scope.vars + | where name =~ $buffer + | sort-by name | each { |it| {value: $it.name description: $it.type} } } } @@ -300,7 +246,7 @@ let $config = { type: { layout: description columns: 4 - col_width: 20 + col_width: 20 col_padding: 2 selection_rows: 4 description_rows: 10 @@ -310,9 +256,9 @@ let $config = { selected_text: green_reverse description_text: yellow } - source: { |buffer, position| - $nu.scope.commands - | where command =~ $buffer + source: { |buffer, position| + $nu.scope.commands + | where command =~ $buffer | each { |it| {value: $it.command description: $it.usage} } } } @@ -366,21 +312,21 @@ let $config = { name: commands_menu modifier: control keycode: char_t - mode: [emacs, vi_normal, vi_insert] + mode: [emacs, vi_normal, vi_insert] event: { send: menu name: commands_menu } } { name: commands_menu modifier: control keycode: char_y - mode: [emacs, vi_normal, vi_insert] + mode: [emacs, vi_normal, vi_insert] event: { send: menu name: vars_menu } } { name: commands_with_description modifier: control keycode: char_u - mode: [emacs, vi_normal, vi_insert] + mode: [emacs, vi_normal, vi_insert] event: { send: menu name: commands_with_description } } ] diff --git a/docs/sample_config/default_env.nu b/docs/sample_config/default_env.nu new file mode 100644 index 0000000000..7a3946b000 --- /dev/null +++ b/docs/sample_config/default_env.nu @@ -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, /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, /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') diff --git a/src/config_files.rs b/src/config_files.rs index 882a898eb2..a5317401e2 100644 --- a/src/config_files.rs +++ b/src/config_files.rs @@ -10,6 +10,7 @@ use std::path::PathBuf; pub(crate) const NUSHELL_FOLDER: &str = "nushell"; const CONFIG_FILE: &str = "config.nu"; +const ENV_FILE: &str = "env.nu"; const HISTORY_FILE: &str = "history.txt"; pub(crate) fn read_config_file( @@ -17,6 +18,7 @@ pub(crate) fn read_config_file( stack: &mut Stack, config_file: Option>, is_perf_true: bool, + is_env_config: bool, ) { // Load config startup 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() { - 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): "); let mut answer = String::new(); @@ -54,7 +65,11 @@ pub(crate) fn read_config_file( .read_line(&mut answer) .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() { "y" | "" => { @@ -64,12 +79,16 @@ pub(crate) fn read_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( engine_state, stack, config_file.as_bytes(), - "default_config.nu", + if is_env_config { + "default_env.nu" + } else { + "default_config.nu" + }, PipelineData::new(Span::new(0, 0)), ); return; diff --git a/src/main.rs b/src/main.rs index 5ecb388dc6..d372eca0ce 100644 --- a/src/main.rs +++ b/src/main.rs @@ -101,6 +101,7 @@ fn main() -> Result<()> { || arg == "--testbin" || arg == "--log-level" || arg == "--config" + || arg == "--env-config" || arg == "--threads" || arg == "-t" { @@ -249,7 +250,12 @@ fn main() -> Result<()> { ret_val } 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 ret_val = @@ -269,6 +275,7 @@ fn setup_config( engine_state: &mut EngineState, stack: &mut Stack, config_file: Option>, + env_file: Option>, ) { #[cfg(feature = "plugin")] 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!()); } - 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( @@ -332,6 +340,7 @@ fn parse_commandline_args( let testbin: Option = call.get_flag_expr("testbin"); let perf = call.has_flag("perf"); let config_file: Option = call.get_flag_expr("config"); + let env_file: Option = call.get_flag_expr("env-config"); let log_level: Option = call.get_flag_expr("log-level"); let threads: Option = call.get_flag(engine_state, &mut stack, "threads")?; @@ -352,6 +361,7 @@ fn parse_commandline_args( let commands = extract_contents(commands, engine_state); let testbin = extract_contents(testbin, 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 help = call.has_flag("help"); @@ -387,6 +397,7 @@ fn parse_commandline_args( commands, testbin, config_file, + env_file, log_level, perf, threads, @@ -408,6 +419,7 @@ struct NushellCliArgs { commands: Option>, testbin: Option>, config_file: Option>, + env_file: Option>, log_level: Option>, perf: bool, threads: Option, @@ -451,6 +463,12 @@ impl Command for Nu { "start with an alternate config file", None, ) + .named( + "env-config", + SyntaxShape::String, + "start with an alternate environment config file", + None, + ) .named( "log-level", SyntaxShape::String,