allow for arguments in EDITOR and VISUAL env vars (#8105)

# Description

Fixes #8051.

# User-Facing Changes

You can now put command arguments into the EDITOR and VISUAL config /
env variables.

# Tests + Formatting

I don't know how to write tests for this. However, I set $env.EDITOR to
"nvim -R" and it seemed to work.

# After Submitting

If your PR had any user-facing changes, update [the
documentation](https://github.com/nushell/nushell.github.io) after the
PR is merged, if necessary. This will help us keep the docs up to date.
This commit is contained in:
pwygab 2023-02-26 20:56:38 +08:00 committed by GitHub
parent 680405e527
commit 9bbb9711e4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 73 additions and 51 deletions

View File

@ -2,12 +2,10 @@ use nu_engine::env_to_strings;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, Spanned, Type,
Category, Example, PipelineData, ShellError, Signature, Type,
};
use crate::ExternalCommand;
use super::utils::get_editor;
use super::utils::{gen_command, get_editor};
#[derive(Clone)]
pub struct ConfigEnv;
@ -60,26 +58,13 @@ impl Command for ConfigEnv {
let mut nu_config = config_path.clone();
nu_config.push("env.nu");
let name = Spanned {
item: get_editor(engine_state, stack)?,
span: call.head,
};
let (item, config_args) = get_editor(engine_state, stack)?;
let args = vec![Spanned {
item: nu_config.to_string_lossy().to_string(),
span: Span::unknown(),
}];
let command = ExternalCommand {
name,
args,
arg_keep_raw: vec![false],
redirect_stdout: false,
redirect_stderr: false,
env_vars: env_vars_str,
trim_end_newline: false,
};
command.run_with_input(engine_state, stack, input, true)
gen_command(call.head, nu_config, item, config_args, env_vars_str).run_with_input(
engine_state,
stack,
input,
true,
)
}
}

View File

@ -2,12 +2,10 @@ use nu_engine::env_to_strings;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, Example, PipelineData, ShellError, Signature, Span, Spanned, Type,
Category, Example, PipelineData, ShellError, Signature, Type,
};
use crate::ExternalCommand;
use super::utils::get_editor;
use super::utils::{gen_command, get_editor};
#[derive(Clone)]
pub struct ConfigNu;
@ -60,26 +58,13 @@ impl Command for ConfigNu {
let mut nu_config = config_path.clone();
nu_config.push("config.nu");
let name = Spanned {
item: get_editor(engine_state, stack)?,
span: call.head,
};
let (item, config_args) = get_editor(engine_state, stack)?;
let args = vec![Spanned {
item: nu_config.to_string_lossy().to_string(),
span: Span::unknown(),
}];
let command = ExternalCommand {
name,
args,
arg_keep_raw: vec![false],
redirect_stdout: false,
redirect_stderr: false,
env_vars: env_vars_str,
trim_end_newline: false,
};
command.run_with_input(engine_state, stack, input, true)
gen_command(call.head, nu_config, item, config_args, env_vars_str).run_with_input(
engine_state,
stack,
input,
true,
)
}
}

View File

@ -1,12 +1,19 @@
use nu_protocol::engine::{EngineState, Stack};
use std::{collections::HashMap, path::PathBuf};
use nu_protocol::{
engine::{EngineState, Stack},
Span, Spanned,
};
use crate::ExternalCommand;
pub(crate) fn get_editor(
engine_state: &EngineState,
stack: &mut Stack,
) -> Result<String, nu_protocol::ShellError> {
) -> Result<(String, Vec<String>), nu_protocol::ShellError> {
let config = engine_state.get_config();
let env_vars = stack.get_env_vars(engine_state);
if !config.buffer_editor.is_empty() {
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()
@ -16,5 +23,50 @@ pub(crate) fn get_editor(
Ok("notepad".to_string())
} else {
Ok("nano".to_string())
}?;
if let Some((a, b)) = editor.split_once(' ') {
Ok((
a.to_string(),
b.split(' ')
.into_iter()
.map(|s| s.to_string())
.collect::<Vec<String>>(),
))
} else {
Ok((editor, Vec::new()))
}
}
pub(crate) fn gen_command(
span: Span,
config_path: PathBuf,
item: String,
config_args: Vec<String>,
env_vars_str: HashMap<String, String>,
) -> ExternalCommand {
let name = Spanned { item, span };
let mut args = vec![Spanned {
item: config_path.to_string_lossy().to_string(),
span: Span::unknown(),
}];
let number_of_args = config_args.len() + 1;
for arg in config_args {
args.push(Spanned {
item: arg,
span: Span::unknown(),
})
}
ExternalCommand {
name,
args,
arg_keep_raw: vec![false; number_of_args],
redirect_stdout: false,
redirect_stderr: false,
env_vars: env_vars_str,
trim_end_newline: false,
}
}