diff --git a/src/console.rs b/src/console.rs index 8c73453..fd0bf7c 100644 --- a/src/console.rs +++ b/src/console.rs @@ -11,6 +11,7 @@ use crossterm::{ExecutableCommand, cursor::MoveToPreviousLine}; pub const ERROR: Style = AnsiColor::Red.on_default().effects(Effects::BOLD); pub const GOOD: Style = AnsiColor::Green.on_default().effects(Effects::BOLD); +pub const NOTE: Style = AnsiColor::Cyan.on_default().effects(Effects::BOLD); #[derive(Copy, Clone, Debug, PartialEq, Eq, ValueEnum)] pub enum Color { @@ -76,11 +77,21 @@ macro_rules! error { ); } -macro_rules! info { - ($status:expr, $($arg:tt)+) => ( +macro_rules! note { + ($($arg:tt)+) => ( + crate::console::console().print( + " tip:", + &crate::console::NOTE, + format_args!($($arg)+), + ) + ); +} + +macro_rules! status { + ($status:expr, $style:expr, $($arg:tt)+) => ( crate::console::console().print_right( $status, - &crate::console::GOOD, + $style, format_args!($($arg)+), ) ); @@ -96,10 +107,10 @@ macro_rules! fail { } macro_rules! update { - ($status:expr, $($arg:tt)+) => ( + ($status:expr, $style:expr, $($arg:tt)+) => ( crate::console::console().update_right( $status, - &crate::console::GOOD, + $style, format_args!($($arg)+), ) ); @@ -107,5 +118,6 @@ macro_rules! update { pub(crate) use error; pub(crate) use fail; -pub(crate) use info; +pub(crate) use note; +pub(crate) use status; pub(crate) use update; diff --git a/src/install.rs b/src/install.rs index 966667d..ced745d 100644 --- a/src/install.rs +++ b/src/install.rs @@ -4,16 +4,20 @@ use clap::Args; use git2::Repository; use tempfile::tempdir; -use crate::console::{error, fail, info, update}; +use crate::console::{GOOD, NOTE, error, fail, note, status, update}; use crate::settings::Settings; mod cc; mod languages; -use languages::{InstallInfo, get_install_info}; +use languages::{InstallInfo, get_install_info, is_installed}; #[derive(Debug, Args)] pub struct Install { + /// reinstall already present parsers + #[arg(short, long)] + force: bool, + languages: Vec, } @@ -32,15 +36,22 @@ impl Install { // have to use a canonical path bc compiler runs elsewhere let parser_dir = parser_dir.canonicalize()?; - let mut languages = self.languages; + let Self { + mut languages, + force, + } = self; languages.sort(); languages.dedup(); let mut errors = 0; + let mut skips = 0; for language in &languages { - if let Some(info) = get_install_info(language) { + if !force && is_installed(language, &parser_dir) { + status!("Skipping", &NOTE, "{language} (already installed)"); + skips += 1; + } else if let Some(info) = get_install_info(language) { if let Err(Error::Fatal(_)) = install_with_status( language, info, @@ -58,6 +69,10 @@ impl Install { } } + if skips > 0 { + note!("try '{NOTE}--force{NOTE:#}' to reinstall parsers"); + } + Ok(if errors > 0 { ExitCode::FAILURE } else { @@ -73,13 +88,13 @@ fn install_with_status( src_dir: &Path, compiler: Option<&str>, ) -> Result { - info!("Installing", "{language}"); + status!("Installing", &GOOD, "{language}"); let res = install(language, install_info, parser_dir, src_dir, compiler); match &res { Err(e) => fail!("{e}"), - Ok(revision) => update!("Installed", "{language} {revision:.7}"), + Ok(revision) => update!("Installed", &GOOD, "{language} {revision:.7}"), } res diff --git a/src/install/languages.rs b/src/install/languages.rs index f68d009..a36b963 100644 --- a/src/install/languages.rs +++ b/src/install/languages.rs @@ -1,3 +1,5 @@ +use std::{env::consts::DLL_EXTENSION, path::Path}; + use phf::phf_map; pub(super) type Revision = git2::Oid; @@ -34,3 +36,10 @@ static LANGUAGES: phf::Map<&'static str, InstallInfo> = phf_map! { pub fn get_install_info(language: &str) -> Option<&InstallInfo> { LANGUAGES.get(language) } + +pub fn is_installed(language: &str, parser_dir: &Path) -> bool { + parser_dir + .join(language) + .with_extension(DLL_EXTENSION) + .exists() +}