From f9548af5c7693edf536b4ad45564a964338e2c2e Mon Sep 17 00:00:00 2001 From: lukeflo Date: Fri, 10 Oct 2025 10:31:45 +0200 Subject: set up citekey formatting cli, reformat help output --- src/bibiman/citekeys.rs | 87 ++++++++++++++++++++++++++++++++++++++- src/cliargs.rs | 106 ++++++++++++++++++++++++++++++++---------------- src/main.rs | 14 ++++--- 3 files changed, 166 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/bibiman/citekeys.rs b/src/bibiman/citekeys.rs index b7995ac..cafd124 100644 --- a/src/bibiman/citekeys.rs +++ b/src/bibiman/citekeys.rs @@ -23,7 +23,12 @@ use std::{ use biblatex::{Bibliography, ChunksExt, Entry, Type}; use color_eyre::eyre::eyre; -use owo_colors::OwoColorize; +use indoc::formatdoc; +use lexopt::Arg::{Long, Short}; +use owo_colors::{ + OwoColorize, + colors::{BrightBlue, Green, White}, +}; use serde::{Deserialize, Serialize}; use crate::{bibiman::sanitize::sanitize_single_string_fully, config::BibiConfig}; @@ -48,6 +53,30 @@ pub(crate) struct CitekeyFormatting { } impl CitekeyFormatting { + pub(crate) fn parse_citekey_cli( + parser: &mut lexopt::Parser, + cfg: &BibiConfig, + ) -> color_eyre::Result<()> { + let mut formatter = CitekeyFormatting::default(); + + while let Some(arg) = parser.next()? { + match arg { + Short('h') | Long("help") => { + formatting_help(); + return Ok(()); + } + Short('s') | Short('f') | Long("source") | Long("file") => { + formatter.bibfile_path.0 = parser.value()?.into() + } + Short('t') | Short('o') | Long("target") | Long("output") => { + formatter.bibfile_path.1 = Some(parser.value()?.into()) + } + _ => return Err(arg.unexpected().into()), + } + } + + Ok(()) + } /// Start Citekey formatting with building a new instance of `CitekeyFormatting` /// Formatting is processed file by file, because `bibman` can handle /// multi-file setups. @@ -136,6 +165,62 @@ impl CitekeyFormatting { } } +fn formatting_help() { + let help = vec![ + formatdoc!( + "{} {}\n", + env!("CARGO_PKG_NAME").fg::().bold(), + env!("CARGO_PKG_VERSION") + ), + formatdoc!("{}", "USAGE".bold()), + formatdoc!( + "\t{} {} {} {}\n", + env!("CARGO_PKG_NAME").fg::().bold(), + "format-citekeys".bold(), + "--source=".bold(), + "--output=".bold() + ), + formatdoc!( + " + \tThis help describes the CLI usage for the citekey formatting + \tfunctionality of bibiman. The definition of patterns how the + \tcitekeys should be formatted must be set in the config file. + \tFor further informations how to use this patterns etc. see: + \t{} + ", + "https://codeberg.org/lukeflo/bibiman/src/branch/main#bibiman" + .italic() + .fg::() + ), + formatdoc!("{}", "OPTIONS".bold()), + formatdoc!( + " + \t{} + \tShow this help and exit + ", + "-h, --help".fg::().bold() + ), + formatdoc! {" + \t{} + \tThe bibfile for which the citekey formatting should be processed. + \tTakes a path as argument. + ", "-s, -f, --source=, --file=".fg::().bold()}, + formatdoc!( + " + \t{} + \tThe bibfile to which the updated content should be written. + \tTakes a path as argument. If the file doesn't exist, it will be + \tcreated. + \tIf the argument isn't used, the original file will be {}! + ", + "-t, -o, --target=, --output=".fg::().bold(), + "overwritten".italic(), + ), + ]; + let help = help.join("\n"); + println!("{}", help); +} + /// Build the citekey from the patterns defined in the config file fn build_citekey(entry: &Entry, pattern_fields: &[String], case: Option<&CitekeyCase>) -> String { let mut new_citekey = String::new(); diff --git a/src/cliargs.rs b/src/cliargs.rs index 26a07af..e766e77 100644 --- a/src/cliargs.rs +++ b/src/cliargs.rs @@ -16,6 +16,7 @@ ///// use dirs::{config_dir, home_dir}; +use indoc::formatdoc; use lexopt::prelude::*; use owo_colors::OwoColorize; use owo_colors::colors::css::LightGreen; @@ -25,6 +26,7 @@ use std::path::PathBuf; use walkdir::WalkDir; use crate::app; +use crate::bibiman::citekeys::CitekeyFormatting; use crate::config::BibiConfig; // struct for CLIArgs @@ -37,10 +39,16 @@ pub struct CLIArgs { } impl CLIArgs { - pub fn parse_args() -> color_eyre::Result<(CLIArgs, BibiConfig)> { + /// This struct parses the command line and initializes and returns the + /// necessary structs `CLIArgs` and `BibiConfig`. + /// + /// Additionally, it returns a bool which defines if the TUI should be run + /// or not. The latter is the case for pure CLI processes as `format-citekeys`. + pub fn parse_args() -> color_eyre::Result<(CLIArgs, BibiConfig, bool)> { let mut args = CLIArgs::default(); let mut parser = lexopt::Parser::from_env(); let mut subcommand = None; + let mut run_tui = true; // Default config args.cfg_path = if config_dir().is_some() { @@ -81,6 +89,7 @@ impl CLIArgs { match value.as_str() { "format-citekeys" => { subcommand = Some(value); + run_tui = false; break; } _ => { @@ -111,14 +120,16 @@ impl CLIArgs { if let Some(cmd) = subcommand { match cmd.as_str() { - "format-citekeys" => todo!("write citekey formatting"), + "format-citekeys" => { + CitekeyFormatting::parse_citekey_cli(&mut parser, &cfg)?; + } _ => {} } } cfg.cli_overwrite(&args); - Ok((args, cfg)) + Ok((args, cfg, run_tui)) } } @@ -172,14 +183,21 @@ pub fn help_func() -> String { env!("CARGO_PKG_VERSION").fg::(), ), format!( - "{}:\n\t{} [Flags] [files/dirs]\n", + "{}\n\t{} [OPTIONS] [SUBCOMMAND | POSITIONAL ARGUMENTS]\n", "USAGE".bold(), - "bibiman".bold() + env!("CARGO_PKG_NAME").fg::().bold() + ), + formatdoc!( + " + \tYou can either use a {} or {}, not both! + ", + "subcommand".bold(), + "positional arguments".bold() ), format!( - "{}:\n\t{}\t\tPath to {} file", + "{}\n\t{}\t\tPath to {} file", "POSITIONAL ARGUMENTS".bold(), - "".fg::().bold(), + "".fg::().bold(), ".bib".fg::().bold() ), format!( @@ -188,38 +206,58 @@ pub fn help_func() -> String { ".bib".fg::().bold() ), format!("\n\t{}", "Both can be passed multiple times".italic()), - format!("\n{}:", "FLAGS".bold()), - format!("\t{}", "-h, --help".bold().fg::()), - format!("\t\t{}", "Show this help and exit"), - format!("\t{}", "-v, --version".bold().fg::()), - format!("\t\t{}", "Show the version and exit"), - format!("\t{}", "--light-terminal".bold().fg::()), - format!( - "\t\t{}", - "Enable default colors for light terminal background" + format!("\n{}", "SUBCOMMANDS".bold()), + formatdoc!( + " + \t{} + \tRun the citekey formatting procedure on a specified bibfile. + \tFor further infos run {} + ", + "format-citekeys".fg::().bold(), + "bibiman format-citekeys --help".fg::().bold() ), - format!( - "\t{}{}", - "-c, --config-file=".bold().fg::(), - "".bold().italic().fg::() + format!("{}", "OPTIONS".bold()), + formatdoc!( + " + \t{} + \tShow this help and exit + ", + "-h, --help".bold().fg::() ), - format!("\t\t{}", "Path to config file used for current session."), - format!("\t\t{}", "Takes precedence over standard config file."), - format!( - "\t{}{}", - "--pdf-path=".bold().fg::(), - "".bold().italic().fg::() + formatdoc!( + " + \t{} + \tShow the version and exit + ", + "-v, --version".bold().fg::() ), - format!("\t\t{}", "Path to directory containing PDF files."), - format!( - "\t\t{}", - "If the pdf files basename matches an entrys citekey," + formatdoc!( + " + \t{} + \tEnable default colors for light terminal background + ", + "--light-terminal".bold().fg::() ), - format!( - "\t\t{}", - "its attached as connected PDF file for the current session." + formatdoc!( + " + \t{}{} + \tPath to config file used for current session. + \tTakes precedence over standard config file. + ", + "-c, --config-file=".bold().fg::(), + "".bold().italic().fg::() + ), + formatdoc!( + " + \t{}{} + \tPath to directory containing PDF files. + \tIf the pdf files basename matches an entrys citekey, + \tits attached as connected PDF file for the current session. + \tDoes not edit the bibfile itself! + ", + "--pdf-path=".bold().fg::(), + "".bold().italic().fg::() ), - format!("\t\t{}", "Does not edit the bibfile itself!"), ]; let help = help.join("\n"); help diff --git a/src/main.rs b/src/main.rs index 58805d5..e735eb0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,7 +18,6 @@ use app::App; use cliargs::CLIArgs; use color_eyre::eyre::Result; -use config::BibiConfig; use errorsetup::init_error_hooks; pub mod app; @@ -31,13 +30,16 @@ pub mod tui; #[tokio::main] async fn main() -> Result<()> { // Parse CLI arguments - let (mut parsed_args, mut cfg) = CLIArgs::parse_args()?; + let (mut parsed_args, mut cfg, run_tui) = CLIArgs::parse_args()?; - init_error_hooks()?; + if run_tui { + init_error_hooks()?; - // Create an application. - let mut app = App::new(&mut parsed_args, &mut cfg)?; + // Create an application. + let mut app = App::new(&mut parsed_args, &mut cfg)?; + + app.run(&cfg).await?; + } - app.run(&cfg).await?; Ok(()) } -- cgit v1.2.3