diff --git a/defaults/default-prefs.toml b/defaults/default-prefs.toml index 465fef5..e04649d 100644 --- a/defaults/default-prefs.toml +++ b/defaults/default-prefs.toml @@ -29,8 +29,15 @@ # Set 'enabled' to true to have bacon always export locations # This is equivalent to always adding -e to bacon commands # but can still be cancelled on specific launches with -E +# +# 'add_context_to_message' is used to control whether to ad +# any normal line linked to the diagnostic title. When this +# is on, carriage returns are escaped to ensure we generate +# everything on a single line. They can be expande by replacing +# '\\n' with '\n' when read from the export locations file. [export] enabled = false +add_context_to_message = false path = ".bacon-locations" line_format = "{kind} {path}:{line}:{column} {message}" diff --git a/src/export_config.rs b/src/export_config.rs index 2d6d8e9..f029598 100644 --- a/src/export_config.rs +++ b/src/export_config.rs @@ -10,4 +10,5 @@ pub struct ExportConfig { pub enabled: Option, pub path: Option, pub line_format: Option, + pub add_context_to_message: Option } diff --git a/src/export_settings.rs b/src/export_settings.rs index 012f1ff..aad8a06 100644 --- a/src/export_settings.rs +++ b/src/export_settings.rs @@ -9,6 +9,7 @@ pub struct ExportSettings { pub enabled: bool, pub path: PathBuf, pub line_format: String, + pub add_context_to_message: bool } impl Default for ExportSettings { @@ -17,6 +18,7 @@ impl Default for ExportSettings { enabled: false, path: default_path(), line_format: default_line_format().to_string(), + add_context_to_message: false } } } @@ -45,5 +47,8 @@ impl ExportSettings { if let Some(line_format) = &config.line_format { self.line_format.clone_from(line_format); } + if let Some(add_context_to_message) = config.add_context_to_message { + self.add_context_to_message = add_context_to_message; + } } } diff --git a/src/line.rs b/src/line.rs index 4124cb9..82d1450 100644 --- a/src/line.rs +++ b/src/line.rs @@ -30,6 +30,22 @@ impl Line { _ => None, } } + + /// If the line is normal. get its messages + pub fn context(&self) -> Option { + match self.line_type { + LineType::Normal => Some( + self.content + .strings + .iter() + .map(|ts| ts.raw.as_str()) + .collect::>() + .join(""), + ), + _ => None, + } + } + /// Return the location as given by cargo /// It's usually relative and may contain the line and column pub fn location(&self) -> Option<&str> { diff --git a/src/report.rs b/src/report.rs index 6339bd7..7a226ab 100644 --- a/src/report.rs +++ b/src/report.rs @@ -2,11 +2,7 @@ use { crate::*, anyhow::Result, lazy_regex::*, - std::{ - collections::HashSet, - io, - path::PathBuf, - }, + std::{collections::HashSet, io, path::PathBuf}, }; /// the usable content of cargo watch's output, @@ -167,6 +163,51 @@ impl Report { output: CommandOutput::default(), }) } + + /// Extract all the diagnostic context. + fn extract_diagnostic_context( + &self, + line: &Line, + ) -> Option { + let mut context = String::new(); + for l in &self.lines { + if let LineType::Normal = l.line_type { + if l.item_idx == line.item_idx { + if let Some(ctx) = l.context() { + context = format!("{context}\n{ctx}"); + } + } + } + } + if context.is_empty() { + None + } else { + Some(context.replace("\n", "\\n")) + } + } + + /// Compose the message. + /// + /// If `add_context_to_message` is true and there is context to this error, + /// it will be added to the exported line. + fn compose_message( + &self, + message: Option<&str>, + context: Option, + add_context_to_message: bool, + ) -> String { + if let Some(message) = message { + if add_context_to_message { + if let Some(context) = context { + return format!("{message}{context}"); + } + } + message.to_string() + } else { + "".to_string() + } + } + /// export the report in a file pub fn write_to( &self, @@ -175,19 +216,29 @@ impl Report { ) -> Result<(), io::Error> { let mut last_kind = "???"; let mut message = None; + let mut context = None; for line in &self.lines { match line.line_type { LineType::Title(Kind::Warning) => { last_kind = "warning"; message = line.title_message(); + if mission.settings.export.add_context_to_message { + context = self.extract_diagnostic_context(line); + } } LineType::Title(Kind::Error) => { last_kind = "error"; message = line.title_message(); + if mission.settings.export.add_context_to_message { + context = self.extract_diagnostic_context(line); + } } LineType::Title(Kind::TestFail) => { last_kind = "test"; message = line.title_message(); + if mission.settings.export.add_context_to_message { + context = self.extract_diagnostic_context(line); + } } _ => {} } @@ -208,6 +259,12 @@ impl Report { .to_string(); path = &path_string; } + let message = self.compose_message( + message, + context, + mission.settings.export.add_context_to_message, + ); + context = None; let exported = regex_replace_all!( r#"\{([^\s}]+)\}"#, &mission.settings.export.line_format, @@ -217,7 +274,7 @@ impl Report { "path" => path, "line" => file_line, "column" => file_column, - "message" => message.unwrap_or(""), + "message" => &message, _ => { debug!("unknown export key: {key:?}"); ""