use std::path::PathBuf;
use clap::{Parser, ValueEnum};
const KEYS: &str = "\
Keys:
j/k, Up/Down move the cursor
Space/b page down / up
]] / [[ next / previous heading
/ n N search, next / previous match
x toggle the task under the cursor (saved to the file)
f tag visible links; type a tag to open it, uppercase to copy the URL
Tab / Enter select / open a link
Backspace back to the previous file
o outline
y copy the code block
e edit in $VISUAL or $EDITOR
q quit
Configuration: $XDG_CONFIG_HOME/marustdown/config.toml (usually ~/.config/marustdown/config.toml).
Reference: https://github.com/beshralghalil/marustdown/blob/main/docs/configuration.md";
#[derive(Parser)]
#[command(
name = "mar",
version,
long_about = "Render GitHub-flavored markdown in a full-screen pager, with syntax-highlighted \
code, task lists you can check off, keyboard link following and an outline. \
When stdout isn't a terminal, the rendered document is printed instead.",
after_long_help = KEYS
)]
pub struct Args {
pub file: Option<PathBuf>,
#[arg(long)]
pub cat: bool,
#[arg(long, value_enum, value_name = "WHEN", default_value_t = ColorMode::Auto)]
pub color: ColorMode,
#[arg(long, value_name = "N")]
pub width: Option<usize>,
#[arg(long, value_name = "NAME")]
pub theme: Option<String>,
#[arg(long)]
pub no_color: bool,
#[arg(long)]
pub no_icons: bool,
#[arg(long, value_name = "PATH")]
pub config: Option<PathBuf>,
}
#[derive(Clone, Copy, PartialEq, Eq, ValueEnum)]
pub enum ColorMode {
Auto,
Always,
Never,
}
#[cfg(test)]
mod tests {
use std::fs;
use std::path::Path;
use clap::CommandFactory;
use clap_complete::{Shell, generate};
use super::*;
fn check(path: &str, contents: &[u8]) {
let path = Path::new(env!("CARGO_MANIFEST_DIR")).join(path);
if std::env::var_os("UPDATE_GENERATED").is_some() {
fs::create_dir_all(path.parent().unwrap()).unwrap();
fs::write(&path, contents).unwrap();
return;
}
let current = fs::read(&path).unwrap_or_default();
assert!(
current == contents,
"{} is out of date; run `UPDATE_GENERATED=1 cargo test`",
path.display()
);
}
#[test]
fn man_page_and_completions_are_current() {
let mut man = Vec::new();
clap_mangen::Man::new(Args::command().version(None))
.source("marustdown")
.render(&mut man)
.unwrap();
check("assets/man/mar.1", &man);
for (shell, file) in [
(Shell::Bash, "mar.bash"),
(Shell::Zsh, "_mar"),
(Shell::Fish, "mar.fish"),
] {
let mut out = Vec::new();
generate(shell, &mut Args::command(), "mar", &mut out);
check(&format!("assets/completions/{file}"), &out);
}
}
#[test]
fn cli_is_valid() {
Args::command().debug_assert();
}
}