builtin_metadata!() { /* proc-macro */ }
Expand description
Macro to generate the code to define a new builtin for bash.
§Usage
builtin_metadata!(
name = string literal,
create | try_create = path,
short_doc = string literal,
long_doc = string literal,
);
Arguments are specified as key = value
items, where key
can be:
-
name
.The name of the builtin.
-
create
ortry_create
.A path to a function to initialize the builtin.
Just one of these keys has to be present.
-
short_doc
andlong_doc
.Optional keys for the builtin documentation.
See below for more details.
The generated code requires the bash_builtins
crate to be available in the
package.
§Example
A builtin like eval
can be defined with the following arguments:
builtin_metadata!(
name = "eval",
create = Eval::default,
short_doc = "eval [arg ...]",
long_doc = "
Execute arguments as a shell command.
Combine ARGs into a single string, use the result as input to the shell,
and execute the resulting commands.
Exit Status:
Returns exit status of command or success if command is null.
",
);
Eval::default
is a path to a function that returns an instance of the
Builtin
trait.
§Arguments
§name
The name of the builtin. It is required to be an ASCII identifier.
Users will type this name to invoke the builtin defined by the macro.
§create
A path to a function that returns an instance of the Builtin
trait.
See below for more details on how to define that function.
§try_create
Similar to create
, but the function returns an instance of
Result<T: Builtin, E: Display>
. If the function returns Err
,
the builtin will not be loaded.
§short_doc
(optional)
A single line of text to describe how to use the builtin.
This is optional, but it is recommended.
§long_doc
(optional)
Documentation of the builtin. Bash uses this text for the help
command.
Like short_doc
, it is optional but recommended.
The content of the text is processed to remove the leading new lines, and the left margin introduced to indent the content.
These two long_doc
expressions are equivalent:
// help text for the `true` builtin.
long_doc = "
Return a successful result.
Exit Status:
Always succeeds.
"
long_doc = "Return a successful result.\n\nExit Status:\nAlways succeeds.\n"
This transformation is similar to the indoc crate, the text blocks in Java, “squiggly” heredocs in Ruby, and many others.
§Builtin Initialization
Builtins are implemented as instances of the Builtin
trait. To create
that instance, one of create
or try_create
is required in the
builtin_metadata!()
macro.
The function given in create
returns the instance. In the following example
we use the generated default
function to create a new instance of the
Counter
type.
use bash_builtins::{builtin_metadata, Args, Builtin, Result};
builtin_metadata!(
name = "counter",
create = Counter::default,
// …
);
#[derive(Default)]
struct Counter(isize);
impl Builtin for Counter {
fn call(&mut self, args: &mut Args) -> Result<()> {
// …
}
}
The function given in try_create
returns a Result<T, E>
, where
T
is the type for the builtin, and E
implements Display
. If the
function returns an error then the builtin will not be loaded.
In the following example, the builtin will always fail to load:
builtin_metadata!(
name = "loadfail",
try_create = try_create,
// …
);
fn try_create() -> std::result::Result<LoadFail, &'static str> {
Err("something really bad happened")
}
struct LoadFail;
impl Builtin for LoadFail {
fn call(&mut self, _args: &mut Args) -> Result<()> {
Ok(())
}
}
We can compile this example and then try to load it:
$ cargo build --release --examples
$ enable -f target/release/examples/libloadfail.so loadfail
loadfail: error: something really bad happened
bash: enable: load function for loadfail returns failure (0): not loaded