From 546fffe960b6ebc9114210948c5a569105532a9f Mon Sep 17 00:00:00 2001 From: Horasal Date: Mon, 4 Sep 2023 08:54:58 +0900 Subject: [PATCH] Allow list for editor variable move `get_editor` to `cmd-base` so `nu-cli` can use it --- crates/nu-cmd-base/src/util.rs | 60 +++++++++++++++++++ .../nu-command/src/env/config/config_env.rs | 3 +- crates/nu-command/src/env/config/config_nu.rs | 3 +- crates/nu-command/src/env/config/utils.rs | 40 +------------ 4 files changed, 65 insertions(+), 41 deletions(-) diff --git a/crates/nu-cmd-base/src/util.rs b/crates/nu-cmd-base/src/util.rs index 62f52a6690e7..5a9de8a31a5e 100644 --- a/crates/nu-cmd-base/src/util.rs +++ b/crates/nu-cmd-base/src/util.rs @@ -55,3 +55,63 @@ pub fn process_range(range: &Range) -> Result<(isize, isize), MakeRangeError> { Ok((start, end)) } + +const HELP_MSG: &str = "Nushell's config file can be found with the command: $nu.config-path. \ +For more help: (https://nushell.sh/book/configuration.html#configurations-with-built-in-commands)"; + +fn get_editor_commandline(value: &Value) -> Result<(String, Vec), ShellError> { + match value { + Value::String { val, .. } if !val.is_empty() => Ok((val.to_string(), Vec::new())), + Value::List { vals, .. } if !vals.is_empty() => { + let mut editor_cmd = vals.iter().map(|l| l.as_string()); + match editor_cmd.next().transpose()? { + Some(editor) if !editor.is_empty() => { + let params = editor_cmd.collect::>()?; + Ok((editor, params)) + } + _ => Err(ShellError::GenericError( + "Editor's executable is missing".into(), + "Set the first element to an executable".into(), + Some(value.span()), + Some(HELP_MSG.into()), + vec![], + )), + } + } + Value::String { .. } | Value::List { .. } => Err(ShellError::GenericError( + "$EDITOR or $VISUAL should be a non-empty string or list".into(), + "Specify an executable here".into(), + Some(value.span()), + Some(HELP_MSG.into()), + vec![], + )), + x => Err(ShellError::CantConvert { + to_type: "string or list".into(), + from_type: x.get_type().to_string(), + span: value.span(), + help: None, + }), + } +} + +pub fn get_editor( + engine_state: &EngineState, + stack: &mut Stack, + span: Span, +) -> Result<(String, Vec), ShellError> { + let config = engine_state.get_config(); + let env_vars = stack.get_env_vars(engine_state); + if !config.buffer_editor.is_empty() { + Ok((config.buffer_editor.clone(), Vec::new())) + } else if let Some(value) = env_vars.get("EDITOR").or_else(|| env_vars.get("VISUAL")) { + get_editor_commandline(value) + } else { + Err(ShellError::GenericError( + "No editor configured".into(), + "Please specify one via environment variables $EDITOR or $VISUAL".into(), + Some(span), + Some(HELP_MSG.into()), + vec![], + )) + } +} diff --git a/crates/nu-command/src/env/config/config_env.rs b/crates/nu-command/src/env/config/config_env.rs index 45245b24928a..86f54abee0a3 100644 --- a/crates/nu-command/src/env/config/config_env.rs +++ b/crates/nu-command/src/env/config/config_env.rs @@ -5,7 +5,8 @@ use nu_protocol::{ Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, Type, Value, }; -use super::utils::{gen_command, get_editor}; +use super::utils::gen_command; +use nu_cmd_base::util::get_editor; #[derive(Clone)] pub struct ConfigEnv; diff --git a/crates/nu-command/src/env/config/config_nu.rs b/crates/nu-command/src/env/config/config_nu.rs index 7746a68ca274..90c04fd92ec8 100644 --- a/crates/nu-command/src/env/config/config_nu.rs +++ b/crates/nu-command/src/env/config/config_nu.rs @@ -5,7 +5,8 @@ use nu_protocol::{ Category, Example, IntoPipelineData, PipelineData, ShellError, Signature, Type, Value, }; -use super::utils::{gen_command, get_editor}; +use super::utils::gen_command; +use nu_cmd_base::util::get_editor; #[derive(Clone)] pub struct ConfigNu; diff --git a/crates/nu-command/src/env/config/utils.rs b/crates/nu-command/src/env/config/utils.rs index a7d50eab2c18..0c6e5d4ff7a2 100644 --- a/crates/nu-command/src/env/config/utils.rs +++ b/crates/nu-command/src/env/config/utils.rs @@ -1,48 +1,10 @@ use std::collections::HashMap; use std::path::PathBuf; -use nu_protocol::{ - engine::{EngineState, Stack}, - ShellError, Span, Spanned, -}; +use nu_protocol::{Span, Spanned}; use crate::ExternalCommand; -pub(crate) fn get_editor( - engine_state: &EngineState, - stack: &mut Stack, - span: Span, -) -> Result<(String, Vec), ShellError> { - let config = engine_state.get_config(); - let env_vars = stack.get_env_vars(engine_state); - let editor = if !config.buffer_editor.is_empty() { - Ok(config.buffer_editor.clone()) - } else if let Some(value) = env_vars.get("EDITOR") { - value.as_string() - } else if let Some(value) = env_vars.get("VISUAL") { - value.as_string() - } else { - Err(ShellError::GenericError( - "No editor configured".into(), - "Please specify one via environment variables $EDITOR or $VISUAL".into(), - Some(span), - Some( - "Nushell's config file can be found with the command: $nu.config-path. For more help: (https://nushell.sh/book/configuration.html#configurations-with-built-in-commands)" - .into(), - ), - vec![], - )) - }?; - if let Some((a, b)) = editor.split_once(' ') { - Ok(( - a.to_string(), - b.split(' ').map(|s| s.to_string()).collect::>(), - )) - } else { - Ok((editor, Vec::new())) - } -} - pub(crate) fn gen_command( span: Span, config_path: PathBuf,