diff --git a/members/builtins-proc/src/lib.rs b/members/builtins-proc/src/lib.rs index b4699cad2f8acc4f7027ea269df9afb8e439f70b..e50cd9fef003bea033dcb15fb4e74f99009200b1 100644 --- a/members/builtins-proc/src/lib.rs +++ b/members/builtins-proc/src/lib.rs @@ -10,29 +10,38 @@ pub fn builtin(attr: TokenStream, item: TokenStream) -> TokenStream { let attrs = syn::parse_macro_input!(attr as syn::AttributeArgs); let syn::ItemFn { vis, decl, block, ident, .. } = &input; let syn::FnDecl { ref fn_token, ref inputs, ref output, .. } = **decl; + let mut help = None; + let mut short_description = None; let name = syn::Ident::new(&format!("builtin_{}", &ident), input.ident.span()); - let help = attrs - .iter() - .filter_map(|meta| { - if let syn::NestedMeta::Meta(syn::Meta::NameValue(attr)) = meta { - if attr.ident == "man" { - if let syn::Lit::Str(help) = &attr.lit { - Some(help.value()) - } else { - None - } + for attr in attrs { + if let syn::NestedMeta::Meta(syn::Meta::NameValue(attr)) = attr { + if attr.ident == "man" { + if let syn::Lit::Str(h) = &attr.lit { + help = Some(h.value()); } else { - None + panic!("`man` attribute should be a string variable"); + } + } else if attr.ident == "desc" { + if let syn::Lit::Str(h) = &attr.lit { + short_description = Some(h.value()); + } else { + panic!("`desc` attribute should be a string variable"); } } else { - None + panic!("Only the `man` and `desc` attributes are allowed"); } - }) - .next() - .expect("A man page is required! Please add a documentation comment"); - let man = format!("NAME\n {} - {}", ident, help.trim()); + } else { + panic!("Only the `man` and `desc` attributes are allowed"); + } + } + let help = help.expect("A man page is required! Please add an attribute with name `man`"); + let help = help.trim(); + let short_description = short_description + .expect("A short description is required! Please add an attribute with name `desc`"); + let man = format!("NAME\n {} - {}\n\n{}", ident, short_description, help); + let help = format!("{}\n\n```txt\n{}\n```", short_description, help); let result = quote! { #[doc = #help] diff --git a/members/builtins-proc/tests/test.rs b/members/builtins-proc/tests/test.rs index 09394f13868491938f4cd1bda316d8b49d4d4f93..d04d26c9eb7bd91d8051c7eb1ae6f922a0cb6b27 100644 --- a/members/builtins-proc/tests/test.rs +++ b/members/builtins-proc/tests/test.rs @@ -1,13 +1,15 @@ use ion_shell::{builtins::Status, types, Shell}; -/// print 42 to the screen -/// -/// SYNOPSIS -/// gimme_the_answer_to_life_to_the_universe_and_to_everything_else [-h | --help] -/// -/// DESCRIPTION -/// Who doesn't want 42 printed to screen? -#[builtins_proc::builtin(man = "a comment")] +#[builtins_proc::builtin( + desc = "prints 42 to the screen", + man = " +SYNOPSIS + gimme_the_answer_to_life_to_the_universe_and_to_everything_else [-h | --help] + +DESCRIPTION + Who doesn't want 42 printed to screen? +" +)] fn gimme_the_answer_to_life_to_the_universe_and_to_everything_else( args: &[types::Str], _shell: &mut Shell<'_>, diff --git a/src/lib/builtins/mod.rs b/src/lib/builtins/mod.rs index d83b4cf1d1cb139271ef8356a8120391da23972b..f94703d54a8a5622d4808bf15811af5430729e9f 100644 --- a/src/lib/builtins/mod.rs +++ b/src/lib/builtins/mod.rs @@ -259,16 +259,17 @@ pub fn builtin_dir_depth(args: &[types::Str], shell: &mut Shell<'_>) -> Status { Status::SUCCESS } -#[builtin(man = " -Change directory. - +#[builtin( + desc = "Change directory.", + man = " SYNOPSIS cd DIRECTORY DESCRIPTION Without arguments cd changes the working directory to your home directory. With arguments cd changes the working directory to the directory you provided. -")] +" +)] pub fn cd(args: &[types::Str], shell: &mut Shell<'_>) -> Status { let err = match args.get(1) { Some(dir) => { @@ -304,15 +305,16 @@ pub fn cd(args: &[types::Str], shell: &mut Shell<'_>) -> Status { } } -#[builtin(man = " -Returns true if the value given to it is equal to '1' or 'true'. - +#[builtin( + desc = "Returns true if the value given to it is equal to '1' or 'true'.", + man = " SYNOPSIS bool VALUE DESCRIPTION Returns true if the value given to it is equal to '1' or 'true'. -")] +" +)] pub fn bool(args: &[types::Str], shell: &mut Shell<'_>) -> Status { if args.len() != 2 { return Status::error("bool requires one argument"); @@ -332,15 +334,16 @@ pub fn bool(args: &[types::Str], shell: &mut Shell<'_>) -> Status { Status::SUCCESS } -#[builtin(man = " -prints the directory stack - +#[builtin( + desc = "prints the directory stack", + man = " SYNOPSIS dirs DESCRIPTION dirs prints the current directory stack. -")] +" +)] pub fn dirs(args: &[types::Str], shell: &mut Shell<'_>) -> Status { // converts pbuf to an absolute path if possible fn try_abs_path(pbuf: &PathBuf) -> Cow<'_, str> { @@ -404,15 +407,16 @@ pub fn dirs(args: &[types::Str], shell: &mut Shell<'_>) -> Status { } } -#[builtin(man = " -push a directory to the directory stack - +#[builtin( + desc = "push a directory to the directory stack", + man = " SYNOPSIS pushd DIRECTORY DESCRIPTION pushd pushes a directory to the directory stack. -")] +" +)] pub fn pushd(args: &[types::Str], shell: &mut Shell<'_>) -> Status { enum Action { Switch, // <no arguments> @@ -480,17 +484,18 @@ pub fn pushd(args: &[types::Str], shell: &mut Shell<'_>) -> Status { Status::SUCCESS } -#[builtin(man = " -shift through the directory stack - +#[builtin( + desc = "shift through the directory stack", + man = " SYNOPSIS popd DESCRIPTION popd removes the top directory from the directory stack and changes the working directory to \ - the new top directory. + the new top directory. pushd adds directories to the stack. -")] +" +)] pub fn popd(args: &[types::Str], shell: &mut Shell<'_>) -> Status { let len = shell.dir_stack().dirs().len(); if len <= 1 { diff --git a/src/lib/builtins/status.rs b/src/lib/builtins/status.rs index 6aaec62ebbb80477f1b151010b2737a0d1ca8b1f..51c06c5678ed263618c45c051c5c4a711e81836c 100644 --- a/src/lib/builtins/status.rs +++ b/src/lib/builtins/status.rs @@ -4,9 +4,9 @@ use crate::{shell::Shell, types}; use builtins_proc::builtin; use std::env; -#[builtin(man = " -Evaluates the current runtime status - +#[builtin( + desc = "Evaluates the current runtime status", + man = " SYNOPSIS status [ -h | --help ] [-l] [-i] @@ -20,7 +20,8 @@ OPTIONS returns true if the shell is interactive. Also --is-interactive. -f prints the filename of the currently running script or else stdio. Also --current-filename. -")] +" +)] pub fn status(args: &[types::Str], shell: &mut Shell<'_>) -> Status { let mut login_shell = false; let mut interactive = false;