on master help sign in
Make external terminal provider configurable

Fixes #1699

commitcb7615e0ed119f292eabdce784e4635247ed1eb1 authorBlaž Hrastnik <blaz@mxxn.io> dateMon 22 Aug 2022, 10:11 (4 years ago) parent7e33069
3 files changed+81−28
helix-view/src/clipboard.rs+7−1 helix-view/src/editor.rs+48 helix-view/src/handlers/dap.rs+26−27
helix-view/src/clipboard.rs+7−1
@@ -139,7 +139,7 @@ pub fn get_clipboard_provider() -> Box<dyn ClipboardProvider> {
139139 }
140140}
141141
142−mod provider {
142+pub mod provider {
143143 use super::{ClipboardProvider, ClipboardType};
144144 use anyhow::Result;
145145 use std::borrow::Cow;
@@ -164,6 +164,12 @@ mod provider {
164164 }
165165 }
166166
167+ impl Default for NopProvider {
168+ fn default() -> Self {
169+ Self::new()
170+ }
171+ }
172+
167173 #[cfg(not(target_os = "windows"))]
168174 impl ClipboardProvider for NopProvider {
169175 fn name(&self) -> Cow<str> {
helix-view/src/editor.rs+48
@@ -157,6 +157,7 @@ pub struct Config {
157157 #[serde(default)]
158158 pub search: SearchConfig,
159159 pub lsp: LspConfig,
160+ pub terminal: Option<TerminalConfig>,
160161 /// Column numbers at which to draw the rulers. Default to `[]`, meaning no rulers.
161162 pub rulers: Vec<u16>,
162163 #[serde(default)]
@@ -167,6 +168,52 @@ pub struct Config {
167168 pub color_modes: bool,
168169}
169170
171+#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
172+#[serde(default, rename_all = "kebab-case", deny_unknown_fields)]
173+pub struct TerminalConfig {
174+ pub command: String,
175+ #[serde(default)]
176+ #[serde(skip_serializing_if = "Vec::is_empty")]
177+ pub args: Vec<String>,
178+}
179+
180+#[cfg(windows)]
181+pub fn get_terminal_provider() -> Option<TerminalConfig> {
182+ use crate::clipboard::provider::command::exists;
183+
184+ if exists("wt") {
185+ return Some(TerminalConfig {
186+ command: "wt".to_string(),
187+ args: vec![
188+ "new-tab".to_string(),
189+ "--title".to_string(),
190+ "DEBUG".to_string(),
191+ "cmd".to_string(),
192+ "/C".to_string(),
193+ ],
194+ });
195+ }
196+
197+ return Some(TerminalConfig {
198+ command: "conhost".to_string(),
199+ args: vec!["cmd".to_string(), "/C".to_string()],
200+ });
201+}
202+
203+#[cfg(not(any(windows, target_os = "wasm32")))]
204+pub fn get_terminal_provider() -> Option<TerminalConfig> {
205+ use crate::clipboard::provider::command::{env_var_is_set, exists};
206+
207+ if env_var_is_set("TMUX") && exists("tmux") {
208+ return Some(TerminalConfig {
209+ command: "tmux".to_string(),
210+ args: vec!["split-window".to_string()],
211+ });
212+ }
213+
214+ None
215+}
216+
170217#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
171218#[serde(default, rename_all = "kebab-case", deny_unknown_fields)]
172219pub struct LspConfig {
@@ -497,6 +544,7 @@ impl Default for Config {
497544 true_color: false,
498545 search: SearchConfig::default(),
499546 lsp: LspConfig::default(),
547+ terminal: get_terminal_provider(),
500548 rulers: Vec::new(),
501549 whitespace: WhitespaceConfig::default(),
502550 indent_guides: IndentGuidesConfig::default(),
helix-view/src/handlers/dap.rs+26−27
@@ -5,7 +5,6 @@ use helix_dap::{self as dap, Client, Payload, Request, ThreadId};
55use helix_lsp::block_on;
66use log::warn;
77use std::fmt::Write;
8−use std::io::ErrorKind;
98use std::path::PathBuf;
109
1110#[macro_export]
@@ -287,32 +286,32 @@ impl Editor {
287286 serde_json::from_value(request.arguments.unwrap_or_default()).unwrap();
288287 // TODO: no unwrap
289288
290− let process = if cfg!(windows) {
291− std::process::Command::new("wt")
292− .arg("new-tab")
293− .arg("--title")
294− .arg("DEBUG")
295− .arg("cmd")
296− .arg("/C")
297− .arg(arguments.args.join(" "))
298− .spawn()
299− .unwrap_or_else(|error| match error.kind() {
300− ErrorKind::NotFound => std::process::Command::new("conhost")
301− .arg("cmd")
302− .arg("/C")
303− .arg(arguments.args.join(" "))
304− .spawn()
305− .unwrap(),
306− // TODO replace the pretty print {:?} with a regular format {}
307− // when the MSRV is raised to 1.60.0
308− e => panic!("Error to start debug console: {:?}", e),
309− })
310− } else {
311− std::process::Command::new("tmux")
312− .arg("split-window")
313− .arg(arguments.args.join(" "))
314− .spawn()
315− .unwrap()
289+ let config = match self.config().terminal.clone() {
290+ Some(config) => config,
291+ None => {
292+ self.set_error("No external terminal defined");
293+ return true;
294+ }
295+ };
296+
297+ // Re-borrowing debugger to avoid issues when loading config
298+ let debugger = match self.debugger.as_mut() {
299+ Some(debugger) => debugger,
300+ None => return false,
301+ };
302+
303+ let process = match std::process::Command::new(config.command)
304+ .args(config.args)
305+ .arg(arguments.args.join(" "))
306+ .spawn()
307+ {
308+ Ok(process) => process,
309+ Err(err) => {
310+ // TODO replace the pretty print {:?} with a regular format {}
311+ // when the MSRV is raised to 1.60.0
312+ self.set_error(format!("Error starting external terminal: {:?}", err));
313+ return true;
314+ }
316315 };
317316
318317 let _ = debugger