From cb7615e0ed119f292eabdce784e4635247ed1eb1 Mon Sep 17 00:00:00 2001 From: Blaž Hrastnik Date: Mon, 22 Aug 2022 10:11:04 +0900 Subject: Make external terminal provider configurable Fixes #1699 --- helix-view/src/clipboard.rs | 8 ++++++- helix-view/src/editor.rs | 48 ++++++++++++++++++++++++++++++++++++++ helix-view/src/handlers/dap.rs | 53 +++++++++++++++++++++--------------------- 3 files changed, 81 insertions(+), 28 deletions(-) diff --git a/helix-view/src/clipboard.rs b/helix-view/src/clipboard.rs index 4d57a5b7..8d49ed43 100644 --- a/helix-view/src/clipboard.rs +++ b/helix-view/src/clipboard.rs @@ -139,7 +139,7 @@ pub fn get_clipboard_provider() -> Box { } } -mod provider { +pub mod provider { use super::{ClipboardProvider, ClipboardType}; use anyhow::Result; use std::borrow::Cow; @@ -164,6 +164,12 @@ mod provider { } } + impl Default for NopProvider { + fn default() -> Self { + Self::new() + } + } + #[cfg(not(target_os = "windows"))] impl ClipboardProvider for NopProvider { fn name(&self) -> Cow { diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs index 18c2a343..a49fae00 100644 --- a/helix-view/src/editor.rs +++ b/helix-view/src/editor.rs @@ -157,6 +157,7 @@ pub struct Config { #[serde(default)] pub search: SearchConfig, pub lsp: LspConfig, + pub terminal: Option, /// Column numbers at which to draw the rulers. Default to `[]`, meaning no rulers. pub rulers: Vec, #[serde(default)] @@ -167,6 +168,52 @@ pub struct Config { pub color_modes: bool, } +#[derive(Debug, Default, Clone, PartialEq, 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, +} + +#[cfg(windows)] +pub fn get_terminal_provider() -> Option { + use crate::clipboard::provider::command::exists; + + if exists("wt") { + return Some(TerminalConfig { + command: "wt".to_string(), + args: vec![ + "new-tab".to_string(), + "--title".to_string(), + "DEBUG".to_string(), + "cmd".to_string(), + "/C".to_string(), + ], + }); + } + + return Some(TerminalConfig { + command: "conhost".to_string(), + args: vec!["cmd".to_string(), "/C".to_string()], + }); +} + +#[cfg(not(any(windows, target_os = "wasm32")))] +pub fn get_terminal_provider() -> Option { + use crate::clipboard::provider::command::{env_var_is_set, exists}; + + if env_var_is_set("TMUX") && exists("tmux") { + return Some(TerminalConfig { + command: "tmux".to_string(), + args: vec!["split-window".to_string()], + }); + } + + None +} + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(default, rename_all = "kebab-case", deny_unknown_fields)] pub struct LspConfig { @@ -497,6 +544,7 @@ impl Default for Config { true_color: false, search: SearchConfig::default(), lsp: LspConfig::default(), + terminal: get_terminal_provider(), rulers: Vec::new(), whitespace: WhitespaceConfig::default(), indent_guides: IndentGuidesConfig::default(), diff --git a/helix-view/src/handlers/dap.rs b/helix-view/src/handlers/dap.rs index 4d197680..e39584c3 100644 --- a/helix-view/src/handlers/dap.rs +++ b/helix-view/src/handlers/dap.rs @@ -5,7 +5,6 @@ use helix_dap::{self as dap, Client, Payload, Request, ThreadId}; use helix_lsp::block_on; use log::warn; use std::fmt::Write; -use std::io::ErrorKind; use std::path::PathBuf; #[macro_export] @@ -287,32 +286,32 @@ impl Editor { serde_json::from_value(request.arguments.unwrap_or_default()).unwrap(); // TODO: no unwrap - let process = if cfg!(windows) { - std::process::Command::new("wt") - .arg("new-tab") - .arg("--title") - .arg("DEBUG") - .arg("cmd") - .arg("/C") - .arg(arguments.args.join(" ")) - .spawn() - .unwrap_or_else(|error| match error.kind() { - ErrorKind::NotFound => std::process::Command::new("conhost") - .arg("cmd") - .arg("/C") - .arg(arguments.args.join(" ")) - .spawn() - .unwrap(), - // TODO replace the pretty print {:?} with a regular format {} - // when the MSRV is raised to 1.60.0 - e => panic!("Error to start debug console: {:?}", e), - }) - } else { - std::process::Command::new("tmux") - .arg("split-window") - .arg(arguments.args.join(" ")) - .spawn() - .unwrap() + let config = match self.config().terminal.clone() { + Some(config) => config, + None => { + self.set_error("No external terminal defined"); + return true; + } + }; + + // Re-borrowing debugger to avoid issues when loading config + let debugger = match self.debugger.as_mut() { + Some(debugger) => debugger, + None => return false, + }; + + let process = match std::process::Command::new(config.command) + .args(config.args) + .arg(arguments.args.join(" ")) + .spawn() + { + Ok(process) => process, + Err(err) => { + // TODO replace the pretty print {:?} with a regular format {} + // when the MSRV is raised to 1.60.0 + self.set_error(format!("Error starting external terminal: {:?}", err)); + return true; + } }; let _ = debugger -- cgit v1.2.3-70-g09d2