From 85a3dda8b00defcef187294dc0abfdb80108618f Mon Sep 17 00:00:00 2001 From: reuben olinsky Date: Thu, 18 Jul 2024 14:40:04 -0700 Subject: [PATCH] feat: enable simpler builtins implemented outside brush (#130) --- brush-core/src/builtins.rs | 12 +++++-- brush-core/src/builtins/factory.rs | 50 ++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/brush-core/src/builtins.rs b/brush-core/src/builtins.rs index 4fa056b4..3c5ab696 100644 --- a/brush-core/src/builtins.rs +++ b/brush-core/src/builtins.rs @@ -56,8 +56,8 @@ mod unimp; mod unset; mod wait; -pub use factory::builtin; pub(crate) use factory::get_default_builtins; +pub use factory::{builtin, simple_builtin, SimpleCommand}; /// Macro to define a struct that represents a shell built-in flag argument that can be /// enabled or disabled by specifying an option with a leading '+' or '-' character. @@ -160,6 +160,14 @@ pub type CommandExecuteFunc = fn( Vec, ) -> BoxFuture<'_, Result>; +/// Type of a function to retrieve help content for a built-in command. +/// +/// # Arguments +/// +/// * `name` - The name of the command. +/// * `content_type` - The type of content to retrieve. +pub type CommandContentFunc = fn(&str, ContentType) -> Result; + /// Trait implemented by built-in shell commands. #[async_trait::async_trait] pub trait Command: Parser { @@ -256,7 +264,7 @@ pub struct Registration { pub execute_func: CommandExecuteFunc, /// Function to retrieve the builtin's content/help text. - pub content_func: fn(&str, ContentType) -> Result, + pub content_func: CommandContentFunc, /// Has this registration been disabled? pub disabled: bool, diff --git a/brush-core/src/builtins/factory.rs b/brush-core/src/builtins/factory.rs index b9067f80..0e9790b9 100644 --- a/brush-core/src/builtins/factory.rs +++ b/brush-core/src/builtins/factory.rs @@ -9,6 +9,31 @@ use crate::builtins; use crate::commands::{self, CommandArg}; use crate::error; +/// A simple command that can be registered as a built-in. +pub trait SimpleCommand { + /// Returns the content of the built-in command. + fn get_content(name: &str, content_type: builtins::ContentType) + -> Result; + + /// Executes the built-in command. + fn execute( + context: commands::ExecutionContext<'_>, + args: &[&str], + ) -> Result; +} + +/// Returns a built-in command registration, given an implementation of the +/// `SimpleCommand` trait. +pub fn simple_builtin() -> builtins::Registration { + builtins::Registration { + execute_func: exec_simple_builtin::, + content_func: B::get_content, + disabled: false, + special_builtin: false, + declaration_builtin: false, + } +} + /// Returns a built-in command registration, given an implementation of the /// `Command` trait. pub fn builtin() -> builtins::Registration { @@ -58,6 +83,31 @@ fn get_builtin_content( T::get_content(name, content_type) } +fn exec_simple_builtin( + context: commands::ExecutionContext<'_>, + args: Vec, +) -> BoxFuture<'_, Result> { + Box::pin(async move { exec_simple_builtin_impl::(context, args).await }) +} + +#[allow(clippy::unused_async)] +async fn exec_simple_builtin_impl( + context: commands::ExecutionContext<'_>, + args: Vec, +) -> Result { + let plain_args: Vec<_> = args + .into_iter() + .map(|arg| match arg { + CommandArg::String(s) => s, + CommandArg::Assignment(a) => a.to_string(), + }) + .collect(); + + let plain_args: Vec<_> = plain_args.iter().map(AsRef::as_ref).collect(); + + T::execute(context, plain_args.as_slice()) +} + fn exec_builtin( context: commands::ExecutionContext<'_>, args: Vec,