From 3146e552d199a4db223773e0b80ce8cd510df78a Mon Sep 17 00:00:00 2001 From: Cengiz Can Date: Tue, 30 May 2017 00:13:09 +0300 Subject: [PATCH 1/7] use PAGER to view --explain output #32665 --- src/librustc_driver/lib.rs | 46 +++++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index f2aacbc629fad..f408316c9f923 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -84,10 +84,11 @@ use std::cmp::max; use std::cmp::Ordering::Equal; use std::default::Default; use std::env; +use std::ffi::OsString; use std::io::{self, Read, Write}; use std::iter::repeat; use std::path::PathBuf; -use std::process; +use std::process::{self, Command, Stdio}; use std::rc::Rc; use std::str; use std::sync::{Arc, Mutex}; @@ -354,6 +355,8 @@ fn handle_explain(code: &str, match descriptions.find_description(&normalised) { Some(ref description) => { let mut is_in_code_block = false; + let mut text = String::new(); + // Slice off the leading newline and print. for line in description[1..].lines() { let indent_level = line.find(|c: char| !c.is_whitespace()) @@ -361,13 +364,17 @@ fn handle_explain(code: &str, let dedented_line = &line[indent_level..]; if dedented_line.starts_with("```") { is_in_code_block = !is_in_code_block; - println!("{}", &line[..(indent_level+3)]); + text.push_str(&line[..(indent_level+3)]); + text.push('\n'); } else if is_in_code_block && dedented_line.starts_with("# ") { continue; } else { - println!("{}", line); + text.push_str(line); + text.push('\n'); } } + + show_content_with_pager(&text); } None => { early_error(output, &format!("no extended information for {}", code)); @@ -375,6 +382,39 @@ fn handle_explain(code: &str, } } +fn show_content_with_pager(content: &String) { + let pager_name = env::var_os("PAGER").unwrap_or(if cfg!(windows) { + OsString::from("more.com") + } else { + OsString::from("less") + }); + + let mut fallback_to_println = false; + + match Command::new(pager_name).stdin(Stdio::piped()).spawn() { + Ok(mut pager) => { + if let Some(mut pipe) = pager.stdin.as_mut() { + if pipe.write_all(content.as_bytes()).is_err() { + fallback_to_println = true; + } + } + + if pager.wait().is_err() { + fallback_to_println = true; + } + } + Err(_) => { + fallback_to_println = true; + } + } + + // If pager fails for whatever reason, we should still print the content + // to standard output + if fallback_to_println { + println!("{}", content); + } +} + impl<'a> CompilerCalls<'a> for RustcDefaultCalls { fn early_callback(&mut self, matches: &getopts::Matches, From 1beeb5a277ee18a8817b85d31595c7980fdf3627 Mon Sep 17 00:00:00 2001 From: Cengiz Can Date: Thu, 29 Jun 2017 10:40:51 +0300 Subject: [PATCH 2/7] do not append an extra newline char --- src/librustc_driver/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index f408316c9f923..58dd21c929248 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -411,7 +411,7 @@ fn show_content_with_pager(content: &String) { // If pager fails for whatever reason, we should still print the content // to standard output if fallback_to_println { - println!("{}", content); + print!("{}", content); } } From 08b6bebbad39874a71f37dfb4c607544b6c943e9 Mon Sep 17 00:00:00 2001 From: Cengiz Can Date: Thu, 29 Jun 2017 17:57:54 +0300 Subject: [PATCH 3/7] use unwrap_or_else to prevent unnecessary alloc --- src/librustc_driver/lib.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 58dd21c929248..41a36141cbf78 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -365,13 +365,12 @@ fn handle_explain(code: &str, if dedented_line.starts_with("```") { is_in_code_block = !is_in_code_block; text.push_str(&line[..(indent_level+3)]); - text.push('\n'); } else if is_in_code_block && dedented_line.starts_with("# ") { continue; } else { text.push_str(line); - text.push('\n'); } + text.push('\n'); } show_content_with_pager(&text); @@ -383,7 +382,7 @@ fn handle_explain(code: &str, } fn show_content_with_pager(content: &String) { - let pager_name = env::var_os("PAGER").unwrap_or(if cfg!(windows) { + let pager_name = env::var_os("PAGER").unwrap_or_else(|| if cfg!(windows) { OsString::from("more.com") } else { OsString::from("less") From 7b0a7fdaf250ba5b5c436c8de9aacf94b519b57f Mon Sep 17 00:00:00 2001 From: Cengiz Can Date: Sun, 2 Jul 2017 23:27:10 +0300 Subject: [PATCH 4/7] do not spawn pager if not tty --- src/Cargo.lock | 12 ++++++++++++ src/librustc_driver/Cargo.toml | 1 + src/librustc_driver/lib.rs | 9 ++++++++- 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 2d42903ad0a7d..075a2167ea35d 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -551,6 +551,16 @@ dependencies = [ "xz2 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "isatty" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "itoa" version = "0.3.1" @@ -1202,6 +1212,7 @@ dependencies = [ "arena 0.0.0", "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "graphviz 0.0.0", + "isatty 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "proc_macro_plugin 0.0.0", "rustc 0.0.0", @@ -2056,6 +2067,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum handlebars 0.25.3 (registry+https://github.com/rust-lang/crates.io-index)" = "15bdf598fc3c2de40c6b340213028301c0d225eea55a2294e6cc148074e557a1" "checksum hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d6a22814455d41612f41161581c2883c0c6a1c41852729b17d5ed88f01e153aa" "checksum idna 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2233d4940b1f19f0418c158509cd7396b8d70a5db5705ce410914dc8fa603b37" +"checksum isatty 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fa500db770a99afe2a0f2229be2a3d09c7ed9d7e4e8440bf71253141994e240f" "checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c" "checksum jobserver 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4e28adc987f6d0521ef66ad60b055968107b164b3bb3cf3dc8474e0a380474a6" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml index 2e949f48c175e..6415dbccbfc41 100644 --- a/src/librustc_driver/Cargo.toml +++ b/src/librustc_driver/Cargo.toml @@ -35,3 +35,4 @@ serialize = { path = "../libserialize" } syntax = { path = "../libsyntax" } syntax_ext = { path = "../libsyntax_ext" } syntax_pos = { path = "../libsyntax_pos" } +isatty = "0.1" diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 41a36141cbf78..2ecbb89361e62 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -56,6 +56,7 @@ extern crate log; extern crate syntax; extern crate syntax_ext; extern crate syntax_pos; +extern crate isatty; use driver::CompileController; use pretty::{PpMode, UserIdentifiedItem}; @@ -100,6 +101,8 @@ use syntax::feature_gate::{GatedCfg, UnstableFeatures}; use syntax::parse::{self, PResult}; use syntax_pos::{DUMMY_SP, MultiSpan}; +use isatty::stdout_isatty; + #[cfg(test)] pub mod test; @@ -373,7 +376,11 @@ fn handle_explain(code: &str, text.push('\n'); } - show_content_with_pager(&text); + if stdout_isatty() { + show_content_with_pager(&text); + } else { + print!("{}", text); + } } None => { early_error(output, &format!("no extended information for {}", code)); From 0e18a9cd55826eca5f2804a06527541140a71925 Mon Sep 17 00:00:00 2001 From: Cengiz Can Date: Mon, 3 Jul 2017 01:34:25 +0300 Subject: [PATCH 5/7] use embedded implementation instead of istty crate --- src/librustc_driver/lib.rs | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 2ecbb89361e62..934015c95366b 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -56,7 +56,6 @@ extern crate log; extern crate syntax; extern crate syntax_ext; extern crate syntax_pos; -extern crate isatty; use driver::CompileController; use pretty::{PpMode, UserIdentifiedItem}; @@ -101,8 +100,6 @@ use syntax::feature_gate::{GatedCfg, UnstableFeatures}; use syntax::parse::{self, PResult}; use syntax_pos::{DUMMY_SP, MultiSpan}; -use isatty::stdout_isatty; - #[cfg(test)] pub mod test; @@ -347,6 +344,35 @@ pub trait CompilerCalls<'a> { #[derive(Copy, Clone)] pub struct RustcDefaultCalls; +/** + * TODO remove these and use winapi 0.3 instead + * + * These are duplicated in + * - bootstrap/compile.rs#L478 + * - librustc_errors/emitter.rs#L1253 + */ +#[cfg(unix)] +fn stdout_isatty() -> bool { + unsafe { libc::isatty(libc::STDOUT_FILENO) != 0 } +} +#[cfg(windows)] +fn stdout_isatty() -> bool { + type DWORD = u32; + type BOOL = i32; + type HANDLE = *mut u8; + type LPDWORD = *mut u32; + const STD_OUTPUT_HANDLE: DWORD = -11i32 as DWORD; + extern "system" { + fn GetStdHandle(which: DWORD) -> HANDLE; + fn GetConsoleMode(hConsoleHandle: HANDLE, lpMode: LPDWORD) -> BOOL; + } + unsafe { + let handle = GetStdHandle(STD_OUTPUT_HANDLE); + let mut out = 0; + GetConsoleMode(handle, &mut out) != 0 + } +} + fn handle_explain(code: &str, descriptions: &errors::registry::Registry, output: ErrorOutputType) { From e1a91443cdd78101b0c96c84848b99e07ee133d6 Mon Sep 17 00:00:00 2001 From: Cengiz Can Date: Mon, 3 Jul 2017 11:45:31 +0300 Subject: [PATCH 6/7] use single line comments --- src/librustc_driver/lib.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 934015c95366b..802ed2a489b10 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -344,17 +344,13 @@ pub trait CompilerCalls<'a> { #[derive(Copy, Clone)] pub struct RustcDefaultCalls; -/** - * TODO remove these and use winapi 0.3 instead - * - * These are duplicated in - * - bootstrap/compile.rs#L478 - * - librustc_errors/emitter.rs#L1253 - */ +// FIXME remove these and use winapi 0.3 instead +// Duplicates: bootstrap/compile.rs, librustc_errors/emitter.rs #[cfg(unix)] fn stdout_isatty() -> bool { unsafe { libc::isatty(libc::STDOUT_FILENO) != 0 } } + #[cfg(windows)] fn stdout_isatty() -> bool { type DWORD = u32; From 06de114f898f6f92a3c6cfb220dc957611087ef9 Mon Sep 17 00:00:00 2001 From: Cengiz Can Date: Mon, 3 Jul 2017 11:46:12 +0300 Subject: [PATCH 7/7] remove isatty dependency --- src/Cargo.lock | 12 ------------ src/librustc_driver/Cargo.toml | 1 - 2 files changed, 13 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 075a2167ea35d..2d42903ad0a7d 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -551,16 +551,6 @@ dependencies = [ "xz2 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "isatty" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "itoa" version = "0.3.1" @@ -1212,7 +1202,6 @@ dependencies = [ "arena 0.0.0", "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "graphviz 0.0.0", - "isatty 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "proc_macro_plugin 0.0.0", "rustc 0.0.0", @@ -2067,7 +2056,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum handlebars 0.25.3 (registry+https://github.com/rust-lang/crates.io-index)" = "15bdf598fc3c2de40c6b340213028301c0d225eea55a2294e6cc148074e557a1" "checksum hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d6a22814455d41612f41161581c2883c0c6a1c41852729b17d5ed88f01e153aa" "checksum idna 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2233d4940b1f19f0418c158509cd7396b8d70a5db5705ce410914dc8fa603b37" -"checksum isatty 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fa500db770a99afe2a0f2229be2a3d09c7ed9d7e4e8440bf71253141994e240f" "checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c" "checksum jobserver 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4e28adc987f6d0521ef66ad60b055968107b164b3bb3cf3dc8474e0a380474a6" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml index 6415dbccbfc41..2e949f48c175e 100644 --- a/src/librustc_driver/Cargo.toml +++ b/src/librustc_driver/Cargo.toml @@ -35,4 +35,3 @@ serialize = { path = "../libserialize" } syntax = { path = "../libsyntax" } syntax_ext = { path = "../libsyntax_ext" } syntax_pos = { path = "../libsyntax_pos" } -isatty = "0.1"