diff options
| author | 魏曹先生 <1992414357@qq.com> | 2026-08-10 15:49:31 +0800 |
|---|---|---|
| committer | 魏曹先生 <1992414357@qq.com> | 2026-08-10 15:49:31 +0800 |
| commit | a9d5943939261e27e58bcf5cacbb618a0f63e999 (patch) | |
| tree | d1cacc2af939e993f2d7d2794500e6456659e6a9 /mingling_core/src/program | |
| parent | 782d2458dc4ad4336e1407e1f107e43e39b0b991 (diff) | |
refactor(core): improve code style and public API clarity
Replace bool-based settings with enums, refine visibility and
signatures, and standardize `Self` usage across the crate.
- Introduce `ErrorOutput`, `RenderOutput`, `PanicSilence`, `Verbosity`,
`ColorOutput`, and `ProgressOutput` enums for clearer configuration
semantics
- Make `GlobalResources`, `ProgramCell`, and
`split_input`/`split_input_string` public
- Change hook info parameters to accept references and
`split_input_string` to take `&str`
- Apply `Self` shorthand throughout implementations and add
`#[must_use]` attributes where appropriate
- Enable strict clippy lints with targeted allowances
Diffstat (limited to 'mingling_core/src/program')
| -rw-r--r-- | mingling_core/src/program/collection.rs | 4 | ||||
| -rw-r--r-- | mingling_core/src/program/collection/mock.rs | 12 | ||||
| -rw-r--r-- | mingling_core/src/program/config.rs | 235 | ||||
| -rw-r--r-- | mingling_core/src/program/error.rs | 2 | ||||
| -rw-r--r-- | mingling_core/src/program/exec.rs | 29 | ||||
| -rw-r--r-- | mingling_core/src/program/exec/error.rs | 48 | ||||
| -rw-r--r-- | mingling_core/src/program/flag.rs | 18 | ||||
| -rw-r--r-- | mingling_core/src/program/hook.rs | 121 | ||||
| -rw-r--r-- | mingling_core/src/program/hook/control_unit.rs | 35 | ||||
| -rw-r--r-- | mingling_core/src/program/once_exec.rs | 14 | ||||
| -rw-r--r-- | mingling_core/src/program/repl_exec.rs | 32 | ||||
| -rw-r--r-- | mingling_core/src/program/repl_exec/splitter.rs | 8 | ||||
| -rw-r--r-- | mingling_core/src/program/single_instance.rs | 3 | ||||
| -rw-r--r-- | mingling_core/src/program/string_vec.rs | 11 |
14 files changed, 331 insertions, 241 deletions
diff --git a/mingling_core/src/program/collection.rs b/mingling_core/src/program/collection.rs index 5b1152a..66ec9f1 100644 --- a/mingling_core/src/program/collection.rs +++ b/mingling_core/src/program/collection.rs @@ -41,6 +41,10 @@ pub trait ProgramCollect { #[cfg(not(feature = "dispatch_tree"))] /// Use a prefix tree to quickly match arguments and dispatch to an Entry + /// + /// # Errors + /// + /// Returns an error if the program fails to execute the given arguments. fn dispatch_args_trie( _raw: &[String], ) -> Result<AnyOutput<Self::Enum>, crate::error::ProgramInternalExecuteError> { diff --git a/mingling_core/src/program/collection/mock.rs b/mingling_core/src/program/collection/mock.rs index cd2abf5..52fbd17 100644 --- a/mingling_core/src/program/collection/mock.rs +++ b/mingling_core/src/program/collection/mock.rs @@ -26,17 +26,17 @@ pub enum MockProgramCollect { /// SAFETY: This is a mock type used only for temporary testing. /// It will never actually enter the macro system. /// The internal `panic!` ensures that `member_id` will never be executed. -unsafe impl Grouped<MockProgramCollect> for MockProgramCollect { - fn member_id() -> MockProgramCollect { +unsafe impl Grouped<Self> for MockProgramCollect { + fn member_id() -> Self { panic!("Attempting to read an unsafe enum type"); } } impl ProgramCollect for MockProgramCollect { - type Enum = MockProgramCollect; - type EntryFallback = MockProgramCollect; - type ErrorRendererNotFound = MockProgramCollect; - type ResultEmpty = MockProgramCollect; + type Enum = Self; + type EntryFallback = Self; + type ErrorRendererNotFound = Self; + type ResultEmpty = Self; #[cfg(feature = "dispatch_tree")] fn dispatch_args_trie( diff --git a/mingling_core/src/program/config.rs b/mingling_core/src/program/config.rs index c5f91da..b098961 100644 --- a/mingling_core/src/program/config.rs +++ b/mingling_core/src/program/config.rs @@ -1,41 +1,95 @@ +/// Output mode for error messages +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum ErrorOutput { + /// Show error messages + Show, + /// Hide error messages + Hide, +} + +/// Output mode for rendered results +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum RenderOutput { + /// Render results and output + Show, + /// Hide rendered results + Hide, +} + +/// Panic message handling +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum PanicSilence { + /// Allow panic messages to be shown + Show, + /// Silence panic messages + Silence, +} + +/// Verbosity level for program output +/// +/// **NOTE**: Convention only, not a configuration +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum Verbosity { + /// Normal output + Normal, + /// Verbose output: provide detailed information + Verbose, + /// Quiet mode: suppress status messages, show only errors and results + Quiet, + /// Debug mode: output internal state and detailed diagnostics + Debug, +} + +/// Color output mode +/// +/// **NOTE**: Convention only, not a configuration +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum ColorOutput { + /// Enable colored output + Enabled, + /// Disable colored output + Disabled, +} + +/// Progress indicator mode +/// +/// Automatically disabled when stdout is not a tty. +/// +/// **NOTE**: Convention only, not a configuration +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum ProgressOutput { + /// Show progress indicators (e.g. progress bars, spinners) + Enabled, + /// Hide progress indicators + Disabled, +} + /// Program stdout settings #[derive(Debug, Clone)] pub struct ProgramStdoutSetting { /// Output error messages - pub error_output: bool, + pub error_output: ErrorOutput, /// Render results and output - pub render_output: bool, + pub render_output: RenderOutput, /// Silence panic messages - pub silence_panic: bool, + pub silence_panic: PanicSilence, - /// Verbose output: provide detailed information + /// Verbosity level for program output /// /// **NOTE**: Convention only, not a configuration - pub verbose: bool, - - /// Quiet mode: suppress status messages, show only errors and results - /// - /// **NOTE**: Convention only, not a configuration - pub quiet: bool, - - /// Debug mode: output internal state and detailed diagnostics - /// - /// **NOTE**: Convention only, not a configuration - pub debug: bool, + pub verbosity: Verbosity, /// Enable colored output /// /// **NOTE**: Convention only, not a configuration - pub color: bool, + pub color: ColorOutput, /// Show progress indicators (e.g. progress bars, spinners) /// - /// Automatically disabled when stdout is not a tty. - /// /// **NOTE**: Convention only, not a configuration - pub progress: bool, + pub progress: ProgressOutput, #[cfg(feature = "clap")] /// Behavior when Clap Dispatcher outputs help information @@ -63,21 +117,65 @@ pub enum ClapHelpPrintBehaviour { impl Default for ProgramStdoutSetting { fn default() -> Self { - ProgramStdoutSetting { - error_output: true, - render_output: true, - silence_panic: false, - verbose: false, - quiet: false, - debug: false, - color: true, - progress: true, + Self { + error_output: ErrorOutput::Show, + render_output: RenderOutput::Show, + silence_panic: PanicSilence::Show, + verbosity: Verbosity::Normal, + color: ColorOutput::Enabled, + progress: ProgressOutput::Enabled, #[cfg(feature = "clap")] clap_help_print_behaviour: ClapHelpPrintBehaviour::default(), } } } +/// Confirmation mode for user prompts +/// +/// **NOTE**: Convention only, not a configuration +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum ConfirmationMode { + /// Require confirmation from the user + Confirm, + /// Skip user confirmation step + Skip, +} + +/// Execution mode +/// +/// **NOTE**: Convention only, not a configuration +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum ExecutionMode { + /// Normal execution + Normal, + /// Dry-run mode: simulate actions without making changes + DryRun, + /// Force execution, skipping safety checks + Force, +} + +/// Interaction mode +/// +/// **NOTE**: Convention only, not a configuration +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum InteractionMode { + /// Interactive terminal (has a tty) + Interactive, + /// Non-interactive terminal + NonInteractive, +} + +/// Yes assumption mode for prompts +/// +/// **NOTE**: Convention only, not a configuration +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum YesAssumption { + /// Do not assume "yes" for any prompt + None, + /// Assume "yes" for all confirmation prompts + AssumeYes, +} + /// Program user context #[derive(Debug, Clone)] pub struct ProgramUserContext { @@ -87,30 +185,25 @@ pub struct ProgramUserContext { /// Execute hooks during the program lifecycle pub run_hook: bool, - /// Skip user confirmation step + /// Confirmation mode for user prompts /// /// **NOTE**: Convention only, not a configuration - pub confirm: bool, + pub confirmation: ConfirmationMode, - /// Dry-run mode: simulate actions without making changes + /// Execution mode /// /// **NOTE**: Convention only, not a configuration - pub dry_run: bool, - - /// Force execution, skipping safety checks - /// - /// **NOTE**: Convention only, not a configuration - pub force: bool, + pub execution: ExecutionMode, /// Whether the program is running in an interactive terminal (has a tty) /// /// **NOTE**: Convention only, not a configuration - pub interactive: bool, + pub interaction: InteractionMode, - /// Assume "yes" for all confirmation prompts + /// Whether to assume "yes" for all confirmation prompts /// /// **NOTE**: Convention only, not a configuration - pub assume_yes: bool, + pub yes_assumption: YesAssumption, } impl Default for ProgramUserContext { @@ -118,11 +211,10 @@ impl Default for ProgramUserContext { Self { help: false, run_hook: true, - confirm: false, - dry_run: false, - force: false, - interactive: false, - assume_yes: false, + confirmation: ConfirmationMode::Confirm, + execution: ExecutionMode::Normal, + interaction: InteractionMode::NonInteractive, + yes_assumption: YesAssumption::None, } } } @@ -162,19 +254,19 @@ impl std::str::FromStr for StructuralRendererSetting { fn from_str(s: &str) -> Result<Self, Self::Err> { match just_fmt::kebab_case!(s).as_str() { - "disable" => Ok(StructuralRendererSetting::Disable), + "disable" => Ok(Self::Disable), #[cfg(feature = "json_serde_fmt")] - "json" => Ok(StructuralRendererSetting::Json), + "json" => Ok(Self::Json), #[cfg(feature = "json_serde_fmt")] - "json-pretty" => Ok(StructuralRendererSetting::JsonPretty), + "json-pretty" => Ok(Self::JsonPretty), #[cfg(feature = "yaml_serde_fmt")] - "yaml" => Ok(StructuralRendererSetting::Yaml), + "yaml" => Ok(Self::Yaml), #[cfg(feature = "toml_serde_fmt")] - "toml" => Ok(StructuralRendererSetting::Toml), + "toml" => Ok(Self::Toml), #[cfg(feature = "ron_serde_fmt")] - "ron" => Ok(StructuralRendererSetting::Ron), + "ron" => Ok(Self::Ron), #[cfg(feature = "ron_serde_fmt")] - "ron-pretty" => Ok(StructuralRendererSetting::RonPretty), + "ron-pretty" => Ok(Self::RonPretty), _ => Err(format!("Invalid renderer: '{s}'")), } } @@ -183,7 +275,7 @@ impl std::str::FromStr for StructuralRendererSetting { #[cfg(feature = "structural_renderer")] impl From<&str> for StructuralRendererSetting { fn from(s: &str) -> Self { - s.parse().unwrap_or(StructuralRendererSetting::Disable) + s.parse().unwrap_or(Self::Disable) } } @@ -198,19 +290,19 @@ impl From<String> for StructuralRendererSetting { impl std::fmt::Display for StructuralRendererSetting { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - StructuralRendererSetting::Disable => write!(f, "disable"), + Self::Disable => write!(f, "disable"), #[cfg(feature = "json_serde_fmt")] - StructuralRendererSetting::Json => write!(f, "json"), + Self::Json => write!(f, "json"), #[cfg(feature = "json_serde_fmt")] - StructuralRendererSetting::JsonPretty => write!(f, "json-pretty"), + Self::JsonPretty => write!(f, "json-pretty"), #[cfg(feature = "yaml_serde_fmt")] - StructuralRendererSetting::Yaml => write!(f, "yaml"), + Self::Yaml => write!(f, "yaml"), #[cfg(feature = "toml_serde_fmt")] - StructuralRendererSetting::Toml => write!(f, "toml"), + Self::Toml => write!(f, "toml"), #[cfg(feature = "ron_serde_fmt")] - StructuralRendererSetting::Ron => write!(f, "ron"), + Self::Ron => write!(f, "ron"), #[cfg(feature = "ron_serde_fmt")] - StructuralRendererSetting::RonPretty => write!(f, "ron-pretty"), + Self::RonPretty => write!(f, "ron-pretty"), } } } @@ -222,14 +314,12 @@ mod tests { #[test] fn program_stdout_setting_default() { let s = ProgramStdoutSetting::default(); - assert!(s.error_output); - assert!(s.render_output); - assert!(!s.silence_panic); - assert!(!s.verbose); - assert!(!s.quiet); - assert!(!s.debug); - assert!(s.color); - assert!(s.progress); + assert_eq!(s.error_output, ErrorOutput::Show); + assert_eq!(s.render_output, RenderOutput::Show); + assert_eq!(s.silence_panic, PanicSilence::Show); + assert_eq!(s.verbosity, Verbosity::Normal); + assert_eq!(s.color, ColorOutput::Enabled); + assert_eq!(s.progress, ProgressOutput::Enabled); } #[test] @@ -237,11 +327,10 @@ mod tests { let ctx = ProgramUserContext::default(); assert!(!ctx.help); assert!(ctx.run_hook); - assert!(!ctx.confirm); - assert!(!ctx.dry_run); - assert!(!ctx.force); - assert!(!ctx.interactive); - assert!(!ctx.assume_yes); + assert_eq!(ctx.confirmation, ConfirmationMode::Confirm); + assert_eq!(ctx.execution, ExecutionMode::Normal); + assert_eq!(ctx.interaction, InteractionMode::NonInteractive); + assert_eq!(ctx.yes_assumption, YesAssumption::None); } #[cfg(feature = "structural_renderer")] diff --git a/mingling_core/src/program/error.rs b/mingling_core/src/program/error.rs index 144b5ab..0a5bfd0 100644 --- a/mingling_core/src/program/error.rs +++ b/mingling_core/src/program/error.rs @@ -21,7 +21,7 @@ impl fmt::Display for ProgramPanic { impl ProgramPanic { #[must_use] pub fn new(payload: Box<dyn Any + Send>) -> Self { - ProgramPanic { payload } + Self { payload } } } diff --git a/mingling_core/src/program/exec.rs b/mingling_core/src/program/exec.rs index d9b4dd8..df42249 100644 --- a/mingling_core/src/program/exec.rs +++ b/mingling_core/src/program/exec.rs @@ -1,4 +1,5 @@ #![allow(clippy::borrowed_box)] +#![allow(clippy::too_many_lines)] use crate::{ AnyOutput, ChainProcess, Dispatcher, NextProcess, Program, ProgramCollect, RenderResult, @@ -49,7 +50,7 @@ where // Run hooks control!( - program.run_hook_pre_dispatch(crate::hook::HookPreDispatchInfo { arguments: args }), + program.run_hook_pre_dispatch(&crate::hook::HookPreDispatchInfo { arguments: args }), current ); @@ -62,7 +63,7 @@ where // Run hook control!( - program.run_hook_post_dispatch(crate::hook::HookPostDispatchInfo { + program.run_hook_post_dispatch(&crate::hook::HookPostDispatchInfo { entry: ¤t.member_id, }), current @@ -75,7 +76,7 @@ where let mut render_result = render_help::<C>(program, current); // Run hook - control!(program.run_hook_finish(crate::hook::HookFinishInfo {})); + control!(program.run_hook_finish(&crate::hook::HookFinishInfo {})); render_result.exit_code = exit_code; return Ok(render_result); @@ -89,7 +90,7 @@ where if C::has_chain(¤t) { // Run hook control!( - program.run_hook_pre_chain(crate::hook::HookPreChainInfo { + program.run_hook_pre_chain(&crate::hook::HookPreChainInfo { input: ¤t.member_id, raw: current.inner.as_ref(), }), @@ -102,7 +103,7 @@ where let mut render_result = render::<C>(program, any); // Run hook - control!(program.run_hook_finish(crate::hook::HookFinishInfo {})); + control!(program.run_hook_finish(&crate::hook::HookFinishInfo {})); render_result.exit_code = exit_code; return Ok(render_result); @@ -111,7 +112,7 @@ where ChainProcess::Ok((mut any, NextProcess::Chain)) => { // Run hook control!( - program.run_hook_post_chain(crate::hook::HookPostChainInfo { + program.run_hook_post_chain(&crate::hook::HookPostChainInfo { output: &any }), any @@ -121,7 +122,7 @@ where ChainProcess::Err(e) => { // Run hook control!( - program.run_hook_finish(crate::hook::HookFinishInfo {}), + program.run_hook_finish(&crate::hook::HookFinishInfo {}), &mut C::build_empty_result() ); return Err(e.into()); @@ -132,7 +133,7 @@ where else if C::has_renderer(¤t) { // Run hook control!( - program.run_hook_pre_render(crate::hook::HookPreRenderInfo { + program.run_hook_pre_render(&crate::hook::HookPreRenderInfo { input: ¤t.member_id, raw: current.inner.as_ref(), }), @@ -143,12 +144,12 @@ where // Run hooks control!( - program.run_hook_post_render(crate::hook::HookPostRenderInfo { + program.run_hook_post_render(&crate::hook::HookPostRenderInfo { result: &render_result, }) ); - control!(program.run_hook_finish(crate::hook::HookFinishInfo {})); + control!(program.run_hook_finish(&crate::hook::HookFinishInfo {})); render_result.exit_code = exit_code; return Ok(render_result); @@ -168,7 +169,7 @@ where // Run hook control!( - program.run_hook_finish(crate::hook::HookFinishInfo {}), + program.run_hook_finish(&crate::hook::HookFinishInfo {}), current ); render_result.exit_code = exit_code; @@ -252,7 +253,7 @@ pub(crate) fn handle_program_control<C: ProgramCollect<Enum = C>>( mut current: Option<&mut AnyOutput<C>>, exit_code: &mut i32, ) -> Option<RenderResult> { - for unit in controls.into_iter() { + for unit in controls { match unit { super::hook::ProgramControlUnit::OverrideExitCode(c) => *exit_code = c, super::hook::ProgramControlUnit::RouteToChain(any_output) => { @@ -264,7 +265,7 @@ pub(crate) fn handle_program_control<C: ProgramCollect<Enum = C>>( // Note: Hooks triggered by ProgramControl will not trigger ProgramControl again // Pre render - let _ = program.run_hook_pre_render(crate::hook::HookPreRenderInfo { + let _ = program.run_hook_pre_render(&crate::hook::HookPreRenderInfo { input: &any_output.member_id, raw: any_output.inner.as_ref(), }); @@ -273,7 +274,7 @@ pub(crate) fn handle_program_control<C: ProgramCollect<Enum = C>>( r.exit_code = *exit_code; // Post render - program.run_hook_post_render(crate::hook::HookPostRenderInfo { result: &r }); + program.run_hook_post_render(&crate::hook::HookPostRenderInfo { result: &r }); return Some(r); } diff --git a/mingling_core/src/program/exec/error.rs b/mingling_core/src/program/exec/error.rs index 944e89a..c8cb15a 100644 --- a/mingling_core/src/program/exec/error.rs +++ b/mingling_core/src/program/exec/error.rs @@ -24,12 +24,12 @@ pub enum ProgramExecuteError { impl fmt::Display for ProgramExecuteError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - ProgramExecuteError::DispatcherNotFound => write!(f, "No Dispatcher Found"), - ProgramExecuteError::RendererNotFound(s) => { + Self::DispatcherNotFound => write!(f, "No Dispatcher Found"), + Self::RendererNotFound(s) => { write!(f, "No Renderer (`{s}`) Found") } - ProgramExecuteError::Panic(p) => write!(f, "Panic: {p:?}"), - ProgramExecuteError::Other(s) => write!(f, "Other error: {s}"), + Self::Panic(p) => write!(f, "Panic: {p:?}"), + Self::Other(s) => write!(f, "Other error: {s}"), } } } @@ -38,7 +38,7 @@ impl std::error::Error for ProgramExecuteError {} impl From<ProgramPanic> for ProgramExecuteError { fn from(value: ProgramPanic) -> Self { - ProgramExecuteError::Panic(value) + Self::Panic(value) } } @@ -70,17 +70,11 @@ pub enum ProgramInternalExecuteError { impl fmt::Display for ProgramInternalExecuteError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - ProgramInternalExecuteError::DispatcherNotFound => { - write!(f, "No Dispatcher Found") - } - ProgramInternalExecuteError::RendererNotFound(s) => { - write!(f, "No Renderer (`{s}`) Found") - } - ProgramInternalExecuteError::Other(s) => write!(f, "Other error: {s}"), - ProgramInternalExecuteError::IO(e) => write!(f, "IO error: {e}"), - ProgramInternalExecuteError::REPLPanic(panic) => { - write!(f, "A single REPL execution failed: {panic}") - } + Self::DispatcherNotFound => write!(f, "No Dispatcher Found"), + Self::RendererNotFound(s) => write!(f, "No Renderer (`{s}`) Found"), + Self::Other(s) => write!(f, "Other error: {s}"), + Self::IO(e) => write!(f, "IO error: {e}"), + Self::REPLPanic(panic) => write!(f, "A single REPL execution failed: {panic}"), } } } @@ -88,7 +82,7 @@ impl fmt::Display for ProgramInternalExecuteError { impl std::error::Error for ProgramInternalExecuteError { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { match self { - ProgramInternalExecuteError::IO(e) => Some(e), + Self::IO(e) => Some(e), _ => None, } } @@ -96,23 +90,19 @@ impl std::error::Error for ProgramInternalExecuteError { impl From<std::io::Error> for ProgramInternalExecuteError { fn from(e: std::io::Error) -> Self { - ProgramInternalExecuteError::IO(e) + Self::IO(e) } } impl From<ProgramInternalExecuteError> for ProgramExecuteError { fn from(value: ProgramInternalExecuteError) -> Self { match value { - ProgramInternalExecuteError::DispatcherNotFound => { - ProgramExecuteError::DispatcherNotFound - } - ProgramInternalExecuteError::RendererNotFound(s) => { - ProgramExecuteError::RendererNotFound(s) - } - ProgramInternalExecuteError::Other(s) => ProgramExecuteError::Other(s), - ProgramInternalExecuteError::IO(e) => ProgramExecuteError::Other(format!("{e}")), + ProgramInternalExecuteError::DispatcherNotFound => Self::DispatcherNotFound, + ProgramInternalExecuteError::RendererNotFound(s) => Self::RendererNotFound(s), + ProgramInternalExecuteError::Other(s) => Self::Other(s), + ProgramInternalExecuteError::IO(e) => Self::Other(format!("{e}")), ProgramInternalExecuteError::REPLPanic(p) => { - ProgramExecuteError::Other(format!("A single REPL execution failed: {p}")) + Self::Other(format!("A single REPL execution failed: {p}")) } } } @@ -121,8 +111,8 @@ impl From<ProgramInternalExecuteError> for ProgramExecuteError { impl From<ChainProcessError> for ProgramInternalExecuteError { fn from(value: ChainProcessError) -> Self { match value { - ChainProcessError::Other(s) => ProgramInternalExecuteError::Other(s), - ChainProcessError::IO(error) => ProgramInternalExecuteError::IO(error), + ChainProcessError::Other(s) => Self::Other(s), + ChainProcessError::IO(error) => Self::IO(error), } } } diff --git a/mingling_core/src/program/flag.rs b/mingling_core/src/program/flag.rs index 6cf126d..81d83e6 100644 --- a/mingling_core/src/program/flag.rs +++ b/mingling_core/src/program/flag.rs @@ -44,27 +44,27 @@ pub struct Flag { vec: Vec<&'static str>, } -impl From<&Flag> for Flag { - fn from(value: &Flag) -> Self { +impl From<&Self> for Flag { + fn from(value: &Self) -> Self { value.clone() } } impl From<()> for Flag { fn from((): ()) -> Self { - Flag { vec: vec![] } + Self { vec: vec![] } } } impl From<&'static str> for Flag { fn from(s: &'static str) -> Self { - Flag { vec: vec![s] } + Self { vec: vec![s] } } } impl From<&'static [&'static str]> for Flag { fn from(slice: &'static [&'static str]) -> Self { - Flag { + Self { vec: slice.to_vec(), } } @@ -72,7 +72,7 @@ impl From<&'static [&'static str]> for Flag { impl<const N: usize> From<[&'static str; N]> for Flag { fn from(slice: [&'static str; N]) -> Self { - Flag { + Self { vec: slice.to_vec(), } } @@ -80,7 +80,7 @@ impl<const N: usize> From<[&'static str; N]> for Flag { impl<const N: usize> From<&'static [&'static str; N]> for Flag { fn from(slice: &'static [&'static str; N]) -> Self { - Flag { + Self { vec: slice.to_vec(), } } @@ -169,7 +169,7 @@ where /// Registers a global argument (with value) and its handler. pub fn global_argument<F, A>(&mut self, arguments: A, mut do_fn: F) where - F: FnMut(&mut Program<C>, String), + F: FnMut(&mut Self, String), A: Into<Flag>, { let flag = arguments.into(); @@ -185,7 +185,7 @@ where /// Registers a global flag (boolean) and its handler. pub fn global_flag<F, A>(&mut self, flag: A, mut do_fn: F) where - F: FnMut(&mut Program<C>), + F: FnMut(&mut Self), A: Into<Flag>, { let flag = flag.into(); diff --git a/mingling_core/src/program/hook.rs b/mingling_core/src/program/hook.rs index 50c53d7..0bcc051 100644 --- a/mingling_core/src/program/hook.rs +++ b/mingling_core/src/program/hook.rs @@ -149,19 +149,19 @@ where self } - pub(crate) fn run_hook_on_begin(&self, info: HookBeginInfo) { + pub(crate) fn run_hook_on_begin(&self, info: &HookBeginInfo) { if !self.user_context.run_hook { return; } for hook in &self.hooks { if let Some(ref begin) = hook.begin { - begin(&info); + begin(info); } } } - pub(crate) fn run_hook_pre_dispatch(&self, info: HookPreDispatchInfo) -> ProgramControls<C> { + pub(crate) fn run_hook_pre_dispatch(&self, info: &HookPreDispatchInfo) -> ProgramControls<C> { if !self.user_context.run_hook { return ProgramControls::Empty; } @@ -169,7 +169,7 @@ where let mut controls = ProgramControls::Empty; for hook in &self.hooks { if let Some(ref pre_dispatch) = hook.pre_dispatch { - controls = pre_dispatch(&info); + controls = pre_dispatch(info); } } controls @@ -177,7 +177,7 @@ where pub(crate) fn run_hook_post_dispatch( &self, - info: HookPostDispatchInfo<C>, + info: &HookPostDispatchInfo<C>, ) -> ProgramControls<C> { if !self.user_context.run_hook { return ProgramControls::Empty; @@ -186,13 +186,13 @@ where let mut controls = ProgramControls::Empty; for hook in &self.hooks { if let Some(ref post_dispatch) = hook.post_dispatch { - controls = post_dispatch(&info); + controls = post_dispatch(info); } } controls } - pub(crate) fn run_hook_pre_chain(&self, info: HookPreChainInfo<C>) -> ProgramControls<C> { + pub(crate) fn run_hook_pre_chain(&self, info: &HookPreChainInfo<C>) -> ProgramControls<C> { if !self.user_context.run_hook { return ProgramControls::Empty; } @@ -200,13 +200,13 @@ where let mut controls = ProgramControls::Empty; for hook in &self.hooks { if let Some(ref pre_chain) = hook.pre_chain { - controls = pre_chain(&info); + controls = pre_chain(info); } } controls } - pub(crate) fn run_hook_post_chain(&self, info: HookPostChainInfo<C>) -> ProgramControls<C> { + pub(crate) fn run_hook_post_chain(&self, info: &HookPostChainInfo<C>) -> ProgramControls<C> { if !self.user_context.run_hook { return ProgramControls::Empty; } @@ -214,13 +214,13 @@ where let mut controls = ProgramControls::Empty; for hook in &self.hooks { if let Some(ref post_chain) = hook.post_chain { - controls = post_chain(&info); + controls = post_chain(info); } } controls } - pub(crate) fn run_hook_pre_render(&self, info: HookPreRenderInfo<C>) -> ProgramControls<C> { + pub(crate) fn run_hook_pre_render(&self, info: &HookPreRenderInfo<C>) -> ProgramControls<C> { if !self.user_context.run_hook { return ProgramControls::Empty; } @@ -228,13 +228,13 @@ where let mut controls = ProgramControls::Empty; for hook in &self.hooks { if let Some(ref pre_render) = hook.pre_render { - controls = pre_render(&info); + controls = pre_render(info); } } controls } - pub(crate) fn run_hook_post_render(&self, info: HookPostRenderInfo) -> ProgramControls<C> { + pub(crate) fn run_hook_post_render(&self, info: &HookPostRenderInfo) -> ProgramControls<C> { if !self.user_context.run_hook { return ProgramControls::Empty; } @@ -242,7 +242,7 @@ where let mut controls = ProgramControls::Empty; for hook in &self.hooks { if let Some(ref post_render) = hook.post_render { - controls = post_render(&info); + controls = post_render(info); } } controls @@ -250,19 +250,19 @@ where #[allow(dead_code)] #[cfg(not(feature = "async"))] - pub(crate) fn run_hook_exec_panic(&self, info: HookPanicInfo) { + pub(crate) fn run_hook_exec_panic(&self, info: &HookPanicInfo) { if !self.user_context.run_hook { return; } for hook in &self.hooks { if let Some(ref exec_panic) = hook.exec_panic { - exec_panic(&info); + exec_panic(info); } } } - pub(crate) fn run_hook_finish(&self, info: HookFinishInfo) -> ProgramControls<C> { + pub(crate) fn run_hook_finish(&self, info: &HookFinishInfo) -> ProgramControls<C> { if !self.user_context.run_hook { return ProgramControls::Empty; } @@ -270,7 +270,7 @@ where let mut controls = ProgramControls::Empty; for hook in &self.hooks { if let Some(ref finish) = hook.finish { - controls = finish(&info); + controls = finish(info); } } controls @@ -278,28 +278,28 @@ where /// Runs the REPL begin hooks (only available with `repl` feature) #[cfg(feature = "repl")] - pub(crate) fn run_hook_repl_on_begin(&self, info: HookREPLBeginInfo) { + pub(crate) fn run_hook_repl_on_begin(&self, info: &HookREPLBeginInfo) { if !self.user_context.run_hook { return; } for hook in &self.hooks { if let Some(ref repl_on_begin) = hook.repl_on_begin { - repl_on_begin(&info); + repl_on_begin(info); } } } /// Runs the REPL pre-readline hooks (only available with `repl` feature) #[cfg(feature = "repl")] - pub(crate) fn run_hook_repl_pre_readline(&self, info: HookREPLPreReadlineInfo) { + pub(crate) fn run_hook_repl_pre_readline(&self, info: &HookREPLPreReadlineInfo) { if !self.user_context.run_hook { return; } for hook in &self.hooks { if let Some(ref repl_pre_readline) = hook.repl_pre_readline { - repl_pre_readline(&info); + repl_pre_readline(info); } } } @@ -307,14 +307,14 @@ where /// Runs the custom REPL readline hook (only available with `repl` feature) /// Returns `Some(line)` if a hook was set and returned Some, otherwise `None`. #[cfg(feature = "repl")] - pub(crate) fn run_hook_repl_readline(&self, info: HookREPLReadlineInfo) -> Option<String> { + pub(crate) fn run_hook_repl_readline(&self, info: &HookREPLReadlineInfo) -> Option<String> { if !self.user_context.run_hook { return None; } for hook in &self.hooks { if let Some(ref repl_readline) = hook.repl_readline { - return repl_readline(&info); + return repl_readline(info); } } None @@ -322,98 +322,98 @@ where /// Runs the REPL post-readline hooks (only available with `repl` feature) #[cfg(feature = "repl")] - pub(crate) fn run_hook_repl_post_readline(&self, info: HookREPLPostReadlineInfo) { + pub(crate) fn run_hook_repl_post_readline(&self, info: &HookREPLPostReadlineInfo) { if !self.user_context.run_hook { return; } for hook in &self.hooks { if let Some(ref repl_post_readline) = hook.repl_post_readline { - repl_post_readline(&info); + repl_post_readline(info); } } } /// Runs the REPL pre-exec hooks (only available with `repl` feature) #[cfg(feature = "repl")] - pub(crate) fn run_hook_repl_pre_exec(&self, info: HookREPLPreExecInfo) { + pub(crate) fn run_hook_repl_pre_exec(&self, info: &HookREPLPreExecInfo) { if !self.user_context.run_hook { return; } for hook in &self.hooks { if let Some(ref repl_pre_exec) = hook.repl_pre_exec { - repl_pre_exec(&info); + repl_pre_exec(info); } } } /// Runs the REPL post-exec hooks (only available with `repl` feature) #[cfg(feature = "repl")] - pub(crate) fn run_hook_repl_post_exec(&self, info: HookREPLPostExecInfo) { + pub(crate) fn run_hook_repl_post_exec(&self, info: &HookREPLPostExecInfo) { if !self.user_context.run_hook { return; } for hook in &self.hooks { if let Some(ref repl_post_exec) = hook.repl_post_exec { - repl_post_exec(&info); + repl_post_exec(info); } } } /// Runs the REPL receive result hooks (only available with `repl` feature) #[cfg(feature = "repl")] - pub(crate) fn run_hook_repl_on_receive_result(&self, info: HookREPLOnReceiveResultInfo) { + pub(crate) fn run_hook_repl_on_receive_result(&self, info: &HookREPLOnReceiveResultInfo) { if !self.user_context.run_hook { return; } for hook in &self.hooks { if let Some(ref repl_on_receive_result) = hook.repl_on_receive_result { - repl_on_receive_result(&info); + repl_on_receive_result(info); } } } /// Runs the REPL panic hooks (only available with `repl` feature) #[cfg(all(feature = "repl", not(feature = "async")))] - pub(crate) fn run_hook_repl_on_panic(&self, info: HookREPLOnPanicInfo) { + pub(crate) fn run_hook_repl_on_panic(&self, info: &HookREPLOnPanicInfo) { if !self.user_context.run_hook { return; } for hook in &self.hooks { if let Some(ref repl_on_panic) = hook.repl_on_panic { - repl_on_panic(&info); + repl_on_panic(info); } } } /// Runs the REPL exit hooks (only available with `repl` feature) #[cfg(feature = "repl")] - pub(crate) fn run_hook_repl_exit(&self, info: HookREPLExitInfo) { + pub(crate) fn run_hook_repl_exit(&self, info: &HookREPLExitInfo) { if !self.user_context.run_hook { return; } for hook in &self.hooks { if let Some(ref repl_exit) = hook.repl_exit { - repl_exit(&info); + repl_exit(info); } } } - /// Runs the REPL loop_once hooks (only available with `repl` feature) + /// Runs the REPL [`loop_once`] hooks (only available with `repl` feature) #[cfg(feature = "repl")] - pub(crate) fn run_hook_repl_loop_once(&self, info: HookREPLLoopOnceInfo) { + pub(crate) fn run_hook_repl_loop_once(&self, info: &HookREPLLoopOnceInfo) { if !self.user_context.run_hook { return; } for hook in &self.hooks { if let Some(ref repl_loop_once) = hook.repl_loop_once { - repl_loop_once(&info); + repl_loop_once(info); } } } @@ -663,7 +663,7 @@ where self } - /// Sets the handler for the REPL loop_once event (only available with `repl` feature). + /// Sets the handler for the REPL [`loop_once`] event (only available with `repl` feature). /// This hook runs after each REPL loop iteration. #[cfg(feature = "repl")] #[must_use] @@ -691,7 +691,7 @@ mod tests { impl std::fmt::Display for MockHookEnum { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:?}", self) + write!(f, "{self:?}") } } @@ -701,65 +701,62 @@ mod tests { /// Since this code only constructs `AnyOutput` and calls methods like /// `downcast`, `is`, `restore`, `route_chain`, and `route_renderer` — /// none of which involve `ProgramCollect::do_chain` or - /// `ProgramCollect::render` — the type/member_id correspondence is + /// `ProgramCollect::render` — the `type`/`member_id` correspondence is /// never exploited in an unsafe way here. /// The caller must ensure that the associated `member_id` correctly /// corresponds to the type's role in the group. - unsafe impl Grouped<MockHookEnum> for MockHookEnum { - fn member_id() -> MockHookEnum { - MockHookEnum::A + unsafe impl Grouped<Self> for MockHookEnum { + fn member_id() -> Self { + Self::A } } impl ProgramCollect for MockHookEnum { - type Enum = MockHookEnum; - type EntryFallback = MockHookEnum; - type ErrorRendererNotFound = MockHookEnum; - type ResultEmpty = MockHookEnum; + type Enum = Self; + type EntryFallback = Self; + type ErrorRendererNotFound = Self; + type ResultEmpty = Self; - fn build_renderer_not_found(_member_id: MockHookEnum) -> crate::AnyOutput<MockHookEnum> { + fn build_renderer_not_found(_member_id: Self) -> crate::AnyOutput<Self> { unreachable!() } - fn build_entry_fallback(_args: Vec<String>) -> crate::AnyOutput<MockHookEnum> { + fn build_entry_fallback(_args: Vec<String>) -> crate::AnyOutput<Self> { unreachable!() } - fn build_empty_result() -> crate::AnyOutput<MockHookEnum> { + fn build_empty_result() -> crate::AnyOutput<Self> { unreachable!() } - fn render(_any: crate::AnyOutput<MockHookEnum>) -> crate::RenderResult { + fn render(_any: crate::AnyOutput<Self>) -> crate::RenderResult { unreachable!() } - fn render_help(_any: crate::AnyOutput<MockHookEnum>) -> crate::RenderResult { + fn render_help(_any: crate::AnyOutput<Self>) -> crate::RenderResult { unreachable!() } - fn do_chain(_any: crate::AnyOutput<MockHookEnum>) -> crate::ChainProcess<MockHookEnum> { + fn do_chain(_any: crate::AnyOutput<Self>) -> crate::ChainProcess<Self> { unreachable!() } - fn has_renderer(_any: &crate::AnyOutput<MockHookEnum>) -> bool { + fn has_renderer(_any: &crate::AnyOutput<Self>) -> bool { unreachable!() } - fn has_chain(_any: &crate::AnyOutput<MockHookEnum>) -> bool { + fn has_chain(_any: &crate::AnyOutput<Self>) -> bool { unreachable!() } #[cfg(feature = "comp")] - fn do_comp( - _any: &crate::AnyOutput<MockHookEnum>, - _ctx: &crate::ShellContext, - ) -> crate::Suggest { + fn do_comp(_any: &crate::AnyOutput<Self>, _ctx: &crate::ShellContext) -> crate::Suggest { unreachable!() } #[cfg(feature = "structural_renderer")] fn structural_render( - _any: crate::AnyOutput<MockHookEnum>, + _any: crate::AnyOutput<Self>, _setting: &crate::StructuralRendererSetting, ) -> Result<crate::RenderResult, crate::error::StructuralRendererSerializeError> { unreachable!() diff --git a/mingling_core/src/program/hook/control_unit.rs b/mingling_core/src/program/hook/control_unit.rs index 5bf0e8c..d71a203 100644 --- a/mingling_core/src/program/hook/control_unit.rs +++ b/mingling_core/src/program/hook/control_unit.rs @@ -22,8 +22,8 @@ where C: ProgramCollect<Enum = C>, { /// Returns `true` if the collection is empty. - pub fn is_empty(&self) -> bool { - matches!(self, ProgramControls::Empty) + pub const fn is_empty(&self) -> bool { + matches!(self, Self::Empty) } } @@ -31,7 +31,7 @@ impl<C> From<()> for ProgramControls<C> where C: ProgramCollect<Enum = C>, { - fn from(_: ()) -> Self { + fn from((): ()) -> Self { Self::Empty } } @@ -63,13 +63,13 @@ where fn into_iter(self) -> Self::IntoIter { match self { - ProgramControls::Empty => ProgramControlsIter { + Self::Empty => ProgramControlsIter { inner: vec![].into_iter(), }, - ProgramControls::Single(unit) => ProgramControlsIter { + Self::Single(unit) => ProgramControlsIter { inner: vec![unit].into_iter(), }, - ProgramControls::Multi(units) => ProgramControlsIter { + Self::Multi(units) => ProgramControlsIter { inner: units.into_iter(), }, } @@ -139,17 +139,19 @@ where RouteToHelp(AnyOutput<C>), } -impl<C> From<ChainProcess<C>> for ProgramControlUnit<C> +impl<C> TryFrom<ChainProcess<C>> for ProgramControlUnit<C> where C: ProgramCollect<Enum = C>, { - fn from(val: ChainProcess<C>) -> Self { + type Error = String; + + fn try_from(val: ChainProcess<C>) -> Result<Self, Self::Error> { match val { ChainProcess::Ok((any, next)) => match next { - NextProcess::Chain => ProgramControlUnit::RouteToChain(any), - NextProcess::Renderer => ProgramControlUnit::RouteToRender(any), + NextProcess::Chain => Ok(Self::RouteToChain(any)), + NextProcess::Renderer => Ok(Self::RouteToRender(any)), }, - ChainProcess::Err(e) => panic!("{}", &e), + ChainProcess::Err(e) => Err(e.to_string()), } } } @@ -159,7 +161,14 @@ where C: ProgramCollect<Enum = C>, { fn from(val: ChainProcess<C>) -> Self { - let unit: ProgramControlUnit<C> = val.into(); - unit.into() + match val { + ChainProcess::Ok((any, next)) => match next { + NextProcess::Chain => Self::Single(ProgramControlUnit::RouteToChain(any)), + NextProcess::Renderer => Self::Single(ProgramControlUnit::RouteToRender(any)), + }, + ChainProcess::Err(e) => Self::Single(ProgramControlUnit::OverrideExitCode( + e.to_string().parse::<i32>().unwrap_or(1), + )), + } } } diff --git a/mingling_core/src/program/once_exec.rs b/mingling_core/src/program/once_exec.rs index 96723fd..18e06ef 100644 --- a/mingling_core/src/program/once_exec.rs +++ b/mingling_core/src/program/once_exec.rs @@ -21,7 +21,7 @@ where C: 'static + Send + Sync, { // Run hooks - self.run_hook_on_begin(crate::hook::HookBeginInfo {}); + self.run_hook_on_begin(&crate::hook::HookBeginInfo {}); self.args = self.args.iter().skip(1).cloned().collect(); @@ -43,11 +43,11 @@ where let program = THIS_PROGRAM .get_raw() .unwrap() - .downcast_ref::<Program<C>>() + .downcast_ref::<Self>() .unwrap(); #[cfg(not(feature = "async"))] - program.run_hook_exec_panic(crate::hook::HookPanicInfo { + program.run_hook_exec_panic(&crate::hook::HookPanicInfo { panic: &panic_payload, }); @@ -98,7 +98,7 @@ where // Read exit code // Render result - if stdout_setting.render_output { + if stdout_setting.render_output == crate::RenderOutput::Show { result.std_print(); } @@ -152,17 +152,17 @@ where pub(crate) fn exec_wrapper<F, R>(self, f: F) -> R where C: 'static + Send + Sync, - F: FnOnce(&'static Program<C>) -> R + Send + Sync, + F: FnOnce(&'static Self) -> R + Send + Sync, { THIS_PROGRAM.set(Box::new(self)); let program = THIS_PROGRAM .get_raw() .unwrap() - .downcast_ref::<Program<C>>() + .downcast_ref::<Self>() .unwrap(); #[cfg(not(panic = "abort"))] - if program.stdout_setting.silence_panic { + if program.stdout_setting.silence_panic == super::PanicSilence::Silence { std::panic::set_hook(Box::new(|_| {})); } diff --git a/mingling_core/src/program/repl_exec.rs b/mingling_core/src/program/repl_exec.rs index f84b291..ea36c75 100644 --- a/mingling_core/src/program/repl_exec.rs +++ b/mingling_core/src/program/repl_exec.rs @@ -29,7 +29,7 @@ where // Inject default REPL resource self.with_resource(ResREPL::default()); - self.run_hook_repl_on_begin(crate::hook::HookREPLBeginInfo {}); + self.run_hook_repl_on_begin(&crate::hook::HookREPLBeginInfo {}); might_be_async::select!( self.exec_wrapper(async |p| -> () { @@ -48,43 +48,43 @@ where C: ProgramCollect<Enum = C> + Send + Sync + 'static, { loop { - p.run_hook_repl_pre_readline(crate::hook::HookREPLPreReadlineInfo {}); + p.run_hook_repl_pre_readline(&crate::hook::HookREPLPreReadlineInfo {}); let mut readline = p - .run_hook_repl_readline(crate::hook::HookREPLReadlineInfo {}) + .run_hook_repl_readline(&crate::hook::HookREPLReadlineInfo {}) .unwrap_or_default(); - p.run_hook_repl_post_readline(crate::hook::HookREPLPostReadlineInfo { + p.run_hook_repl_post_readline(&crate::hook::HookREPLPostReadlineInfo { line: &mut readline, }); - let args = split_input_string(readline.clone()); + let args = split_input_string(&readline); - p.run_hook_repl_pre_exec(crate::hook::HookREPLPreExecInfo { args: &args }); - match might_be_async::invoke!(exec_once(p, args)) { + p.run_hook_repl_pre_exec(&crate::hook::HookREPLPreExecInfo { args: &args }); + match might_be_async::invoke!(exec_once(p, &args)) { Ok(r) => { - p.run_hook_repl_on_receive_result(crate::hook::HookREPLOnReceiveResultInfo { + p.run_hook_repl_on_receive_result(&crate::hook::HookREPLOnReceiveResultInfo { result: &r, }); } Err(ProgramInternalExecuteError::REPLPanic(panic)) => { - p.run_hook_repl_on_panic(crate::hook::HookREPLOnPanicInfo { panic: &panic }); + p.run_hook_repl_on_panic(&crate::hook::HookREPLOnPanicInfo { panic: &panic }); } _ => {} } - p.run_hook_repl_post_exec(crate::hook::HookREPLPostExecInfo {}); + p.run_hook_repl_post_exec(&crate::hook::HookREPLPostExecInfo {}); if this::<C>().res::<ResREPL>().unwrap().exit { - p.run_hook_repl_exit(crate::hook::HookREPLExitInfo {}); + p.run_hook_repl_exit(&crate::hook::HookREPLExitInfo {}); break; } - p.run_hook_repl_loop_once(crate::hook::HookREPLLoopOnceInfo {}); + p.run_hook_repl_loop_once(&crate::hook::HookREPLLoopOnceInfo {}); } } #[cfg(not(feature = "async"))] fn exec_once<C>( p: &'static Program<C>, - args: Vec<String>, + args: &[String], ) -> Result<RenderResult, ProgramInternalExecuteError> where C: ProgramCollect<Enum = C> + Send + Sync + 'static, @@ -95,7 +95,7 @@ where #[cfg(not(panic = "abort"))] let exec_result = { let exec_unwind_result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { - super::exec::exec_with_args(p, &args) + super::exec::exec_with_args(p, args) })); match exec_unwind_result { @@ -108,7 +108,7 @@ where .unwrap() .downcast_ref::<Program<C>>() .unwrap(); - program.run_hook_repl_on_panic(crate::hook::HookREPLOnPanicInfo { + program.run_hook_repl_on_panic(&crate::hook::HookREPLOnPanicInfo { panic: &panic_payload, }); Err(ProgramInternalExecuteError::REPLPanic(panic_payload)) @@ -123,7 +123,7 @@ where #[cfg(feature = "async")] async fn exec_once<C>( p: &'static Program<C>, - args: Vec<String>, + args: &[String], ) -> Result<RenderResult, ProgramInternalExecuteError> where C: ProgramCollect<Enum = C> + Send + Sync + 'static, diff --git a/mingling_core/src/program/repl_exec/splitter.rs b/mingling_core/src/program/repl_exec/splitter.rs index 267f42c..c74a3f1 100644 --- a/mingling_core/src/program/repl_exec/splitter.rs +++ b/mingling_core/src/program/repl_exec/splitter.rs @@ -1,14 +1,14 @@ /// Wraps `split_input` to work with owned `String` inputs. -pub(crate) fn split_input_string(input: String) -> Vec<String> { - split_input(&input) +pub fn split_input_string(input: &str) -> Vec<String> { + split_input(input) } /// Splits a string input into arguments, respecting single quotes, double quotes, /// and backslash escaping. -pub(crate) fn split_input(input: &str) -> Vec<String> { +pub fn split_input(input: &str) -> Vec<String> { let mut result: Vec<String> = Vec::new(); let mut current = String::new(); - let mut chars = input.chars().peekable(); + let mut chars = input.chars(); while let Some(ch) = chars.next() { match ch { diff --git a/mingling_core/src/program/single_instance.rs b/mingling_core/src/program/single_instance.rs index 8b165bf..083897d 100644 --- a/mingling_core/src/program/single_instance.rs +++ b/mingling_core/src/program/single_instance.rs @@ -13,7 +13,7 @@ use crate::{Program, ProgramCollect}; /// the inner value is immutable once set until `take()`). /// - `take()` is called only after execution completes, when no code still /// holds a reference from `get_raw()`. -pub(crate) struct ProgramCell { +pub struct ProgramCell { initialized: AtomicBool, inner: UnsafeCell<Option<Box<dyn std::any::Any + Send + Sync>>>, } @@ -88,6 +88,7 @@ impl ProgramCell { } /// Global static reference to the current program instance +#[allow(clippy::redundant_pub_crate)] pub(crate) static THIS_PROGRAM: ProgramCell = ProgramCell::new(); /// Returns a reference to the current program instance, panics if not set. diff --git a/mingling_core/src/program/string_vec.rs b/mingling_core/src/program/string_vec.rs index c2e6220..a2eb433 100644 --- a/mingling_core/src/program/string_vec.rs +++ b/mingling_core/src/program/string_vec.rs @@ -20,7 +20,7 @@ impl From<StringVec> for Vec<String> { impl<const N: usize> From<[&str; N]> for StringVec { fn from(slice: [&str; N]) -> Self { - StringVec { + Self { vec: slice.iter().map(|&s| s.to_string()).collect(), } } @@ -28,21 +28,20 @@ impl<const N: usize> From<[&str; N]> for StringVec { impl From<&[&str]> for StringVec { fn from(slice: &[&str]) -> Self { - StringVec { + Self { vec: slice.iter().map(|&s| s.to_string()).collect(), } } } - impl From<Vec<String>> for StringVec { fn from(vec: Vec<String>) -> Self { - StringVec { vec } + Self { vec } } } impl From<&[String]> for StringVec { fn from(slice: &[String]) -> Self { - StringVec { + Self { vec: slice.to_vec(), } } @@ -50,7 +49,7 @@ impl From<&[String]> for StringVec { impl From<Vec<&str>> for StringVec { fn from(vec: Vec<&str>) -> Self { - StringVec { + Self { vec: vec.iter().map(|&s| s.to_string()).collect(), } } |
