feat: run shell commands asynchronously from command mode
This commit is contained in:
@@ -4,6 +4,77 @@ use std::{
|
||||
sync::atomic::{AtomicU64, Ordering},
|
||||
};
|
||||
|
||||
#[cfg(unix)]
|
||||
#[test]
|
||||
fn shell_commands_leave_editing_live_and_present_both_streams_and_exit_status() {
|
||||
let fixture = Fixture::new();
|
||||
fixture.file("buffer.txt", "source");
|
||||
let mut session = fixture.open("");
|
||||
session.editor.set_project_root(fixture.0.clone());
|
||||
for ch in
|
||||
":!while [ ! -f release ]; do sleep 0.01; done; pwd; printf 'out'; printf 'err' >&2; exit 7"
|
||||
.chars()
|
||||
{
|
||||
session.handle(Input::Char(ch));
|
||||
}
|
||||
session.handle(Input::Enter);
|
||||
let fixed = Instant::now();
|
||||
session.shell.as_mut().unwrap().2 = fixed;
|
||||
assert!(session.poll_shell_at(fixed + Duration::from_millis(100)));
|
||||
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"]);
|
||||
fixture.file("release", "");
|
||||
drain_until(&mut session, |session| {
|
||||
session.editor.command_output().is_some()
|
||||
});
|
||||
let output = session.editor.command_output().unwrap();
|
||||
assert!(output.title.contains("exit 7"));
|
||||
let text = output.content.lines.join("\n");
|
||||
assert!(text.contains(fixture.0.to_str().unwrap()));
|
||||
assert!(text.ends_with("out\n[stderr]\nerr"), "{text}");
|
||||
assert_eq!(session.editor.shell_label(), "");
|
||||
assert_eq!(session.editor.mode(), Mode::Insert);
|
||||
session.handle(Input::Char('Z'));
|
||||
assert_eq!(session.editor.lines(), ["Xsource"]);
|
||||
session.handle(Input::Escape);
|
||||
session.handle(Input::Char('Y'));
|
||||
assert_eq!(session.editor.lines(), ["XYsource"]);
|
||||
assert_eq!(
|
||||
fs::read_to_string(fixture.0.join("buffer.txt")).unwrap(),
|
||||
"source"
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[test]
|
||||
fn shell_commands_reject_empty_input_and_show_empty_success_without_editing() {
|
||||
let fixture = Fixture::new();
|
||||
fixture.file("buffer.txt", "source");
|
||||
let mut session = fixture.open("");
|
||||
session.execute(":!");
|
||||
assert_eq!(session.editor.message(), "Shell command is empty");
|
||||
assert!(session.shell.is_none());
|
||||
session.execute(":!true");
|
||||
drain_until(&mut session, |session| {
|
||||
session.editor.command_output().is_some()
|
||||
});
|
||||
let output = session.editor.command_output().unwrap();
|
||||
assert_eq!(output.content.lines, ["(no output)"]);
|
||||
assert!(output.title.contains("exit 0"));
|
||||
session.handle(Input::Enter);
|
||||
assert!(session.editor.command_output().is_none());
|
||||
assert_eq!(session.editor.lines(), ["source"]);
|
||||
assert!(!session.editor.dirty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn oversized_repository_text_skips_snapshots_and_recovers_after_shrinking() {
|
||||
let fixture = Fixture::new();
|
||||
|
||||
Reference in New Issue
Block a user