Extend task templates with shell and hide fields to use custom shells and custom close behavior (#15031)

This commit is contained in:
Kirill Bulatov 2024-07-23 22:58:36 +03:00 committed by GitHub
parent 4a43084cb7
commit b2b9d4ccb6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 302 additions and 148 deletions

View file

@ -14,9 +14,9 @@ use project::{Fs, ProjectEntryId};
use search::{buffer_search::DivRegistrar, BufferSearchBar};
use serde::{Deserialize, Serialize};
use settings::Settings;
use task::{RevealStrategy, SpawnInTerminal, TaskId, TerminalWorkDir};
use task::{RevealStrategy, Shell, SpawnInTerminal, TaskId, TerminalWorkDir};
use terminal::{
terminal_settings::{Shell, TerminalDockPosition, TerminalSettings},
terminal_settings::{TerminalDockPosition, TerminalSettings},
Terminal,
};
use ui::{
@ -363,15 +363,15 @@ impl TerminalPanel {
fn spawn_task(&mut self, spawn_in_terminal: &SpawnInTerminal, cx: &mut ViewContext<Self>) {
let mut spawn_task = spawn_in_terminal.clone();
// Set up shell args unconditionally, as tasks are always spawned inside of a shell.
let Some((shell, mut user_args)) = (match TerminalSettings::get_global(cx).shell.clone() {
Shell::System => Shell::retrieve_system_shell().map(|shell| (shell, Vec::new())),
let Some((shell, mut user_args)) = (match spawn_in_terminal.shell.clone() {
Shell::System => retrieve_system_shell().map(|shell| (shell, Vec::new())),
Shell::Program(shell) => Some((shell, Vec::new())),
Shell::WithArguments { program, args } => Some((program, args)),
}) else {
return;
};
#[cfg(target_os = "windows")]
let windows_shell_type = Shell::to_windows_shell_type(&shell);
let windows_shell_type = to_windows_shell_type(&shell);
#[cfg(not(target_os = "windows"))]
{
@ -379,7 +379,7 @@ impl TerminalPanel {
}
#[cfg(target_os = "windows")]
{
use terminal::terminal_settings::WindowsShellType;
use crate::terminal_panel::WindowsShellType;
match windows_shell_type {
WindowsShellType::Powershell => {
@ -404,7 +404,7 @@ impl TerminalPanel {
#[cfg(not(target_os = "windows"))]
command.push_str(&arg);
#[cfg(target_os = "windows")]
command.push_str(&Shell::to_windows_shell_variable(windows_shell_type, arg));
command.push_str(&to_windows_shell_variable(windows_shell_type, arg));
command
});
@ -412,7 +412,7 @@ impl TerminalPanel {
user_args.extend(["-i".to_owned(), "-c".to_owned(), combined_command]);
#[cfg(target_os = "windows")]
{
use terminal::terminal_settings::WindowsShellType;
use crate::terminal_panel::WindowsShellType;
match windows_shell_type {
WindowsShellType::Powershell => {
@ -845,3 +845,93 @@ struct SerializedTerminalPanel {
width: Option<Pixels>,
height: Option<Pixels>,
}
fn retrieve_system_shell() -> Option<String> {
#[cfg(not(target_os = "windows"))]
{
use anyhow::Context;
use util::ResultExt;
return std::env::var("SHELL")
.context("Error finding SHELL in env.")
.log_err();
}
// `alacritty_terminal` uses this as default on Windows. See:
// https://github.com/alacritty/alacritty/blob/0d4ab7bca43213d96ddfe40048fc0f922543c6f8/alacritty_terminal/src/tty/windows/mod.rs#L130
#[cfg(target_os = "windows")]
return Some("powershell".to_owned());
}
#[cfg(target_os = "windows")]
fn to_windows_shell_variable(shell_type: WindowsShellType, input: String) -> String {
match shell_type {
WindowsShellType::Powershell => to_powershell_variable(input),
WindowsShellType::Cmd => to_cmd_variable(input),
WindowsShellType::Other => input,
}
}
#[cfg(target_os = "windows")]
fn to_windows_shell_type(shell: &str) -> WindowsShellType {
if shell == "powershell" || shell.ends_with("powershell.exe") {
WindowsShellType::Powershell
} else if shell == "cmd" || shell.ends_with("cmd.exe") {
WindowsShellType::Cmd
} else {
// Someother shell detected, the user might install and use a
// unix-like shell.
WindowsShellType::Other
}
}
/// Convert `${SOME_VAR}`, `$SOME_VAR` to `%SOME_VAR%`.
#[inline]
#[cfg(target_os = "windows")]
fn to_cmd_variable(input: String) -> String {
if let Some(var_str) = input.strip_prefix("${") {
if var_str.find(':').is_none() {
// If the input starts with "${", remove the trailing "}"
format!("%{}%", &var_str[..var_str.len() - 1])
} else {
// `${SOME_VAR:-SOME_DEFAULT}`, we currently do not handle this situation,
// which will result in the task failing to run in such cases.
input
}
} else if let Some(var_str) = input.strip_prefix('$') {
// If the input starts with "$", directly append to "$env:"
format!("%{}%", var_str)
} else {
// If no prefix is found, return the input as is
input
}
}
/// Convert `${SOME_VAR}`, `$SOME_VAR` to `$env:SOME_VAR`.
#[inline]
#[cfg(target_os = "windows")]
fn to_powershell_variable(input: String) -> String {
if let Some(var_str) = input.strip_prefix("${") {
if var_str.find(':').is_none() {
// If the input starts with "${", remove the trailing "}"
format!("$env:{}", &var_str[..var_str.len() - 1])
} else {
// `${SOME_VAR:-SOME_DEFAULT}`, we currently do not handle this situation,
// which will result in the task failing to run in such cases.
input
}
} else if let Some(var_str) = input.strip_prefix('$') {
// If the input starts with "$", directly append to "$env:"
format!("$env:{}", var_str)
} else {
// If no prefix is found, return the input as is
input
}
}
#[cfg(target_os = "windows")]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum WindowsShellType {
Powershell,
Cmd,
Other,
}