Skip to content

Commit aaa912b

Browse files
Rollup merge of rust-lang#42732 - cengizIO:master, r=Mark-Simulacrum
Add pager support for `rustc --explain EXXXX` Hello! This is my take on rust-lang#32665. Thanks! **EDIT:** _I've limited access to a Windows machine so this is taking longer than I've anticipated_. 🐢 cc @alexcrichton @nikomatsakis @Mark-Simulacrum @retep998 @ollie27 @afiune
2 parents bf3e8ce + d2a0ead commit aaa912b

File tree

1 file changed

+42
-3
lines changed

1 file changed

+42
-3
lines changed

src/librustc_driver/lib.rs

+42-3
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,11 @@ use std::cmp::max;
8383
use std::cmp::Ordering::Equal;
8484
use std::default::Default;
8585
use std::env;
86+
use std::ffi::OsString;
8687
use std::io::{self, Read, Write};
8788
use std::iter::repeat;
8889
use std::path::PathBuf;
89-
use std::process;
90+
use std::process::{self, Command, Stdio};
9091
use std::rc::Rc;
9192
use std::str;
9293
use std::sync::{Arc, Mutex};
@@ -356,27 +357,65 @@ fn handle_explain(code: &str,
356357
match descriptions.find_description(&normalised) {
357358
Some(ref description) => {
358359
let mut is_in_code_block = false;
360+
let mut text = String::new();
361+
359362
// Slice off the leading newline and print.
360363
for line in description[1..].lines() {
361364
let indent_level = line.find(|c: char| !c.is_whitespace())
362365
.unwrap_or_else(|| line.len());
363366
let dedented_line = &line[indent_level..];
364367
if dedented_line.starts_with("```") {
365368
is_in_code_block = !is_in_code_block;
366-
println!("{}", &line[..(indent_level+3)]);
369+
text.push_str(&line[..(indent_level+3)]);
367370
} else if is_in_code_block && dedented_line.starts_with("# ") {
368371
continue;
369372
} else {
370-
println!("{}", line);
373+
text.push_str(line);
371374
}
375+
text.push('\n');
372376
}
377+
378+
show_content_with_pager(&text);
373379
}
374380
None => {
375381
early_error(output, &format!("no extended information for {}", code));
376382
}
377383
}
378384
}
379385

386+
fn show_content_with_pager(content: &String) {
387+
let pager_name = env::var_os("PAGER").unwrap_or_else(|| if cfg!(windows) {
388+
OsString::from("more.com")
389+
} else {
390+
OsString::from("less")
391+
});
392+
393+
let mut fallback_to_println = false;
394+
395+
match Command::new(pager_name).stdin(Stdio::piped()).spawn() {
396+
Ok(mut pager) => {
397+
if let Some(mut pipe) = pager.stdin.as_mut() {
398+
if pipe.write_all(content.as_bytes()).is_err() {
399+
fallback_to_println = true;
400+
}
401+
}
402+
403+
if pager.wait().is_err() {
404+
fallback_to_println = true;
405+
}
406+
}
407+
Err(_) => {
408+
fallback_to_println = true;
409+
}
410+
}
411+
412+
// If pager fails for whatever reason, we should still print the content
413+
// to standard output
414+
if fallback_to_println {
415+
print!("{}", content);
416+
}
417+
}
418+
380419
impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
381420
fn early_callback(&mut self,
382421
matches: &getopts::Matches,

0 commit comments

Comments
 (0)