aboutsummaryrefslogtreecommitdiff
path: root/mingling/src
diff options
context:
space:
mode:
Diffstat (limited to 'mingling/src')
-rw-r--r--mingling/src/example_docs.rs80
-rw-r--r--mingling/src/lib.rs10
-rw-r--r--mingling/src/parser/args.rs40
-rw-r--r--mingling/src/parser/picker.rs60
-rw-r--r--mingling/src/parser/picker/bools.rs4
-rw-r--r--mingling/src/parser/picker/builtin.rs4
-rw-r--r--mingling/src/parser/picker/path.rs2
-rw-r--r--mingling/src/parser/picker/path/rule.rs12
-rw-r--r--mingling/src/res/exit_code.rs1
-rw-r--r--mingling/src/setups/exit_code.rs2
-rw-r--r--mingling/src/setups/general_renderer.rs2
11 files changed, 137 insertions, 80 deletions
diff --git a/mingling/src/example_docs.rs b/mingling/src/example_docs.rs
index b665485..7e87d9c 100644
--- a/mingling/src/example_docs.rs
+++ b/mingling/src/example_docs.rs
@@ -57,7 +57,7 @@
/// // Name
/// // ^^^^_ finally, pick positional arg
/// .pick::<String>(())
-/// .after(|str| str.trim().replace(" ", ""))
+/// .after(|str| str.trim().replace(' ', ""))
/// // Unpack to tuple (is_dir, size, name)
/// .unpack()
/// // Convert into ResultFile
@@ -78,7 +78,7 @@
/// .pick_or::<usize>("--size", 1024 * 1024_usize)
/// // Finally parse the positional argument; if not found, route to `ErrorNoNameProvided`
/// .pick_or_route::<String, _>((), ErrorNoNameProvided::default().to_chain())
-/// .after(|str| str.trim().replace(" ", ""))
+/// .after(|str| str.trim().replace(' ', ""))
/// .unpack()
/// }
/// // Convert into ResultFile
@@ -87,6 +87,7 @@
/// result.to_chain()
/// }
///
+/// /// Renders the parsed transfer result (file/dir, size, name).
/// #[renderer]
/// fn render_result_file(result: ResultFile) {
/// let (is_dir, size, name) = result.into();
@@ -98,6 +99,7 @@
/// )
/// }
///
+/// /// Renders the error when no name is provided.
/// #[renderer]
/// fn render_error_no_name_provided(_: ErrorNoNameProvided) {
/// r_println!("Error: name is not provided")
@@ -189,6 +191,7 @@ pub mod example_argument_parse {}
/// fake_download(file_name).await
/// }
///
+/// /// Renders the downloaded file name.
/// #[renderer]
/// // But renderers cannot use the `async` keyword
/// pub fn render_downloaded(result: ResultDownloaded) {
@@ -277,6 +280,7 @@ pub mod example_async_support {}
/// }
///
/// // Define renderer `render_name`, used to render `ResultName`
+/// /// Renders the greeting message with the provided name.
/// #[renderer]
/// fn render_name(name: ResultName) {
/// r_println!("Hello, {}!", *name);
@@ -403,6 +407,7 @@ pub mod example_basic {}
/// repeat: i32,
/// }
///
+/// /// Renders the greet output with optional repetition.
/// #[renderer]
/// fn render_greet(greet: EntryGreet) {
/// let name = greet.name;
@@ -418,9 +423,10 @@ pub mod example_basic {}
/// r_println!("!");
/// }
///
+/// /// Renders the error message when greet argument parsing fails.
/// #[renderer]
/// fn render_greet_parse_failed(err: ErrorGreetParsed) {
-/// r_println!("{}", err.to_string());
+/// r_println!("{}", *err);
/// }
///
/// gen_program!();
@@ -575,6 +581,7 @@ pub mod example_clap_binding {}
/// result
/// }
///
+/// /// Renders the greeting with the result name and repeat count.
/// #[renderer]
/// fn render_name(result: ResultName) {
/// let (repeat, name) = result.inner;
@@ -619,7 +626,7 @@ pub mod example_completion {}
///
/// Source code (./src/main.rs)
/// ```ignore
-/// use mingling::{Groupped, macros::route, parser::Pickable, prelude::*};
+/// use mingling::{macros::route, parser::Pickable, prelude::*, Groupped};
///
/// // Define types that can be recognized by Mingling
/// // ________________________ `Pickable` trait needs to implement Default
@@ -637,7 +644,7 @@ pub mod example_completion {}
/// type Output = Address;
/// fn pick(args: &mut mingling::parser::Argument, flag: mingling::Flag) -> Option<Self::Output> {
/// // Extract the raw string from Argument using the Flag
-/// let raw: String = args.pick_argument(flag)?.to_string();
+/// let raw: String = args.pick_argument(flag)?.clone();
///
/// // Use TryFrom to parse the address
/// Address::try_from(raw).ok()
@@ -655,11 +662,13 @@ pub mod example_completion {}
/// connect.to_chain()
/// }
///
+/// /// Renders the connected address.
/// #[renderer]
/// fn render_address(addr: Address) {
/// r_println!("Connected to \"{}\"", addr.to_string());
/// }
///
+/// /// Renders the error message when address parsing fails.
/// #[renderer]
/// fn render_error_parse_address_failed(_: ErrorParseAddressFailed) {
/// r_println!("Failed to parse address");
@@ -698,13 +707,13 @@ pub mod example_completion {}
/// for (i, part) in ip_parts.iter().enumerate() {
/// ip[i] = part
/// .parse::<u8>()
-/// .map_err(|_| format!("Invalid IP octet: {}", part))?;
+/// .map_err(|_| format!("Invalid IP octet: {part}"))?;
/// }
///
/// // Parse port
/// let port = port_str
/// .parse::<u16>()
-/// .map_err(|_| format!("Invalid port: {}", port_str))?;
+/// .map_err(|_| format!("Invalid port: {port_str}"))?;
///
/// Ok(Address { ip, port })
/// }
@@ -796,9 +805,10 @@ pub mod example_custom_pickable {}
/// // // it'll be collected automatically once the `dispatch_tree` feature is enabled
/// // program.with_dispatcher(...);
///
-/// program.exec_and_exit()
+/// program.exec_and_exit();
/// }
///
+/// /// Renders the confirmation message for the `cmd5` command.
/// #[renderer]
/// fn render_cmd5(_: Entry5) {
/// r_println!("It's works!");
@@ -908,6 +918,7 @@ pub mod example_dispatch_tree {}
/// lang
/// }
///
+/// /// Renders the selected programming language with its name and description.
/// #[renderer]
/// fn render_programming_language(lang: ProgrammingLanguages) {
/// // You can use `enum_info()` to get the name and description of the current enum
@@ -1005,29 +1016,34 @@ pub mod example_enum_tag {}
/// ResultName::new(name).to_render()
/// }
///
+/// /// Renders a successful greeting with the given name.
/// #[renderer]
/// fn render_result_name(name: ResultName) {
/// r_println!("Hello, {}", *name);
/// }
///
+/// /// Renders the error when no name is provided.
/// #[renderer]
/// fn render_error_no_name_provided(_: ErrorNoNameProvided) {
/// // Prompt when no name is provided
/// r_println!("No name provided");
/// }
///
+/// /// Renders the error when the name is already taken.
/// #[renderer]
/// fn render_error_name_not_available(_: ErrorNameNotAvailable) {
/// // Prompt when name is already taken
/// r_println!("Name not available");
/// }
///
+/// /// Renders the error when the name exceeds the maximum length.
/// #[renderer]
/// fn render_error_name_too_long(len: ErrorNameTooLong) {
/// // Prompt when name is too long, showing actual length
/// r_println!("Name too long: {} > 10", *len);
/// }
///
+/// /// Renders the error when the dispatcher (subcommand) is not found.
/// #[renderer]
/// fn render_dispatcher_not_found(err: ErrorDispatcherNotFound) {
/// // Prompt when command is not found, showing the input command
@@ -1102,6 +1118,7 @@ pub mod example_error_handling {}
/// ResultName::new(name).to_render()
/// }
///
+/// /// Renders a successful greeting with the given name.
/// #[renderer]
/// fn render_result_name(name: ResultName) {
/// r_println!("Hello, {}", *name);
@@ -1109,6 +1126,7 @@ pub mod example_error_handling {}
///
/// // Define renderer, render error message _____________ Inject exit code resource
/// // /
+/// /// Renders the error when no name is provided |
/// #[renderer] // vvvvvvvvvvvvv
/// fn render_error_no_name_provided(_: ErrorNoNameProvided, ec: &mut ExitCode) {
/// ec.exit_code = 1;
@@ -1160,7 +1178,7 @@ pub mod example_exitcode {}
/// Source code (./src/main.rs)
/// ```ignore
/// use mingling::prelude::*;
-/// use mingling::{Groupped, parser::Picker, setup::GeneralRendererSetup};
+/// use mingling::{parser::Picker, setup::GeneralRendererSetup, Groupped};
/// use serde::Serialize;
///
/// dispatcher!("render", CMDRender => EntryRender);
@@ -1170,7 +1188,7 @@ pub mod example_exitcode {}
/// // Add `GeneralRendererSetup` to receive user input `--json` `--yaml` parameters
/// program.with_setup(GeneralRendererSetup);
/// program.with_dispatcher(CMDRender);
-/// program.exec();
+/// let _ = program.exec();
/// }
///
/// // --------- IMPORTANT ---------
@@ -1203,7 +1221,7 @@ pub mod example_exitcode {}
/// Info { name, age }.to_render()
/// }
///
-/// // Implement default renderer for when general_renderer is not specified
+/// /// Implement default renderer for when general_renderer is not specified
/// #[renderer]
/// fn render_info(prev: Info) {
/// r_println!("{} is {} years old", prev.name, prev.age);
@@ -1314,17 +1332,17 @@ pub mod example_help {}
/// program.with_hook(
/// ProgramHook::<ThisProgram>::empty()
/// .on_begin(|| println!("[DEBUG] Program is begin"))
-/// .on_pre_dispatch(|args| println!("[DEBUG] Pre dispatch: {:?}", args))
-/// .on_post_dispatch(|c: &_| println!("[DEBUG] Post dispatch: {:?}", c))
+/// .on_pre_dispatch(|args| println!("[DEBUG] Pre dispatch: {args:?}"))
+/// .on_post_dispatch(|c: &_| println!("[DEBUG] Post dispatch: {c:?}"))
/// .on_pre_chain(|c: &_, _| {
-/// println!("[DEBUG] Pre chain: {}", c);
+/// println!("[DEBUG] Pre chain: {c}");
/// })
/// .on_post_chain(|any_output| println!("[DEBUG] Post chain: {}", any_output.member_id))
/// .on_finish(|| {
/// println!("[DEBUG] Loop end");
/// 0 // Override exit code
/// })
-/// .on_pre_render(|c: &_, _| println!("[DEBUG] Pre render: {}", c))
+/// .on_pre_render(|c: &_, _| println!("[DEBUG] Pre render: {c}"))
/// .on_post_render(|_| println!("[DEBUG] Post render")),
/// );
/// // --------- IMPORTANT ---------
@@ -1346,6 +1364,7 @@ pub mod example_help {}
/// name
/// }
///
+/// /// Renders the greeting message with the provided name.
/// #[renderer]
/// fn render_name(name: ResultName) {
/// r_println!("Hello, {}!", *name);
@@ -1446,11 +1465,10 @@ pub mod example_implicit_dispatcher {}
/// program.stdout_setting.silence_panic = true;
///
/// // Define a hook to output &ProgramPanic when a Panic occurs
-/// program
-/// .with_hook(ProgramHook::empty().on_exec_panic(|info| println!("Program panic: {}", info)));
+/// program.with_hook(ProgramHook::empty().on_exec_panic(|info| println!("Program panic: {info}")));
/// // --------- IMPORTANT ---------
///
-/// program.exec();
+/// let _ = program.exec();
/// }
///
/// #[chain]
@@ -1465,6 +1483,7 @@ pub mod example_implicit_dispatcher {}
/// }
/// }
///
+/// /// Renders the message when no panic occurs.
/// #[renderer]
/// fn render(_: NotPanic) {
/// r_println!("Program not panic");
@@ -1558,7 +1577,7 @@ pub mod example_panic_unwind {}
/// // Add hooks to handle REPL-related events
/// program.with_hook(ProgramHook::empty().on_repl_begin(|| {
/// // Print welcome message
-/// println!("Welcome!")
+/// println!("Welcome!");
/// }));
///
/// // Start the REPL loop
@@ -1610,11 +1629,11 @@ pub mod example_panic_unwind {}
/// let dir = &current_dir.dir;
/// let entries: Vec<String> = std::fs::read_dir(dir)
/// .into_iter()
-/// .flat_map(|rd| rd.filter_map(|e| e.ok()))
+/// .flat_map(|rd| rd.filter_map(std::result::Result::ok))
/// .map(|e| {
/// let name = e.file_name().to_string_lossy().to_string();
/// if e.file_type().map(|t| t.is_dir()).unwrap_or(false) {
-/// format!("{}/", name)
+/// format!("{name}/")
/// } else {
/// name
/// }
@@ -1625,11 +1644,11 @@ pub mod example_panic_unwind {}
/// ResultList::new(entries).to_render()
/// }
///
-/// // Render ResultList data
+/// /// Render ResultList data
/// #[renderer]
/// fn render_list(list: ResultList) {
/// for item in list.inner {
-/// r_println!("{}", item)
+/// r_println!("{}", item);
/// }
/// }
///
@@ -1643,20 +1662,21 @@ pub mod example_panic_unwind {}
/// repl.exit = true;
/// }
///
-/// // Handle clear command event
+/// /// Handle clear command event
/// #[chain]
/// fn handle_clear(_prev: EntryClear) {
/// // Clear the terminal screen
/// print!("\x1B[2J\x1B[1;1H");
/// }
///
-/// // Handle path not found event
+/// /// Handle path not found event
/// #[renderer]
/// fn render_error_directory_not_exist(err: ErrorDirectoryNotExist) {
/// r_println!("Directory not found: {}", err.inner.display())
/// }
///
-/// // Handle dispatcher not found event
+/// /// Handle dispatcher not found event
+/// /// Renders the error when a command is not found.
/// #[renderer]
/// fn dispatcher_not_found(prev: ErrorDispatcherNotFound) {
/// r_println!("Command not found: \"{}\"", prev.join(", "))
@@ -1737,6 +1757,7 @@ pub mod example_repl_basic {}
///
/// // Define renderer for output current path _____________ Injected resource
/// // /
+/// /// Renders the current directory path. |
/// #[renderer] // vvvvvvvvvvvvvv
/// fn render_current(_: EntryCurrent, current_dir: &ResCurrentDir) {
/// r_println!("Current directory: {}", current_dir.current_dir.display());
@@ -1762,7 +1783,7 @@ pub mod example_resources {}
///
/// Source code (./src/main.rs)
/// ```ignore
-/// use mingling::{Program, macros::program_setup, prelude::*};
+/// use mingling::{macros::program_setup, prelude::*, Program};
///
/// fn main() {
/// let mut program = ThisProgram::new();
@@ -1897,26 +1918,31 @@ pub mod example_setup {}
/// ResultName::new(name).to_render()
/// }
///
+/// /// Renders a successful greeting with the given name.
/// #[renderer]
/// fn render_result_name(name: ResultName) -> String {
/// r_println!("Hello, {}!", *name);
/// }
///
+/// /// Renders the error when no name is provided.
/// #[renderer]
/// fn render_error_no_name_provided(_: ErrorNoNameProvided) -> String {
/// r_println!("No name provided");
/// }
///
+/// /// Renders the error when the name is already taken.
/// #[renderer]
/// fn render_error_name_not_available(_: ErrorNameNotAvailable) -> String {
/// r_println!("Name not available");
/// }
///
+/// /// Renders the error when the name exceeds the maximum length.
/// #[renderer]
/// fn render_error_name_too_long(len: ErrorNameTooLong) -> String {
/// r_println!("Name too long: {} > 10", *len);
/// }
///
+/// /// Renders the error when the dispatcher (subcommand) is not found.
/// #[renderer]
/// fn render_dispatcher_not_found(err: ErrorDispatcherNotFound) {
/// r_println!("Command not found: \"{}\"", err.inner.join(" "));
diff --git a/mingling/src/lib.rs b/mingling/src/lib.rs
index ee01fb7..db9b063 100644
--- a/mingling/src/lib.rs
+++ b/mingling/src/lib.rs
@@ -100,11 +100,11 @@ pub mod macros {
/// Used to create a wrapper type for use with `Chain` and `Renderer`
pub use mingling_macros::pack;
#[cfg(feature = "comp")]
- /// Internal macro for 'gen_program' used to finally generate the completion structure
+ /// Internal macro for '`gen_program`' used to finally generate the completion structure
pub use mingling_macros::program_comp_gen;
- /// Internal macro for 'gen_program' used to finally generate the fallback
+ /// Internal macro for '`gen_program`' used to finally generate the fallback
pub use mingling_macros::program_fallback_gen;
- /// Internal macro for 'gen_program' used to finally generate the program
+ /// Internal macro for '`gen_program`' used to finally generate the program
pub use mingling_macros::program_final_gen;
/// Used to generate program setup
#[cfg(feature = "extra_macros")]
@@ -115,7 +115,7 @@ pub mod macros {
pub use mingling_macros::r_println;
/// Used to register a chain
pub use mingling_macros::register_chain;
- /// Used to register a dispatcher for dispatch_tree feature
+ /// Used to register a dispatcher for `dispatch_tree` feature
pub use mingling_macros::register_dispatcher;
/// Used to register a help
pub use mingling_macros::register_help;
@@ -136,7 +136,7 @@ pub mod macros {
pub use mingling_macros::suggest_enum;
}
-/// derive macro EnumTag
+/// derive macro `EnumTag`
pub use mingling_macros::EnumTag;
/// derive macro Groupped
diff --git a/mingling/src/parser/args.rs b/mingling/src/parser/args.rs
index 2dc0feb..23275c2 100644
--- a/mingling/src/parser/args.rs
+++ b/mingling/src/parser/args.rs
@@ -11,7 +11,10 @@ pub struct Argument {
impl From<Vec<&str>> for Argument {
fn from(vec: Vec<&str>) -> Self {
Argument {
- vec: vec.into_iter().map(|s| s.to_string()).collect(),
+ vec: vec
+ .into_iter()
+ .map(std::string::ToString::to_string)
+ .collect(),
}
}
}
@@ -85,18 +88,17 @@ impl Argument {
}
let flag: Flag = flag.into();
- if !flag.is_empty() {
- // Has any flag
- for argument in flag.iter() {
- let value = special_argument!(self.vec, argument);
- if value.is_some() {
- return value;
- }
- }
- } else {
+ if flag.is_empty() {
// No flag
return Some(self.vec.remove(0));
}
+ // Has any flag
+ for argument in flag.iter() {
+ let value = special_argument!(self.vec, argument);
+ if value.is_some() {
+ return value;
+ }
+ }
None
}
@@ -135,15 +137,7 @@ impl Argument {
}
let flag: Flag = flag.into();
- if !flag.is_empty() {
- // Has any flag
- for argument in flag.iter() {
- let enabled = special_flag!(self.vec, argument);
- if enabled {
- return enabled;
- }
- }
- } else {
+ if flag.is_empty() {
let first = self.vec.remove(0);
let first_lower = first.to_lowercase();
let trimmed = first_lower.trim();
@@ -154,6 +148,13 @@ impl Argument {
};
return result;
}
+ // Has any flag
+ for argument in flag.iter() {
+ let enabled = special_flag!(self.vec, argument);
+ if enabled {
+ return enabled;
+ }
+ }
false
}
@@ -167,6 +168,7 @@ impl Argument {
///
/// This method filters out all command-line style flags from the arguments,
/// returning a new `Argument` instance containing only non-flag arguments.
+ #[must_use]
pub fn strip_all_flags(mut self) -> Self {
self.vec.retain(|f| !f.starts_with('-'));
self
diff --git a/mingling/src/parser/picker.rs b/mingling/src/parser/picker.rs
index b0cdb70..21ba9a6 100644
--- a/mingling/src/parser/picker.rs
+++ b/mingling/src/parser/picker.rs
@@ -71,15 +71,12 @@ impl Picker {
where
TNext: Pickable<Output = TNext> + Default,
{
- let v = match TNext::pick(&mut self.args, val.into()) {
- Some(value) => value,
- None => {
- return PickWithRoute1 {
- args: self.args,
- val_1: TNext::default(),
- route: Some(route),
- };
- }
+ let Some(v) = TNext::pick(&mut self.args, val.into()) else {
+ return PickWithRoute1 {
+ args: self.args,
+ val_1: TNext::default(),
+ route: Some(route),
+ };
};
PickWithRoute1 {
args: self.args,
@@ -112,6 +109,7 @@ impl Picker {
/// Takes a closure that receives the current `Argument` and returns a new `Argument`.
/// The returned `Argument` replaces the original arguments in the builder.
/// This method can be used to modify or transform the parsed arguments before extracting values.
+ #[must_use]
pub fn operate_args<F: FnOnce(Argument) -> Argument>(mut self, operation: F) -> Self {
self.args = operation(self.args);
self
@@ -141,7 +139,7 @@ pub trait Pickable {
// Non-routed Pick structs (no R parameter, no route field)
/// Internal macro: generates the struct definition and common methods
-/// (after, after_or_route, operate_args) for non-routed Pick structs.
+/// (after, `after_or_route`, `operate_args`) for non-routed Pick structs.
macro_rules! define_pick_struct {
($n:ident $final:ident $final_val:ident $route_self:ident $($T:ident $val:ident),+ $(,)?) => {
#[doc(hidden)]
@@ -163,6 +161,7 @@ macro_rules! define_pick_struct {
/// Takes a closure that receives the last extracted value and returns a new value of the same type.
/// The transformed value replaces the original value in the builder.
/// This method can be used to modify or validate the extracted value before final unpacking.
+ #[must_use]
pub fn after<F>(mut self, mut edit: F) -> Self
where
F: FnMut($final) -> $final,
@@ -177,6 +176,7 @@ macro_rules! define_pick_struct {
/// If the closure returns `Ok(new_value)`, the new value replaces the original value in the builder.
/// If the closure returns `Err(route)`, the provided `route` is stored in the builder for later error handling.
/// If a route was already stored from a previous `pick_or_route` call, the existing route is preserved.
+ #[must_use]
pub fn after_or_route<F, R>(mut self, mut edit: F) -> $route_self<$($T,)+ R>
where
F: FnMut(&$final) -> Result<$final, R>,
@@ -205,6 +205,7 @@ macro_rules! define_pick_struct {
/// Takes a closure that receives the current `Argument` and returns a new `Argument`.
/// The returned `Argument` replaces the original arguments in the builder.
/// This method can be used to modify or transform the parsed arguments before extracting values.
+ #[must_use]
pub fn operate_args<F: FnOnce(Argument) -> Argument>(mut self, operation: F) -> Self {
self.args = operation(self.args);
self
@@ -359,17 +360,14 @@ macro_rules! impl_pick_next {
where
TNext: Pickable<Output = TNext> + Default,
{
- let v = match TNext::pick(&mut self.args, val.into()) {
- Some(value) => value,
- None => {
- return $route_next {
- args: self.args,
- $($val: self.$val,)+
- $next_val: TNext::default(),
- route: Some(route),
- };
- }
- };
+ let Some(v) = TNext::pick(&mut self.args, val.into()) else {
+ return $route_next {
+ args: self.args,
+ $($val: self.$val,)+
+ $next_val: TNext::default(),
+ route: Some(route),
+ };
+ };
$route_next {
args: self.args,
$($val: self.$val,)+
@@ -413,7 +411,7 @@ impl_pick_next! { Pick11 Pick12 val_12 PickWithRoute12 T1 val_1, T2 val_2, T3 va
// Routed PickWithRoute structs (with R parameter, route field)
/// Internal macro: generates the routed struct definition and common methods
-/// (after, after_or_route, operate_args) for PickWithRoute structs.
+/// (after, `after_or_route`, `operate_args`) for `PickWithRoute` structs.
macro_rules! define_pick_with_route_struct {
($n:ident $final:ident $final_val:ident $($T:ident $val:ident),+) => {
#[doc(hidden)]
@@ -436,6 +434,7 @@ macro_rules! define_pick_with_route_struct {
/// Takes a closure that receives the last extracted value and returns a new value of the same type.
/// The transformed value replaces the original value in the builder.
/// This method can be used to modify or validate the extracted value before final unpacking.
+ #[must_use]
pub fn after<F>(mut self, mut edit: F) -> Self
where
F: FnMut($final) -> $final,
@@ -450,6 +449,7 @@ macro_rules! define_pick_with_route_struct {
/// If the closure returns `Ok(new_value)`, the new value replaces the original value in the builder.
/// If the closure returns `Err(route)`, the provided `route` is stored in the builder for later error handling.
/// If a route was already stored from a previous `pick_or_route` call, the existing route is preserved.
+ #[must_use]
pub fn after_or_route<F>(mut self, mut edit: F) -> Self
where
F: FnMut(&$final) -> Result<$final, R>,
@@ -475,6 +475,7 @@ macro_rules! define_pick_with_route_struct {
/// Takes a closure that receives the current `Argument` and returns a new `Argument`.
/// The returned `Argument` replaces the original arguments in the builder.
/// This method can be used to modify or transform the parsed arguments before extracting values.
+ #[must_use]
pub fn operate_args<F: FnOnce(Argument) -> Argument>(mut self, operation: F) -> Self {
self.args = operation(self.args);
self
@@ -483,7 +484,7 @@ macro_rules! define_pick_with_route_struct {
};
}
-/// Internal macro: generates `From` impl for routed PickWithRouteN into a tuple.
+/// Internal macro: generates `From` impl for routed `PickWithRouteN` into a tuple.
macro_rules! impl_pick_with_route_from_tuple {
($n:ident $($T:ident $val:ident),+) => {
impl<$($T,)+ R> From<$n<$($T,)+ R>> for ($($T,)+)
@@ -497,7 +498,7 @@ macro_rules! impl_pick_with_route_from_tuple {
};
}
-/// Internal macro: generates `unpack` and `unpack_directly` for routed PickWithRouteN (N >= 2).
+/// Internal macro: generates `unpack` and `unpack_directly` for routed `PickWithRouteN` (N >= 2).
macro_rules! impl_pick_with_route_unpack_tuple {
($n:ident $($T:ident $val:ident),+) => {
impl<$($T,)+ R> $n<$($T,)+ R>
@@ -508,6 +509,10 @@ macro_rules! impl_pick_with_route_unpack_tuple {
///
/// Returns `Ok((T1, T2, ...))` if no route was stored.
/// Returns `Err(R)` if a route was stored via `pick_or_route` or `after_or_route`.
+ ///
+ /// # Errors
+ ///
+ /// Returns `Err(R)` if a route was stored via `pick_or_route` or `after_or_route`.
pub fn unpack(self) -> Result<($($T,)+), R> {
match self.route {
Some(route) => Err(route),
@@ -518,6 +523,7 @@ macro_rules! impl_pick_with_route_unpack_tuple {
/// Unpacks the builder into a tuple of extracted values.
///
/// Returns the tuple of extracted values regardless of route state.
+ #[must_use]
pub fn unpack_directly(self) -> ($($T,)+) {
($(self.$val,)+)
}
@@ -546,6 +552,10 @@ where
///
/// Returns `Ok(T1)` if no route was stored.
/// Returns `Err(R)` if a route was stored via `pick_or_route` or `after_or_route`.
+ ///
+ /// # Errors
+ ///
+ /// Returns `Err(R)` if a route was stored via `pick_or_route` or `after_or_route`.
pub fn unpack(self) -> Result<T1, R> {
match self.route {
Some(route) => Err(route),
@@ -556,6 +566,7 @@ where
/// Unpacks the builder into the extracted value.
///
/// Returns the extracted value regardless of route state.
+ #[must_use]
pub fn unpack_directly(self) -> T1 {
self.val_1
}
@@ -650,6 +661,7 @@ macro_rules! impl_pick_with_route_next {
///
/// If a route was already stored from a previous `pick_or_route` or `after_or_route` call,
/// the existing route is preserved and the new `route` parameter is ignored.
+ #[allow(clippy::manual_let_else)]
pub fn pick_or_route<TNext>(mut self, val: impl Into<mingling_core::Flag>, route: R) -> $next<$($T,)+ TNext, R>
where
TNext: Pickable<Output = TNext> + Default,
diff --git a/mingling/src/parser/picker/bools.rs b/mingling/src/parser/picker/bools.rs
index aa2335a..ede8812 100644
--- a/mingling/src/parser/picker/bools.rs
+++ b/mingling/src/parser/picker/bools.rs
@@ -37,10 +37,12 @@ impl std::ops::Deref for Yes {
}
impl Yes {
+ #[must_use]
pub fn is_yes(&self) -> bool {
matches!(self, Yes::Yes)
}
+ #[must_use]
pub fn is_no(&self) -> bool {
matches!(self, Yes::No)
}
@@ -92,10 +94,12 @@ impl std::ops::Deref for True {
}
impl True {
+ #[must_use]
pub fn is_true(&self) -> bool {
matches!(self, True::True)
}
+ #[must_use]
pub fn is_false(&self) -> bool {
matches!(self, True::False)
}
diff --git a/mingling/src/parser/picker/builtin.rs b/mingling/src/parser/picker/builtin.rs
index e7a178d..6194955 100644
--- a/mingling/src/parser/picker/builtin.rs
+++ b/mingling/src/parser/picker/builtin.rs
@@ -68,7 +68,7 @@ impl Pickable for usize {
let picked = args.pick_argument(flag)?;
let size_parse = Size::from_str(picked.as_str());
match size_parse {
- Ok(size) => Some(size.bytes() as usize),
+ Ok(size) => usize::try_from(size.bytes()).ok(),
Err(_) => None,
}
}
@@ -84,7 +84,7 @@ impl Pickable for Vec<usize> {
for picked in picked_vec {
let size_parse = Size::from_str(picked.as_str());
match size_parse {
- Ok(size) => result.push(size.bytes() as usize),
+ Ok(size) => result.push(usize::try_from(size.bytes()).unwrap_or(usize::MAX)),
Err(_) => return None,
}
}
diff --git a/mingling/src/parser/picker/path.rs b/mingling/src/parser/picker/path.rs
index c97250f..961542e 100644
--- a/mingling/src/parser/picker/path.rs
+++ b/mingling/src/parser/picker/path.rs
@@ -91,7 +91,7 @@ impl<T: Into<PathBuf>> PathChecker for T where T: Into<PathBuf> {}
fn check_paths(path: impl Into<Vec<PathBuf>>, rule: &PathCheckRule) -> Result<(), ()> {
let paths = path.into();
- for p in paths.iter() {
+ for p in &paths {
check_exist(p, rule)?;
check_type(p, rule)?;
}
diff --git a/mingling/src/parser/picker/path/rule.rs b/mingling/src/parser/picker/path/rule.rs
index 07df705..bf5cab3 100644
--- a/mingling/src/parser/picker/path/rule.rs
+++ b/mingling/src/parser/picker/path/rule.rs
@@ -25,6 +25,7 @@ pub struct PathTypeCheck {
impl PathCheckRule {
/// Creates a new `PathCheckRule` with default values
+ #[must_use]
pub fn new() -> Self {
Self {
exist_check: None,
@@ -33,6 +34,7 @@ impl PathCheckRule {
}
/// Allows the path to be a file
+ #[must_use]
pub fn allow_file(self) -> Self {
match self.type_check {
Some(type_check) => Self {
@@ -55,6 +57,7 @@ impl PathCheckRule {
}
/// Allows the path to be a directory
+ #[must_use]
pub fn allow_dir(self) -> Self {
match self.type_check {
Some(type_check) => Self {
@@ -77,6 +80,7 @@ impl PathCheckRule {
}
/// Allows the path to be a symlink
+ #[must_use]
pub fn allow_symlink(self) -> Self {
match self.type_check {
Some(type_check) => Self {
@@ -99,6 +103,7 @@ impl PathCheckRule {
}
/// Denies the path from being a file
+ #[must_use]
pub fn deny_file(self) -> Self {
match self.type_check {
Some(type_check) => Self {
@@ -121,6 +126,7 @@ impl PathCheckRule {
}
/// Denies the path from being a directory
+ #[must_use]
pub fn deny_dir(self) -> Self {
match self.type_check {
Some(type_check) => Self {
@@ -143,6 +149,7 @@ impl PathCheckRule {
}
/// Denies the path from being a symlink
+ #[must_use]
pub fn deny_symlink(self) -> Self {
match self.type_check {
Some(type_check) => Self {
@@ -165,6 +172,7 @@ impl PathCheckRule {
}
/// Requires the path to be a file (overrides type checks)
+ #[must_use]
pub fn must_file(self) -> Self {
Self {
type_check: Some(PathTypeCheck {
@@ -177,6 +185,7 @@ impl PathCheckRule {
}
/// Requires the path to be a directory (overrides type checks)
+ #[must_use]
pub fn must_dir(self) -> Self {
Self {
type_check: Some(PathTypeCheck {
@@ -189,6 +198,7 @@ impl PathCheckRule {
}
/// Requires the path to be a symlink (overrides type checks)
+ #[must_use]
pub fn must_symlink(self) -> Self {
Self {
type_check: Some(PathTypeCheck {
@@ -201,6 +211,7 @@ impl PathCheckRule {
}
/// Requires the path to exist
+ #[must_use]
pub fn must_exist(self) -> Self {
Self {
exist_check: Some(PathExistCheck::Exists),
@@ -209,6 +220,7 @@ impl PathCheckRule {
}
/// Requires the path to not exist
+ #[must_use]
pub fn must_not_exist(self) -> Self {
Self {
exist_check: Some(PathExistCheck::NotExists),
diff --git a/mingling/src/res/exit_code.rs b/mingling/src/res/exit_code.rs
index b483139..e90d067 100644
--- a/mingling/src/res/exit_code.rs
+++ b/mingling/src/res/exit_code.rs
@@ -24,6 +24,7 @@ where
/// Retrieves the globally stored exit code for the given `ProgramCollect` type.
/// Returns `0` if no exit code has been set.
+#[must_use]
pub fn exit_code<C>() -> i32
where
C: ProgramCollect<Enum = C> + 'static,
diff --git a/mingling/src/setups/exit_code.rs b/mingling/src/setups/exit_code.rs
index 0412a78..9513363 100644
--- a/mingling/src/setups/exit_code.rs
+++ b/mingling/src/setups/exit_code.rs
@@ -18,7 +18,7 @@ where
{
fn default() -> Self {
Self {
- _collect: Default::default(),
+ _collect: PhantomData,
}
}
}
diff --git a/mingling/src/setups/general_renderer.rs b/mingling/src/setups/general_renderer.rs
index 81b6cd0..e0a0d61 100644
--- a/mingling/src/setups/general_renderer.rs
+++ b/mingling/src/setups/general_renderer.rs
@@ -35,7 +35,7 @@ where
fn setup(&mut self, program: &mut Program<C>) {
#[cfg(feature = "json_serde_fmt")]
program.global_flag("--json", |p| {
- p.general_renderer_name = crate::GeneralRendererSetting::Json
+ p.general_renderer_name = crate::GeneralRendererSetting::Json;
});
#[cfg(feature = "json_serde_fmt")]
program.global_flag("--json-pretty", |p| {