use clap::ValueHint;
use clap_complete::Shell;
fn after_help() -> &'static str {
"See 'man 1 mdcat' for more information.
Two binaries ship: mdcat prints to stdout, mdless opens the
interactive pager. Report issues at
<https://github.com/pawelb0/mdcat-ng>."
}
fn long_version() -> &'static str {
concat!(
env!("CARGO_PKG_VERSION"),
"
Licensed under the Mozilla Public License, v. 2.0.
See <http://mozilla.org/MPL/2.0/>."
)
}
#[derive(Debug, clap::Parser)]
#[command(multicall = true)]
pub struct Args {
#[command(subcommand)]
pub command: Command,
}
#[derive(Debug, clap::Subcommand)]
pub enum Command {
#[command(version, about, after_help = after_help(), long_version = long_version())]
Mdcat {
#[command(flatten)]
args: CommonArgs,
#[arg(short, long, overrides_with = "no_pager")]
paginate: bool,
#[arg(short = 'P', long)]
no_pager: bool,
},
#[command(version, about, after_help = after_help(), long_version = long_version())]
Mdless {
#[command(flatten)]
args: CommonArgs,
#[arg(short = 'P', long, overrides_with_all = ["external_pager"])]
no_pager: bool,
#[arg(long)]
external_pager: bool,
#[arg(long = "search", value_name = "PATTERN")]
search: Option<String>,
#[arg(long)]
case_sensitive: bool,
#[arg(long)]
regex: bool,
#[arg(long, hide = true)]
render_only: bool,
#[arg(short = 'n', long = "line-numbers")]
line_numbers: bool,
},
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum PagingMode {
None,
ExternalLess,
Interactive,
}
impl Command {
pub fn paging_mode(&self) -> PagingMode {
match *self {
Command::Mdcat { paginate: true, .. } => PagingMode::ExternalLess,
Command::Mdcat { .. } => PagingMode::None,
Command::Mdless { no_pager: true, .. }
| Command::Mdless {
render_only: true, ..
} => PagingMode::None,
Command::Mdless {
external_pager: true,
..
} => PagingMode::ExternalLess,
Command::Mdless { .. } => PagingMode::Interactive,
}
}
}
impl PagingMode {
pub fn is_paginated(self) -> bool {
!matches!(self, PagingMode::None)
}
}
impl std::ops::Deref for Command {
type Target = CommonArgs;
fn deref(&self) -> &Self::Target {
match self {
Command::Mdcat { args, .. } => args,
Command::Mdless { args, .. } => args,
}
}
}
#[derive(Debug, clap::Args)]
pub struct CommonArgs {
#[arg(default_value="-", value_hint = ValueHint::FilePath)]
pub filenames: Vec<String>,
#[arg(short = 'c', long, aliases=["nocolour", "no-color", "nocolor"])]
pub no_colour: bool,
#[arg(long)]
pub columns: Option<u16>,
#[arg(short = 'l', long = "local", hide = true)]
pub local_only: bool,
#[arg(long = "remote-images")]
pub remote_images: bool,
#[arg(long = "fail")]
pub fail_fast: bool,
#[arg(long = "detect-terminal")]
pub detect_and_exit: bool,
#[arg(long = "ansi", conflicts_with = "no_colour")]
pub ansi_only: bool,
#[arg(long = "no-probe-terminal")]
pub no_probe_terminal: bool,
#[arg(long = "probe-timeout-ms", default_value_t = 50)]
pub probe_timeout_ms: u64,
#[arg(long)]
pub completions: Option<Shell>,
#[arg(long = "wrap-code")]
pub wrap_code: bool,
}
#[derive(Debug, Copy, Clone)]
pub enum ResourceAccess {
LocalOnly,
Remote,
}
impl CommonArgs {
pub fn resource_access(&self) -> ResourceAccess {
if self.remote_images && !self.local_only {
ResourceAccess::Remote
} else {
ResourceAccess::LocalOnly
}
}
}
#[cfg(test)]
mod tests {
use super::Args;
use clap::CommandFactory;
#[test]
fn verify_app() {
Args::command().debug_assert();
}
}