fix: place command status left of battery as a separate segment

This commit is contained in:
2026-10-18 01:35:52 +02:00
parent e310b76794
commit d8cfd27ee6
10 changed files with 165 additions and 58 deletions
+61 -8
View File
@@ -4,6 +4,65 @@ use std::{
sync::atomic::{AtomicU64, Ordering},
};
#[cfg(unix)]
#[test]
fn concurrent_shell_commands_share_status_and_queue_every_completed_output() {
let fixture = Fixture::new();
fixture.file("buffer.txt", "source");
let mut session = fixture.open("");
session.editor.set_project_root(fixture.0.clone());
session.execute("!printf FIRST; while [ ! -f first ]; do sleep 0.01; done");
session.execute("!echo SECOND; while [ ! -f second ]; do sleep 0.01; done; exit 9");
assert_eq!(session.shell.len(), 2);
let fixed = Instant::now();
for running in &mut session.shell {
running.started = fixed;
}
session.poll_shell_at(fixed + Duration::from_millis(199));
assert_eq!(session.editor.shell_label(), "");
session.poll_shell_at(fixed + Duration::from_millis(200));
assert_eq!(session.editor.shell_label(), "pri... - ech... -");
fixture.file("second", "");
drain_until(&mut session, |session| session.shell.len() == 1);
assert_eq!(
session.editor.command_output().unwrap().content.lines[0],
"SECOND"
);
assert!(
session
.editor
.command_output()
.unwrap()
.title
.contains("exit 9")
);
assert!(session.editor.shell_label().starts_with("pri... "));
assert!(!session.editor.shell_label().contains("ech..."));
fixture.file("first", "");
drain_until(&mut session, |session| session.shell.is_empty());
assert_eq!(session.editor.shell_label(), "");
assert_eq!(
session.editor.command_output().unwrap().content.lines[0],
"SECOND"
);
session.handle(Input::Enter);
assert_eq!(
session.editor.command_output().unwrap().content.lines,
["FIRST"]
);
assert!(
session
.editor
.command_output()
.unwrap()
.title
.contains("exit 0")
);
session.handle(Input::Escape);
assert!(session.editor.command_output().is_none());
assert_eq!(session.editor.lines(), ["source"]);
}
#[cfg(unix)]
#[test]
fn shell_commands_leave_editing_live_and_present_both_streams_and_exit_status() {
@@ -19,17 +78,11 @@ fn shell_commands_leave_editing_live_and_present_both_streams_and_exit_status()
}
session.handle(Input::Enter);
let fixed = Instant::now();
session.shell.as_mut().unwrap().2 = fixed;
session.shell[0].started = fixed;
assert!(!session.poll_shell_at(fixed + Duration::from_millis(199)));
assert_eq!(session.editor.shell_label(), "");
assert!(session.poll_shell_at(fixed + Duration::from_millis(200)));
assert_eq!(session.editor.shell_label(), "whi... -");
session.execute("!printf should-not-run > unexpected");
assert_eq!(
session.editor.message(),
"A shell command is already running"
);
assert!(!fixture.0.join("unexpected").exists());
session.handle(Input::Char('i'));
session.handle(Input::Char('X'));
assert_eq!(session.editor.lines(), ["Xsource"]);
@@ -63,7 +116,7 @@ fn shell_commands_reject_empty_input_and_show_empty_success_without_editing() {
let mut session = fixture.open("");
session.execute(":!");
assert_eq!(session.editor.message(), "Shell command is empty");
assert!(session.shell.is_none());
assert!(session.shell.is_empty());
session.execute(":!true");
drain_until(&mut session, |session| {
session.editor.command_output().is_some()
+21
View File
@@ -15528,3 +15528,24 @@ fn shell_output_wrap_bindings_respect_remaps_disabled_keys_and_sequence_cancella
editor.handle(Input::Escape);
assert!(editor.command_output().is_none());
}
#[test]
fn shared_shell_status_is_a_separate_segment_left_of_the_battery() {
let mut editor = Editor::open(None, vec![]).unwrap();
editor.set_battery_charge(Some(27));
editor.set_shell_label("sle... | pwd /".into());
let mut terminal = Terminal::new(ratatui::backend::TestBackend::new(80, 12)).unwrap();
let mut views = BufferViewports::default();
terminal
.draw(|frame| views.draw(frame, &mut editor))
.unwrap();
let top = pane_screen(&terminal, Rect::new(0, 0, 80, 1));
assert!(top.contains("░▓ sle... | pwd / ▓░ ░▓ bat 27%"), "{top}");
editor.set_shell_label(String::new());
terminal
.draw(|frame| views.draw(frame, &mut editor))
.unwrap();
let top = pane_screen(&terminal, Rect::new(0, 0, 80, 1));
assert!(!top.contains("sle..."));
assert!(top.trim_end().ends_with("bat 27%"), "{top}");
}