diff --git a/brush-core/src/builtins.rs b/brush-core/src/builtins.rs index 2d19bb0..7ba0912 100644 --- a/brush-core/src/builtins.rs +++ b/brush-core/src/builtins.rs @@ -170,7 +170,7 @@ pub type CommandExecuteFunc = fn( pub type CommandContentFunc = fn(&str, ContentType) -> Result; /// Trait implemented by built-in shell commands. -#[async_trait::async_trait] + pub trait Command: Parser { /// Instantiates the built-in command with the given arguments. /// @@ -208,10 +208,11 @@ pub trait Command: Parser { /// # Arguments /// /// * `context` - The context in which the command is being executed. - async fn execute( + // NOTE: we use desugared async here because we need a Send marker + fn execute( &self, context: commands::ExecutionContext<'_>, - ) -> Result; + ) -> impl std::future::Future> + std::marker::Send; /// Returns the textual help content associated with the command. /// @@ -236,7 +237,7 @@ pub trait Command: Parser { /// Trait implemented by built-in shell commands that take specially handled declarations /// as arguments. -#[async_trait::async_trait] + pub trait DeclarationCommand: Command { /// Stores the declarations within the command instance. /// @@ -395,8 +396,7 @@ fn brush_help_styles() -> clap::builder::Styles { /// # Returns /// /// * a parsed struct T from [`clap::Parser::parse_from`] -/// * the remain iterator `args` with `--` and the rest arguments if they present -/// othervise None +/// * the remain iterator `args` with `--` and the rest arguments if they present othervise None /// /// # Examples /// ``` @@ -420,8 +420,8 @@ where S: Into + Clone + PartialEq<&'static str>, { let mut args = args.into_iter(); - // the best way to save `--` is to get it out with a side effect while `clap` iterates over the args - // this way we can be 100% sure that we have '--' and the remaining args + // the best way to save `--` is to get it out with a side effect while `clap` iterates over the + // args this way we can be 100% sure that we have '--' and the remaining args // and we will iterate only once let mut hyphen = None; let args_before_hyphen = args.by_ref().take_while(|a| { @@ -437,7 +437,8 @@ where } /// Similar to [`parse_known`] but with [`clap::Parser::try_parse_from`] -/// This function is used to parse arguments in builtins such as [`crate::builtins::echo::EchoCommand`] +/// This function is used to parse arguments in builtins such as +/// [`crate::builtins::echo::EchoCommand`] pub fn try_parse_known( args: impl IntoIterator, ) -> Result<(T, Option>), clap::Error> { diff --git a/brush-core/src/builtins/alias.rs b/brush-core/src/builtins/alias.rs index 375c062..7b9f7c2 100644 --- a/brush-core/src/builtins/alias.rs +++ b/brush-core/src/builtins/alias.rs @@ -15,7 +15,6 @@ pub(crate) struct AliasCommand { aliases: Vec, } -#[async_trait::async_trait] impl builtins::Command for AliasCommand { async fn execute( &self, diff --git a/brush-core/src/builtins/bg.rs b/brush-core/src/builtins/bg.rs index ed14d5f..7faca92 100644 --- a/brush-core/src/builtins/bg.rs +++ b/brush-core/src/builtins/bg.rs @@ -10,7 +10,6 @@ pub(crate) struct BgCommand { job_specs: Vec, } -#[async_trait::async_trait] impl builtins::Command for BgCommand { async fn execute( &self, diff --git a/brush-core/src/builtins/break_.rs b/brush-core/src/builtins/break_.rs index 15b2c24..246c15b 100644 --- a/brush-core/src/builtins/break_.rs +++ b/brush-core/src/builtins/break_.rs @@ -10,7 +10,6 @@ pub(crate) struct BreakCommand { which_loop: i8, } -#[async_trait::async_trait] impl builtins::Command for BreakCommand { async fn execute( &self, diff --git a/brush-core/src/builtins/brushinfo.rs b/brush-core/src/builtins/brushinfo.rs index 3da0720..9db907c 100644 --- a/brush-core/src/builtins/brushinfo.rs +++ b/brush-core/src/builtins/brushinfo.rs @@ -53,7 +53,6 @@ enum CompleteCommand { }, } -#[async_trait::async_trait] impl builtins::Command for BrushInfoCommand { async fn execute( &self, diff --git a/brush-core/src/builtins/builtin_.rs b/brush-core/src/builtins/builtin_.rs index 8075405..a6fbd42 100644 --- a/brush-core/src/builtins/builtin_.rs +++ b/brush-core/src/builtins/builtin_.rs @@ -14,7 +14,6 @@ pub(crate) struct BuiltinCommand { args: Vec, } -#[async_trait::async_trait] impl builtins::Command for BuiltinCommand { async fn execute( &self, diff --git a/brush-core/src/builtins/cd.rs b/brush-core/src/builtins/cd.rs index 860c3c9..63a67d9 100644 --- a/brush-core/src/builtins/cd.rs +++ b/brush-core/src/builtins/cd.rs @@ -28,7 +28,6 @@ pub(crate) struct CdCommand { target_dir: Option, } -#[async_trait::async_trait] impl builtins::Command for CdCommand { async fn execute( &self, diff --git a/brush-core/src/builtins/colon.rs b/brush-core/src/builtins/colon.rs index 50640ee..371d1ed 100644 --- a/brush-core/src/builtins/colon.rs +++ b/brush-core/src/builtins/colon.rs @@ -10,7 +10,6 @@ pub(crate) struct ColonCommand { args: Vec, } -#[async_trait::async_trait] impl builtins::Command for ColonCommand { async fn execute( &self, diff --git a/brush-core/src/builtins/command.rs b/brush-core/src/builtins/command.rs index bc0c2ea..eb6ed8b 100644 --- a/brush-core/src/builtins/command.rs +++ b/brush-core/src/builtins/command.rs @@ -26,7 +26,6 @@ pub(crate) struct CommandCommand { args: Vec, } -#[async_trait::async_trait] impl builtins::Command for CommandCommand { async fn execute( &self, diff --git a/brush-core/src/builtins/complete.rs b/brush-core/src/builtins/complete.rs index 0f70bfd..dcbf23c 100644 --- a/brush-core/src/builtins/complete.rs +++ b/brush-core/src/builtins/complete.rs @@ -210,7 +210,6 @@ pub(crate) struct CompleteCommand { names: Vec, } -#[async_trait::async_trait] impl builtins::Command for CompleteCommand { async fn execute( &self, @@ -435,7 +434,6 @@ pub(crate) struct CompGenCommand { word: Option, } -#[async_trait::async_trait] impl builtins::Command for CompGenCommand { async fn execute( &self, @@ -514,7 +512,6 @@ pub(crate) struct CompOptCommand { names: Vec, } -#[async_trait::async_trait] impl builtins::Command for CompOptCommand { async fn execute( &self, diff --git a/brush-core/src/builtins/continue_.rs b/brush-core/src/builtins/continue_.rs index 117f5ff..7963118 100644 --- a/brush-core/src/builtins/continue_.rs +++ b/brush-core/src/builtins/continue_.rs @@ -10,7 +10,6 @@ pub(crate) struct ContinueCommand { which_loop: i8, } -#[async_trait::async_trait] impl builtins::Command for ContinueCommand { async fn execute( &self, diff --git a/brush-core/src/builtins/declare.rs b/brush-core/src/builtins/declare.rs index 407af94..1515338 100644 --- a/brush-core/src/builtins/declare.rs +++ b/brush-core/src/builtins/declare.rs @@ -110,7 +110,6 @@ impl builtins::DeclarationCommand for DeclareCommand { } #[allow(clippy::too_many_lines)] -#[async_trait::async_trait] impl builtins::Command for DeclareCommand { fn takes_plus_options() -> bool { true diff --git a/brush-core/src/builtins/dirs.rs b/brush-core/src/builtins/dirs.rs index 4ab5dd8..9024f72 100644 --- a/brush-core/src/builtins/dirs.rs +++ b/brush-core/src/builtins/dirs.rs @@ -25,7 +25,6 @@ pub(crate) struct DirsCommand { // TODO: implement +N and -N } -#[async_trait::async_trait] impl builtins::Command for DirsCommand { async fn execute( &self, diff --git a/brush-core/src/builtins/dot.rs b/brush-core/src/builtins/dot.rs index 1c012e2..34b0dac 100644 --- a/brush-core/src/builtins/dot.rs +++ b/brush-core/src/builtins/dot.rs @@ -15,7 +15,6 @@ pub(crate) struct DotCommand { pub script_args: Vec, } -#[async_trait::async_trait] impl builtins::Command for DotCommand { async fn execute( &self, diff --git a/brush-core/src/builtins/echo.rs b/brush-core/src/builtins/echo.rs index ffa07de..d3f08d4 100644 --- a/brush-core/src/builtins/echo.rs +++ b/brush-core/src/builtins/echo.rs @@ -24,10 +24,9 @@ pub(crate) struct EchoCommand { args: Vec, } -#[async_trait::async_trait] impl builtins::Command for EchoCommand { - /// Override the default [builtins::Command::new] function to handle clap's limitation related to `--`. - /// See [crate::builtins::parse_known] for more information + /// Override the default [`builtins::Command::new`] function to handle clap's limitation related + /// to `--`. See [`builtins::parse_known`] for more information /// TODO: we can safely remove this after the issue is resolved fn new(args: I) -> Result where @@ -75,6 +74,6 @@ impl builtins::Command for EchoCommand { write!(context.stdout(), "{s}")?; context.stdout().flush()?; - return Ok(builtins::ExitCode::Success); + Ok(builtins::ExitCode::Success) } } diff --git a/brush-core/src/builtins/enable.rs b/brush-core/src/builtins/enable.rs index aa1f590..6bc0da6 100644 --- a/brush-core/src/builtins/enable.rs +++ b/brush-core/src/builtins/enable.rs @@ -37,7 +37,6 @@ pub(crate) struct EnableCommand { names: Vec, } -#[async_trait::async_trait] impl builtins::Command for EnableCommand { async fn execute( &self, diff --git a/brush-core/src/builtins/eval.rs b/brush-core/src/builtins/eval.rs index 85887b5..c970a32 100644 --- a/brush-core/src/builtins/eval.rs +++ b/brush-core/src/builtins/eval.rs @@ -9,7 +9,6 @@ pub(crate) struct EvalCommand { pub args: Vec, } -#[async_trait::async_trait] impl builtins::Command for EvalCommand { async fn execute( &self, diff --git a/brush-core/src/builtins/exec.rs b/brush-core/src/builtins/exec.rs index 6ab3443..0137e99 100644 --- a/brush-core/src/builtins/exec.rs +++ b/brush-core/src/builtins/exec.rs @@ -23,7 +23,6 @@ pub(crate) struct ExecCommand { args: Vec, } -#[async_trait::async_trait] impl builtins::Command for ExecCommand { async fn execute( &self, diff --git a/brush-core/src/builtins/exit.rs b/brush-core/src/builtins/exit.rs index 5ce7d7e..9c5b9d0 100644 --- a/brush-core/src/builtins/exit.rs +++ b/brush-core/src/builtins/exit.rs @@ -9,7 +9,6 @@ pub(crate) struct ExitCommand { code: Option, } -#[async_trait::async_trait] impl builtins::Command for ExitCommand { async fn execute( &self, diff --git a/brush-core/src/builtins/export.rs b/brush-core/src/builtins/export.rs index 28c48b9..19541f4 100644 --- a/brush-core/src/builtins/export.rs +++ b/brush-core/src/builtins/export.rs @@ -37,7 +37,6 @@ impl builtins::DeclarationCommand for ExportCommand { } } -#[async_trait::async_trait] impl builtins::Command for ExportCommand { async fn execute( &self, diff --git a/brush-core/src/builtins/false_.rs b/brush-core/src/builtins/false_.rs index d837939..a2be7aa 100644 --- a/brush-core/src/builtins/false_.rs +++ b/brush-core/src/builtins/false_.rs @@ -6,7 +6,6 @@ use crate::{builtins, commands}; #[derive(Parser)] pub(crate) struct FalseCommand {} -#[async_trait::async_trait] impl builtins::Command for FalseCommand { async fn execute( &self, diff --git a/brush-core/src/builtins/fg.rs b/brush-core/src/builtins/fg.rs index e553aad..231d38c 100644 --- a/brush-core/src/builtins/fg.rs +++ b/brush-core/src/builtins/fg.rs @@ -10,7 +10,6 @@ pub(crate) struct FgCommand { job_spec: Option, } -#[async_trait::async_trait] impl builtins::Command for FgCommand { async fn execute( &self, diff --git a/brush-core/src/builtins/getopts.rs b/brush-core/src/builtins/getopts.rs index 895b926..3d97160 100644 --- a/brush-core/src/builtins/getopts.rs +++ b/brush-core/src/builtins/getopts.rs @@ -18,7 +18,6 @@ pub(crate) struct GetOptsCommand { args: Vec, } -#[async_trait::async_trait] impl builtins::Command for GetOptsCommand { async fn execute( &self, diff --git a/brush-core/src/builtins/help.rs b/brush-core/src/builtins/help.rs index 014c7d0..32d0fde 100644 --- a/brush-core/src/builtins/help.rs +++ b/brush-core/src/builtins/help.rs @@ -22,7 +22,6 @@ pub(crate) struct HelpCommand { topic_patterns: Vec, } -#[async_trait::async_trait] impl builtins::Command for HelpCommand { async fn execute( &self, diff --git a/brush-core/src/builtins/jobs.rs b/brush-core/src/builtins/jobs.rs index e26b707..b0ef597 100644 --- a/brush-core/src/builtins/jobs.rs +++ b/brush-core/src/builtins/jobs.rs @@ -31,7 +31,6 @@ pub(crate) struct JobsCommand { job_specs: Vec, } -#[async_trait::async_trait] impl builtins::Command for JobsCommand { async fn execute( &self, diff --git a/brush-core/src/builtins/kill.rs b/brush-core/src/builtins/kill.rs index 342e3b5..f94b978 100644 --- a/brush-core/src/builtins/kill.rs +++ b/brush-core/src/builtins/kill.rs @@ -16,7 +16,6 @@ pub(crate) struct KillCommand { // // TODO: implement -sigspec syntax - // /// List known signal names. #[arg(short = 'l', short_alias = 'L')] list_signals: bool, @@ -25,7 +24,6 @@ pub(crate) struct KillCommand { args: Vec, } -#[async_trait::async_trait] impl builtins::Command for KillCommand { async fn execute( &self, @@ -39,7 +37,7 @@ impl builtins::Command for KillCommand { } if self.list_signals { - return error::unimp("kill -l"); + error::unimp("kill -l") } else { if self.args.len() != 1 { writeln!(context.stderr(), "{}: invalid usage", context.command_name)?; diff --git a/brush-core/src/builtins/let_.rs b/brush-core/src/builtins/let_.rs index 774c662..9f2cb4a 100644 --- a/brush-core/src/builtins/let_.rs +++ b/brush-core/src/builtins/let_.rs @@ -11,7 +11,6 @@ pub(crate) struct LetCommand { exprs: Vec, } -#[async_trait::async_trait] impl builtins::Command for LetCommand { async fn execute( &self, diff --git a/brush-core/src/builtins/popd.rs b/brush-core/src/builtins/popd.rs index ed6409d..d525feb 100644 --- a/brush-core/src/builtins/popd.rs +++ b/brush-core/src/builtins/popd.rs @@ -11,10 +11,8 @@ pub(crate) struct PopdCommand { no_directory_change: bool, // // TODO: implement +N and -N - // } -#[async_trait::async_trait] impl builtins::Command for PopdCommand { async fn execute( &self, diff --git a/brush-core/src/builtins/printf.rs b/brush-core/src/builtins/printf.rs index fcdc712..248d24a 100644 --- a/brush-core/src/builtins/printf.rs +++ b/brush-core/src/builtins/printf.rs @@ -16,7 +16,6 @@ pub(crate) struct PrintfCommand { format_and_args: Vec, } -#[async_trait::async_trait] impl builtins::Command for PrintfCommand { async fn execute( &self, @@ -31,7 +30,7 @@ impl builtins::Command for PrintfCommand { context.stdout().flush()?; } - return Ok(builtins::ExitCode::Success); + Ok(builtins::ExitCode::Success) } } diff --git a/brush-core/src/builtins/pushd.rs b/brush-core/src/builtins/pushd.rs index 08240b2..595dedd 100644 --- a/brush-core/src/builtins/pushd.rs +++ b/brush-core/src/builtins/pushd.rs @@ -13,10 +13,8 @@ pub(crate) struct PushdCommand { dir: String, // // TODO: implement +N and -N - // } -#[async_trait::async_trait] impl builtins::Command for PushdCommand { async fn execute( &self, diff --git a/brush-core/src/builtins/pwd.rs b/brush-core/src/builtins/pwd.rs index 72874da..8ad06db 100644 --- a/brush-core/src/builtins/pwd.rs +++ b/brush-core/src/builtins/pwd.rs @@ -14,7 +14,6 @@ pub(crate) struct PwdCommand { allow_symlinks: bool, } -#[async_trait::async_trait] impl builtins::Command for PwdCommand { async fn execute( &self, diff --git a/brush-core/src/builtins/read.rs b/brush-core/src/builtins/read.rs index b3c045c..ab70f84 100644 --- a/brush-core/src/builtins/read.rs +++ b/brush-core/src/builtins/read.rs @@ -59,7 +59,6 @@ pub(crate) struct ReadCommand { variable_names: Vec, } -#[async_trait::async_trait] impl builtins::Command for ReadCommand { async fn execute( &self, diff --git a/brush-core/src/builtins/return_.rs b/brush-core/src/builtins/return_.rs index ebcf9ef..f52e3d4 100644 --- a/brush-core/src/builtins/return_.rs +++ b/brush-core/src/builtins/return_.rs @@ -9,7 +9,6 @@ pub(crate) struct ReturnCommand { code: Option, } -#[async_trait::async_trait] impl builtins::Command for ReturnCommand { async fn execute( &self, diff --git a/brush-core/src/builtins/set.rs b/brush-core/src/builtins/set.rs index 8504e63..9fa6448 100644 --- a/brush-core/src/builtins/set.rs +++ b/brush-core/src/builtins/set.rs @@ -130,7 +130,6 @@ pub(crate) struct SetCommand { positional_args: Vec, } -#[async_trait::async_trait] impl builtins::Command for SetCommand { fn takes_plus_options() -> bool { true diff --git a/brush-core/src/builtins/shift.rs b/brush-core/src/builtins/shift.rs index e81bf77..df38628 100644 --- a/brush-core/src/builtins/shift.rs +++ b/brush-core/src/builtins/shift.rs @@ -9,7 +9,6 @@ pub(crate) struct ShiftCommand { n: Option, } -#[async_trait::async_trait] impl builtins::Command for ShiftCommand { async fn execute( &self, diff --git a/brush-core/src/builtins/shopt.rs b/brush-core/src/builtins/shopt.rs index a3d4477..d1604b2 100644 --- a/brush-core/src/builtins/shopt.rs +++ b/brush-core/src/builtins/shopt.rs @@ -31,7 +31,6 @@ pub(crate) struct ShoptCommand { options: Vec, } -#[async_trait::async_trait] impl builtins::Command for ShoptCommand { async fn execute( &self, diff --git a/brush-core/src/builtins/test.rs b/brush-core/src/builtins/test.rs index bb151fb..532552c 100644 --- a/brush-core/src/builtins/test.rs +++ b/brush-core/src/builtins/test.rs @@ -11,7 +11,6 @@ pub(crate) struct TestCommand { args: Vec, } -#[async_trait::async_trait] impl builtins::Command for TestCommand { async fn execute( &self, diff --git a/brush-core/src/builtins/trap.rs b/brush-core/src/builtins/trap.rs index 69e24e9..1a9cc71 100644 --- a/brush-core/src/builtins/trap.rs +++ b/brush-core/src/builtins/trap.rs @@ -17,7 +17,6 @@ pub(crate) struct TrapCommand { args: Vec, } -#[async_trait::async_trait] impl builtins::Command for TrapCommand { async fn execute( &self, diff --git a/brush-core/src/builtins/true_.rs b/brush-core/src/builtins/true_.rs index 99ca5a0..c70c34c 100644 --- a/brush-core/src/builtins/true_.rs +++ b/brush-core/src/builtins/true_.rs @@ -6,7 +6,6 @@ use crate::{builtins, commands}; #[derive(Parser)] pub(crate) struct TrueCommand {} -#[async_trait::async_trait] impl builtins::Command for TrueCommand { async fn execute( &self, diff --git a/brush-core/src/builtins/type_.rs b/brush-core/src/builtins/type_.rs index fded6e2..8723981 100644 --- a/brush-core/src/builtins/type_.rs +++ b/brush-core/src/builtins/type_.rs @@ -44,7 +44,6 @@ enum ResolvedType { File(PathBuf), } -#[async_trait::async_trait] impl builtins::Command for TypeCommand { async fn execute( &self, diff --git a/brush-core/src/builtins/umask.rs b/brush-core/src/builtins/umask.rs index 8a83f3b..3b8c45d 100644 --- a/brush-core/src/builtins/umask.rs +++ b/brush-core/src/builtins/umask.rs @@ -20,7 +20,6 @@ pub(crate) struct UmaskCommand { mode: Option, } -#[async_trait::async_trait] impl builtins::Command for UmaskCommand { async fn execute( &self, @@ -28,7 +27,7 @@ impl builtins::Command for UmaskCommand { ) -> Result { if let Some(mode) = &self.mode { if mode.starts_with(|c: char| c.is_digit(8)) { - let parsed = u32::from_str_radix(mode.as_str(), 8)?; + let parsed = nix::sys::stat::mode_t::from_str_radix(mode.as_str(), 8)?; set_umask(parsed)?; } else { return crate::error::unimp("umask setting mode from symbolic value"); @@ -64,17 +63,18 @@ cfg_if! { status.umask.ok_or_else(|| error::Error::InvalidUmask) } } else { + #[allow(clippy::unnecessary_wraps)] fn get_umask() -> Result { let u = nix::sys::stat::umask(Mode::empty()); nix::sys::stat::umask(u); - Ok(u.bits() as u32) + Ok(u32::from(u.bits())) } } } -fn set_umask(value: u32) -> Result<(), error::Error> { - let mode = - nix::sys::stat::Mode::from_bits(value as _).ok_or_else(|| error::Error::InvalidUmask)?; +fn set_umask(value: nix::sys::stat::mode_t) -> Result<(), error::Error> { + // value of mode_t can be platform dependent + let mode = nix::sys::stat::Mode::from_bits(value).ok_or_else(|| error::Error::InvalidUmask)?; nix::sys::stat::umask(mode); Ok(()) } diff --git a/brush-core/src/builtins/unalias.rs b/brush-core/src/builtins/unalias.rs index 6c5c5c3..50992a9 100644 --- a/brush-core/src/builtins/unalias.rs +++ b/brush-core/src/builtins/unalias.rs @@ -14,7 +14,6 @@ pub(crate) struct UnaliasCommand { aliases: Vec, } -#[async_trait::async_trait] impl builtins::Command for UnaliasCommand { async fn execute( &self, diff --git a/brush-core/src/builtins/unimp.rs b/brush-core/src/builtins/unimp.rs index 67afa64..db60c69 100644 --- a/brush-core/src/builtins/unimp.rs +++ b/brush-core/src/builtins/unimp.rs @@ -13,7 +13,6 @@ pub(crate) struct UnimplementedCommand { declarations: Vec, } -#[async_trait::async_trait] impl builtins::Command for UnimplementedCommand { async fn execute( &self, diff --git a/brush-core/src/builtins/unset.rs b/brush-core/src/builtins/unset.rs index b212091..94ac005 100644 --- a/brush-core/src/builtins/unset.rs +++ b/brush-core/src/builtins/unset.rs @@ -34,7 +34,6 @@ impl UnsetNameInterpretation { } } -#[async_trait::async_trait] impl builtins::Command for UnsetCommand { async fn execute( &self, diff --git a/brush-core/src/builtins/wait.rs b/brush-core/src/builtins/wait.rs index 049164b..c8dbf0b 100644 --- a/brush-core/src/builtins/wait.rs +++ b/brush-core/src/builtins/wait.rs @@ -22,7 +22,6 @@ pub(crate) struct WaitCommand { job_specs: Vec, } -#[async_trait::async_trait] impl builtins::Command for WaitCommand { async fn execute( &self, diff --git a/brush-core/src/interp.rs b/brush-core/src/interp.rs index 1b986b0..bacdf0e 100644 --- a/brush-core/src/interp.rs +++ b/brush-core/src/interp.rs @@ -1048,19 +1048,15 @@ async fn expand_assignment_value( ast::AssignmentValue::Array(arr) => { let mut expanded_values = vec![]; for (key, value) in arr { - match key { - Some(k) => { - let expanded_key = expansion::basic_expand_word(shell, k).await?.into(); - let expanded_value = - expansion::basic_expand_word(shell, value).await?.into(); - expanded_values.push((Some(expanded_key), expanded_value)); - } - None => { - let split_expanded_value = - expansion::full_expand_and_split_word(shell, value).await?; - for expanded_value in split_expanded_value { - expanded_values.push((None, expanded_value.into())); - } + if let Some(k) = key { + let expanded_key = expansion::basic_expand_word(shell, k).await?.into(); + let expanded_value = expansion::basic_expand_word(shell, value).await?.into(); + expanded_values.push((Some(expanded_key), expanded_value)); + } else { + let split_expanded_value = + expansion::full_expand_and_split_word(shell, value).await?; + for expanded_value in split_expanded_value { + expanded_values.push((None, expanded_value.into())); } } } diff --git a/brush-core/src/variables.rs b/brush-core/src/variables.rs index ec3848f..1d5470c 100644 --- a/brush-core/src/variables.rs +++ b/brush-core/src/variables.rs @@ -215,8 +215,8 @@ impl ShellVariable { if append { match (&self.value, &value) { - // If we're appending an array to a declared-but-unset variable (or appending anything to a declared-but-unset array), - // then fill it out first. + // If we're appending an array to a declared-but-unset variable (or appending + // anything to a declared-but-unset array), then fill it out first. (ShellValue::Unset(_), ShellValueLiteral::Array(_)) | ( ShellValue::Unset( @@ -226,8 +226,8 @@ impl ShellVariable { ) => { self.assign(ShellValueLiteral::Array(ArrayLiteral(vec![])), false)?; } - // If we're trying to append an array to a string, we first promote the string to be an array - // with the string being present at index 0. + // If we're trying to append an array to a string, we first promote the string to be + // an array with the string being present at index 0. (ShellValue::String(_), ShellValueLiteral::Array(_)) => { self.convert_to_indexed_array()?; } @@ -289,9 +289,9 @@ impl ShellVariable { ShellValueLiteral::Scalar(s), ) => self.assign_at_index(String::from("0"), s, false), - // If we're updating an indexed array value with an array, then preserve the array type. - // We also default to using an indexed array if we are assigning an array to a previously - // string-holding variable. + // If we're updating an indexed array value with an array, then preserve the array + // type. We also default to using an indexed array if we are + // assigning an array to a previously string-holding variable. ( ShellValue::IndexedArray(_) | ShellValue::Unset( @@ -305,7 +305,8 @@ impl ShellVariable { Ok(()) } - // If we're updating an associative array value with an array, then preserve the array type. + // If we're updating an associative array value with an array, then preserve the + // array type. ( ShellValue::AssociativeArray(_) | ShellValue::Unset(ShellValueUnsetType::AssociativeArray), @@ -334,7 +335,8 @@ impl ShellVariable { /// /// * `array_index` - The index at which to assign the value. /// * `value` - The value to assign to the variable at the given index. - /// * `append` - Whether or not to append the value to the preexisting value stored at the given index. + /// * `append` - Whether or not to append the value to the preexisting value stored at the given + /// index. #[allow(clippy::needless_pass_by_value)] pub fn assign_at_index( &mut self, diff --git a/brush-interactive/src/interactive_shell.rs b/brush-interactive/src/interactive_shell.rs index 3d8921c..914c09a 100644 --- a/brush-interactive/src/interactive_shell.rs +++ b/brush-interactive/src/interactive_shell.rs @@ -32,7 +32,7 @@ pub struct InteractivePrompt { } /// Represents a shell capable of taking commands from standard input. -#[async_trait::async_trait] + pub trait InteractiveShell { /// Returns an immutable reference to the inner shell object. fn shell(&self) -> impl AsRef + Send; @@ -53,94 +53,102 @@ pub trait InteractiveShell { /// Runs the interactive shell loop, reading commands from standard input and writing /// results to standard output and standard error. Continues until the shell /// normally exits or until a fatal error occurs. - async fn run_interactively(&mut self) -> Result<(), ShellError> { - // TODO: Consider finding a better place for this. - let _ = brush_core::TerminalControl::acquire()?; - - loop { - let result = self.run_interactively_once().await?; - match result { - InteractiveExecutionResult::Executed(brush_core::ExecutionResult { - exit_shell, - return_from_function_or_script, - .. - }) => { - if exit_shell { - break; + // NOTE: we use desugared async here because [async_fn_in_trait] "warning: use of `async fn` in + // public traits is discouraged as auto trait bounds cannot be specified" + fn run_interactively(&mut self) -> impl std::future::Future> { + async { + // TODO: Consider finding a better place for this. + let _ = brush_core::TerminalControl::acquire()?; + + loop { + let result = self.run_interactively_once().await?; + match result { + InteractiveExecutionResult::Executed(brush_core::ExecutionResult { + exit_shell, + return_from_function_or_script, + .. + }) => { + if exit_shell { + break; + } + + if return_from_function_or_script { + tracing::error!("return from non-function/script"); + } } - - if return_from_function_or_script { - tracing::error!("return from non-function/script"); + InteractiveExecutionResult::Failed(e) => { + // Report the error, but continue to execute. + tracing::error!("error: {:#}", e); + } + InteractiveExecutionResult::Eof => { + break; } - } - InteractiveExecutionResult::Failed(e) => { - // Report the error, but continue to execute. - tracing::error!("error: {:#}", e); - } - InteractiveExecutionResult::Eof => { - break; } } - } - if self.shell().as_ref().options.interactive { - writeln!(self.shell().as_ref().stderr(), "exit")?; - } + if self.shell().as_ref().options.interactive { + writeln!(self.shell().as_ref().stderr(), "exit")?; + } - if let Err(e) = self.update_history() { - // N.B. This seems like the sort of thing that's worth being noisy about, - // but bash doesn't do that -- and probably for a reason. - tracing::debug!("couldn't save history: {e}"); - } + if let Err(e) = self.update_history() { + // N.B. This seems like the sort of thing that's worth being noisy about, + // but bash doesn't do that -- and probably for a reason. + tracing::debug!("couldn't save history: {e}"); + } - Ok(()) + Ok(()) + } } /// Runs the interactive shell loop once, reading a single command from standard input. - async fn run_interactively_once(&mut self) -> Result { - let mut shell_mut = self.shell_mut(); - - // Check for any completed jobs. - shell_mut.as_mut().check_for_completed_jobs()?; + fn run_interactively_once( + &mut self, + ) -> impl std::future::Future> { + async { + let mut shell_mut = self.shell_mut(); - // If there's a variable called PROMPT_COMMAND, then run it first. - if let Some((_, prompt_cmd)) = shell_mut.as_mut().env.get("PROMPT_COMMAND") { - let prompt_cmd = prompt_cmd.value().to_cow_string().to_string(); + // Check for any completed jobs. + shell_mut.as_mut().check_for_completed_jobs()?; - // Save (and later restore) the last exit status. - let prev_last_result = shell_mut.as_mut().last_exit_status; + // If there's a variable called PROMPT_COMMAND, then run it first. + if let Some((_, prompt_cmd)) = shell_mut.as_mut().env.get("PROMPT_COMMAND") { + let prompt_cmd = prompt_cmd.value().to_cow_string().to_string(); - let params = shell_mut.as_mut().default_exec_params(); + // Save (and later restore) the last exit status. + let prev_last_result = shell_mut.as_mut().last_exit_status; - shell_mut.as_mut().run_string(prompt_cmd, ¶ms).await?; - shell_mut.as_mut().last_exit_status = prev_last_result; - } - - // Now that we've done that, compose the prompt. - let prompt = InteractivePrompt { - prompt: shell_mut.as_mut().compose_prompt().await?, - alt_side_prompt: shell_mut.as_mut().compose_alt_side_prompt().await?, - continuation_prompt: shell_mut.as_mut().continuation_prompt()?, - }; + let params = shell_mut.as_mut().default_exec_params(); - drop(shell_mut); + shell_mut.as_mut().run_string(prompt_cmd, ¶ms).await?; + shell_mut.as_mut().last_exit_status = prev_last_result; + } - match self.read_line(prompt)? { - ReadResult::Input(read_result) => { - let mut shell_mut = self.shell_mut(); - let params = shell_mut.as_mut().default_exec_params(); - match shell_mut.as_mut().run_string(read_result, ¶ms).await { - Ok(result) => Ok(InteractiveExecutionResult::Executed(result)), - Err(e) => Ok(InteractiveExecutionResult::Failed(e)), + // Now that we've done that, compose the prompt. + let prompt = InteractivePrompt { + prompt: shell_mut.as_mut().compose_prompt().await?, + alt_side_prompt: shell_mut.as_mut().compose_alt_side_prompt().await?, + continuation_prompt: shell_mut.as_mut().continuation_prompt()?, + }; + + drop(shell_mut); + + match self.read_line(prompt)? { + ReadResult::Input(read_result) => { + let mut shell_mut = self.shell_mut(); + let params = shell_mut.as_mut().default_exec_params(); + match shell_mut.as_mut().run_string(read_result, ¶ms).await { + Ok(result) => Ok(InteractiveExecutionResult::Executed(result)), + Err(e) => Ok(InteractiveExecutionResult::Failed(e)), + } + } + ReadResult::Eof => Ok(InteractiveExecutionResult::Eof), + ReadResult::Interrupted => { + let mut shell_mut = self.shell_mut(); + shell_mut.as_mut().last_exit_status = 130; + Ok(InteractiveExecutionResult::Executed( + brush_core::ExecutionResult::new(130), + )) } - } - ReadResult::Eof => Ok(InteractiveExecutionResult::Eof), - ReadResult::Interrupted => { - let mut shell_mut = self.shell_mut(); - shell_mut.as_mut().last_exit_status = 130; - Ok(InteractiveExecutionResult::Executed( - brush_core::ExecutionResult::new(130), - )) } } } diff --git a/brush-interactive/src/reedline/highlighter.rs b/brush-interactive/src/reedline/highlighter.rs index 5f9036f..6b2f04d 100644 --- a/brush-interactive/src/reedline/highlighter.rs +++ b/brush-interactive/src/reedline/highlighter.rs @@ -244,7 +244,8 @@ impl<'a> StyledInputLine<'a> { } fn skip_ahead(&mut self, dest: usize) { - // Append a no-op style to make sure we cover any trailing gaps in the input line not otherwise styled. + // Append a no-op style to make sure we cover any trailing gaps in the input line not + // otherwise styled. self.append_style(Style::new(), dest, dest); } diff --git a/brush-shell/src/brushctl.rs b/brush-shell/src/brushctl.rs index c50a2f9..07627d9 100644 --- a/brush-shell/src/brushctl.rs +++ b/brush-shell/src/brushctl.rs @@ -42,7 +42,6 @@ enum EventsCommand { }, } -#[async_trait::async_trait] impl brush_core::builtins::Command for BrushCtlCommand { async fn execute( &self, diff --git a/brush-shell/src/shell_factory.rs b/brush-shell/src/shell_factory.rs index bab0215..58d70c0 100644 --- a/brush-shell/src/shell_factory.rs +++ b/brush-shell/src/shell_factory.rs @@ -1,4 +1,3 @@ -#[async_trait::async_trait] pub(crate) trait ShellFactory { type ShellType: brush_interactive::InteractiveShell + Send; @@ -53,7 +52,6 @@ impl AsMut for StubShell { pub(crate) struct RustylineShellFactory; -#[async_trait::async_trait] impl ShellFactory for RustylineShellFactory { #[cfg(all(feature = "rustyline", any(windows, unix)))] type ShellType = brush_interactive::RustylineShell; @@ -78,7 +76,6 @@ impl ShellFactory for RustylineShellFactory { pub(crate) struct ReedlineShellFactory; -#[async_trait::async_trait] impl ShellFactory for ReedlineShellFactory { #[cfg(all(feature = "reedline", any(windows, unix)))] type ShellType = brush_interactive::ReedlineShell; @@ -103,7 +100,6 @@ impl ShellFactory for ReedlineShellFactory { pub(crate) struct BasicShellFactory; -#[async_trait::async_trait] impl ShellFactory for BasicShellFactory { #[cfg(feature = "basic")] type ShellType = brush_interactive::BasicShell;