//! Runs, keyed terminals and plugin-owned content editors (API 1.4). use serde::{Deserialize, Serialize}; /// ContentAction data exchanged with the IDE. #[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ContentAction { pub id: String, pub label: String, pub icon: Option, pub primary: bool, pub save: bool, } /// ContentTab data exchanged with the IDE. #[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ContentTab { pub key: String, pub title: String, pub file_name: Option, pub language: Option, pub content: String, pub read_only: bool, pub actions: Vec, } /// ContentDiff data exchanged with the IDE. #[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ContentDiff { pub left: String, pub right: String, pub left_label: Option, pub right_label: Option, pub title: Option, } /// ContentTabReply data exchanged with the IDE. #[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ContentTabReply { pub content: Option, pub saved: Option, pub read_only: Option, pub status: Option, pub error: Option, pub diff: Option, } /// PluginRunConfiguration data exchanged with the IDE. #[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct PluginRunConfiguration { pub id: String, pub name: String, pub program: String, pub args: Vec, pub cwd: Option, pub test: bool, pub framework: Option, } /// RunExited data exchanged with the IDE. #[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct RunExited { pub id: String, pub config: String, pub status: Option, pub killed: bool, } /// TerminalExited data exchanged with the IDE. #[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct TerminalExited { pub id: String, pub key: String, pub status: Option, pub closed: bool, } /// ContentTabAction data exchanged with the IDE. #[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ContentTabAction { pub request_id: String, pub key: String, pub action: String, pub content: String, } /// Incremental test tree data. #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct TestStart { pub id: String, pub parent: Option, pub name: String, pub location: Option, } /// Incremental test tree data. #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct TestPassed { pub id: String, pub duration_ms: Option, } /// Incremental test tree data. #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct TestFailed { pub id: String, pub duration_ms: Option, pub message: String, pub expected: Option, pub actual: Option, pub location: Option, } /// Incremental test tree data. #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct TestSkipped { pub id: String, pub reason: Option, } /// Incremental test tree data. #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct TestOutput { pub id: String, pub text: String, } /// A test update, carried by the optional test-results export. #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[serde(tag = "type", rename_all = "camelCase")] pub enum PluginTestEvent { SuiteStarted(TestStart), TestStarted(TestStart), Passed(TestPassed), Failed(TestFailed), Skipped(TestSkipped), Output(TestOutput), Other { kind: String, data: String }, } /// Supplies complete project configurations; register with run_configurations. pub trait RunConfigurations { fn configurations(&mut self, project_root: &str) -> Vec; } /// Parses bounded test output batches; register with test_results. pub trait TestResults { fn parse(&mut self, config: &str, chunk: &str) -> Vec; /// Full replacement argv for test-tree name paths, or None when filtering is unsupported. fn select_tests(&mut self, _config: &str, _tests: &[Vec]) -> Option> { None } } impl crate::Event { /// Completion of a run started by this plugin, even after idle reclamation. pub fn run_exited(&self) -> Option { self.execution_event("run-exited") } /// Exactly one completion for a keyed terminal operation. pub fn terminal_exited(&self) -> Option { self.execution_event("terminal-exited") } /// A toolbar action or Save from this plugin's wasm content tab. pub fn content_tab_action(&self) -> Option { self.execution_event("content-tab-action") } fn execution_event(&self, expected: &str) -> Option { let Self::Other { kind, data } = self else { return None }; (kind == expected).then(|| serde_json::from_str(data).ok()).flatten() } } /// A plugin-owned argv wrapper for project runs (API 1.4). #[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct PluginRunTarget { pub id: String, pub name: String, pub program: String, pub args: Vec, pub workdir_args: Vec, pub container_root: Option, pub commands: Vec<(String, Vec)>, } /// Per-command argv prefix and optional working-directory arguments (API 1.5). #[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct PluginCommandOverride { pub name: String, pub args: Vec, /// None inherits the target's list; Some(Vec::new()) suppresses it. #[serde(default)] pub workdir_args: Option>, } /// A project run target with per-command working-directory control (API 1.5). #[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct PluginRunTargetWithOverrides { pub id: String, pub name: String, pub program: String, pub args: Vec, pub workdir_args: Vec, pub container_root: Option, pub commands: Vec, } impl From for PluginRunTargetWithOverrides { fn from(target: PluginRunTarget) -> Self { Self { id: target.id, name: target.name, program: target.program, args: target.args, workdir_args: target.workdir_args, container_root: target.container_root, commands: target .commands .into_iter() .map(|(name, args)| PluginCommandOverride { name, args, workdir_args: None }) .collect(), } } } /// Operation about to launch through a plugin-owned run target (API 1.5). #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum RunTargetOperation { Run, Test, } /// Launch metadata available to a target validator; arguments and environment are omitted. #[derive(Clone, Debug, PartialEq, Eq)] pub struct RunTargetLaunch { pub operation: RunTargetOperation, pub program: String, pub cwd: String, } /// Optional pre-launch validation; register with `run_target_validation`. pub trait RunTargetValidation { /// Refuse with a user-facing explanation, or allow with `Ok(())`. fn validate(&mut self, project: &str, target_id: &str, launch: &RunTargetLaunch) -> Result<(), String>; }