Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add rustc --drawing to use Unicode line drawing characters for span output #21406

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions man/rustc.1
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ Configure coloring of output:
auto = colorize, if output goes to a tty (default);
always = always colorize output;
never = never colorize output
.TP
\fB\-\-drawing\fR
Use drawing characters in diagnostic output

.SH CODEGEN OPTIONS

Expand Down
1 change: 1 addition & 0 deletions src/etc/zsh/_rust
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ _rustc_opts_switches=(
{-V,--verbose}'[use verbose output]'
-O'[Equivalent to -C opt-level=2]'
--test'[Build a test harness]'
--drawing'[Use drawing characters in diagnostic output]'
)


Expand Down
37 changes: 21 additions & 16 deletions src/librustc/session/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,16 @@ use syntax::ast;
use syntax::ast::{IntTy, UintTy};
use syntax::attr;
use syntax::attr::AttrMetaMethods;
use syntax::diagnostic::{ColorConfig, Auto, Always, Never, SpanHandler};
use syntax::diagnostic;
use syntax::diagnostic::{ColorConfig, SpanHandler};
use syntax::parse;
use syntax::parse::token::InternedString;

use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use getopts;
use std::fmt;
use std::default;

use llvm;

Expand Down Expand Up @@ -104,7 +106,7 @@ pub struct Options {
pub write_dependency_info: (bool, Option<Path>),
pub prints: Vec<PrintRequest>,
pub cg: CodegenOptions,
pub color: ColorConfig,
pub emit_cfg: diagnostic::EmitterConfig,
pub show_span: Option<String>,
pub externs: HashMap<String, Vec<String>>,
pub crate_name: Option<String>,
Expand Down Expand Up @@ -228,7 +230,7 @@ pub fn basic_options() -> Options {
write_dependency_info: (false, None),
prints: Vec::new(),
cg: basic_codegen_options(),
color: Auto,
emit_cfg: default::Default::default(),
show_span: None,
externs: HashMap::new(),
crate_name: None,
Expand Down Expand Up @@ -793,6 +795,7 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
auto = colorize, if output goes to a tty (default);
always = always colorize output;
never = never colorize output", "auto|always|never"),
opt::flag("", "drawing", "Use drawing characters in diagnostic output"),

// DEPRECATED
opt::flag("", "print-crate-name", "Output the crate name and exit"),
Expand Down Expand Up @@ -1072,19 +1075,21 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
--debuginfo");
}

let color = match matches.opt_str("color").as_ref().map(|s| &s[]) {
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)[])
}
let mut emit_cfg: diagnostic::EmitterConfig = default::Default::default();
if let Some(arg) = matches.opt_str("color").as_ref() {
emit_cfg.color = match &arg[] {
"auto" => ColorConfig::Auto,
"always" => ColorConfig::Always,
"never" => ColorConfig::Never,
_ => {
early_error(&format!("argument for --color must be auto, always \
or never (instead was `{}`)", arg)[]);
}
};
};
if matches.opt_present("drawing") {
emit_cfg.drawing = true;
}

let mut externs = HashMap::new();
for arg in matches.opt_strs("extern").iter() {
Expand Down Expand Up @@ -1126,7 +1131,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
write_dependency_info: write_dependency_info,
prints: prints,
cg: cg,
color: color,
emit_cfg: emit_cfg,
show_span: None,
externs: externs,
crate_name: crate_name,
Expand Down
13 changes: 8 additions & 5 deletions src/librustc/session/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ use rustc_back::target::Target;

use std::os;
use std::cell::{Cell, RefCell};
use std::default::Default;

pub mod config;
pub mod search_paths;
Expand Down Expand Up @@ -291,7 +292,7 @@ pub fn build_session(sopts: config::Options,
-> Session {
let codemap = codemap::CodeMap::new();
let diagnostic_handler =
diagnostic::default_handler(sopts.color, Some(registry));
diagnostic::default_handler(sopts.emit_cfg, Some(registry));
let span_diagnostic_handler =
diagnostic::mk_span_handler(diagnostic_handler, codemap);

Expand Down Expand Up @@ -365,13 +366,15 @@ pub fn expect<T, M>(sess: &Session, opt: Option<T>, msg: M) -> T where
diagnostic::expect(sess.diagnostic(), opt, msg)
}

pub fn fallback_emitter() -> diagnostic::EmitterWriter {
diagnostic::EmitterWriter::stderr(Default::default(), None)
}

pub fn early_error(msg: &str) -> ! {
let mut emitter = diagnostic::EmitterWriter::stderr(diagnostic::Auto, None);
emitter.emit(None, msg, None, diagnostic::Fatal);
fallback_emitter().emit(None, msg, None, diagnostic::Fatal);
panic!(diagnostic::FatalError);
}

pub fn early_warn(msg: &str) {
let mut emitter = diagnostic::EmitterWriter::stderr(diagnostic::Auto, None);
emitter.emit(None, msg, None, diagnostic::Warning);
fallback_emitter().emit(None, msg, None, diagnostic::Warning);
}
2 changes: 1 addition & 1 deletion src/librustc_back/target/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ impl Target {
// this is 1. ugly, 2. error prone.


let handler = diagnostic::default_handler(diagnostic::Auto, None);
let handler = diagnostic::default_handler(Default::default(), None);

let get_req_field = |&: name: &str| {
match obj.find(name)
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_driver/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ use std::os;
use std::sync::mpsc::channel;
use std::thread;

use rustc::session::early_error;
use rustc::session::{early_error, fallback_emitter};

use syntax::ast;
use syntax::parse;
Expand Down Expand Up @@ -616,7 +616,7 @@ pub fn monitor<F:FnOnce()+Send>(f: F) {
Err(value) => {
// Thread panicked without emitting a fatal diagnostic
if !value.is::<diagnostic::FatalError>() {
let mut emitter = diagnostic::EmitterWriter::stderr(diagnostic::Auto, None);
let mut emitter = fallback_emitter();

// a .span_bug or .bug call has already printed what
// it wants to print.
Expand Down
3 changes: 2 additions & 1 deletion src/librustdoc/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use syntax::{ast, ast_map, codemap, diagnostic};

use std::cell::RefCell;
use std::collections::{HashMap, HashSet};
use std::default::Default;

use visit_ast::RustdocVisitor;
use clean;
Expand Down Expand Up @@ -103,7 +104,7 @@ pub fn run_core(search_paths: SearchPaths, cfgs: Vec<String>, externs: Externs,
};

let codemap = codemap::CodeMap::new();
let diagnostic_handler = diagnostic::default_handler(diagnostic::Auto, None);
let diagnostic_handler = diagnostic::default_handler(Default::default(), None);
let span_diagnostic_handler =
diagnostic::mk_span_handler(diagnostic_handler, codemap);

Expand Down
3 changes: 2 additions & 1 deletion src/librustdoc/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use std::os;
use std::str;
use std::thread::Thread;
use std::thunk::Thunk;
use std::default::Default;

use std::collections::{HashSet, HashMap};
use testing;
Expand Down Expand Up @@ -58,7 +59,7 @@ pub fn run(input: &str,
};

let codemap = CodeMap::new();
let diagnostic_handler = diagnostic::default_handler(diagnostic::Auto, None);
let diagnostic_handler = diagnostic::default_handler(Default::default(), None);
let span_diagnostic_handler =
diagnostic::mk_span_handler(diagnostic_handler, codemap);

Expand Down
86 changes: 68 additions & 18 deletions src/libsyntax/diagnostic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@

pub use self::Level::*;
pub use self::RenderSpan::*;
pub use self::ColorConfig::*;
use self::Destination::*;

use codemap::{COMMAND_LINE_SP, COMMAND_LINE_EXPN, Pos, Span};
Expand All @@ -22,6 +21,7 @@ use std::fmt;
use std::io;
use std::iter::range;
use std::string::String;
use std::default::Default;
use term::WriterWrapper;
use term;

Expand Down Expand Up @@ -61,6 +61,49 @@ pub enum ColorConfig {
Never
}

#[derive(Clone, Copy)]
pub struct EmitterConfig {
pub color: ColorConfig,
pub drawing: bool,
}

impl Default for EmitterConfig {
fn default() -> EmitterConfig {
EmitterConfig {
color: ColorConfig::Auto,
drawing: false,
}
}
}

#[derive(Clone, Copy)]
struct SpanFormat {
single: char,
begin: char,
middle: char,
end: char,
}

impl EmitterConfig {
#[inline]
fn span_format(&self) -> SpanFormat {
match self.drawing {
false => SpanFormat {
single: '^',
begin: '^',
middle: '~',
end: '~',
},
true => SpanFormat {
single: '\u{25B2}', // BLACK UP-POINTING TRIANGLE
begin: '\u{2517}', // BOX DRAWINGS HEAVY UP AND RIGHT
middle: '\u{2501}', // BOX DRAWINGS HEAVY HORIZONTAL
end: '\u{251B}', // BOX DRAWINGS HEAVY UP AND LEFT
},
}
}
}

pub trait Emitter {
fn emit(&mut self, cmsp: Option<(&codemap::CodeMap, Span)>,
msg: &str, code: Option<&str>, lvl: Level);
Expand Down Expand Up @@ -213,9 +256,9 @@ pub fn mk_span_handler(handler: Handler, cm: codemap::CodeMap) -> SpanHandler {
}
}

pub fn default_handler(color_config: ColorConfig,
pub fn default_handler(cfg: EmitterConfig,
registry: Option<diagnostics::registry::Registry>) -> Handler {
mk_handler(box EmitterWriter::stderr(color_config, registry))
mk_handler(box EmitterWriter::stderr(cfg, registry))
}

pub fn mk_handler(e: Box<Emitter + Send>) -> Handler {
Expand Down Expand Up @@ -321,7 +364,8 @@ fn print_diagnostic(dst: &mut EmitterWriter, topic: &str, lvl: Level,

pub struct EmitterWriter {
dst: Destination,
registry: Option<diagnostics::registry::Registry>
registry: Option<diagnostics::registry::Registry>,
cfg: EmitterConfig,
}

enum Destination {
Expand All @@ -330,30 +374,30 @@ enum Destination {
}

impl EmitterWriter {
pub fn stderr(color_config: ColorConfig,
pub fn stderr(cfg: EmitterConfig,
registry: Option<diagnostics::registry::Registry>) -> EmitterWriter {
let stderr = io::stderr();

let use_color = match color_config {
Always => true,
Never => false,
Auto => stderr.get_ref().isatty()
let use_color = match cfg.color {
ColorConfig::Always => true,
ColorConfig::Never => false,
ColorConfig::Auto => stderr.get_ref().isatty()
};

if use_color {
let dst = match term::stderr() {
Some(t) => Terminal(t),
None => Raw(box stderr),
};
EmitterWriter { dst: dst, registry: registry }
EmitterWriter { dst: dst, registry: registry, cfg: cfg }
} else {
EmitterWriter { dst: Raw(box stderr), registry: registry }
EmitterWriter { dst: Raw(box stderr), registry: registry, cfg: cfg }
}
}

pub fn new(dst: Box<Writer + Send>,
registry: Option<diagnostics::registry::Registry>) -> EmitterWriter {
EmitterWriter { dst: Raw(dst), registry: registry }
EmitterWriter { dst: Raw(dst), registry: registry, cfg: Default::default() }
}
}

Expand Down Expand Up @@ -498,14 +542,20 @@ fn highlight_lines(err: &mut EmitterWriter,
}

try!(write!(&mut err.dst, "{}", s));
let mut s = String::from_str("^");
let fmt = err.cfg.span_format();
let mut s = String::new();

let hi = cm.lookup_char_pos(sp.hi);
if hi.col != lo.col {
// the ^ already takes up one space
let num_squigglies = hi.col.to_uint() - lo.col.to_uint() - 1u;
let len = hi.col.to_uint() - lo.col.to_uint();
if len <= 1 {
s.push(fmt.single);
} else {
s.push(fmt.begin);
let num_squigglies = len - 2u;
for _ in range(0, num_squigglies) {
s.push('~');
s.push(fmt.middle);
}
s.push(fmt.end);
}
try!(print_maybe_styled(err,
&format!("{}\n", s)[],
Expand Down Expand Up @@ -556,7 +606,7 @@ fn custom_highlight_lines(w: &mut EmitterWriter,
for _ in range(0, skip) {
s.push(' ');
}
s.push('^');
s.push(w.cfg.span_format().single);
s.push('\n');
print_maybe_styled(w,
&s[],
Expand Down
6 changes: 4 additions & 2 deletions src/libsyntax/parse/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

use ast;
use codemap::{Span, CodeMap, FileMap};
use diagnostic::{SpanHandler, mk_span_handler, default_handler, Auto};
use diagnostic::{SpanHandler, mk_span_handler, default_handler};
use parse::attr::ParserAttr;
use parse::parser::Parser;
use ptr::P;
Expand All @@ -21,6 +21,7 @@ use std::cell::{Cell, RefCell};
use std::io::File;
use std::rc::Rc;
use std::num::Int;
use std::default::Default;
use std::str;
use std::iter;

Expand All @@ -45,7 +46,8 @@ pub struct ParseSess {

pub fn new_parse_sess() -> ParseSess {
ParseSess {
span_diagnostic: mk_span_handler(default_handler(Auto, None), CodeMap::new()),
span_diagnostic: mk_span_handler(default_handler(Default::default(), None),
CodeMap::new()),
included_mod_stack: RefCell::new(Vec::new()),
node_id: Cell::new(1),
}
Expand Down
Loading