mirror of
https://github.com/openai/codex.git
synced 2026-11-10 21:00:47 +00:00
Add keyboard selection support to the transcript view (#53693)
## What changed Add transcript select-mode state with an underlined cursor, grapheme-aware movement via arrow keys or `h`/`j`/`k`/`l`, and vertical movement that preserves the preferred display column. Support marking with `v`, Space, or Shift-arrow keys and copying through the existing selection machinery. Keep the displayed transcript snapshot and reading position paused during selection and after exiting the mode. Add entry and exit methods; this change does not yet bind mode entry to a user-facing key. ## Testing Add unit tests for initial cursor placement, movement across empty lines and entry boundaries, wrapped text, preferred-column preservation, and Enter behavior with and without a marked range. GitOrigin-RevId: e5bc380ea0eb6e2c6157ba73ac063d548a7de145
This commit is contained in:
@@ -17,6 +17,7 @@ mod layout;
|
||||
mod mutations;
|
||||
mod prompt_header;
|
||||
mod search;
|
||||
mod select_mode;
|
||||
mod selection;
|
||||
mod snapshot;
|
||||
mod text;
|
||||
@@ -38,6 +39,7 @@ use ratatui::widgets::Widget;
|
||||
|
||||
use layout::LayoutCache;
|
||||
use search::Search;
|
||||
use select_mode::SelectMode;
|
||||
use selection::Selection;
|
||||
use snapshot::ViewSnapshot;
|
||||
use text::TextLayout;
|
||||
@@ -126,6 +128,7 @@ pub(crate) struct TranscriptView {
|
||||
suppressed_prompt_header: Option<prompt_header::SuppressedHeader>,
|
||||
visible: Vec<VisibleRow>,
|
||||
selection: Option<Selection>,
|
||||
select_mode: Option<SelectMode>,
|
||||
copy_mode: Option<copy_mode::CopyMode>,
|
||||
held_reading: Option<ViewSnapshot>,
|
||||
search: Search,
|
||||
@@ -164,6 +167,7 @@ impl Default for TranscriptView {
|
||||
suppressed_prompt_header: None,
|
||||
visible: Vec::new(),
|
||||
selection: None,
|
||||
select_mode: None,
|
||||
copy_mode: None,
|
||||
held_reading: None,
|
||||
search: Search::default(),
|
||||
@@ -313,6 +317,7 @@ impl TranscriptView {
|
||||
self.unseen_activity = false;
|
||||
}
|
||||
self.render_selection(buf);
|
||||
self.render_select_cursor(buf);
|
||||
if self.history == TranscriptHistoryState::LoadingBeginning && self.is_following() {
|
||||
self.scroll(current_cells, /*rows*/ 0);
|
||||
}
|
||||
@@ -380,6 +385,7 @@ impl TranscriptView {
|
||||
return;
|
||||
}
|
||||
self.selection = None;
|
||||
self.select_mode = None;
|
||||
self.copy_mode = None;
|
||||
self.release_live_reading();
|
||||
self.cache.clear();
|
||||
@@ -397,7 +403,10 @@ impl TranscriptView {
|
||||
}
|
||||
|
||||
pub(crate) fn has_active_interaction(&self) -> bool {
|
||||
self.selection.is_some() || self.search.is_active() || self.is_activity_focused()
|
||||
self.select_mode.is_some()
|
||||
|| self.selection.is_some()
|
||||
|| self.search.is_active()
|
||||
|| self.is_activity_focused()
|
||||
}
|
||||
|
||||
pub(crate) fn is_detailed(&self) -> bool {
|
||||
@@ -405,7 +414,7 @@ impl TranscriptView {
|
||||
}
|
||||
|
||||
pub(crate) fn is_following(&self) -> bool {
|
||||
self.selection.is_none() && self.position == Position::Latest
|
||||
self.select_mode.is_none() && self.selection.is_none() && self.position == Position::Latest
|
||||
}
|
||||
|
||||
/// Hold the current reading position until every older page has arrived.
|
||||
@@ -426,6 +435,7 @@ impl TranscriptView {
|
||||
self.cancel_beginning();
|
||||
self.position = Position::Latest;
|
||||
self.selection = None;
|
||||
self.select_mode = None;
|
||||
self.copy_mode = None;
|
||||
self.release_live_reading();
|
||||
self.unseen_activity = false;
|
||||
|
||||
Reference in New Issue
Block a user