ecformat 0.1.1

command line tool to keep files correct in respect of your EditorConfig
Documentation
// SPDX-FileCopyrightText: Contributors to ecformat project <https://codeberg.org/BaumiCoder/ecformat>
//
// SPDX-License-Identifier: BlueOak-1.0.0

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 => {
            // See also example for scrollable view of `termimad`:
            // https://github.com/Canop/termimad/blob/main/examples/scrollable/main.rs
            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 /* Pos 1 */ => 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;