mirror of
https://github.com/openai/codex.git
synced 2026-09-16 12:13:30 +00:00
botom pane height, restore cmd
This commit is contained in:
@@ -74,7 +74,7 @@ pub enum HistoryPersistence {
|
||||
}
|
||||
|
||||
/// Collection of settings that are specific to the TUI.
|
||||
#[derive(Deserialize, Debug, Clone, PartialEq, Default)]
|
||||
#[derive(Deserialize, Debug, Clone, PartialEq)]
|
||||
pub struct Tui {
|
||||
/// By default, mouse capture is enabled in the TUI so that it is possible
|
||||
/// to scroll the conversation history with a mouse. This comes at the cost
|
||||
@@ -87,7 +87,27 @@ pub struct Tui {
|
||||
/// the mouse is not possible, though the keyboard shortcuts e.g. `b` and
|
||||
/// `space` still work. This allows the user to select text in the TUI
|
||||
/// using the mouse without needing to hold down a modifier key.
|
||||
#[serde(default)]
|
||||
pub disable_mouse_capture: bool,
|
||||
|
||||
/// Maximum number of visible lines in the chat input composer before scrolling.
|
||||
/// The composer will expand up to this many lines; additional content will enable
|
||||
/// an internal scrollbar.
|
||||
#[serde(default = "default_composer_max_rows")]
|
||||
pub composer_max_rows: usize,
|
||||
}
|
||||
|
||||
fn default_composer_max_rows() -> usize {
|
||||
10
|
||||
}
|
||||
|
||||
impl Default for Tui {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
disable_mouse_capture: Default::default(),
|
||||
composer_max_rows: default_composer_max_rows(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone, PartialEq, Default)]
|
||||
|
||||
@@ -9,8 +9,7 @@ use crate::scroll_event_helper::ScrollEventHelper;
|
||||
use crate::slash_command::SlashCommand;
|
||||
use crate::tui;
|
||||
use codex_core::config::Config;
|
||||
use codex_core::protocol::Event;
|
||||
use codex_core::protocol::Op;
|
||||
use codex_core::protocol::{Event, EventMsg, Op, SessionConfiguredEvent};
|
||||
use color_eyre::eyre::Result;
|
||||
use crossterm::event::KeyCode;
|
||||
use crossterm::event::KeyEvent;
|
||||
@@ -20,6 +19,8 @@ use std::path::PathBuf;
|
||||
use std::sync::mpsc::Receiver;
|
||||
use std::sync::mpsc::channel;
|
||||
|
||||
use uuid::Uuid;
|
||||
|
||||
/// Top-level application state: which full-screen view is currently active.
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
enum AppState<'a> {
|
||||
@@ -46,6 +47,9 @@ pub(crate) struct App<'a> {
|
||||
/// Stored parameters needed to instantiate the ChatWidget later, e.g.,
|
||||
/// after dismissing the Git-repo warning.
|
||||
chat_args: Option<ChatWidgetArgs>,
|
||||
|
||||
/// Session ID reported by the backend; used for resuming the session.
|
||||
session_id: Option<Uuid>,
|
||||
}
|
||||
|
||||
/// Aggregate parameters needed to create a `ChatWidget`, as creation may be
|
||||
@@ -162,6 +166,7 @@ impl<'a> App<'a> {
|
||||
app_state,
|
||||
config,
|
||||
chat_args,
|
||||
session_id: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,6 +176,11 @@ impl<'a> App<'a> {
|
||||
self.app_event_tx.clone()
|
||||
}
|
||||
|
||||
/// Returns the session ID assigned by the backend for this session, if available.
|
||||
pub fn session_id(&self) -> Option<Uuid> {
|
||||
self.session_id
|
||||
}
|
||||
|
||||
pub(crate) fn run(
|
||||
&mut self,
|
||||
terminal: &mut tui::Tui,
|
||||
@@ -316,6 +326,10 @@ impl<'a> App<'a> {
|
||||
}
|
||||
|
||||
fn dispatch_codex_event(&mut self, event: Event) {
|
||||
// Capture session ID when the session is initially configured
|
||||
if let EventMsg::SessionConfigured(SessionConfiguredEvent { session_id, .. }) = &event.msg {
|
||||
self.session_id = Some(*session_id);
|
||||
}
|
||||
match &mut self.app_state {
|
||||
AppState::Chat { widget } => widget.handle_codex_event(event),
|
||||
AppState::Login { .. } | AppState::GitWarning { .. } => {}
|
||||
|
||||
@@ -35,10 +35,12 @@ pub(crate) struct ChatComposer<'a> {
|
||||
command_popup: Option<CommandPopup>,
|
||||
app_event_tx: AppEventSender,
|
||||
history: ChatComposerHistory,
|
||||
/// Maximum number of visible lines in the chat input composer.
|
||||
max_rows: usize,
|
||||
}
|
||||
|
||||
impl ChatComposer<'_> {
|
||||
pub fn new(has_input_focus: bool, app_event_tx: AppEventSender) -> Self {
|
||||
pub fn new(has_input_focus: bool, app_event_tx: AppEventSender, max_rows: usize) -> Self {
|
||||
let mut textarea = TextArea::default();
|
||||
textarea.set_placeholder_text("send a message");
|
||||
textarea.set_cursor_line_style(ratatui::style::Style::default());
|
||||
@@ -48,6 +50,7 @@ impl ChatComposer<'_> {
|
||||
command_popup: None,
|
||||
app_event_tx,
|
||||
history: ChatComposerHistory::new(),
|
||||
max_rows,
|
||||
};
|
||||
this.update_border(has_input_focus);
|
||||
this
|
||||
@@ -249,7 +252,12 @@ impl ChatComposer<'_> {
|
||||
}
|
||||
|
||||
pub fn calculate_required_height(&self, area: &Rect) -> u16 {
|
||||
let rows = self.textarea.lines().len().max(MIN_TEXTAREA_ROWS);
|
||||
let rows = self
|
||||
.textarea
|
||||
.lines()
|
||||
.len()
|
||||
.max(MIN_TEXTAREA_ROWS)
|
||||
.min(self.max_rows);
|
||||
let num_popup_rows = if let Some(popup) = &self.command_popup {
|
||||
popup.calculate_required_height(area)
|
||||
} else {
|
||||
|
||||
@@ -41,12 +41,18 @@ pub(crate) struct BottomPane<'a> {
|
||||
pub(crate) struct BottomPaneParams {
|
||||
pub(crate) app_event_tx: AppEventSender,
|
||||
pub(crate) has_input_focus: bool,
|
||||
/// Maximum number of visible lines in the chat input composer.
|
||||
pub(crate) composer_max_rows: usize,
|
||||
}
|
||||
|
||||
impl BottomPane<'_> {
|
||||
pub fn new(params: BottomPaneParams) -> Self {
|
||||
Self {
|
||||
composer: ChatComposer::new(params.has_input_focus, params.app_event_tx.clone()),
|
||||
composer: ChatComposer::new(
|
||||
params.has_input_focus,
|
||||
params.app_event_tx.clone(),
|
||||
params.composer_max_rows,
|
||||
),
|
||||
active_view: None,
|
||||
app_event_tx: params.app_event_tx,
|
||||
has_input_focus: params.has_input_focus,
|
||||
|
||||
@@ -124,6 +124,7 @@ impl ChatWidget<'_> {
|
||||
bottom_pane: BottomPane::new(BottomPaneParams {
|
||||
app_event_tx,
|
||||
has_input_focus: true,
|
||||
composer_max_rows: config.tui.composer_max_rows,
|
||||
}),
|
||||
input_focus: InputFocus::BottomPane,
|
||||
config,
|
||||
|
||||
@@ -197,6 +197,11 @@ fn run_ratatui_app(
|
||||
let app_result = app.run(&mut terminal, &mut mouse_capture);
|
||||
|
||||
restore();
|
||||
// On exit, display a command that can be used to resume this session
|
||||
#[allow(clippy::print_stderr)]
|
||||
if let Some(session_id) = app.session_id() {
|
||||
eprintln!("Resume this session with: codex session {session_id}");
|
||||
}
|
||||
app_result
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user