use super::*;
use crate::output::StreamingRedactor;
impl MissionControlState {
fn apply_prompt_edit_result(&mut self, result: PromptEditResult) -> PromptEditResult {
if result == PromptEditResult::RejectedTooLarge {
self.status = PROMPT_TOO_LARGE_STATUS.to_string();
} else if result == PromptEditResult::Failed {
self.status = PROMPT_MOVEMENT_FAILED_STATUS.to_string();
}
result
}
pub(crate) fn prompt_selection_text(&self) -> Option<String> {
self.prompt_editor.selection_text()
}
pub(crate) fn prompt_plain_text(&self) -> String {
self.prompt_editor.text()
}
pub(crate) fn prompt_content_revision(&self) -> u64 {
self.prompt_editor.content_revision()
}
pub(crate) fn prompt_is_empty(&self) -> bool {
self.prompt_editor.is_empty()
}
pub(crate) fn prompt_starts_with_bang(&self) -> bool {
self.prompt_editor.starts_with_bang()
}
#[cfg(test)]
pub(crate) fn prompt_cursor(&self) -> usize {
self.prompt_editor.cursor()
}
#[cfg(test)]
pub(crate) fn prompt_cursor_visible(&self) -> bool {
self.prompt_editor.cursor_visible()
}
pub(crate) fn prompt_cursor_at_position(&self, position: Position) -> Option<usize> {
self.prompt_editor.cursor_at_position(position)
}
pub(crate) fn set_prompt_text(&mut self, text: &str, cursor: usize) -> PromptEditResult {
let result = self.prompt_editor.set_text(text, cursor);
self.apply_prompt_edit_result(result)
}
#[cfg(test)]
pub(crate) fn set_prompt_cursor_visible(&mut self, visible: bool) {
self.prompt_editor.set_cursor_visible(visible);
}
pub(crate) fn move_prompt_cursor_to(
&mut self,
byte: usize,
visible_rows: u16,
wrap_width: u16,
) {
if self
.prompt_editor
.move_to_byte(byte, visible_rows, wrap_width)
== PromptMovementOutcome::Failed
{
self.status = PROMPT_MOVEMENT_FAILED_STATUS.to_string();
}
self.focus_prompt();
}
pub(crate) fn move_prompt_cursor_left(&mut self, visible_rows: u16, wrap_width: u16) {
if self.prompt_editor.move_left(visible_rows, wrap_width) == PromptMovementOutcome::Failed {
self.status = PROMPT_MOVEMENT_FAILED_STATUS.to_string();
}
}
pub(crate) fn move_prompt_cursor_right(&mut self, visible_rows: u16, wrap_width: u16) {
if self.prompt_editor.move_right(visible_rows, wrap_width) == PromptMovementOutcome::Failed
{
self.status = PROMPT_MOVEMENT_FAILED_STATUS.to_string();
}
}
pub(crate) fn move_prompt_cursor_up(&mut self, visible_rows: u16, wrap_width: u16) {
self.prompt_editor.move_up(visible_rows, wrap_width);
}
pub(crate) fn move_prompt_cursor_down(&mut self, visible_rows: u16, wrap_width: u16) {
self.prompt_editor.move_down(visible_rows, wrap_width);
}
pub(crate) fn move_prompt_word_left(&mut self, visible_rows: u16, wrap_width: u16) {
self.prompt_editor.move_word_left(visible_rows, wrap_width);
}
pub(crate) fn move_prompt_word_right(&mut self, visible_rows: u16, wrap_width: u16) {
self.prompt_editor.move_word_right(visible_rows, wrap_width);
}
pub(crate) fn extend_prompt_selection_left(&mut self, visible_rows: u16, wrap_width: u16) {
if self
.prompt_editor
.extend_selection_left(visible_rows, wrap_width)
== PromptMovementOutcome::Failed
{
self.status = PROMPT_MOVEMENT_FAILED_STATUS.to_string();
}
}
pub(crate) fn extend_prompt_selection_right(&mut self, visible_rows: u16, wrap_width: u16) {
if self
.prompt_editor
.extend_selection_right(visible_rows, wrap_width)
== PromptMovementOutcome::Failed
{
self.status = PROMPT_MOVEMENT_FAILED_STATUS.to_string();
}
}
pub(crate) fn extend_prompt_selection_up(&mut self, visible_rows: u16, wrap_width: u16) {
self.prompt_editor
.extend_selection_up(visible_rows, wrap_width);
}
pub(crate) fn extend_prompt_selection_down(&mut self, visible_rows: u16, wrap_width: u16) {
self.prompt_editor
.extend_selection_down(visible_rows, wrap_width);
}
pub(crate) fn insert_prompt_char(
&mut self,
ch: char,
visible_rows: u16,
wrap_width: u16,
) -> PromptEditResult {
let result = self.prompt_editor.insert_char(ch, visible_rows, wrap_width);
self.apply_prompt_edit_result(result)
}
pub(crate) fn insert_prompt_str(
&mut self,
text: &str,
visible_rows: u16,
wrap_width: u16,
) -> PromptEditResult {
let result = self
.prompt_editor
.insert_paste(text, visible_rows, wrap_width);
self.apply_prompt_edit_result(result)
}
pub(crate) fn backspace_prompt_char(
&mut self,
visible_rows: u16,
wrap_width: u16,
) -> PromptEditResult {
let result = self.prompt_editor.backspace(visible_rows, wrap_width);
self.apply_prompt_edit_result(result)
}
pub(crate) fn delete_prompt_char(
&mut self,
visible_rows: u16,
wrap_width: u16,
) -> PromptEditResult {
let result = self.prompt_editor.delete_forward(visible_rows, wrap_width);
self.apply_prompt_edit_result(result)
}
pub(crate) fn undo_prompt_edit(&mut self) -> PromptEditResult {
let result = self.prompt_editor.undo(1, 80);
self.apply_prompt_edit_result(result)
}
pub(crate) fn redo_prompt_edit(&mut self) -> PromptEditResult {
let result = self.prompt_editor.redo(1, 80);
self.apply_prompt_edit_result(result)
}
pub(crate) fn delete_prompt_word(&mut self) -> PromptEditResult {
let result = self.prompt_editor.delete_word();
self.apply_prompt_edit_result(result)
}
pub(crate) fn delete_prompt_next_word(&mut self) -> PromptEditResult {
let result = self.prompt_editor.delete_next_word();
self.apply_prompt_edit_result(result)
}
pub(crate) fn select_all_prompt(&mut self) {
self.prompt_editor.select_all();
}
pub(crate) fn clear_prompt_input(&mut self) {
self.prompt_editor.clear();
self.prompt_editor.commit_submission();
self.clear_autocomplete();
}
pub(crate) fn take_prompt_for_submit(&mut self) -> String {
let submitted = self.prompt_editor.take_for_submit();
self.clear_autocomplete();
submitted
}
pub(crate) fn restore_rejected_prompt(&mut self, prompt: String) {
let result = self.prompt_editor.restore_rejected_submit(prompt);
self.apply_prompt_edit_result(result);
self.focus_prompt();
}
pub(crate) fn commit_prompt_submission(&mut self) {
self.prompt_editor.commit_submission();
}
pub(crate) fn autocomplete_visible(&self) -> bool {
autocomplete::visible(&self.autocomplete)
}
pub(crate) fn clear_autocomplete(&mut self) {
autocomplete::clear(
&mut self.autocomplete,
&mut self.autocomplete_dismissed_token,
);
}
pub(crate) fn reset_for_new_session(&mut self) {
self.session_files = Default::default();
self.session_usage = Default::default();
self.last_known_session_cache_percent = None;
self.pending_compaction_transcript_index = None;
self.nodes.clear();
self.roots.clear();
self.children.clear();
self.expanded.clear();
self.transcript.clear();
self.transcript_timestamp_context = None;
self.last_session_header = None;
self.thinking_transcript_identities.clear();
self.clear_fast_observations();
self.fast_observation_accept_sequence = 0;
self.active_tool_transcripts.clear();
self.subagent_card_selection.clear();
self.activity_update_sequence = 0;
self.running_prompt = None;
self.activity_motion = Default::default();
self.active_worker_id = None;
self.last_run_finished_worker_id = None;
self.assistant_streaming = false;
self.active_assistant_text.clear();
self.active_assistant_redactor = StreamingRedactor::default();
self.active_assistant_transcript_index = None;
self.pending_assistant_completion_index = None;
self.active_thinking_text.clear();
self.active_thinking_redactor = StreamingRedactor::default();
self.active_thinking_control_sanitizer.reset();
self.active_thinking_transcript_index = None;
self.context_usage = None;
self.pending_steering_count = 0;
self.selected = 0;
self.detail_metadata_expanded = false;
self.reset_core_scroll_views();
self.activity_follow_tail = false;
self.modals.system_prompt_modal = None;
self.modals.skills_modal = None;
self.modals.session_picker = None;
self.modals.subagent_viewer = None;
self.selection = None;
self.toast = None;
self.clear_autocomplete();
self.commit_prompt_submission();
self.invalidate_transcript_cache();
self.invalidate_activity_render_cache();
}
pub(crate) fn hide_autocomplete(&mut self) {
autocomplete::hide(&mut self.autocomplete);
}
pub(crate) fn recompute_autocomplete(&mut self, candidates: &[AutocompleteCandidate]) {
let text = self.prompt_editor.visible_text();
autocomplete::recompute(
&text,
self.prompt_editor.visible_cursor(),
&mut self.autocomplete,
&self.autocomplete_dismissed_token,
candidates,
);
}
pub(crate) fn dismiss_autocomplete_for_current_token(&mut self) {
autocomplete::dismiss_for_current_token(
&mut self.autocomplete,
&mut self.autocomplete_dismissed_token,
);
}
pub(crate) fn move_autocomplete_selection_down(&mut self) {
autocomplete::move_selection_down(&mut self.autocomplete);
}
pub(crate) fn move_autocomplete_selection_up(&mut self) {
autocomplete::move_selection_up(&mut self.autocomplete);
}
pub(crate) fn accept_autocomplete(
&mut self,
visible_rows: u16,
wrap_width: u16,
) -> PromptEditResult {
let mut autocomplete = self.autocomplete.take();
let mut dismissed = self.autocomplete_dismissed_token.take();
let result = autocomplete::accept(
&mut self.prompt_editor,
&mut autocomplete,
&mut dismissed,
visible_rows,
wrap_width,
);
self.autocomplete = autocomplete;
self.autocomplete_dismissed_token = dismissed;
self.apply_prompt_edit_result(result)
}
pub(crate) fn prompt_visible_rows(&self, wrap_width: u16) -> u16 {
self.prompt_editor.visible_rows(wrap_width)
}
#[cfg(test)]
pub(crate) fn prompt_visual_rows(&self, wrap_width: u16) -> usize {
self.prompt_editor.visual_rows(wrap_width)
}
}