about summary refs log tree commit diff
path: root/src/librustc_driver/lib.rs
diff options
context:
space:
mode:
authorCengiz Can <cengizc@gmail.com>2017-05-30 00:13:09 +0300
committerCengiz Can <cengizc@gmail.com>2017-07-03 14:13:01 +0300
commit3146e552d199a4db223773e0b80ce8cd510df78a (patch)
tree1a920a0459dcd7a0314a35026c61234ce7167ff5 /src/librustc_driver/lib.rs
parent1d2db7b9e8082f0459e000985d77fc7ad0dabade (diff)
downloadrust-3146e552d199a4db223773e0b80ce8cd510df78a.tar.gz
rust-3146e552d199a4db223773e0b80ce8cd510df78a.zip
use PAGER to view --explain output #32665
Diffstat (limited to 'src/librustc_driver/lib.rs')
-rw-r--r--src/librustc_driver/lib.rs46
1 files changed, 43 insertions, 3 deletions
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index f2aacbc629f..f408316c9f9 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,