mod plain;
mod rich;
use std::env;
use std::io;
use crate::args;
use crate::doc;
use crate::source;
use crate::viewer::{self, utils};
#[derive(Clone, Debug)]
pub struct TextViewer {
mode: TextMode,
}
#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub enum TextMode {
Plain,
Rich,
}
impl TextViewer {
pub fn new(mode: TextMode) -> Self {
TextViewer { mode }
}
fn exec<F>(&self, args: args::ViewerArgs, op: F) -> anyhow::Result<()>
where
F: FnOnce(Box<dyn utils::ManRenderer<Error = io::Error>>) -> io::Result<()>,
{
let viewer: Box<dyn utils::ManRenderer<Error = io::Error>> = match self.mode {
TextMode::Plain => Box::new(plain::PlainTextRenderer::new(&args)),
TextMode::Rich => Box::new(rich::RichTextRenderer::new(&args)?),
};
spawn_pager(&args);
op(viewer).or_else(ignore_pipe_error).map_err(Into::into)
}
}
impl viewer::Viewer for TextViewer {
fn open(
&self,
_sources: source::Sources,
args: args::ViewerArgs,
doc: &doc::Doc,
) -> anyhow::Result<()> {
self.exec(args, |mut viewer| viewer.render_doc(doc))
}
fn open_examples(
&self,
_sources: source::Sources,
args: args::ViewerArgs,
doc: &doc::Doc,
examples: Vec<doc::Example>,
) -> anyhow::Result<()> {
self.exec(args, |mut viewer| viewer.render_examples(doc, &examples))
}
}
pub fn spawn_pager(args: &args::ViewerArgs) {
if env::var_os("LESS").is_none() {
env::set_var("LESS", "cR");
}
let mut pager = if let Some(pager) = &args.pager {
pager::Pager::with_pager(pager)
} else {
pager::Pager::with_default_pager("less")
};
pager.setup();
}
fn ignore_pipe_error(error: io::Error) -> io::Result<()> {
if error.kind() == io::ErrorKind::BrokenPipe {
Ok(())
} else {
Err(error)
}
}
pub fn list_link(url: &str) -> bool {
(url.starts_with("http") || url.starts_with("https"))
&& !url.starts_with("http://play.rust-lang.org")
&& !url.starts_with("https://play.rust-lang.org")
}
pub fn format_title(line_length: usize, left: &str, middle: &str, right: &str) -> String {
let mut s = String::with_capacity(line_length);
s.push_str(left);
let mut idx = left.len();
let middle_idx = line_length / 2;
let offset = middle.len() / 2;
let spacing = if idx + offset >= middle_idx {
1
} else {
middle_idx - offset - idx
};
s.push_str(&" ".repeat(spacing));
s.push_str(middle);
idx += middle.len() + spacing;
let end_idx = line_length;
let offset = right.len();
let spacing = if idx + offset >= end_idx {
1
} else {
end_idx - offset - idx
};
s.push_str(&" ".repeat(spacing));
s.push_str(right);
s
}