Skip to content

Commit 9e45df5

Browse files
authored
DUX-5095 stdout: add buffer_and_drain_prompts and read_until_marker (#432)
1 parent 4fd9349 commit 9e45df5

2 files changed

Lines changed: 38 additions & 2 deletions

File tree

src/ghci/stdout.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::time::Duration;
2+
13
use aho_corasick::AhoCorasick;
24
use miette::Context;
35
use miette::IntoDiagnostic;
@@ -98,6 +100,42 @@ impl GhciStdout {
98100
Ok(())
99101
}
100102

103+
/// Read any immediately-available output from the pipe, then drain stale prompts from
104+
/// the internal buffer. Returns the number of prompts found and discarded.
105+
#[expect(unused)]
106+
pub async fn buffer_and_drain_prompts(&mut self, timeout: Duration) -> miette::Result<usize> {
107+
self.reader
108+
.buffer_available(&mut self.buffer, timeout, WriteBehavior::NoFinalLine)
109+
.await?;
110+
111+
self.reader
112+
.drain_buffered_chunks(&ReadOpts {
113+
end_marker: &self.prompt_patterns,
114+
find: FindAt::Anywhere,
115+
writing: WriteBehavior::NoFinalLine,
116+
buffer: &mut self.buffer,
117+
})
118+
.await
119+
}
120+
121+
/// Read stdout until the given marker string is found, discarding everything before it.
122+
///
123+
/// Used by `send_sigint` to synchronize with GHCi after an interrupt: a sync expression
124+
/// is sent on stdin and this method reads until its output appears, guaranteeing that all
125+
/// prior output has been consumed.
126+
#[expect(unused)]
127+
pub async fn read_until_marker(&mut self, marker: &str) -> miette::Result<String> {
128+
let pattern = AhoCorasick::from_anchored_patterns([marker]);
129+
self.reader
130+
.read_until(&mut ReadOpts {
131+
end_marker: &pattern,
132+
find: FindAt::Anywhere,
133+
writing: WriteBehavior::NoFinalLine,
134+
buffer: &mut self.buffer,
135+
})
136+
.await
137+
}
138+
101139
#[instrument(skip_all, level = "debug")]
102140
pub async fn show_paths(&mut self) -> miette::Result<ShowPaths> {
103141
let lines = self

src/incremental_reader.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,6 @@ where
177177
/// This method is cancel-safe: decoded data is stored in `self.pending` (synchronously,
178178
/// before any `.await`) so it survives if the future is dropped. Any un-forwarded data in
179179
/// `pending` is drained on the next operation via [`Self::drain_pending`].
180-
#[expect(unused)]
181180
pub async fn buffer_available(
182181
&mut self,
183182
buffer: &mut [u8],
@@ -419,7 +418,6 @@ where
419418
///
420419
/// This is used after `send_sigint` to discard stale prompts left behind by an aborted
421420
/// `prompt()` call. Returns the number of chunks drained.
422-
#[cfg_attr(not(test), expect(unused))]
423421
pub async fn drain_buffered_chunks(&mut self, opts: &ReadOpts<'_>) -> miette::Result<usize> {
424422
self.drain_pending(opts.writing).await?;
425423
let mut count = 0;

0 commit comments

Comments
 (0)