Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'helix-dap/src/config.rs')
| -rw-r--r-- | helix-dap/src/config.rs | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/helix-dap/src/config.rs b/helix-dap/src/config.rs new file mode 100644 index 00000000..9644c63b --- /dev/null +++ b/helix-dap/src/config.rs @@ -0,0 +1,146 @@ +use anyhow::bail; +use helix_config::*; +use serde::{Deserialize, Serialize}; + +options! { + struct DebugAdapterConfig { + #[name = "debugger.name"] + name: Option<String> = None, + #[name = "debugger.transport"] + #[read = copy] + transport: Transport = Transport::Stdio, + #[name = "debugger.command"] + #[read = deref] + command: String = "", + #[name = "debugger.args"] + #[read = deref] + args: List<String> = List::default(), + #[name = "debugger.port-arg"] + #[read = deref] + port_arg: String = "", + #[name = "debugger.templates"] + #[read = deref] + templates: List<DebugTemplate> = List::default(), + #[name = "debugger.quirks.absolut-path"] + #[read = copy] + absolut_path: bool = false, + #[name = "terminal.command"] + terminal_command: Option<String> = get_terminal_provider().map(|term| term.command), + #[name = "terminal.args"] + #[read = deref] + terminal_args: List<String> = get_terminal_provider().map(|term| term.args.into_boxed_slice()).unwrap_or_default(), + } +} + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum Transport { + Stdio, + Tcp, +} + +impl Ty for Transport { + fn from_value(val: Value) -> anyhow::Result<Self> { + match &*String::from_value(val)? { + "stdio" => Ok(Transport::Stdio), + "tcp" => Ok(Transport::Tcp), + val => bail!("expected 'stdio' or 'tcp' (got {val:?})"), + } + } + fn to_value(&self) -> Value { + match self { + Transport::Stdio => "stdio".into(), + Transport::Tcp => "tcp".into(), + } + } +} + +#[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)] +#[serde(untagged)] +pub enum DebugArgumentValue { + String(String), + Array(Vec<String>), + Boolean(bool), +} + +#[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)] +#[serde(rename_all = "kebab-case")] +pub struct AdvancedCompletion { + pub name: Option<String>, + pub completion: Option<String>, + pub default: Option<String>, +} + +#[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)] +#[serde(rename_all = "kebab-case", untagged)] +pub enum DebugConfigCompletion { + Named(String), + Advanced(AdvancedCompletion), +} + +#[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)] +#[serde(rename_all = "kebab-case")] +pub struct DebugTemplate { + pub name: String, + pub request: String, + pub completion: Vec<DebugConfigCompletion>, + pub args: Map<DebugArgumentValue>, +} + +// TODO: integrate this better with the new config system (less nesting) +// the best way to do that is probably a rewrite. I think these templates +// are probably overkill here. This may be easier to solve by moving the logic +// to scheme +config_serde_adapter!(DebugTemplate); + +#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(default, rename_all = "kebab-case", deny_unknown_fields)] +pub struct TerminalConfig { + pub command: String, + #[serde(default)] + #[serde(skip_serializing_if = "Vec::is_empty")] + pub args: Vec<String>, +} + +#[cfg(windows)] +pub fn get_terminal_provider() -> Option<TerminalConfig> { + use helix_config::env::binary_exists; + + if binary_exists("wt") { + return Some(TerminalConfig { + command: "wt".into(), + args: vec![ + "new-tab".into(), + "--title".into(), + "DEBUG".into(), + "cmd".into(), + "/C".into(), + ], + }); + } + + Some(TerminalConfig { + command: "conhost".into(), + args: vec!["cmd".into(), "/C".into()], + }) +} + +#[cfg(not(any(windows, target_os = "wasm32")))] +fn get_terminal_provider() -> Option<TerminalConfig> { + use helix_config::env::{binary_exists, env_var_is_set}; + + if env_var_is_set("TMUX") && binary_exists("tmux") { + return Some(TerminalConfig { + command: "tmux".into(), + args: vec!["split-window".into()], + }); + } + + if env_var_is_set("WEZTERM_UNIX_SOCKET") && binary_exists("wezterm") { + return Some(TerminalConfig { + command: "wezterm".into(), + args: vec!["cli".into(), "split-pane".into()], + }); + } + + None +} |