Skip to content

Commit

Permalink
new: pager support
Browse files Browse the repository at this point in the history
  • Loading branch information
pamburus committed Aug 6, 2020
1 parent e60db9e commit 220b4f9
Show file tree
Hide file tree
Showing 6 changed files with 161 additions and 16 deletions.
53 changes: 53 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@ num_cpus = "1.0"
structopt = "0.3"
serde = { version = "1.0", features = ["derive"] }
serde_json = { version = "1.0", features = ["raw_value"] }
shellwords = "1.1"
8 changes: 4 additions & 4 deletions src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ use std::path::PathBuf;
use ansi_term::Colour;
use flate2::bufread::GzDecoder;

pub type Stream = Box<dyn Read + Send + Sync>;
pub type InputStream = Box<dyn Read + Send + Sync>;

pub struct Input {
pub name: String,
pub stream: Stream,
pub stream: InputStream,
}

pub struct ConcatReader<I> {
Expand All @@ -23,7 +23,7 @@ pub fn open(path: &PathBuf) -> Result<Input> {
let f = File::open(path)
.map_err(|e| Error::new(e.kind(), format!("failed to open {}: {}", name, e)))?;

let stream: Stream = match path.extension().map(|x| x.to_str()) {
let stream: InputStream = match path.extension().map(|x| x.to_str()) {
Some(Some("gz")) => Box::new(GzDecoder::new(BufReader::new(f))),
_ => Box::new(f),
};
Expand All @@ -32,7 +32,7 @@ pub fn open(path: &PathBuf) -> Result<Input> {
}

impl Input {
pub fn new(name: String, stream: Stream) -> Self {
pub fn new(name: String, stream: InputStream) -> Self {
Self { name, stream }
}
}
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ mod eseq;
mod formatting;
pub mod input;
mod model;
pub mod output;
mod scanning;
pub mod theme;
pub mod types;
Expand Down
57 changes: 45 additions & 12 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use std::env;
use std::io::Read;
use std::path::PathBuf;
use std::process;
use std::sync::Arc;
Expand All @@ -10,7 +9,8 @@ use structopt::clap::arg_enum;
use structopt::StructOpt;

use hl::error::*;
use hl::input::{open, ConcatReader, Input};
use hl::input::{open, ConcatReader, Input, InputStream};
use hl::output::{OutputStream, Pager};

/// JSON log converter to human readable representation.
#[derive(StructOpt)]
Expand All @@ -19,34 +19,39 @@ struct Opt {
/// Color output options, one of { auto, always, never }
#[structopt(long, default_value = "auto")]
color: Color,

//
/// Handful alias for --color=always, overrides --color option
#[structopt(short)]
color_always: bool,

//
/// Output paging options, one of { auto, always, never }
#[structopt(long, default_value = "auto")]
paging: Paging,
//
/// Color theme, one of { auto, dark, dark24, light }
#[structopt(long, default_value = "auto")]
theme: Theme,
//
/// Do not unescape string fields.
#[structopt(short, long)]
raw_fields: bool,

//
/// Buffer size, kibibytes.
#[structopt(long, default_value = "2048")]
buffer_size: usize,

//
/// Number of processing threads. Zero means automatic selection.
#[structopt(long, default_value = "0")]
concurrency: usize,

//
/// Filtering by field values in form <key>=<value> or <key>~=<value>.
#[structopt(short, long)]
filter: Vec<String>,

//
/// Filtering by level, valid values: ['d', 'i', 'w', 'e'].
#[structopt(short, long, default_value = "d")]
level: char,

//
/// Files to process
#[structopt(name = "FILE", parse(from_os_str))]
files: Vec<PathBuf>,
Expand All @@ -71,6 +76,15 @@ arg_enum! {
}
}

arg_enum! {
#[derive(Debug)]
enum Paging {
Auto,
Always,
Never,
}
}

fn run() -> Result<()> {
let opt = Opt::from_args();

Expand Down Expand Up @@ -151,15 +165,34 @@ fn run() -> Result<()> {
}
})
.collect::<std::io::Result<Vec<_>>>()?;
let mut input: Box<dyn Read + Send + Sync> = if inputs.len() == 0 {
let mut input: InputStream = if inputs.len() == 0 {
Box::new(std::io::stdin())
} else {
Box::new(ConcatReader::new(inputs.into_iter().map(|x| Ok(x))))
};
let mut stdout = std::io::stdout();
let paging = match opt.paging {
Paging::Auto => {
if stdout_isatty() {
true
} else {
false
}
}
Paging::Always => true,
Paging::Never => false,
};
let mut output: OutputStream = if paging {
if let Ok(pager) = Pager::new() {
Box::new(pager)
} else {
Box::new(std::io::stdout())
}
} else {
Box::new(std::io::stdout())
};

// Run app.
match app.run(input.as_mut(), &mut stdout) {
match app.run(input.as_mut(), output.as_mut()) {
Ok(()) => Ok(()),
Err(Error(ErrorKind::Io(ref e), _)) if e.kind() == std::io::ErrorKind::BrokenPipe => Ok(()),
Err(err) => Err(err),
Expand Down
57 changes: 57 additions & 0 deletions src/output.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
use std::env;
use std::ffi::OsString;
use std::io::Write;
use std::path::PathBuf;
use std::process::{Child, Command, Stdio};

use crate::error::*;

pub type OutputStream = Box<dyn Write + Send + Sync>;

pub struct Pager {
process: Child,
}

impl Pager {
pub fn new() -> Result<Self> {
let pager = match env::var("PAGER") {
Ok(pager) => pager,
_ => "less".into(),
};

let pager = shellwords::split(&pager).unwrap_or(vec![pager]);
let (pager, args) = match pager.split_first() {
Some((pager, args)) => (pager, args),
None => (&pager[0], &pager[0..0]),
};
let pager = PathBuf::from(pager);
let mut command = Command::new(&pager);
for arg in args {
command.arg(arg);
}
if pager.file_stem() == Some(&OsString::from("less")) {
command.arg("-R");
command.env("LESSCHARSET", "UTF-8");
}

let process = command.stdin(Stdio::piped()).spawn()?;

Ok(Self { process })
}
}

impl Drop for Pager {
fn drop(&mut self) {
self.process.wait().ok();
}
}

impl Write for Pager {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.process.stdin.as_mut().unwrap().write(buf)
}

fn flush(&mut self) -> std::io::Result<()> {
self.process.stdin.as_mut().unwrap().flush()
}
}

0 comments on commit 220b4f9

Please sign in to comment.