diff --git a/src/error.rs b/src/error.rs index da1a1fc..478d287 100644 --- a/src/error.rs +++ b/src/error.rs @@ -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 { - kind: SassErrorKind::ParseError { message, loc }, + kind: SassErrorKind::ParseError { + message, + loc, + unicode, + }, } } } @@ -60,6 +64,7 @@ enum SassErrorKind { ParseError { message: String, loc: SpanLoc, + unicode: bool, }, // we put IoErrors in an `Rc` to allow it to be // cloneable @@ -73,30 +78,47 @@ impl Display for SassError { // TODO: integrate with codemap-diagnostics #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let (message, loc) = match &self.kind { - SassErrorKind::ParseError { message, loc } => (message, loc), + let (message, loc, unicode) = match &self.kind { + SassErrorKind::ParseError { + message, + loc, + unicode, + } => (message, loc, *unicode), SassErrorKind::FromUtf8Error(s) => return writeln!(f, "Error: {}", s), SassErrorKind::IoError(s) => return writeln!(f, "Error: {}", s), 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 col = loc.begin.column + 1; writeln!(f, "Error: {}", message)?; let padding = vec![' '; format!("{}", line).len() + 1] .iter() .collect::(); - writeln!(f, "{}|", padding)?; - writeln!(f, "{} | {}", line, loc.file.source_line(loc.begin.line))?; + writeln!(f, "{}{}", padding, first_bar)?; writeln!( f, - "{}| {}{}", + "{} {} {}", + line, + second_bar, + loc.file.source_line(loc.begin.line) + )?; + writeln!( + f, + "{}{} {}{}", padding, + third_bar, vec![' '; loc.begin.column].iter().collect::(), vec!['^'; loc.end.column.max(loc.begin.column) - loc.begin.column.min(loc.end.column)] .iter() .collect::() )?; - writeln!(f, "{}|", padding)?; + writeln!(f, "{}{}", padding, fourth_bar)?; writeln!(f, "./{}:{}:{}", loc.file.name(), line, col)?; Ok(()) } diff --git a/src/lib.rs b/src/lib.rs index 1234886..575cd8a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -252,9 +252,9 @@ impl<'a> Options<'a> { } } -fn raw_to_parse_error(map: &CodeMap, err: Error) -> Box { +fn raw_to_parse_error(map: &CodeMap, err: Error, unicode: bool) -> Box { 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 @@ -294,12 +294,12 @@ pub fn from_path(p: &str, options: &Options) -> Result { options, } .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) - .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) - .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 @@ -338,12 +338,12 @@ pub fn from_string(p: String, options: &Options) -> Result { options, } .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) - .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) - .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")] @@ -373,10 +373,10 @@ pub fn from_string(p: String, options: &'_ Options<'_>) -> std::result::Result std::io::Result<()> { .arg( Arg::with_name("NO_UNICODE") .long("no-unicode") - .hidden(true) .help("Whether to use Unicode characters for messages.") ) .arg( Arg::with_name("QUIET") .short("q") .long("quiet") - .hidden(true) .help("Don't print warnings."), ) .arg( @@ -189,7 +187,10 @@ fn main() -> std::io::Result<()> { 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(path) = matches.value_of("OUTPUT") {