mirror of
https://github.com/openai/codex.git
synced 2026-10-21 05:09:33 +00:00
Simplify the custom terminal drawing API (#53156)
## What changed Remove `Terminal::autoresize` and the fallible `try_draw` helpers. Render directly in `draw_with_size`, retaining automatic size updates and the existing buffer flush and cursor handling. Update the cursor-ordering test to use `draw`, preserving its assertion that the cursor moves before it is shown. GitOrigin-RevId: 5889e9603d772945660e7ae35690d2b7326b10ae
This commit is contained in:
committed by
copyberry
parent
95db2cd5d5
commit
72f999edc7
@@ -326,25 +326,8 @@ where
|
||||
self.visible_history_rows = self.visible_history_rows.min(area.top());
|
||||
}
|
||||
|
||||
/// Queries the backend for size and resizes if it doesn't match the previous size.
|
||||
pub fn autoresize(&mut self) -> io::Result<()> {
|
||||
let screen_size = self.size()?;
|
||||
if screen_size != self.last_known_screen_size {
|
||||
self.resize(screen_size)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Draws a single frame to the terminal.
|
||||
///
|
||||
/// Returns a [`CompletedFrame`] if successful, otherwise a [`std::io::Error`].
|
||||
///
|
||||
/// If the render callback passed to this method can fail, use [`try_draw`] instead.
|
||||
///
|
||||
/// Applications should call `draw` or [`try_draw`] in a loop to continuously render the
|
||||
/// terminal. These methods are the main entry points for drawing to the terminal.
|
||||
///
|
||||
/// [`try_draw`]: Terminal::try_draw
|
||||
/// Applications should call `draw` in a loop to continuously render the terminal.
|
||||
///
|
||||
/// This method will:
|
||||
///
|
||||
@@ -367,71 +350,20 @@ where
|
||||
}
|
||||
|
||||
/// Draws a single frame using a screen size already obtained by the caller.
|
||||
pub(crate) fn draw_with_size<F>(&mut self, screen_size: Size, render: F) -> io::Result<()>
|
||||
pub(crate) fn draw_with_size<F>(
|
||||
&mut self,
|
||||
screen_size: Size,
|
||||
render_callback: F,
|
||||
) -> io::Result<()>
|
||||
where
|
||||
F: FnOnce(&mut Frame),
|
||||
{
|
||||
self.try_draw_with_size(screen_size, |frame| {
|
||||
render(frame);
|
||||
io::Result::Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
/// Tries to draw a single frame to the terminal.
|
||||
///
|
||||
/// Returns [`Result::Ok`] containing a [`CompletedFrame`] if successful, otherwise
|
||||
/// [`Result::Err`] containing the [`std::io::Error`] that caused the failure.
|
||||
///
|
||||
/// This is the equivalent of [`Terminal::draw`] but the render callback is a function or
|
||||
/// closure that returns a `Result` instead of nothing.
|
||||
///
|
||||
/// Applications should call `try_draw` or [`draw`] in a loop to continuously render the
|
||||
/// terminal. These methods are the main entry points for drawing to the terminal.
|
||||
///
|
||||
/// [`draw`]: Terminal::draw
|
||||
///
|
||||
/// This method will:
|
||||
///
|
||||
/// - autoresize the terminal if necessary
|
||||
/// - call the render callback, passing it a [`Frame`] reference to render to
|
||||
/// - flush the current internal state by copying the current buffer to the backend
|
||||
/// - move the cursor to the last known position if it was set during the rendering closure
|
||||
/// - return a [`CompletedFrame`] with the current buffer and the area of the terminal
|
||||
///
|
||||
/// The render callback passed to `try_draw` can return any [`Result`] with an error type that
|
||||
/// can be converted into an [`std::io::Error`] using the [`Into`] trait. This makes it possible
|
||||
/// to use the `?` operator to propagate errors that occur during rendering. If the render
|
||||
/// callback returns an error, the error will be returned from `try_draw` as an
|
||||
/// [`std::io::Error`] and the terminal will not be updated.
|
||||
///
|
||||
/// The [`CompletedFrame`] returned by this method can be useful for debugging or testing
|
||||
/// purposes, but it is often not used in regular applicationss.
|
||||
///
|
||||
/// The render callback should fully render the entire frame when called, including areas that
|
||||
/// are unchanged from the previous frame. This is because each frame is compared to the
|
||||
/// previous frame to determine what has changed, and only the changes are written to the
|
||||
/// terminal. If the render function does not fully render the frame, the terminal will not be
|
||||
/// in a consistent state.
|
||||
pub fn try_draw<F, E>(&mut self, render_callback: F) -> io::Result<()>
|
||||
where
|
||||
F: FnOnce(&mut Frame) -> Result<(), E>,
|
||||
E: Into<io::Error>,
|
||||
{
|
||||
let screen_size = self.size()?;
|
||||
self.try_draw_with_size(screen_size, render_callback)
|
||||
}
|
||||
|
||||
fn try_draw_with_size<F, E>(&mut self, screen_size: Size, render_callback: F) -> io::Result<()>
|
||||
where
|
||||
F: FnOnce(&mut Frame) -> Result<(), E>,
|
||||
E: Into<io::Error>,
|
||||
{
|
||||
if screen_size != self.last_known_screen_size {
|
||||
self.resize(screen_size)?;
|
||||
}
|
||||
let mut frame = self.get_frame();
|
||||
|
||||
render_callback(&mut frame).map_err(Into::into)?;
|
||||
render_callback(&mut frame);
|
||||
|
||||
// We can't change the cursor position right away because we have to flush the frame to
|
||||
// stdout first. But we also can't keep the frame around, since it holds a &mut to
|
||||
@@ -1348,10 +1280,7 @@ mod tests {
|
||||
));
|
||||
|
||||
terminal
|
||||
.try_draw(|frame| {
|
||||
frame.set_cursor_position(cursor_position);
|
||||
io::Result::Ok(())
|
||||
})
|
||||
.draw(|frame| frame.set_cursor_position(cursor_position))
|
||||
.expect("draw");
|
||||
|
||||
let mut expected_move = Vec::new();
|
||||
|
||||
Reference in New Issue
Block a user