From 2aa7bda3cb21ce6c052b82e08bcab79a625d04f2 Mon Sep 17 00:00:00 2001 From: Weicao-CatilGrass <1992414357@qq.com> Date: Sun, 31 May 2026 02:42:52 +0800 Subject: Enhance code quality across the entire codebase --- mling/Cargo.toml | 4 ++++ mling/src/cli.rs | 7 ++++++- mling/src/cli/list.rs | 24 +++++++++++------------ mling/src/cli/read.rs | 9 ++++++--- mling/src/display.rs | 44 ++++++++++++++---------------------------- mling/src/namespace_manager.rs | 24 +++++++++++++++++------ mling/src/project_installer.rs | 25 +++++++++++++++++++----- mling/src/project_solver.rs | 27 +++++++++++++++++--------- 8 files changed, 99 insertions(+), 65 deletions(-) (limited to 'mling') diff --git a/mling/Cargo.toml b/mling/Cargo.toml index 2d01bdf..df9c675 100644 --- a/mling/Cargo.toml +++ b/mling/Cargo.toml @@ -2,9 +2,13 @@ name = "mingling-cli" version.workspace = true edition.workspace = true +authors = ["Weicao-CatilGrass"] license.workspace = true +readme = "README.md" repository.workspace = true description = "Mingling's scaffolding tool" +keywords = ["cli", "scaffolding", "command-line", "framework"] +categories = ["command-line-interface"] [[bin]] name = "mling" diff --git a/mling/src/cli.rs b/mling/src/cli.rs index 705c6b4..b628021 100644 --- a/mling/src/cli.rs +++ b/mling/src/cli.rs @@ -17,6 +17,11 @@ pub use read::*; pub mod install; pub use install::*; +/// Entry point for the CLI application. +/// +/// # Panics +/// +/// Panics on Windows if the virtual terminal processing cannot be enabled. pub fn cli_entry() { let mut program = ThisProgram::new(); @@ -62,7 +67,7 @@ pub fn cli_entry() { #[cfg(windows)] colored::control::set_virtual_terminal(true).unwrap(); - program.exec(); + let _ = program.exec(); } #[renderer] diff --git a/mling/src/cli/list.rs b/mling/src/cli/list.rs index ac9a65f..a2a9434 100644 --- a/mling/src/cli/list.rs +++ b/mling/src/cli/list.rs @@ -78,44 +78,44 @@ pub(crate) fn render_installed(prev: ResultInstalledNamespaces) { match prev.option { StateListInstalledOptions::All => { print_list( - "Trusted".bright_green().bold().to_string(), - prev.trusted, + &"Trusted".bright_green().bold().to_string(), + &prev.trusted, __renderer_inner_result, ); print_list( - "Untrusted".bright_red().bold().to_string(), - prev.untrusted, + &"Untrusted".bright_red().bold().to_string(), + &prev.untrusted, __renderer_inner_result, ); print_list( - "Untagged".bright_black().bold().to_string(), - prev.untagged, + &"Untagged".bright_black().bold().to_string(), + &prev.untagged, __renderer_inner_result, ); } StateListInstalledOptions::OnlyTrusted => { print_list( - "Trusted".bright_green().bold().to_string(), - prev.trusted, + &"Trusted".bright_green().bold().to_string(), + &prev.trusted, __renderer_inner_result, ); } StateListInstalledOptions::OnlyUntrusted => { print_list( - "Untrusted".bright_red().bold().to_string(), - prev.untrusted, + &"Untrusted".bright_red().bold().to_string(), + &prev.untrusted, __renderer_inner_result, ); } } } -fn print_list(title: String, list: Vec, __renderer_inner_result: &mut RenderResult) { +fn print_list(title: &str, list: &[String], __renderer_inner_result: &mut RenderResult) { if list.is_empty() { return; } - r_println!("{}", title); + r_println!("{title}"); for (i, namespace) in (1..).zip(list.iter()) { r_println!(" {}. {}", i.to_string(), namespace.bold()); diff --git a/mling/src/cli/read.rs b/mling/src/cli/read.rs index 82f8fd5..e51e78f 100644 --- a/mling/src/cli/read.rs +++ b/mling/src/cli/read.rs @@ -25,7 +25,8 @@ pub(crate) struct ResultBinaries { } #[chain] -pub(crate) fn handle_target_dir_entry(_prev: ReadTargetDirEntry) -> Next { +#[allow(unused_variables)] +pub(crate) fn handle_target_dir_entry(entry: ReadTargetDirEntry) -> Next { match solve_current_dir() { Ok(solved) => { let dir = solved.target_dir; @@ -36,7 +37,8 @@ pub(crate) fn handle_target_dir_entry(_prev: ReadTargetDirEntry) -> Next { } #[chain] -pub(crate) fn handle_workspace_root_entry(_prev: ReadWorkspaceRootEntry) -> Next { +#[allow(unused_variables)] +pub(crate) fn handle_workspace_root_entry(entry: ReadWorkspaceRootEntry) -> Next { match solve_current_dir() { Ok(solved) => { let dir = solved.workspace_root; @@ -47,7 +49,8 @@ pub(crate) fn handle_workspace_root_entry(_prev: ReadWorkspaceRootEntry) -> Next } #[chain] -pub(crate) fn handle_binaries_entry(_prev: ReadBinariesEntry) -> Next { +#[allow(unused_variables)] +pub(crate) fn handle_binaries_entry(entry: ReadBinariesEntry) -> Next { match solve_current_dir() { Ok(solved) => { let binaries = solved.binaries; diff --git a/mling/src/display.rs b/mling/src/display.rs index 9182692..3816d89 100644 --- a/mling/src/display.rs +++ b/mling/src/display.rs @@ -120,8 +120,7 @@ pub fn markdown(text: impl AsRef) -> String { // Format heading as white background, black text, bold // ANSI codes: \x1b[1m for bold, \x1b[47m for white background, \x1b[30m for black text - let formatted_heading = - format!("\x1b[1m\x1b[47m\x1b[30m {} \x1b[0m", processed_content); + let formatted_heading = format!("\x1b[1m\x1b[47m\x1b[30m {processed_content} \x1b[0m"); // Add indentation to the heading line itself // Heading indentation = level - 1 @@ -187,7 +186,7 @@ fn process_line_with_quote(line: &str) -> String { let processed_rest = process_line(&rest_of_line); // Combine the gray background space with the processed rest - format!("{}{}", gray_bg_space, processed_rest) + format!("{gray_bg_space}{processed_rest}") } else { // No > at the beginning, process normally process_line(line) @@ -266,7 +265,7 @@ fn process_line(line: &str) -> String { && let Some(end) = find_matching(&chars, i + 1, "_") { let underline_text: String = chars[i + 1..end].iter().collect(); - let mut formatted_text = format!("\x1b[4m{}\x1b[0m", underline_text); + let mut formatted_text = format!("\x1b[4m{underline_text}\x1b[0m"); apply_color_stack(&mut formatted_text, &color_stack); result.push_str(&formatted_text); i = end + 1; @@ -357,16 +356,18 @@ fn apply_color(text: impl AsRef, color_name: impl AsRef) -> String { let text = text.as_ref(); let color_name = color_name.as_ref(); match color_name { - // Normal colors - "black" => text.black().to_string(), - "red" => text.red().to_string(), - "green" => text.green().to_string(), - "yellow" => text.yellow().to_string(), - "blue" => text.blue().to_string(), - "magenta" => text.magenta().to_string(), - "cyan" => text.cyan().to_string(), - "white" => text.white().to_string(), - "bright_black" => text.bright_black().to_string(), + // Normal colors and their bright short aliases + "black" | "b_black" => text.black().to_string(), + "red" | "b_red" => text.red().to_string(), + "green" | "b_green" => text.green().to_string(), + "yellow" | "b_yellow" => text.yellow().to_string(), + "blue" | "b_blue" => text.blue().to_string(), + "magenta" | "b_magenta" => text.magenta().to_string(), + "cyan" | "b_cyan" => text.cyan().to_string(), + "white" | "b_white" | "bright_gray" | "bright_grey" | "b_gray" | "b_grey" => { + text.white().to_string() + } + "bright_black" | "gray" | "grey" => text.bright_black().to_string(), "bright_red" => text.bright_red().to_string(), "bright_green" => text.bright_green().to_string(), "bright_yellow" => text.bright_yellow().to_string(), @@ -375,21 +376,6 @@ fn apply_color(text: impl AsRef, color_name: impl AsRef) -> String { "bright_cyan" => text.bright_cyan().to_string(), "bright_white" => text.bright_white().to_string(), - // Short aliases for bright colors - "b_black" => text.black().to_string(), - "b_red" => text.red().to_string(), - "b_green" => text.green().to_string(), - "b_yellow" => text.yellow().to_string(), - "b_blue" => text.blue().to_string(), - "b_magenta" => text.magenta().to_string(), - "b_cyan" => text.cyan().to_string(), - "b_white" => text.white().to_string(), - - // Gray colors using truecolor - "gray" | "grey" => text.bright_black().to_string(), - "bright_gray" | "bright_grey" => text.white().to_string(), - "b_gray" | "b_grey" => text.white().to_string(), - // Default to white if color not recognized _ => text.to_string(), } diff --git a/mling/src/namespace_manager.rs b/mling/src/namespace_manager.rs index 51181c3..d5176dd 100644 --- a/mling/src/namespace_manager.rs +++ b/mling/src/namespace_manager.rs @@ -2,6 +2,7 @@ use std::path::PathBuf; use just_fmt::kebab_case; +#[must_use] pub fn list_namespaces( show_trusted: bool, show_untrusted: bool, @@ -13,14 +14,12 @@ pub fn list_namespaces( } let mut namespaces = Vec::new(); - let entries = match std::fs::read_dir(&wdir) { - Ok(entries) => entries, - Err(_) => return Vec::new(), + let Ok(entries) = std::fs::read_dir(&wdir) else { + return Vec::new(); }; for entry in entries { - let entry = match entry { - Ok(e) => e, - Err(_) => continue, + let Ok(entry) = entry else { + continue; }; let path = entry.path(); if path.is_dir() @@ -71,24 +70,34 @@ pub fn remove_namespace(namespace: String) { } } +/// Returns the mingling data directory. +/// +/// # Panics +/// +/// Panics if the platform's data directory cannot be determined. +#[must_use] pub fn working_dir() -> PathBuf { dirs::data_dir().unwrap().join("mingling") } +#[must_use] pub fn namespace_dir(namespace: String) -> PathBuf { working_dir().join(kebab_case!(namespace)) } +#[must_use] pub fn is_untrusted_namespace(namespace: String) -> bool { let untrusted_file = namespace_dir(namespace).join("UNTRUSTED"); untrusted_file.exists() } +#[must_use] pub fn is_trusted_namespace(namespace: String) -> bool { let trusted = namespace_dir(namespace).join("TRUSTED"); trusted.exists() } +#[must_use] pub fn is_untagged_namespace(namespace: String) -> bool { let ndir = namespace_dir(namespace); let trusted = ndir.join("TRUSTED"); @@ -96,14 +105,17 @@ pub fn is_untagged_namespace(namespace: String) -> bool { !trusted.exists() && !untrusted.exists() } +#[must_use] pub fn bin_dir(namespace: String) -> PathBuf { namespace_dir(namespace).join("bin") } +#[must_use] pub fn comp_dir(namespace: String) -> PathBuf { namespace_dir(namespace).join("comp") } +#[must_use] pub fn exe_path(namespace: String, bin_name_without_ext: String) -> PathBuf { if cfg!(target_os = "windows") { bin_dir(namespace).join(bin_name_without_ext + ".exe") diff --git a/mling/src/project_installer.rs b/mling/src/project_installer.rs index 2e9ca8d..983307f 100644 --- a/mling/src/project_installer.rs +++ b/mling/src/project_installer.rs @@ -1,5 +1,3 @@ -use std::path::PathBuf; - use mingling::{ShellFlag, build::build_comp_script_to}; use crate::{ @@ -21,15 +19,27 @@ struct Package { name: String, } +/// Installs all projects and shell scripts. +/// +/// # Errors +/// +/// Returns an `io::Error` if the current directory cannot be determined, if the project +/// installation fails, or if the shell scripts cannot be installed. pub fn install_all(clean_before_build: bool) -> Result<(), std::io::Error> { let current = std::env::current_dir()?; - install_this_project(current, clean_before_build)?; + install_this_project(¤t, clean_before_build)?; install_shell_scripts()?; Ok(()) } +/// Installs a project from the given path. +/// +/// # Errors +/// +/// Returns an `io::Error` if the project installation fails, e.g., if `cargo build` +/// fails, the Cargo.toml cannot be parsed, or file operations (copy, create dir) fail. pub fn install_this_project( - current: PathBuf, + current: &std::path::PathBuf, clean_before_build: bool, ) -> Result<(), std::io::Error> { // Obtain context data @@ -95,6 +105,11 @@ pub fn install_this_project( Ok(()) } +/// Installs shell completion scripts for the `mling` command. +/// +/// # Errors +/// +/// Returns an `io::Error` if the shell scripts cannot be built or installed. pub fn install_shell_scripts() -> Result<(), std::io::Error> { // Get the working directory (mingling data dir) let wdir = working_dir(); @@ -138,7 +153,7 @@ pub fn install_shell_scripts() -> Result<(), std::io::Error> { .args(["+x", &dest.to_string_lossy()]) .status()?; if !status.success() { - eprintln!("Failed to chmod {}", filename); + eprintln!("Failed to chmod {filename}"); } } } diff --git a/mling/src/project_solver.rs b/mling/src/project_solver.rs index b6517b3..3aec2b4 100644 --- a/mling/src/project_solver.rs +++ b/mling/src/project_solver.rs @@ -17,13 +17,24 @@ pub struct BinaryItem { pub path: PathBuf, } +/// Solves the current directory for project metadata. +/// +/// # Errors +/// +/// Returns an `io::Error` if the current directory cannot be determined +/// or if `cargo metadata` fails. pub fn solve_current_dir() -> Result { let current = std::env::current_dir()?; - solve(current) + solve(¤t) } -pub fn solve(current: PathBuf) -> Result { - let (target_dir, workspace_root, binaries) = solve_inner(¤t)?; +/// Solves the given directory path for project metadata. +/// +/// # Errors +/// +/// Returns an `io::Error` if `cargo metadata` fails for the given path. +pub fn solve(current: &PathBuf) -> Result { + let (target_dir, workspace_root, binaries) = solve_inner(current)?; Ok(ProjectSolveResult { target_dir, workspace_root, @@ -40,9 +51,9 @@ fn solve_inner(current: &PathBuf) -> Result<(PathBuf, PathBuf, Vec), .output()?; if !output.status.success() { let stderr = String::from_utf8_lossy(&output.stderr); - return Err(std::io::Error::other( - format!("cargo metadata failed: {}", stderr), - )); + return Err(std::io::Error::other(format!( + "cargo metadata failed: {stderr}" + ))); } let metadata: serde_json::Value = serde_json::from_slice(&output.stdout) .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?; @@ -75,9 +86,7 @@ fn solve_inner(current: &PathBuf) -> Result<(PathBuf, PathBuf, Vec), if let Some(targets) = pkg["targets"].as_array() { for target in targets { let kind = target["kind"].as_array(); - let is_bin = kind - .map(|k| k.iter().any(|v| v.as_str() == Some("bin"))) - .unwrap_or(false); + let is_bin = kind.is_some_and(|k| k.iter().any(|v| v.as_str() == Some("bin"))); if is_bin { let name = target["name"].as_str().ok_or_else(|| { std::io::Error::new( -- cgit