// bibiman - a TUI for managing BibLaTeX databases // Copyright (C) 2024 lukeflo // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . ///// use color_eyre::eyre::Result; use dirs::{config_dir, home_dir}; use lexopt::prelude::*; use owo_colors::colors::css::LightGreen; use owo_colors::colors::*; use owo_colors::OwoColorize; use std::env; use std::path::PathBuf; use walkdir::WalkDir; use crate::app; // struct for CLIArgs #[derive(Debug, Default, Clone)] pub struct CLIArgs { pub helparg: bool, pub versionarg: bool, pub pos_args: Vec, pub cfg_path: Option, pub light_theme: bool, pub pdf_path: Option, } impl CLIArgs { pub fn parse_args() -> Result { let mut args = CLIArgs::default(); let mut parser = lexopt::Parser::from_env(); // Default config args.cfg_path = if config_dir().is_some() { Some(config_dir().unwrap().join("bibiman/bibiman.toml")) } else if home_dir().is_some() { Some(home_dir().unwrap().join(".config/bibiman/bibiman.toml")) } else { None }; while let Some(arg) = parser.next()? { match arg { Short('h') | Long("help") => args.helparg = true, Short('v') | Long("version") => args.versionarg = true, Short('c') | Long("config-file") => args.cfg_path = Some(parser.value()?.parse()?), Long("light-terminal") => args.light_theme = true, Long("pdf-path") => { args.pdf_path = Some(parser.value()?.parse()?); } // Value(pos_arg) => parse_files(&mut args, pos_arg), Value(pos_arg) => args.pos_args.push(pos_arg.into()), _ => return Err(arg.unexpected()), } } Ok(args) } } /// This function maps a vector containing paths to another vector containing paths. /// But it will walk all entries of the first vec which are directories /// and put only valid file paths with `.bib` ending to the resulting vec. pub fn parse_files(args: Vec) -> Vec { let mut files: Vec = Vec::new(); // If pos arg is file, just push it to path vec for i in args { // Expand tilde to /home/user let i = if i.starts_with("~") { app::expand_home(&i) } else { i }; if i.is_file() { files.push(i); // If pos arg is dir, walk dir and collect bibfiles } else if i.is_dir() { for file in WalkDir::new(i) { let f = file.unwrap().into_path(); if f.is_file() && f.extension().is_some() && f.extension().unwrap_or_default() == "bib" { files.push(f) } } } else { println!( "{}\n{}", "The positional argument is neither a valid file, nor a directory:" .red() .bold(), i.as_os_str().to_string_lossy().bright_red().italic() ); println!(); println!("{}", help_func()); std::process::exit(1) } } files } pub fn help_func() -> String { let help = format!( "\ {} {} USAGE: bibiman [FLAGS] [files/dirs] POSITIONAL ARGS: Path to .bib file Path to directory containing .bib files Both can be passed multiple times FLAGS: -h, --help Show this help and exit -v, --version Show the version and exit -c, --config-file= Path to config file used for current session. Takes precedence over standard config file. --light-terminal Enable color mode for light terminal background --pdf-path= Use PDF files named by citekey at the given path and its subdirs as value for the `file` field of the entry matching the citekey for the current session. Does not overwrite or change the original file. (might not work with citekeys containing special chars)", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION"), ); help } // pub fn version_func() -> String { // let version = format!( // "\ // {} {} // {} // {} // Target Triple: {}", // env!("CARGO_PKG_NAME"), // env!("CARGO_PKG_VERSION"), // env!("CARGO_PKG_AUTHORS"), // env!("CARGO_PKG_LICENSE"), // env!("TARGET") // ); // version // } pub fn version_func() -> String { let version: Vec = vec![ format!( "{} {}", env!("CARGO_PKG_NAME").fg::().bold(), env!("CARGO_PKG_VERSION").fg::() ), format!("{}", env!("CARGO_PKG_AUTHORS").bold()), format!("{}", env!("CARGO_PKG_LICENSE")), format!("\n"), format!( "{} {}", "Target Triple:".bold(), env!("TARGET").fg::() ), ]; let version = version.join("\n"); version }