1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
use super::{Formatter, Logger, OsStr}; use std::fmt::{Display, Write}; pub use ansi_term::{Color, Style}; pub struct SyntaxHighLight<Prompt: Display> { prompt: Prompt, program: Style, argument: Style, short_flag: Style, long_flag: Style, } impl SyntaxHighLight<String> { const DEFAULT_PROMPT: &'static str = "$"; pub fn default_colorless() -> Self { Self { prompt: Self::DEFAULT_PROMPT.to_owned(), program: Style::default(), argument: Style::default(), short_flag: Style::default(), long_flag: Style::default(), } } pub fn default_color() -> Self { Self { prompt: Style::default() .dimmed() .paint(Self::DEFAULT_PROMPT) .to_string(), program: Color::Green.into(), argument: Style::default(), short_flag: Color::Red.into(), long_flag: Color::Red.into(), } } } impl<Prompt: Display> Formatter for SyntaxHighLight<Prompt> { fn fmt(&self, program: impl AsRef<OsStr>, arguments: &[impl AsRef<OsStr>]) -> String { use pipe_trait::*; use shell_escape::unix::escape; let mut result = String::new(); let prompt = format!("{}", self.prompt); if !prompt.is_empty() { write!(result, "{} ", prompt).expect("write prompt"); } write!( result, "{}", program .as_ref() .to_string_lossy() .pipe(escape) .pipe(|x| self.program.paint(x)) ) .expect("write program name"); for argument in arguments { let argument = argument.as_ref().to_string_lossy(); let paint = |text: &str, style: &Style| { text.to_owned() .pipe(std::borrow::Cow::from) .pipe(escape) .pipe(|x| style.paint(x)) }; let argument = if argument.starts_with("--") { let segments: Vec<_> = argument.splitn(2, '=').collect(); match segments[..] { [_] => paint(&argument, &self.long_flag), [flag, val] => Style::default().paint(format!( "{flag}{eq}{val}", flag = paint(flag, &self.long_flag), eq = self.argument.paint("="), val = paint(val, &self.argument), )), _ => unreachable!(), } } else if argument.starts_with('-') { paint(&argument, &self.short_flag) } else { paint(&argument, &self.argument) }; write!(result, " {}", argument).expect("write argument"); } result } } impl<Prompt: Display> Logger for SyntaxHighLight<Prompt> { fn log(&self, program: impl AsRef<OsStr>, arguments: &[impl AsRef<OsStr>]) { eprintln!("{}", self.fmt(program, arguments)) } }