Skip to content

Commit 1e017e8

Browse files
authored
fix: preserve prompt position after ExternalBreak (#1042)
1 parent 0080077 commit 1e017e8

2 files changed

Lines changed: 20 additions & 11 deletions

File tree

examples/break_signal.rs

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
// Demonstrates the external break signal feature.
2-
// A background thread sets the break signal after 3 seconds,
2+
//
3+
// A background thread sets the break signal every 5 seconds,
34
// causing `read_line()` to return `Signal::ExternalBreak` with
4-
// the current buffer contents.
5+
// the current buffer contents. The example then resumes editing
6+
// by calling `read_line()` again — the prompt stays on the same
7+
// line thanks to suspended-state preservation.
58
//
69
// To run:
710
// cargo run --example break_signal
@@ -23,15 +26,15 @@ fn main() -> io::Result<()> {
2326
let mut line_editor = Reedline::create().with_break_signal(break_signal.clone());
2427
let prompt = DefaultPrompt::default();
2528

26-
// Spawn a thread that triggers the break signal after 3 seconds
29+
// Spawn a thread that triggers the break signal periodically
2730
let signal = break_signal.clone();
28-
thread::spawn(move || {
29-
thread::sleep(Duration::from_secs(3));
30-
println!("\n[background] Setting break signal in...");
31+
thread::spawn(move || loop {
32+
thread::sleep(Duration::from_secs(5));
3133
signal.store(true, Ordering::Relaxed);
3234
});
3335

34-
println!("Type something. The break signal will fire in 3 seconds...");
36+
println!("Type something. The break signal fires every 5 seconds.");
37+
println!("The prompt will stay in place after each ExternalBreak.\n");
3538

3639
loop {
3740
let sig = line_editor.read_line(&prompt)?;
@@ -44,8 +47,13 @@ fn main() -> io::Result<()> {
4447
break Ok(());
4548
}
4649
Signal::ExternalBreak(buffer) => {
47-
println!("\nExternalBreak received! Buffer contents: {buffer:?}");
48-
break Ok(());
50+
// The buffer contents are preserved across the break.
51+
// Simply call read_line() again to let the user continue
52+
// editing — the prompt stays on the same line as long as
53+
// nothing is printed between the break and the next
54+
// read_line() call.
55+
eprintln!("[break] buffer: {buffer:?}");
56+
continue;
4957
}
5058
_ => {}
5159
}

src/engine.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -797,7 +797,7 @@ impl Reedline {
797797
self.painter
798798
.initialize_prompt_position(self.suspended_state.as_ref())?;
799799
if self.suspended_state.is_some() {
800-
// Last editor was suspended to run a ExecuteHostCommand event,
800+
// Last editor was suspended (ExecuteHostCommand or ExternalBreak),
801801
// we are resuming operation now.
802802
self.suspended_state = None;
803803
}
@@ -816,7 +816,8 @@ impl Reedline {
816816
if signal.swap(false, std::sync::atomic::Ordering::Relaxed) {
817817
let buffer = self.editor.get_buffer().to_string();
818818
self.input_mode = InputMode::Regular;
819-
self.painter.move_cursor_to_end()?;
819+
self.last_render_snapshot = None;
820+
self.suspended_state = Some(self.painter.state_before_suspension());
820821
self.editor.reset_undo_stack();
821822
return Ok(Signal::ExternalBreak(buffer));
822823
}

0 commit comments

Comments
 (0)