magi-code 0.77.1

Repository-aware CLI coding agent for terminal work
Documentation
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)
    }
}