Codex Handbook
tui/src/ide_context.rs 117 lines
//! IDE context data model and public helpers for TUI `/ide` support.mod ipc;mod prompt;#[cfg(windows)]mod windows_pipe;pub(crate) use ipc::fetch_ide_context;pub(crate) use prompt::apply_ide_context_to_user_input;pub(crate) use prompt::extract_prompt_request_with_offset;pub(crate) use prompt::has_prompt_context;use serde::Deserialize;#[derive(Debug, Clone, Deserialize, PartialEq)]#[serde(rename_all = "camelCase")]pub(crate) struct IdeContext {    active_file: Option<ActiveFile>,    #[serde(default)]    open_tabs: Vec<FileDescriptor>,}#[derive(Debug, Clone, Deserialize, PartialEq)]#[serde(rename_all = "camelCase")]struct ActiveFile {    #[serde(flatten)]    descriptor: FileDescriptor,    selection: Range,    #[serde(default)]    active_selection_content: String,    #[serde(default)]    selections: Vec<Range>,}#[derive(Debug, Clone, Deserialize, PartialEq)]#[serde(rename_all = "camelCase")]struct FileDescriptor {    label: String,    path: String,}#[derive(Debug, Clone, Deserialize, PartialEq)]struct Range {    start: Position,    end: Position,}#[derive(Debug, Clone, Deserialize, PartialEq)]struct Position {    line: u32,    character: u32,}#[cfg(test)]mod tests {    use super::*;    use pretty_assertions::assert_eq;    use serde_json::json;    #[test]    fn deserializes_existing_ide_context_shape() {        let value = json!({            "activeFile": {                "label": "lib.rs",                "path": "src/lib.rs",                "fsPath": "/repo/src/lib.rs",                "selection": {                    "start": { "line": 1, "character": 2 },                    "end": { "line": 3, "character": 4 }                },                "activeSelectionContent": "selected",                "selections": []            },            "openTabs": [                {                    "label": "main.rs",                    "path": "src/main.rs",                    "fsPath": "/repo/src/main.rs",                    "startLine": 2,                    "endLine": 10                }            ],            "processEnv": {                "path": "/usr/bin"            }        });        let context: IdeContext = serde_json::from_value(value).expect("deserialize ide context");        assert_eq!(            context,            IdeContext {                active_file: Some(ActiveFile {                    descriptor: FileDescriptor {                        label: "lib.rs".to_string(),                        path: "src/lib.rs".to_string(),                    },                    selection: Range {                        start: Position {                            line: 1,                            character: 2,                        },                        end: Position {                            line: 3,                            character: 4,                        },                    },                    active_selection_content: "selected".to_string(),                    selections: Vec::new(),                }),                open_tabs: vec![FileDescriptor {                    label: "main.rs".to_string(),                    path: "src/main.rs".to_string(),                }],            }        );    }}