1use crate::editor::git_memory::GitJob;
8use crate::editor::{ClipboardResult, ShellResult};
9use serde_json::json;
10use strop_trace::{record_with, EventKind};
11
12#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
15pub struct NativePath(#[serde(with = "strop_core::path_serde")] pub std::path::PathBuf);
16
17pub fn rejected(service: &'static str, reason: &str) {
18 record_with(
19 EventKind::JobRejected,
20 || json!({"service":service,"reason":reason}),
21 );
22}
23fn outcome<T>(value: &strop_core::worker::Outcome<T>) -> serde_json::Value {
24 use strop_core::worker::Outcome;
25 match value {
26 Outcome::Success(_) => json!({"kind":"success"}),
27 Outcome::Failed { failure, partial } => {
28 json!({"kind":"failed","failure":failure,"partial":partial.is_some()})
29 }
30 Outcome::Cancelled(reason) => json!({"kind":"cancelled","reason":reason}),
31 }
32}
33
34fn completion<K: serde::Serialize, T>(
35 service: &str,
36 result: &str,
37 value: &strop_core::worker::Completion<K, T>,
38) -> serde_json::Value {
39 json!({"service":service,"result":result,"ticket":value.ticket,"outcome":outcome(&value.outcome)})
40}
41
42pub fn git(job: &GitJob) {
43 record_with(EventKind::JobFinished, || match job {
44 GitJob::Context(value) => completion("git", "context", value),
45 GitJob::Hunks(value) => completion("git", "hunks", value),
46 GitJob::Mutation(value) => completion("git", "mutation", value),
47 GitJob::Log(value) => completion("git", "log", value),
48 GitJob::Gutter(value) => completion("git", "gutter", value),
49 GitJob::Card(value) => completion("git", "blame_card", value),
50 GitJob::Dive(value) => completion("git", "dive", value),
51 });
52}
53
54pub fn io(event: &crate::editor::io::IoEvent) {
55 use crate::editor::io::IoEvent;
56 record_with(EventKind::JobFinished, || match event {
57 IoEvent::Open(value) => completion("io", "open", value),
58 IoEvent::Save(value) => completion("io", "save", value),
59 IoEvent::Native(value) => completion("io", "native", value),
60 IoEvent::Remote(event) => {
61 use crate::editor::remote::RemoteEvent;
62 match event {
63 RemoteEvent::Tick(ticket) => {
64 json!({"service":"remote","result":"follow_tick","ticket":ticket})
65 }
66 RemoteEvent::Timer(value) => completion("remote", "follow_clock", value),
67 RemoteEvent::Read(value) => completion("remote", "follow_read", value),
68 RemoteEvent::Control(value) => completion("remote", "control", value),
69 RemoteEvent::Filter(value) => completion("remote", "directory_filter", value),
70 RemoteEvent::Choices(value) => completion("remote", "destinations", value),
71 RemoteEvent::Write(value) => {
72 let mut record = completion("remote", "write", value);
73 if let strop_core::worker::Outcome::Success(
74 crate::editor::remote::save::RemoteWriteResult::Refused(error),
75 ) = &value.outcome
76 {
77 record["outcome"] = outcome(&strop_core::worker::Outcome::<()>::failed(
78 strop_core::worker::FailureKind::Io,
79 error.to_string(),
80 ));
81 }
82 record
83 }
84 RemoteEvent::DestinationWritten(value) => {
85 completion("remote", "destination_write", value)
86 }
87 }
88 }
89 IoEvent::Session {
90 request,
91 outcome: value,
92 } => json!({"service":"io","result":"session","request":request,"outcome":outcome(value)}),
93 });
94}
95
96pub fn shell(result: &ShellResult) {
97 record_with(EventKind::JobFinished, || {
98 let key = match &result.ticket.key {
99 crate::editor::ShellKey::Display {
100 origin, revision, ..
101 } => json!({
102 "kind":"display","document":super::snapshot::document_id(*origin),
103 "revision":revision,
104 }),
105 crate::editor::ShellKey::Pipe {
106 document,
107 revision,
108 start,
109 end,
110 } => json!({
111 "kind":"pipe","document":super::snapshot::document_id(*document),
112 "revision":revision,"start_byte":start,"end_byte":end,
113 }),
114 };
115 let outcome = match &result.outcome {
116 strop_core::worker::Outcome::Success(output) => json!({
117 "stdout_bytes":output.stdout.len(),"stderr_bytes":output.stderr.len(),
118 }),
119 strop_core::worker::Outcome::Failed { failure, .. } => {
120 json!({"error": failure.message})
121 }
122 _ => json!({"cancelled": true}),
123 };
124 json!({"service":"shell","request":result.ticket.request.get(),
125 "key":key,"outcome":outcome})
126 });
127}
128
129pub fn clipboard(result: &ClipboardResult) {
130 record_with(EventKind::JobFinished, || {
131 let outcome = match &result.outcome {
132 strop_core::worker::Outcome::Success(text) => json!({"bytes": text.len()}),
133 strop_core::worker::Outcome::Failed { failure, .. } => {
134 json!({"error": failure.message})
135 }
136 _ => json!({"cancelled": true}),
137 };
138 json!({"service":"clipboard","request":result.ticket.request.get(),
139 "document":super::snapshot::document_id(result.ticket.key.document),
140 "outcome":outcome})
141 });
142}
143
144pub fn lsp(event: &strop_lsp::LspEvent) {
145 use strop_lsp::LspEvent;
146 record_with(EventKind::JobFinished, || {
147 if strop_trace::capture_content() {
148 return json!({"service":"lsp", "event":event});
149 }
150 match event {
151 LspEvent::Ready { server, name } => {
152 json!({"service":"lsp","result":"ready","server":server,"name":name})
153 }
154 LspEvent::Failed { server, name, hint } => {
155 json!({"service":"lsp","result":"failed","server":server,"name":name,"hint":hint})
157 }
158 LspEvent::ServerMessage { server, name, text } => {
159 json!({"service":"lsp","result":"message","server":server,"name":name,"bytes":text.len()})
160 }
161 LspEvent::Diagnostics { context, diags, .. } => json!({
162 "service":"lsp","result":"diagnostics","context":context,"count":diags.len(),
163 }),
164 LspEvent::Edits { context, edits } => json!({
165 "service":"lsp","result":"edits","context":context,"count":edits.len(),
166 }),
167 LspEvent::WorkspaceEdits { context, edits } => json!({
168 "service":"lsp","result":"workspace_edits","context":context,"targets":edits.len(),
169 }),
170 LspEvent::Symbols { context, symbols } => json!({
171 "service":"lsp","result":"symbols","context":context,"count":symbols.len(),
172 }),
173 LspEvent::ActionList { context, actions } => json!({
174 "service":"lsp","result":"code_actions","context":context,"count":actions.len(),
175 }),
176 LspEvent::HoverText { context, text } => json!({
177 "service":"lsp","result":"hover","context":context,"bytes":text.len(),
178 }),
179 LspEvent::Note { context, text } => json!({
180 "service":"lsp","result":"note","context":context,"bytes":text.len(),
181 }),
182 LspEvent::GotoLocation { context, .. } => json!({
183 "service":"lsp","result":"goto","context":context,
184 }),
185 LspEvent::Locations {
186 context,
187 kind,
188 items,
189 } => json!({
190 "service":"lsp","result":kind.label(),"context":context,"count":items.len(),
191 }),
192 }
193 });
194}
195
196pub fn picker(event: &crate::editor::picker::PickerEvent) {
197 use strop_picker::PickerMsg;
198 record_with(EventKind::JobFinished, || {
199 let outcome = match &event.msg {
200 PickerMsg::Items(items) => json!({"result":"items","count":items.len()}),
201 PickerMsg::Warning(warning) => json!({"result":"warning","bytes":warning.len()}),
202 PickerMsg::Finished(outcome) => match outcome {
203 strop_core::worker::Outcome::Success(()) => json!({"result":"finished"}),
204 strop_core::worker::Outcome::Failed { failure, .. } => {
205 json!({"result":"error","error":failure.message})
206 }
207 _ => json!({"result":"cancelled"}),
208 },
209 };
210 json!({"service":"picker","request":event.ticket.request.get(),
211 "outcome":outcome})
212 });
213}