Skip to content

Commit

Permalink
toggle-backtrace accepts an optional level: 1 or full (#219)
Browse files Browse the repository at this point in the history
Fix #210

With this PR, it's possible to decide that the backtrace level, when enabled, won't be "1" but "full" by adding this to your bacon.toml

```
[keybindings]
b = "toggle-backtrace(full)"

```

Of course you can bind to a different key.

This is experimental and may change depending on feedback (if you use it, do report).
  • Loading branch information
Canop authored Oct 5, 2024
1 parent b0e5b66 commit 861f6b3
Show file tree
Hide file tree
Showing 13 changed files with 416 additions and 29 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
- support for nextest output & default nextest job, bound by default to the 'n' key - Fix #196
- new `exports` structure in configuration. New `analysis` export bound by default to `ctrl-e`. The old syntax defining locations export is still supported but won't appear in documentations anymore.
- recognize panic location in test - Fix #208
- `toggle-backtrace` accepts an optional level: `toggle-backtrace(1)` or `toggle-backtrace(full)` - Experimental - Fix #210

<a name="v2.21.0"></a>
### v2.21.0 - 2024/09/14
Expand Down
1 change: 1 addition & 0 deletions defaults/default-prefs.toml
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ path = "bacon-analysis.json"
# s = "toggle-summary"
# w = "toggle-wrap"
# b = "toggle-backtrace"
# f = "toggle-backtrace(full)"
# Home = "scroll-to-top"
# End = "scroll-to-bottom"
# Up = "scroll-lines(-1)"
Expand Down
2 changes: 1 addition & 1 deletion src/analysis/standard_analyzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub fn analyze_line(cmd_line: &CommandOutputLine) -> LineAnalysis {
} else if regex_is_match!("^failures:$", content) {
// this isn't very discriminant...
LineType::Title(Kind::Sum)
} else if regex_is_match!("^note: run with `RUST_BACKTRACE=", content) {
} else if regex_is_match!("[Rr]un with (`)?RUST_BACKTRACE=", content) {
LineType::BacktraceSuggestion
} else if regex_is_match!(r#", [^:\s'"]+:\d+:\d+$"#, content) {
// this kind of location comes up in test failures
Expand Down
4 changes: 2 additions & 2 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,8 +201,8 @@ pub fn run(
Internal::ToggleWrap => {
state.toggle_wrap_mode();
}
Internal::ToggleBacktrace => {
state.toggle_backtrace();
Internal::ToggleBacktrace(level) => {
state.toggle_backtrace(level);
task_executor.die();
task_executor = state.start_computation(&mut executor)?;
}
Expand Down
15 changes: 14 additions & 1 deletion src/command_result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,12 @@ impl CommandResult {
if report.stats.errors + report.stats.test_fails == 0 {
// report shows no error while the command exe reported
// an error, so the report can't be trusted
return Ok(Self::Failure(Failure { error_code, output }));
let suggest_backtrace = report.suggest_backtrace;
return Ok(Self::Failure(Failure {
error_code,
output,
suggest_backtrace,
}));
}
}
report.output = output;
Expand All @@ -56,6 +61,14 @@ impl CommandResult {
}
}

pub fn suggest_backtrace(&self) -> bool {
match self {
Self::Report(report) => report.suggest_backtrace,
Self::Failure(failure) => failure.suggest_backtrace,
_ => false,
}
}

/// return true when the report has been computed and there's been no
/// error, warning, or test failures
pub fn is_success(&self) -> bool {
Expand Down
4 changes: 2 additions & 2 deletions src/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ enum StopMessage {
/// Settings for one execution of job's command
#[derive(Debug, Clone, Copy, PartialEq, Default)]
pub struct Task {
pub backtrace: bool,
pub backtrace: Option<&'static str>,
}

impl TaskExecutor {
Expand Down Expand Up @@ -105,7 +105,7 @@ impl MissionExecutor {
info!("start task {task:?}");
let mut child = self
.command
.env("RUST_BACKTRACE", if task.backtrace { "1" } else { "0" })
.env("RUST_BACKTRACE", task.backtrace.unwrap_or("0"))
.spawn()
.context("failed to launch command")?;
let kill_command = self.kill_command.clone();
Expand Down
1 change: 1 addition & 0 deletions src/failure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ use {
pub struct Failure {
pub error_code: i32,
pub output: CommandOutput,
pub suggest_backtrace: bool,
}
16 changes: 9 additions & 7 deletions src/help_line.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ impl HelpLine {
.shortest_internal_key(Internal::ToggleWrap)
.map(|k| format!("*{k}* to not wrap lines"));
let toggle_backtrace = kb
.shortest_internal_key(Internal::ToggleBacktrace)
.shortest_action_key(|action| {
matches!(action, Action::Internal(Internal::ToggleBacktrace(_)))
})
.map(|k| format!("*{k}* to toggle backtraces"));
let help = kb
.shortest_internal_key(Internal::Help)
Expand Down Expand Up @@ -73,12 +75,12 @@ impl HelpLine {
parts.push(s);
}
}
if let CommandResult::Report(report) = &state.cmd_result {
if report.suggest_backtrace {
if let Some(s) = &self.toggle_backtrace {
parts.push(s);
}
} else if !state.mission.is_success(report) {
if state.cmd_result.suggest_backtrace() {
if let Some(s) = &self.toggle_backtrace {
parts.push(s);
}
} else if let CommandResult::Report(report) = &state.cmd_result {
if !state.mission.is_success(report) {
if let Some(s) = &self.toggle_summary {
parts.push(s);
}
Expand Down
9 changes: 6 additions & 3 deletions src/internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub enum Internal {
Refresh, // clear and rerun
ReRun,
Scroll(ScrollCommand),
ToggleBacktrace,
ToggleBacktrace(&'static str),
ToggleRawOutput,
ToggleSummary,
ToggleWrap,
Expand All @@ -34,7 +34,7 @@ impl fmt::Display for Internal {
Self::Refresh => write!(f, "clear then run current job again"),
Self::ReRun => write!(f, "run current job again"),
Self::Scroll(scroll_command) => scroll_command.fmt(f),
Self::ToggleBacktrace => write!(f, "toggle backtrace"),
Self::ToggleBacktrace(level) => write!(f, "toggle backtrace ({level})"),
Self::ToggleRawOutput => write!(f, "toggle raw output"),
Self::ToggleSummary => write!(f, "toggle summary"),
Self::ToggleWrap => write!(f, "toggle wrap"),
Expand All @@ -58,7 +58,10 @@ impl std::str::FromStr for Internal {
"refresh" => Ok(Self::Refresh),
"rerun" => Ok(Self::ReRun),
"toggle-raw-output" => Ok(Self::ToggleRawOutput),
"toggle-backtrace" => Ok(Self::ToggleBacktrace),
"toggle-backtrace" => Ok(Self::ToggleBacktrace("1")),
"toggle-backtrace(1)" => Ok(Self::ToggleBacktrace("1")),
"toggle-backtrace(2)" => Ok(Self::ToggleBacktrace("2")),
"toggle-backtrace(full)" => Ok(Self::ToggleBacktrace("full")),
"toggle-summary" => Ok(Self::ToggleSummary),
"toggle-wrap" => Ok(Self::ToggleWrap),
"pause" => Ok(Self::Pause),
Expand Down
22 changes: 16 additions & 6 deletions src/keybindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ impl Default for KeyBindings {
bindings.set(key!(F5), Internal::Refresh);
bindings.set(key!(s), Internal::ToggleSummary);
bindings.set(key!(w), Internal::ToggleWrap);
bindings.set(key!(b), Internal::ToggleBacktrace);
bindings.set(key!(b), Internal::ToggleBacktrace("1"));
bindings.set(key!(Home), Internal::Scroll(ScrollCommand::Top));
bindings.set(key!(End), Internal::Scroll(ScrollCommand::Bottom));
bindings.set(key!(Up), Internal::Scroll(ScrollCommand::Lines(-1)));
Expand Down Expand Up @@ -83,14 +83,16 @@ impl KeyBindings {
self.map.get(&key)
}
/// return the shortest key.to_string for the internal, if any
pub fn shortest_internal_key(
pub fn shortest_action_key<F>(
&self,
internal: Internal,
) -> Option<String> {
filter: F,
) -> Option<String>
where
F: Fn(&Action) -> bool,
{
let mut shortest: Option<String> = None;
let searched_action = Action::Internal(internal);
for (ck, action) in &self.map {
if action == &searched_action {
if filter(action) {
let s = ck.to_string();
match &shortest {
Some(previous) if previous.len() < s.len() => {}
Expand All @@ -102,6 +104,14 @@ impl KeyBindings {
}
shortest
}
/// return the shortest key.to_string for the internal, if any
pub fn shortest_internal_key(
&self,
internal: Internal,
) -> Option<String> {
let internal_action = Action::Internal(internal);
self.shortest_action_key(|action| action == &internal_action)
}
/// build and return a map from actions to all the possible shortcuts
pub fn build_reverse_map(&self) -> HashMap<&Action, Vec<KeyCombination>> {
let mut reverse_map = HashMap::new();
Expand Down
17 changes: 12 additions & 5 deletions src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ pub struct AppState<'s> {
computing: bool,
/// whether the user wants wrapped lines
pub wrap: bool,
/// whether the user wants backtraces
pub backtrace: bool,
/// the optional RUST_BACKTRACE env var to set
pub backtrace: Option<&'static str>,
/// whether we should display only titles and locations
summary: bool,
/// whether we display the gui bottom-to-top
Expand Down Expand Up @@ -92,7 +92,7 @@ impl<'s> AppState<'s> {
computing: true,
summary: mission.settings.summary,
wrap: mission.settings.wrap,
backtrace: false,
backtrace: None,
reverse: mission.settings.reverse,
show_changes_count: mission.settings.show_changes_count,
status_skin,
Expand Down Expand Up @@ -309,8 +309,15 @@ impl<'s> AppState<'s> {
self.summary ^= true;
self.try_scroll_to_last_top_item();
}
pub fn toggle_backtrace(&mut self) {
self.backtrace ^= true;
pub fn toggle_backtrace(
&mut self,
level: &'static str,
) {
self.backtrace = if self.backtrace == Some(level) {
None
} else {
Some(level)
};
}
pub fn toggle_wrap_mode(&mut self) {
self.wrap ^= true;
Expand Down
Loading

0 comments on commit 861f6b3

Please sign in to comment.