diff --git a/Cargo.lock b/Cargo.lock index f1483f2..980e034 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "ansi_term" version = "0.12.1" @@ -67,6 +69,27 @@ dependencies = [ "winapi", ] +[[package]] +name = "errno" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" +dependencies = [ + "errno-dragonfly", + "libc", + "winapi", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "form_urlencoded" version = "1.0.1" @@ -109,7 +132,10 @@ version = "0.1.4" dependencies = [ "ansi_term", "argparse", + "atty", "colored", + "libc", + "pager", "serde_json", "ureq", "webbrowser", @@ -132,9 +158,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.93" +version = "0.2.139" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9385f66bf6105b241aa65a61cb923ef20efc665cb9f9bb50ac2f0c4b7f378d41" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" [[package]] name = "log" @@ -157,6 +183,16 @@ version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3" +[[package]] +name = "pager" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2599211a5c97fbbb1061d3dc751fa15f404927e4846e07c643287d6d1f462880" +dependencies = [ + "errno", + "libc", +] + [[package]] name = "percent-encoding" version = "2.1.0" diff --git a/Cargo.toml b/Cargo.toml index fcd2d24..e430d6a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,10 +10,13 @@ edition = "2018" [dependencies] ureq = { version = "2.1.0", features = ["json"] } +libc = "0.2.139" serde_json = "1.0.64" ansi_term = "0.12.1" colored = "2.0.0" argparse = "0.2.2" webbrowser = "0.5.5" +atty = "0.2" +pager = "0.16.1" [features] diff --git a/src/main.rs b/src/main.rs index 3b8ec9d..504e560 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,11 +1,15 @@ use std::{ io::{stdin, stdout, Write}, thread::{self, JoinHandle}, + env, }; +use libc::{c_ushort, ioctl, STDOUT_FILENO, TIOCGWINSZ}; use argparse::{ArgumentParser, List, Print, Store, StoreTrue}; use colored::*; use serde_json::Value; +use atty::Stream; +use pager::Pager; macro_rules! JISHO_URL { () => { @@ -24,7 +28,7 @@ struct Options { impl Default for Options { fn default() -> Self { Self { - limit: 4, + limit: 0, query: String::default(), kanji: false, interactive: false, @@ -33,6 +37,18 @@ impl Default for Options { } fn main() -> Result<(), ureq::Error> { + let term_size; + + if atty::is(Stream::Stdout) { + match terminal_size() { + Ok(s) => term_size = s, + Err(_e) => term_size = 0 + } + } else { + term_size = 0; + } + + let mut lines_output = 0; let options = parse_args(); let mut query = { @@ -89,17 +105,30 @@ fn main() -> Result<(), ureq::Error> { println!(); } + let mut output = String::new(); // Iterate over meanings and print them for (i, entry) in body.iter().enumerate() { - if i >= options.limit { + if i >= options.limit && options.limit != 0 { break; } - - if print_item(&query, entry).is_some() && i + 2 <= options.limit { - println!(); + match print_item(&query, entry, &mut output) { + Some(r) => lines_output += r, + None => continue, } + + output.push('\n'); + lines_output += 1; } - println!(); + output.pop(); + lines_output -= 1; + + if lines_output >= term_size - 1 && term_size != 0{ + /* output is a different process that is not a tty (i.e. less), but we want to keep colour */ + env::set_var("CLICOLOR_FORCE", "1"); + Pager::with_pager("less -R").setup(); + } + print!("{}", output); + } if !options.interactive { @@ -119,7 +148,8 @@ fn main() -> Result<(), ureq::Error> { Ok(()) } -fn print_item(query: &str, value: &Value) -> Option<()> { +fn print_item(query: &str, value: &Value, output: &mut String) -> Option { + let mut aux; let japanese = value_to_arr(value.get("japanese")?).get(0)?.to_owned(); let reading = japanese @@ -129,20 +159,22 @@ fn print_item(query: &str, value: &Value) -> Option<()> { let word = value_to_str(japanese.get("word").unwrap_or(japanese.get("reading")?)); - println!("{}[{}] {}", word, reading, format_result_tags(value)); + aux = format!("{}[{}] {}\n", word, reading, format_result_tags(value)); + *output += &aux; // Print senses - let senses = value.get("senses")?; - for (i, sense) in value_to_arr(senses).iter().enumerate() { + let senses = value_to_arr(value.get("senses")?); + for (i, sense) in senses.iter().enumerate() { let sense_str = format_sense(&sense, i); if sense_str.is_empty() { continue; } - println!(" {}", sense_str); + aux = format!(" {}\n", sense_str); + *output += &aux; } - Some(()) + Some(senses.iter().count() + 1) } fn format_sense(value: &Value, index: usize) -> String { @@ -304,10 +336,17 @@ fn parse_args() -> Options { ap.parse_args_or_exit(); } - if options.limit == 0 { - options.limit = 1; - } - options.query = query_vec.join(" "); options } + +fn terminal_size() -> Result { + unsafe { + let mut size: c_ushort = 0; + if ioctl(STDOUT_FILENO, TIOCGWINSZ.into(), &mut size as *mut _) != 0 { + Err(-1) + } else { + Ok(size as usize) + } + } +}