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

[RFC] Add flag for Unicode based Frontend support #37703

Closed
wants to merge 1 commit 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
48 changes: 36 additions & 12 deletions src/librustc/session/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use syntax::parse;
use syntax::parse::token::InternedString;
use syntax::feature_gate::UnstableFeatures;

use errors::{ColorConfig, FatalError, Handler};
use errors::{ColorConfig, Drawing, EmitterConfig, FatalError, Handler};

use getopts;
use std::collections::{BTreeMap, BTreeSet};
Expand Down Expand Up @@ -80,13 +80,13 @@ pub enum OutputType {

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ErrorOutputType {
HumanReadable(ColorConfig),
HumanReadable(EmitterConfig),
Json,
}

impl Default for ErrorOutputType {
fn default() -> ErrorOutputType {
ErrorOutputType::HumanReadable(ColorConfig::Auto)
ErrorOutputType::HumanReadable(EmitterConfig::default())
}
}

Expand Down Expand Up @@ -1204,11 +1204,18 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
opt::opt_s("", "error-format",
"How errors and other messages are produced",
"human|json"),
opt::opt_s("", "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"),

opt::opt_s("", "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"),
opt::opt_s("", "unicode",
"Configure characters used on output:
ascii = ascii safe characters (default)
style1 = unicode
style2 = unicode box drawing characters",
"ascii|style1|style2"),
opt::flagopt_ubnr("", "pretty",
"Pretty-print the input instead of compiling;
valid types are: `normal` (un-annotated source),
Expand Down Expand Up @@ -1269,26 +1276,43 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
}
};

let drawing = match matches.opt_str("unicode").as_ref().map(|s| &s[..]) {
Some("style1") => Drawing::unicode(),
Some("style2") => Drawing::unicode_2(),
Some("ascii") => Drawing::ascii(),
None => Drawing::ascii(),
Some(arg) => {
early_error(ErrorOutputType::default(), &format!("argument for --unicode must be style1, \
style2 or ascii (instead was `{}`)",
arg))
}
};

let config = EmitterConfig {
color: color,
drawing: drawing,
};

// We need the opts_present check because the driver will send us Matches
// with only stable options if no unstable options are used. Since error-format
// is unstable, it will not be present. We have to use opts_present not
// opt_present because the latter will panic.
let error_format = if matches.opts_present(&["error-format".to_owned()]) {
match matches.opt_str("error-format").as_ref().map(|s| &s[..]) {
Some("human") => ErrorOutputType::HumanReadable(color),
Some("human") => ErrorOutputType::HumanReadable(config),
Some("json") => ErrorOutputType::Json,

None => ErrorOutputType::HumanReadable(color),
None => ErrorOutputType::HumanReadable(config),

Some(arg) => {
early_error(ErrorOutputType::HumanReadable(color),
early_error(ErrorOutputType::HumanReadable(config),
&format!("argument for --error-format must be human or json (instead \
was `{}`)",
arg))
}
}
} else {
ErrorOutputType::HumanReadable(color)
ErrorOutputType::HumanReadable(config)
};

let unparsed_crate_types = matches.opt_strs("crate-type");
Expand Down
17 changes: 9 additions & 8 deletions src/librustc/session/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use mir::transform as mir_pass;

use syntax::ast::NodeId;
use errors::{self, DiagnosticBuilder};
use errors::emitter::{Emitter, EmitterWriter};
use errors::emitter::{Emitter, EmitterConfig, EmitterWriter};
use syntax::json::JsonEmitter;
use syntax::feature_gate;
use syntax::parse;
Expand Down Expand Up @@ -528,13 +528,14 @@ pub fn build_session_with_codemap(sopts: config::Options,
let treat_err_as_bug = sopts.debugging_opts.treat_err_as_bug;

let emitter: Box<Emitter> = match (sopts.error_format, emitter_dest) {
(config::ErrorOutputType::HumanReadable(color_config), None) => {
Box::new(EmitterWriter::stderr(color_config,
(config::ErrorOutputType::HumanReadable(config), None) => {
Box::new(EmitterWriter::stderr(config,
Some(codemap.clone())))
}
(config::ErrorOutputType::HumanReadable(_), Some(dst)) => {
Box::new(EmitterWriter::new(dst,
Some(codemap.clone())))
Some(codemap.clone()),
EmitterConfig::default()))
}
(config::ErrorOutputType::Json, None) => {
Box::new(JsonEmitter::stderr(Some(registry), codemap.clone()))
Expand Down Expand Up @@ -707,8 +708,8 @@ unsafe fn configure_llvm(sess: &Session) {

pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! {
let emitter: Box<Emitter> = match output {
config::ErrorOutputType::HumanReadable(color_config) => {
Box::new(EmitterWriter::stderr(color_config,
config::ErrorOutputType::HumanReadable(config) => {
Box::new(EmitterWriter::stderr(config,
None))
}
config::ErrorOutputType::Json => Box::new(JsonEmitter::basic()),
Expand All @@ -720,8 +721,8 @@ pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! {

pub fn early_warn(output: config::ErrorOutputType, msg: &str) {
let emitter: Box<Emitter> = match output {
config::ErrorOutputType::HumanReadable(color_config) => {
Box::new(EmitterWriter::stderr(color_config,
config::ErrorOutputType::HumanReadable(config) => {
Box::new(EmitterWriter::stderr(config,
None))
}
config::ErrorOutputType::Json => Box::new(JsonEmitter::basic()),
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 @@ -142,7 +142,7 @@ pub fn run<F>(run_compiler: F) -> isize
Some(sess) => sess.fatal(&abort_msg(err_count)),
None => {
let emitter =
errors::emitter::EmitterWriter::stderr(errors::ColorConfig::Auto, None);
errors::emitter::EmitterWriter::stderr(errors::EmitterConfig::default(), None);
let handler = errors::Handler::with_emitter(true, false, Box::new(emitter));
handler.emit(&MultiSpan::new(),
&abort_msg(err_count),
Expand Down Expand Up @@ -1081,7 +1081,7 @@ pub fn monitor<F: FnOnce() + Send + 'static>(f: F) {
// Thread panicked without emitting a fatal diagnostic
if !value.is::<errors::FatalError>() {
let emitter =
Box::new(errors::emitter::EmitterWriter::stderr(errors::ColorConfig::Auto, None));
Box::new(errors::emitter::EmitterWriter::stderr(errors::EmitterConfig::default(), None));
let handler = errors::Handler::with_emitter(true, false, emitter);

// a .span_bug or .bug call has already printed what
Expand Down
176 changes: 146 additions & 30 deletions src/librustc_errors/emitter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,105 @@ impl Emitter for EmitterWriter {
/// maximum number of lines we will print for each error; arbitrary.
pub const MAX_HIGHLIGHT_LINES: usize = 6;

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct LineStyle {
pub start: Option<char>,
/// The middle char must always be set to Some(char)
pub middle: Option<char>,
pub end: Option<char>,
pub single: Option<char>,
}

impl LineStyle {
pub fn homogeneous(c: char) -> LineStyle {
LineStyle {
start: Some(c),
middle: Some(c),
end: Some(c),
single: Some(c),
}
}

pub fn homogeneous_with_start(c: char, start: Option<char>) -> LineStyle {
LineStyle {
start: start,
middle: Some(c),
end: Some(c),
single: Some(c),
}
}
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Drawing {
pub primary_underline: LineStyle ,
pub secondary_underline: LineStyle,
pub vertical_line: LineStyle,
}

impl Drawing {
pub fn ascii() -> Drawing {
Drawing {
primary_underline: LineStyle::homogeneous('^'),
secondary_underline: LineStyle::homogeneous('-'),
vertical_line: LineStyle::homogeneous_with_start('|', None),
}
}

pub fn unicode() -> Drawing {
Drawing {
primary_underline: LineStyle {
start: Some('\u{2594}'), // UPPER ONE EIGHTH BLOCK ▔
middle: Some('\u{2594}'), // UPPER ONE EIGHTH BLOCK ▔
end: None,
single: Some('⌅'), // '\u{2580}', // UPPER HALF BLOCK ▀
},
secondary_underline: LineStyle::homogeneous('‾'),
vertical_line: LineStyle::homogeneous_with_start('⎸', None),
}
}

pub fn unicode_2() -> Drawing {
Drawing {
primary_underline: LineStyle::homogeneous('\u{25B2}'), // BLACK UP-POINTING TRIANGLE
secondary_underline: LineStyle {
start: Some('\u{2517}'), // BOX DRAWINGS HEAVY UP AND RIGHT ┗
middle: Some('\u{2501}'), // BOX DRAWINGS HEAVY HORIZONTAL ━
end: Some('\u{251B}'), // BOX DRAWINGS HEAVY UP AND LEFT ┛
single: Some('⎵'), // BOX DRAWINGS HEAVY HORIZONTAL ━
},
vertical_line: LineStyle {
start: Some('\u{2523}'), // BOX DRAWINGS HEAVY VERTICAL AND RIGHT ┣
middle: Some('\u{2503}'), // BOX DRAWINGS HEAVY VERTICAL ┃
end: Some('\u{2503}'), // BOX DRAWINGS HEAVY VERTICAL ┃
single: None,
},
}
}
}

impl Default for Drawing {
fn default() -> Drawing {
//Drawing::ascii()
Drawing::unicode()
}
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct EmitterConfig {
pub color: ColorConfig,
pub drawing: Drawing,
}

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

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ColorConfig {
Auto,
Expand All @@ -60,6 +159,7 @@ impl ColorConfig {
pub struct EmitterWriter {
dst: Destination,
cm: Option<Rc<CodeMapper>>,
cfg: EmitterConfig,
}

struct FileWithAnnotatedLines {
Expand All @@ -83,25 +183,32 @@ macro_rules! println_maybe_styled {
}

impl EmitterWriter {
pub fn stderr(color_config: ColorConfig, code_map: Option<Rc<CodeMapper>>) -> EmitterWriter {
if color_config.use_color() {
pub fn stderr(config: EmitterConfig, code_map: Option<Rc<CodeMapper>>) -> EmitterWriter {
if config.color.use_color() {
let dst = Destination::from_stderr();
EmitterWriter {
dst: dst,
cm: code_map,
cfg: config,
}
} else {
EmitterWriter {
dst: Raw(Box::new(io::stderr())),
cm: code_map,
cfg: config,
}
}
}

pub fn new(dst: Box<Write + Send>, code_map: Option<Rc<CodeMapper>>) -> EmitterWriter {
pub fn new(dst: Box<Write + Send>,
code_map: Option<Rc<CodeMapper>>,
config: EmitterConfig)
-> EmitterWriter
{
EmitterWriter {
dst: Raw(dst),
cm: code_map,
cfg: config,
}
}

Expand Down Expand Up @@ -230,23 +337,28 @@ impl EmitterWriter {

// Next, create the highlight line.
for annotation in &annotations {
for p in annotation.start_col..annotation.end_col {
if annotation.is_primary {
buffer.putc(line_offset + 1,
width_offset + p,
'^',
Style::UnderlinePrimary);
if !annotation.is_minimized {
buffer.set_style(line_offset, width_offset + p, Style::UnderlinePrimary);
}
let l = annotation.end_col - annotation.start_col;
for (i, p) in (annotation.start_col..annotation.end_col).enumerate() {
let (underline, color) = if annotation.is_primary {
(self.cfg.drawing.primary_underline, Style::UnderlinePrimary)
} else {
buffer.putc(line_offset + 1,
width_offset + p,
'-',
Style::UnderlineSecondary);
if !annotation.is_minimized {
buffer.set_style(line_offset, width_offset + p, Style::UnderlineSecondary);
}
(self.cfg.drawing.secondary_underline, Style::UnderlineSecondary)
};
let middle = underline.middle.unwrap();
buffer.putc(line_offset + 1,
width_offset + p,
if l == 1 {
underline.single.unwrap_or(middle)
} else if i == 0 {
underline.start.unwrap_or(middle)
} else if i == l - 1 {
underline.end.unwrap_or(middle)
} else {
middle
},
color);
if !annotation.is_minimized {
buffer.set_style(line_offset, width_offset + p, color);
}
}
}
Expand Down Expand Up @@ -329,18 +441,22 @@ impl EmitterWriter {

// For each blank line, draw a `|` at our column. The
// text ought to be long enough for this.
let color = if annotation.is_primary {
Style::UnderlinePrimary
} else {
Style::UnderlineSecondary
};
if let Some(line) = self.cfg.drawing.vertical_line.start {
buffer.putc(line_offset + 1,
width_offset + annotation.start_col,
line,
color);
}
for index in 2..blank_lines {
if annotation.is_primary {
buffer.putc(line_offset + index,
width_offset + annotation.start_col,
'|',
Style::UnderlinePrimary);
} else {
buffer.putc(line_offset + index,
width_offset + annotation.start_col,
'|',
Style::UnderlineSecondary);
}
buffer.putc(line_offset + index,
width_offset + annotation.start_col,
self.cfg.drawing.vertical_line.middle.unwrap(),
color);
draw_col_separator(buffer, line_offset + index, width_offset - 2);
}

Expand Down
Loading