From 621a44c4760ae02dc5ed8c6fa2a48b0e68e0f5c9 Mon Sep 17 00:00:00 2001 From: Xavier L'Heureux <xavier.lheureux@icloud.com> Date: Mon, 24 Jun 2019 11:10:09 -0400 Subject: [PATCH] Remove the map macro and use the function directly --- Cargo.toml | 1 + src/lib/builtins/mod.rs | 169 ++++++++++++++++++++-------------------- src/main.rs | 8 +- 3 files changed, 90 insertions(+), 88 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ab191ab3..fc7e0ba0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -85,6 +85,7 @@ errno-dragonfly = "0.1.1" [lib] path = "src/lib/lib.rs" +# proc-macro = true [profile.release] lto = true diff --git a/src/lib/builtins/mod.rs b/src/lib/builtins/mod.rs index 27e3fa37..7bb2bde3 100644 --- a/src/lib/builtins/mod.rs +++ b/src/lib/builtins/mod.rs @@ -29,21 +29,18 @@ use self::{ variables::{alias, drop_alias, drop_array, drop_variable}, }; pub use self::{helpers::Status, man_pages::check_help}; - -use std::{ - borrow::Cow, - io::{self, BufRead}, - path::PathBuf, -}; - -use hashbrown::HashMap; -use liner::{Completer, Context}; - use crate::{ shell::{sys, Capture, Shell, Value}, types, }; +use hashbrown::HashMap; use itertools::Itertools; +use liner::{Completer, Context}; +use std::{ + borrow::Cow, + io::{self, BufRead}, + path::PathBuf, +}; const HELP_DESC: &str = "Display helpful information about a given command or list commands if \ none specified\n help <command>"; @@ -56,15 +53,6 @@ const DISOWN_DESC: &str = /// The type for builtin functions. Builtins have direct access to the shell pub type BuiltinFunction<'a> = &'a dyn Fn(&[types::Str], &mut Shell<'_>) -> Status; -macro_rules! map { - ($builtins:ident, $($name:expr => $func:ident: $help:expr),+) => {{ - $( - $builtins.add($name, &$func, $help); - )+ - $builtins - }}; -} - // parses -N or +N patterns // required for popd, pushd, dirs fn parse_numeric_arg(arg: &str) -> Option<(bool, usize)> { @@ -89,7 +77,8 @@ fn parse_numeric_arg(arg: &str) -> Option<(bool, usize)> { /// }; /// /// // create a builtin map with some predefined builtins -/// let mut builtins = BuiltinMap::new().with_basic().with_variables(); +/// let mut builtins = BuiltinMap::new(); +/// builtins.with_basic().with_variables(); /// /// // add a builtin /// builtins.add("custom builtin", &mut custom, "Very helpful comment to display to the user"); @@ -106,12 +95,14 @@ pub struct BuiltinMap<'a> { impl<'a> Default for BuiltinMap<'a> { fn default() -> Self { - Self::with_capacity(64) + let mut builtins = Self::with_capacity(64); + builtins .with_basic() .with_variables() .with_process_control() .with_values_tests() - .with_files_and_directory() + .with_files_and_directory(); + builtins } } @@ -145,102 +136,110 @@ impl<'a> BuiltinMap<'a> { pub fn get(&self, func: &str) -> Option<BuiltinFunction<'a>> { self.fcts.get(func).cloned() } /// Add a new builtin - pub fn add(&mut self, name: &'static str, func: BuiltinFunction<'a>, help: &'static str) { + pub fn add( + &mut self, + name: &'static str, + func: BuiltinFunction<'a>, + help: &'static str, + ) -> &mut Self { self.fcts.insert(name, func); self.help.insert(name, help); + self } /// Create and control variables /// /// Contains `fn`, `alias`, `unalias`, `drop`, `read` - pub fn with_variables(mut self) -> Self { - map!( - self, - "fn" => builtin_fn : "Print list of functions", - "alias" => builtin_alias : "View, set or unset aliases", - "unalias" => builtin_unalias : "Delete an alias", - "drop" => builtin_drop : "Delete a variable", - "read" => builtin_read : "Read some variables\n read <variable>" - ) + pub fn with_variables(&mut self) -> &mut Self { + self.add("fn", &builtin_fn, "Print list of functions") + .add("alias", &builtin_alias, "View, set or unset aliases") + .add("unalias", &builtin_unalias, "Delete an alias") + .add("drop", &builtin_drop, "Delete a variable") + .add("read", &builtin_read, "Read some variables\n read <variable>") } /// Control subrpocesses states /// /// Contains `disown`, `bg`, `fg`, `wait`, `isatty`, `jobs` - pub fn with_process_control(mut self) -> Self { - map!( - self, - "disown" => builtin_disown : DISOWN_DESC, - "bg" => builtin_bg : "Resumes a stopped background process", - "fg" => builtin_fg : "Resumes and sets a background process as the active process", - "wait" => builtin_wait : "Waits until all running background processes have completed", - "isatty" => builtin_isatty : "Returns 0 exit status if the supplied FD is a tty", - "jobs" => builtin_jobs : "Displays all jobs that are attached to the background" - ) + pub fn with_process_control(&mut self) -> &mut Self { + self.add("disown", &builtin_disown, DISOWN_DESC) + .add("bg", &builtin_bg, "Resumes a stopped background process") + .add("fg", &builtin_fg, "Resumes and sets a background process as the active process") + .add( + "wait", + &builtin_wait, + "Waits until all running background processes have completed", + ) + .add("isatty", &builtin_isatty, "Returns 0 exit status if the supplied FD is a tty") + .add("jobs", &builtin_jobs, "Displays all jobs that are attached to the background") } /// Utilities concerning the filesystem /// /// Contains `which`, `test`, `exists`, `popd`, `pushd`, `dirs`, `cd` - pub fn with_files_and_directory(mut self) -> Self { - map!( - self, - "which" => builtin_which : "Shows the full path of commands", - "test" => builtin_test : "Performs tests on files and text", - "exists" => builtin_exists : "Performs tests on files and text", - "popd" => builtin_popd : "Pop a directory from the stack", - "pushd" => builtin_pushd : "Push a directory to the stack", - "dirs" => builtin_dirs : "Display the current directory stack", - "cd" => builtin_cd : "Change the current directory\n cd <path>", - "dir_depth" => builtin_dir_depth : "Set the maximum directory depth" - ) + pub fn with_files_and_directory(&mut self) -> &mut Self { + self.add("which", &builtin_which, "Shows the full path of commands") + .add("test", &builtin_test, "Performs tests on files and text") + .add("exists", &builtin_exists, "Performs tests on files and text") + .add("popd", &builtin_popd, "Pop a directory from the stack") + .add("pushd", &builtin_pushd, "Push a directory to the stack") + .add("dirs", &builtin_dirs, "Display the current directory stack") + .add("cd", &builtin_cd, "Change the current directory\n cd <path>") + .add("dir_depth", &builtin_dir_depth, "Set the maximum directory depth") } /// Utilities to test values /// /// Contains `bool`, `calc`, `eq`, `is`, `true`, `false`, `starts-with`, `ends-with`, /// `contains`, `matches`, `random` - pub fn with_values_tests(mut self) -> Self { - map!( - self, - "bool" => builtin_bool : "If the value is '1' or 'true', return 0 exit status", - "calc" => builtin_calc : "Calculate a mathematical expression", - "eq" => builtin_eq : "Simple alternative to == and !=", - "is" => builtin_is : "Simple alternative to == and !=", - "true" => builtin_true : "Do nothing, successfully", - "false" => builtin_false : "Do nothing, unsuccessfully", - "starts-with" => starts_with : "Evaluates if the supplied argument starts with a given string", - "ends-with" => ends_with : "Evaluates if the supplied argument ends with a given string", - "contains" => contains : "Evaluates if the supplied argument contains a given string", - "matches" => builtin_matches : "Checks if a string matches a given regex", - "random" => builtin_random : "Outputs a random u64" - ) + pub fn with_values_tests(&mut self) -> &mut Self { + self.add("bool", &builtin_bool, "If the value is '1' or 'true', return 0 exit status") + .add("calc", &builtin_calc, "Calculate a mathematical expression") + .add("eq", &builtin_eq, "Simple alternative to == and !=") + .add("is", &builtin_is, "Simple alternative to == and !=") + .add("true", &builtin_true, "Do nothing, successfully") + .add("false", &builtin_false, "Do nothing, unsuccessfully") + .add( + "starts-with", + &starts_with, + "Evaluates if the supplied argument starts with a given string", + ) + .add( + "ends-with", + &ends_with, + "Evaluates if the supplied argument ends with a given string", + ) + .add( + "contains", + &contains, + "Evaluates if the supplied argument contains a given string", + ) + .add("matches", &builtin_matches, "Checks if a string matches a given regex") + .add("random", &builtin_random, "Outputs a random u64") } /// Basic utilities for any ion embedded library /// /// Contains `help`, `source`, `status`, `echo`, `type` - pub fn with_basic(mut self) -> Self { - map!( - self, - "help" => builtin_help : HELP_DESC, - "source" => builtin_source : SOURCE_DESC, - "status" => builtin_status : "Evaluates the current runtime status", - "echo" => builtin_echo : "Display a line of text", - "type" => builtin_type : "indicates how a command would be interpreted" - ) + pub fn with_basic(&mut self) -> &mut Self { + self.add("help", &builtin_help, HELP_DESC) + .add("source", &builtin_source, SOURCE_DESC) + .add("status", &builtin_status, "Evaluates the current runtime status") + .add("echo", &builtin_echo, "Display a line of text") + .add("type", &builtin_type, "indicates how a command would be interpreted") } /// Utilities specific for a shell, that should probably not be included in an embedded context /// /// Contains `eval`, `exec`, `exit`, `set`, `suspend` - pub fn with_shell_unsafe(mut self) -> Self { - map!( - self, - "eval" => builtin_eval : "Evaluates the evaluated expression", - "set" => builtin_set : "Set or unset values of shell options and positional parameters.", - "suspend" => builtin_suspend : "Suspends the shell with a SIGTSTOP signal" - ) + pub fn with_shell_unsafe(&mut self) -> &mut Self { + self.add("eval", &builtin_eval, "Evaluates the evaluated expression") + .add( + "set", + &builtin_set, + "Set or unset values of shell options and positional parameters.", + ) + .add("suspend", &builtin_suspend, "Suspends the shell with a SIGTSTOP signal") } } diff --git a/src/main.rs b/src/main.rs index 8232cfd1..86d216d9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -133,9 +133,11 @@ fn main() { return; } - let mut builtins = BuiltinMap::default().with_shell_unsafe(); - builtins.add("exec", &builtins::exec, "Replace the shell with the given command."); - builtins.add("exit", &builtins::exit, "Exits the current session"); + let mut builtins = BuiltinMap::default(); + builtins + .with_shell_unsafe() + .add("exec", &builtins::exec, "Replace the shell with the given command.") + .add("exit", &builtins::exit, "Exits the current session"); let stdin_is_a_tty = atty::is(Stream::Stdin); let mut shell = Shell::with_builtins(builtins); -- GitLab