implement unicode error message configuration

This commit is contained in:
Connor Skees 2020-07-15 23:54:46 -04:00
parent 9d55adf927
commit 2ea48b4445
3 changed files with 45 additions and 22 deletions

View File

@ -44,9 +44,13 @@ impl SassError {
} }
} }
pub(crate) const fn from_loc(message: String, loc: SpanLoc) -> Self { pub(crate) const fn from_loc(message: String, loc: SpanLoc, unicode: bool) -> Self {
SassError { SassError {
kind: SassErrorKind::ParseError { message, loc }, kind: SassErrorKind::ParseError {
message,
loc,
unicode,
},
} }
} }
} }
@ -60,6 +64,7 @@ enum SassErrorKind {
ParseError { ParseError {
message: String, message: String,
loc: SpanLoc, loc: SpanLoc,
unicode: bool,
}, },
// we put IoErrors in an `Rc` to allow it to be // we put IoErrors in an `Rc` to allow it to be
// cloneable // cloneable
@ -73,30 +78,47 @@ impl Display for SassError {
// TODO: integrate with codemap-diagnostics // TODO: integrate with codemap-diagnostics
#[inline] #[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let (message, loc) = match &self.kind { let (message, loc, unicode) = match &self.kind {
SassErrorKind::ParseError { message, loc } => (message, loc), SassErrorKind::ParseError {
message,
loc,
unicode,
} => (message, loc, *unicode),
SassErrorKind::FromUtf8Error(s) => return writeln!(f, "Error: {}", s), SassErrorKind::FromUtf8Error(s) => return writeln!(f, "Error: {}", s),
SassErrorKind::IoError(s) => return writeln!(f, "Error: {}", s), SassErrorKind::IoError(s) => return writeln!(f, "Error: {}", s),
SassErrorKind::Raw(..) => todo!(), SassErrorKind::Raw(..) => todo!(),
}; };
let first_bar = if unicode { '╷' } else { '|' };
let second_bar = if unicode { '│' } else { '|' };
let third_bar = if unicode { '│' } else { '|' };
let fourth_bar = if unicode { '╵' } else { '|' };
let line = loc.begin.line + 1; let line = loc.begin.line + 1;
let col = loc.begin.column + 1; let col = loc.begin.column + 1;
writeln!(f, "Error: {}", message)?; writeln!(f, "Error: {}", message)?;
let padding = vec![' '; format!("{}", line).len() + 1] let padding = vec![' '; format!("{}", line).len() + 1]
.iter() .iter()
.collect::<String>(); .collect::<String>();
writeln!(f, "{}|", padding)?; writeln!(f, "{}{}", padding, first_bar)?;
writeln!(f, "{} | {}", line, loc.file.source_line(loc.begin.line))?;
writeln!( writeln!(
f, f,
"{}| {}{}", "{} {} {}",
line,
second_bar,
loc.file.source_line(loc.begin.line)
)?;
writeln!(
f,
"{}{} {}{}",
padding, padding,
third_bar,
vec![' '; loc.begin.column].iter().collect::<String>(), vec![' '; loc.begin.column].iter().collect::<String>(),
vec!['^'; loc.end.column.max(loc.begin.column) - loc.begin.column.min(loc.end.column)] vec!['^'; loc.end.column.max(loc.begin.column) - loc.begin.column.min(loc.end.column)]
.iter() .iter()
.collect::<String>() .collect::<String>()
)?; )?;
writeln!(f, "{}|", padding)?; writeln!(f, "{}{}", padding, fourth_bar)?;
writeln!(f, "./{}:{}:{}", loc.file.name(), line, col)?; writeln!(f, "./{}:{}:{}", loc.file.name(), line, col)?;
Ok(()) Ok(())
} }

View File

@ -252,9 +252,9 @@ impl<'a> Options<'a> {
} }
} }
fn raw_to_parse_error(map: &CodeMap, err: Error) -> Box<Error> { fn raw_to_parse_error(map: &CodeMap, err: Error, unicode: bool) -> Box<Error> {
let (message, span) = err.raw(); let (message, span) = err.raw();
Box::new(Error::from_loc(message, map.look_up_span(span))) Box::new(Error::from_loc(message, map.look_up_span(span), unicode))
} }
/// Compile CSS from a path /// Compile CSS from a path
@ -294,12 +294,12 @@ pub fn from_path(p: &str, options: &Options) -> Result<String> {
options, options,
} }
.parse() .parse()
.map_err(|e| raw_to_parse_error(&map, *e))?; .map_err(|e| raw_to_parse_error(&map, *e, options.unicode_error_messages))?;
Css::from_stmts(stmts, false) Css::from_stmts(stmts, false)
.map_err(|e| raw_to_parse_error(&map, *e))? .map_err(|e| raw_to_parse_error(&map, *e, options.unicode_error_messages))?
.pretty_print(&map) .pretty_print(&map)
.map_err(|e| raw_to_parse_error(&map, *e)) .map_err(|e| raw_to_parse_error(&map, *e, options.unicode_error_messages))
} }
/// Compile CSS from a string /// Compile CSS from a string
@ -338,12 +338,12 @@ pub fn from_string(p: String, options: &Options) -> Result<String> {
options, options,
} }
.parse() .parse()
.map_err(|e| raw_to_parse_error(&map, *e))?; .map_err(|e| raw_to_parse_error(&map, *e, options.unicode_error_messages))?;
Css::from_stmts(stmts, false) Css::from_stmts(stmts, false)
.map_err(|e| raw_to_parse_error(&map, *e))? .map_err(|e| raw_to_parse_error(&map, *e, options.unicode_error_messages))?
.pretty_print(&map) .pretty_print(&map)
.map_err(|e| raw_to_parse_error(&map, *e)) .map_err(|e| raw_to_parse_error(&map, *e, options.unicode_error_messages))
} }
#[cfg(feature = "wasm")] #[cfg(feature = "wasm")]
@ -373,10 +373,10 @@ pub fn from_string(p: String, options: &'_ Options<'_>) -> std::result::Result<S
options, options,
} }
.parse() .parse()
.map_err(|e| raw_to_parse_error(&map, *e).to_string())?; .map_err(|e| raw_to_parse_error(&map, *e, options.unicode_error_messages).to_string())?;
Ok(Css::from_stmts(stmts, false) Ok(Css::from_stmts(stmts, false)
.map_err(|e| raw_to_parse_error(&map, *e).to_string())? .map_err(|e| raw_to_parse_error(&map, *e, options.unicode_error_messages).to_string())?
.pretty_print(&map) .pretty_print(&map)
.map_err(|e| raw_to_parse_error(&map, *e).to_string())?) .map_err(|e| raw_to_parse_error(&map, *e, options.unicode_error_messages).to_string())?)
} }

View File

@ -153,14 +153,12 @@ fn main() -> std::io::Result<()> {
.arg( .arg(
Arg::with_name("NO_UNICODE") Arg::with_name("NO_UNICODE")
.long("no-unicode") .long("no-unicode")
.hidden(true)
.help("Whether to use Unicode characters for messages.") .help("Whether to use Unicode characters for messages.")
) )
.arg( .arg(
Arg::with_name("QUIET") Arg::with_name("QUIET")
.short("q") .short("q")
.long("quiet") .long("quiet")
.hidden(true)
.help("Don't print warnings."), .help("Don't print warnings."),
) )
.arg( .arg(
@ -189,7 +187,10 @@ fn main() -> std::io::Result<()> {
vals = Vec::new(); vals = Vec::new();
} }
let options = &Options::default().load_paths(&vals); let options = &Options::default()
.load_paths(&vals)
.quiet(matches.is_present("QUIET"))
.unicode_error_messages(!matches.is_present("NO_UNICODE"));
if let Some(name) = matches.value_of("INPUT") { if let Some(name) = matches.value_of("INPUT") {
if let Some(path) = matches.value_of("OUTPUT") { if let Some(path) = matches.value_of("OUTPUT") {