Skip to main content

strop_engine/editor/trace/
snapshot.rs

1//! State snapshots retain native paths and complete prompt ownership.
2use crate::editor::Editor;
3use serde_json::json;
4use strop_core::id::DocumentId;
5use strop_trace::{capture_content, enabled, record, EventKind};
6
7pub(super) fn document_id(id: DocumentId) -> serde_json::Value {
8    json!(id)
9}
10
11fn pending_state(editor: &Editor) -> serde_json::Value {
12    let Some(prompt) = editor.pending.prompt() else {
13        return serde_json::Value::Null;
14    };
15    let origin = prompt.origin();
16    let context = match prompt.context() {
17        crate::editor::pending::PromptContext::Ex(_) => json!({"kind":"ex"}),
18        crate::editor::pending::PromptContext::Pipe { range, visual, .. } => {
19            json!({"kind":"pipe","range":range,"visual":visual})
20        }
21        crate::editor::pending::PromptContext::Search { backward, .. } => {
22            json!({"kind":"search","backward":backward})
23        }
24    };
25    json!({"text":capture_content().then(||prompt.text()),"cursor_byte":prompt.cursor(),
26        "normal":prompt.normal(),"context":context,"pane_index":origin.pane_index,
27        "origin":origin.pane,"revision":origin.revision})
28}
29
30impl Editor {
31    pub fn trace_state(&mut self) {
32        if !enabled() {
33            return;
34        }
35        self.trace_documents
36            .retain(|id, _| self.docs.get(*id).is_some());
37        for (id, document) in self.docs.iter() {
38            if self.trace_documents.insert(id, document.buf.trace_id())
39                != Some(document.buf.trace_id())
40            {
41                #[derive(serde::Serialize)]
42                struct DocumentRecord<'a> {
43                    document: DocumentId,
44                    buffer: strop_core::diagnostics::BufferTraceId,
45                    #[serde(with = "strop_core::path_serde::option")]
46                    path: &'a Option<std::path::PathBuf>,
47                    name: &'a Option<String>,
48                    revision: strop_core::id::BufferRevision,
49                    bytes: usize,
50                    readonly: bool,
51                    text: Option<String>,
52                }
53                record(
54                    EventKind::Document,
55                    &DocumentRecord {
56                        document: id,
57                        buffer: document.buf.trace_id(),
58                        path: &document.buf.path,
59                        name: &document.buf.name,
60                        revision: document.buf.revision(),
61                        bytes: document.buf.len_bytes(),
62                        readonly: document.buf.readonly,
63                        text: capture_content().then(|| document.buf.text().to_string()),
64                    },
65                );
66            }
67        }
68        let documents: Vec<_> = self.docs.iter().map(|(id, document)| json!({
69            "document":id,"buffer":document.buf.trace_id(),"revision":document.buf.revision(),
70            "bytes":document.buf.len_bytes(),"dirty":document.buf.dirty,"history_nodes":document.buf.history().depth(),
71        })).collect();
72        let cursor = self.panes.get(self.active_pane).and_then(|pane| {
73            let document = self.docs.get(pane.doc)?;
74            let selection = pane.sels.primary();
75            Some(json!({"document":pane.doc,"head_byte":selection.head,"anchor_byte":selection.anchor,
76                "line":document.buf.line_of(selection.head),"byte_column":document.buf.col_of(selection.head)}))
77        });
78        record(
79            EventKind::State,
80            &json!({
81                "mode":self.mode.chip(),"pending":pending_state(self),"walker":self.walker.display(),
82                "last_search":self.last_search.as_ref().map(|search|json!({
83                    "pattern":capture_content().then(||search.query.source()),"backward":search.backward,
84                    "whole_word":search.query.whole_word()})),
85                "cursor":cursor,"documents":documents,"panes":self.panes,"active_pane":self.active_pane,
86                "view_rows":self.view_rows,"message":self.message,"should_quit":self.should_quit,
87                "picker":self.picker.as_ref().map(|glue|json!({"id":glue.id.0.get(),
88                    "request":glue.active.as_ref().map(|ticket|ticket.request.get()),"query":glue.picker.input.text,
89                    "items":glue.picker.items.len(),"streaming":glue.picker.streaming})),
90                "config":self.config,
91            }),
92        );
93    }
94}