Add compiler flag to configure output coloring

This adds the flag --color, which allows the user to force coloring or
turn it off. The default behavior stays the same as before (colorize, if
output goes to tty).
Why this is beneficial is explained in issue #12881.

Please note that this commit doesn't include any regression tests. I
thought about how I'd write a test for this and it doesn't seem to be
worth the effort to me for a UI change like this.

Fixes #12881.
This commit is contained in:
Hanno Braun 2014-05-08 13:10:03 +00:00
parent 579e0a5f55
commit b7676f2df5
7 changed files with 46 additions and 12 deletions

View File

@ -27,6 +27,7 @@ use syntax::ast;
use syntax::ast::{IntTy, UintTy};
use syntax::attr;
use syntax::attr::AttrMetaMethods;
use syntax::diagnostic::{ColorConfig, Auto, Always, Never};
use syntax::parse;
use syntax::parse::token::InternedString;
@ -92,6 +93,7 @@ pub struct Options {
/// Crate id-related things to maybe print. It's (crate_id, crate_name, crate_file_name).
pub print_metas: (bool, bool, bool),
pub cg: CodegenOptions,
pub color: ColorConfig,
}
/// Some reasonable defaults
@ -115,6 +117,7 @@ pub fn basic_options() -> Options {
write_dependency_info: (false, None),
print_metas: (false, false, false),
cg: basic_codegen_options(),
color: Auto,
}
}
@ -536,7 +539,11 @@ pub fn optgroups() -> Vec<getopts::OptGroup> {
optmulti("F", "forbid", "Set lint forbidden", "OPT"),
optmulti("C", "codegen", "Set a codegen option", "OPT[=VALUE]"),
optmulti("Z", "", "Set internal debugging options", "FLAG"),
optflag( "v", "version", "Print version info and exit")
optflag("v", "version", "Print version info and exit"),
optopt("", "color", "Configure coloring of output:
auto = colorize, if output goes to a tty (default);
always = always colorize output;
never = never colorize output", "auto|always|never")
)
}
@ -707,6 +714,18 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
matches.opt_present("crate-file-name"));
let cg = build_codegen_options(matches);
let color = match matches.opt_str("color").as_ref().map(|s| s.as_slice()) {
Some("auto") => Auto,
Some("always") => Always,
Some("never") => Never,
None => Auto,
Some(arg) => early_error(format!(
"argument for --color must be auto, always or never (instead was `{}`)",
arg))
};
Options {
crate_types: crate_types,
gc: gc,
@ -726,6 +745,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
write_dependency_info: write_dependency_info,
print_metas: print_metas,
cg: cg,
color: color
}
}

View File

@ -323,7 +323,7 @@ fn parse_crate_attrs(sess: &Session, input: &Input) ->
}
pub fn early_error(msg: &str) -> ! {
let mut emitter = diagnostic::EmitterWriter::stderr();
let mut emitter = diagnostic::EmitterWriter::stderr(diagnostic::Auto);
emitter.emit(None, msg, diagnostic::Fatal);
fail!(diagnostic::FatalError);
}
@ -368,7 +368,7 @@ fn monitor(f: proc():Send) {
Err(value) => {
// Task failed without emitting a fatal diagnostic
if !value.is::<diagnostic::FatalError>() {
let mut emitter = diagnostic::EmitterWriter::stderr();
let mut emitter = diagnostic::EmitterWriter::stderr(diagnostic::Auto);
// a .span_bug or .bug call has already printed what
// it wants to print.

View File

@ -196,7 +196,7 @@ pub fn build_session(sopts: config::Options,
-> Session {
let codemap = codemap::CodeMap::new();
let diagnostic_handler =
diagnostic::default_handler();
diagnostic::default_handler(sopts.color);
let span_diagnostic_handler =
diagnostic::mk_span_handler(diagnostic_handler, codemap);

View File

@ -78,7 +78,7 @@ fn get_ast_and_resolve(cpath: &Path, libs: HashSet<Path>, cfgs: Vec<StrBuf>)
let codemap = syntax::codemap::CodeMap::new();
let diagnostic_handler = syntax::diagnostic::default_handler();
let diagnostic_handler = syntax::diagnostic::default_handler(syntax::diagnostic::Auto);
let span_diagnostic_handler =
syntax::diagnostic::mk_span_handler(diagnostic_handler, codemap);

View File

@ -53,7 +53,7 @@ pub fn run(input: &str,
let codemap = CodeMap::new();
let diagnostic_handler = diagnostic::default_handler();
let diagnostic_handler = diagnostic::default_handler(diagnostic::Auto);
let span_diagnostic_handler =
diagnostic::mk_span_handler(diagnostic_handler, codemap);

View File

@ -49,6 +49,13 @@ impl RenderSpan {
}
}
#[deriving(Clone)]
pub enum ColorConfig {
Auto,
Always,
Never
}
pub trait Emitter {
fn emit(&mut self, cmsp: Option<(&codemap::CodeMap, Span)>,
msg: &str, lvl: Level);
@ -176,8 +183,8 @@ pub fn mk_span_handler(handler: Handler, cm: codemap::CodeMap) -> SpanHandler {
}
}
pub fn default_handler() -> Handler {
mk_handler(box EmitterWriter::stderr())
pub fn default_handler(color_config: ColorConfig) -> Handler {
mk_handler(box EmitterWriter::stderr(color_config))
}
pub fn mk_handler(e: Box<Emitter:Send>) -> Handler {
@ -257,9 +264,16 @@ enum Destination {
}
impl EmitterWriter {
pub fn stderr() -> EmitterWriter {
pub fn stderr(color_config: ColorConfig) -> EmitterWriter {
let stderr = io::stderr();
if stderr.get_ref().isatty() {
let use_color = match color_config {
Always => true,
Never => false,
Auto => stderr.get_ref().isatty()
};
if use_color {
let dst = match term::Terminal::new(stderr.unwrap()) {
Ok(t) => Terminal(t),
Err(..) => Raw(box io::stderr()),

View File

@ -13,7 +13,7 @@
use ast;
use codemap::{Span, CodeMap, FileMap};
use diagnostic::{SpanHandler, mk_span_handler, default_handler};
use diagnostic::{SpanHandler, mk_span_handler, default_handler, Auto};
use parse::attr::ParserAttr;
use parse::parser::Parser;
@ -41,7 +41,7 @@ pub struct ParseSess {
pub fn new_parse_sess() -> ParseSess {
ParseSess {
span_diagnostic: mk_span_handler(default_handler(), CodeMap::new()),
span_diagnostic: mk_span_handler(default_handler(Auto), CodeMap::new()),
included_mod_stack: RefCell::new(Vec::new()),
}
}