diff options
Diffstat (limited to 'mingling')
| -rw-r--r-- | mingling/src/example_docs.rs | 80 | ||||
| -rw-r--r-- | mingling/src/lib.rs | 10 | ||||
| -rw-r--r-- | mingling/src/parser/args.rs | 40 | ||||
| -rw-r--r-- | mingling/src/parser/picker.rs | 60 | ||||
| -rw-r--r-- | mingling/src/parser/picker/bools.rs | 4 | ||||
| -rw-r--r-- | mingling/src/parser/picker/builtin.rs | 4 | ||||
| -rw-r--r-- | mingling/src/parser/picker/path.rs | 2 | ||||
| -rw-r--r-- | mingling/src/parser/picker/path/rule.rs | 12 | ||||
| -rw-r--r-- | mingling/src/res/exit_code.rs | 1 | ||||
| -rw-r--r-- | mingling/src/setups/exit_code.rs | 2 | ||||
| -rw-r--r-- | mingling/src/setups/general_renderer.rs | 2 |
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 = ¤t_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| { |
