use std::{
cell::LazyCell,
io::{self, IsTerminal, Write},
process::{self, ExitCode},
};
use anyhow::Result;
use clap::Parser;
use log::error;
use simplelog::{ColorChoice, Config, TermLogger, TerminalMode};
use ecformat::cli::{Cli, Commands, LibCommands, LicenseArgs, MarkdownFormat};
use termimad::{
Area, MadSkin, MadView,
crossterm::{
event::{self, Event, KeyCode, KeyEvent},
queue,
terminal::{self, Clear, ClearType, EnterAlternateScreen, LeaveAlternateScreen},
},
};
fn main() -> process::ExitCode {
let cli = Cli::parse();
let result = match cli.command {
Commands::Lib(lib_command) => run_lib_command(lib_command),
Commands::License(args) => run_license_command(args),
};
if let Err(e) = result.as_ref() {
error!("{}", e);
ExitCode::FAILURE
} else {
ExitCode::SUCCESS
}
}
fn run_lib_command(lib_command: LibCommands) -> Result<()> {
TermLogger::init(
lib_command.get_args().verbosity().into(),
Config::default(),
TerminalMode::Mixed,
ColorChoice::Auto,
)
.expect("There should not be a logger set already");
ecformat::execute(&lib_command)
}
fn run_license_command(args: LicenseArgs) -> Result<()> {
let about = get_license_information();
let format = match args.format {
MarkdownFormat::Auto => {
if io::stdout().is_terminal() {
MarkdownFormat::Paginate
} else {
MarkdownFormat::Plain
}
}
other => other,
};
match format {
MarkdownFormat::Auto => unreachable!("Auto is converted in the match before"),
MarkdownFormat::Paginate => {
let mut out = io::stdout();
queue!(out, EnterAlternateScreen)?;
terminal::enable_raw_mode()?;
let mut view =
MadView::from(String::from(about), Area::full_screen(), MadSkin::default());
let line_count = LazyCell::new(|| about.lines().count() as i32);
loop {
view.write_on(&mut out)?;
out.flush()?;
match event::read() {
Ok(Event::Key(KeyEvent { code, .. })) => match code {
KeyCode::Up | KeyCode::PageUp => view.try_scroll_lines(-1),
KeyCode::Down | KeyCode::PageDown | KeyCode::Enter => {
view.try_scroll_lines(1)
}
KeyCode::Home => view.try_scroll_lines(-*line_count),
KeyCode::End => {
view.try_scroll_lines(*line_count);
}
_ => break,
},
Ok(Event::Resize(..)) => {
queue!(out, Clear(ClearType::All))?;
view.resize(&Area::full_screen());
}
_ => {}
}
}
terminal::disable_raw_mode()?;
queue!(out, LeaveAlternateScreen)?;
out.flush()?;
}
MarkdownFormat::Pretty => termimad::print_text(about),
MarkdownFormat::Plain => println!("{about}"),
}
Ok(())
}
fn get_license_information() -> &'static str {
include_str!(concat!(env!("OUT_DIR"), "/about.md"))
}
#[cfg(test)]
mod license_tests;