Merge pull request #6 from Hiers/master
Print to less if output is bigger than terminal window height.
This commit is contained in:
commit
9b2e51fee3
3 changed files with 188 additions and 18 deletions
75
Cargo.lock
generated
75
Cargo.lock
generated
|
@ -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"
|
||||
|
@ -109,10 +111,13 @@ version = "0.1.4"
|
|||
dependencies = [
|
||||
"ansi_term",
|
||||
"argparse",
|
||||
"atty",
|
||||
"colored",
|
||||
"libc",
|
||||
"serde_json",
|
||||
"ureq",
|
||||
"webbrowser",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -132,9 +137,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"
|
||||
|
@ -455,3 +460,69 @@ name = "winapi-x86_64-pc-windows-gnu"
|
|||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.45.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"
|
||||
|
|
|
@ -8,12 +8,17 @@ repository = "https://github.com/JojiiOfficial/jisho-cli"
|
|||
license = "GPL-3.0"
|
||||
edition = "2018"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
windows-sys = { version = "0.45.0", features = ["Win32_Foundation", "Win32_System_Console"] }
|
||||
|
||||
[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"
|
||||
|
||||
[features]
|
||||
|
|
126
src/main.rs
126
src/main.rs
|
@ -1,11 +1,14 @@
|
|||
use std::{
|
||||
io::{stdin, stdout, Write},
|
||||
process::{Command, Stdio},
|
||||
thread::{self, JoinHandle},
|
||||
env,
|
||||
};
|
||||
|
||||
use argparse::{ArgumentParser, List, Print, Store, StoreTrue};
|
||||
use colored::*;
|
||||
use serde_json::Value;
|
||||
use atty::Stream;
|
||||
|
||||
macro_rules! JISHO_URL {
|
||||
() => {
|
||||
|
@ -24,7 +27,7 @@ struct Options {
|
|||
impl Default for Options {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
limit: 4,
|
||||
limit: 0,
|
||||
query: String::default(),
|
||||
kanji: false,
|
||||
interactive: false,
|
||||
|
@ -33,6 +36,14 @@ impl Default for Options {
|
|||
}
|
||||
|
||||
fn main() -> Result<(), ureq::Error> {
|
||||
let term_size;
|
||||
|
||||
if atty::is(Stream::Stdout) {
|
||||
term_size = terminal_size().unwrap_or(0);
|
||||
} else {
|
||||
term_size = 0;
|
||||
}
|
||||
|
||||
let options = parse_args();
|
||||
|
||||
let mut query = {
|
||||
|
@ -50,6 +61,9 @@ fn main() -> Result<(), ureq::Error> {
|
|||
};
|
||||
|
||||
loop {
|
||||
let mut lines_output = 0;
|
||||
let mut output = String::new();
|
||||
|
||||
if options.kanji {
|
||||
// Open kanji page here
|
||||
let threads = query
|
||||
|
@ -91,15 +105,30 @@ fn main() -> Result<(), ureq::Error> {
|
|||
|
||||
// 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();
|
||||
if lines_output > 0 {
|
||||
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");
|
||||
pipe_to_less(output);
|
||||
} else {
|
||||
print!("{}", output);
|
||||
}
|
||||
|
||||
if !options.interactive {
|
||||
|
@ -119,7 +148,7 @@ 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<usize> {
|
||||
let japanese = value_to_arr(value.get("japanese")?).get(0)?.to_owned();
|
||||
|
||||
let reading = japanese
|
||||
|
@ -129,20 +158,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));
|
||||
let mut 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 +335,73 @@ fn parse_args() -> Options {
|
|||
ap.parse_args_or_exit();
|
||||
}
|
||||
|
||||
if options.limit == 0 {
|
||||
options.limit = 1;
|
||||
}
|
||||
|
||||
options.query = query_vec.join(" ");
|
||||
options
|
||||
}
|
||||
|
||||
fn pipe_to_less(output: String) {
|
||||
|
||||
let command = Command::new("less")
|
||||
.arg("-R")
|
||||
.stdin(Stdio::piped())
|
||||
.spawn();
|
||||
|
||||
match command {
|
||||
Ok(mut process) => {
|
||||
if let Err(e) = process.stdin.as_ref().unwrap().write_all(output.as_bytes()) {
|
||||
panic!("couldn't pipe to less: {}", e);
|
||||
}
|
||||
|
||||
// We don't care about the return value, only whether wait failed or not
|
||||
if process.wait().is_err() {
|
||||
panic!("wait() was called on non-existent child process\
|
||||
- this should not be possible");
|
||||
}
|
||||
}
|
||||
|
||||
// less not found in PATH; print normally
|
||||
Err(_e) => print!("{}", output)
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn terminal_size() -> Result<usize, i16> {
|
||||
use libc::{c_ushort, ioctl, STDOUT_FILENO, TIOCGWINSZ};
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn terminal_size() -> Result<usize, i16> {
|
||||
use windows_sys::Win32::System::Console::*;
|
||||
|
||||
unsafe {
|
||||
let handle = GetStdHandle(STD_OUTPUT_HANDLE) as windows_sys::Win32::Foundation::HANDLE;
|
||||
|
||||
// Unlike the linux function, rust will complain if only part of the struct is sent
|
||||
let mut window = CONSOLE_SCREEN_BUFFER_INFO {
|
||||
dwSize: COORD { X: 0, Y: 0},
|
||||
dwCursorPosition: COORD { X: 0, Y: 0},
|
||||
wAttributes: 0,
|
||||
dwMaximumWindowSize: COORD {X: 0, Y: 0},
|
||||
srWindow: SMALL_RECT {
|
||||
Top: 0,
|
||||
Bottom: 0,
|
||||
Left: 0,
|
||||
Right: 0
|
||||
}
|
||||
};
|
||||
if GetConsoleScreenBufferInfo(handle, &mut window) == 0 {
|
||||
Err(0)
|
||||
} else {
|
||||
Ok((window.srWindow.Bottom - window.srWindow.Top) as usize)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue