Populate project path context on shell creation
This commit is contained in:
parent
8e11e6a03e
commit
c9eb9a9e41
9 changed files with 311 additions and 37 deletions
|
@ -13,6 +13,7 @@ use async_trait::async_trait;
|
||||||
use collections::{FxHashMap, HashMap};
|
use collections::{FxHashMap, HashMap};
|
||||||
use gpui::{AsyncApp, SharedString};
|
use gpui::{AsyncApp, SharedString};
|
||||||
use settings::WorktreeId;
|
use settings::WorktreeId;
|
||||||
|
use task::ShellKind;
|
||||||
|
|
||||||
use crate::{LanguageName, ManifestName};
|
use crate::{LanguageName, ManifestName};
|
||||||
|
|
||||||
|
@ -26,7 +27,7 @@ pub struct Toolchain {
|
||||||
/// Full toolchain data (including language-specific details)
|
/// Full toolchain data (including language-specific details)
|
||||||
pub as_json: serde_json::Value,
|
pub as_json: serde_json::Value,
|
||||||
/// shell -> script
|
/// shell -> script
|
||||||
pub startup_script: FxHashMap<String, String>,
|
pub activation_script: FxHashMap<ShellKind, String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::hash::Hash for Toolchain {
|
impl std::hash::Hash for Toolchain {
|
||||||
|
@ -36,7 +37,7 @@ impl std::hash::Hash for Toolchain {
|
||||||
path,
|
path,
|
||||||
language_name,
|
language_name,
|
||||||
as_json: _,
|
as_json: _,
|
||||||
startup_script: _,
|
activation_script: _,
|
||||||
} = self;
|
} = self;
|
||||||
name.hash(state);
|
name.hash(state);
|
||||||
path.hash(state);
|
path.hash(state);
|
||||||
|
@ -51,7 +52,7 @@ impl PartialEq for Toolchain {
|
||||||
path,
|
path,
|
||||||
language_name,
|
language_name,
|
||||||
as_json: _,
|
as_json: _,
|
||||||
startup_script,
|
activation_script: startup_script,
|
||||||
} = self;
|
} = self;
|
||||||
// Do not use as_json for comparisons; it shouldn't impact equality, as it's not user-surfaced.
|
// Do not use as_json for comparisons; it shouldn't impact equality, as it's not user-surfaced.
|
||||||
// Thus, there could be multiple entries that look the same in the UI.
|
// Thus, there could be multiple entries that look the same in the UI.
|
||||||
|
@ -59,7 +60,7 @@ impl PartialEq for Toolchain {
|
||||||
&other.name,
|
&other.name,
|
||||||
&other.path,
|
&other.path,
|
||||||
&other.language_name,
|
&other.language_name,
|
||||||
&other.startup_script,
|
&other.activation_script,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ use std::{
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
use task::{TaskTemplate, TaskTemplates, VariableName};
|
use task::{ShellKind, TaskTemplate, TaskTemplates, VariableName};
|
||||||
use util::ResultExt;
|
use util::ResultExt;
|
||||||
|
|
||||||
pub(crate) struct PyprojectTomlManifestProvider;
|
pub(crate) struct PyprojectTomlManifestProvider;
|
||||||
|
@ -872,14 +872,17 @@ impl ToolchainLister for PythonToolchainProvider {
|
||||||
if let Some(nk) = name_and_kind {
|
if let Some(nk) = name_and_kind {
|
||||||
_ = write!(name, " {nk}");
|
_ = write!(name, " {nk}");
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(Toolchain {
|
Some(Toolchain {
|
||||||
name: name.into(),
|
name: name.into(),
|
||||||
path: toolchain.executable.as_ref()?.to_str()?.to_owned().into(),
|
path: toolchain.executable.as_ref()?.to_str()?.to_owned().into(),
|
||||||
language_name: LanguageName::new("Python"),
|
language_name: LanguageName::new("Python"),
|
||||||
as_json: serde_json::to_value(toolchain).ok()?,
|
as_json: serde_json::to_value(toolchain).ok()?,
|
||||||
startup_script: std::iter::once(("fish".to_owned(), "test".to_owned()))
|
activation_script: std::iter::once((
|
||||||
.collect(),
|
ShellKind::Fish,
|
||||||
|
"echo python recognized a venv and injected a fish startup command"
|
||||||
|
.to_owned(),
|
||||||
|
))
|
||||||
|
.collect(),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -1691,3 +1694,180 @@ mod tests {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
fn python_venv_directory(
|
||||||
|
abs_path: Arc<Path>,
|
||||||
|
venv_settings: VenvSettings,
|
||||||
|
cx: &Context<Project>,
|
||||||
|
) -> Task<Option<PathBuf>> {
|
||||||
|
cx.spawn(async move |this, cx| {
|
||||||
|
if let Some((worktree, relative_path)) = this
|
||||||
|
.update(cx, |this, cx| this.find_worktree(&abs_path, cx))
|
||||||
|
.ok()?
|
||||||
|
{
|
||||||
|
let toolchain = this
|
||||||
|
.update(cx, |this, cx| {
|
||||||
|
this.active_toolchain(
|
||||||
|
ProjectPath {
|
||||||
|
worktree_id: worktree.read(cx).id(),
|
||||||
|
path: relative_path.into(),
|
||||||
|
},
|
||||||
|
LanguageName::new("Python"),
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.ok()?
|
||||||
|
.await;
|
||||||
|
|
||||||
|
if let Some(toolchain) = toolchain {
|
||||||
|
let toolchain_path = Path::new(toolchain.path.as_ref());
|
||||||
|
return Some(toolchain_path.parent()?.parent()?.to_path_buf());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let venv_settings = venv_settings.as_option()?;
|
||||||
|
this.update(cx, move |this, cx| {
|
||||||
|
if let Some(path) = this.find_venv_in_worktree(&abs_path, &venv_settings, cx) {
|
||||||
|
return Some(path);
|
||||||
|
}
|
||||||
|
this.find_venv_on_filesystem(&abs_path, &venv_settings, cx)
|
||||||
|
})
|
||||||
|
.ok()
|
||||||
|
.flatten()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_venv_in_worktree(
|
||||||
|
&self,
|
||||||
|
abs_path: &Path,
|
||||||
|
venv_settings: &terminal_settings::VenvSettingsContent,
|
||||||
|
cx: &App,
|
||||||
|
) -> Option<PathBuf> {
|
||||||
|
venv_settings
|
||||||
|
.directories
|
||||||
|
.iter()
|
||||||
|
.map(|name| abs_path.join(name))
|
||||||
|
.find(|venv_path| {
|
||||||
|
let bin_path = venv_path.join(PYTHON_VENV_BIN_DIR);
|
||||||
|
self.find_worktree(&bin_path, cx)
|
||||||
|
.and_then(|(worktree, relative_path)| {
|
||||||
|
worktree.read(cx).entry_for_path(&relative_path)
|
||||||
|
})
|
||||||
|
.is_some_and(|entry| entry.is_dir())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_venv_on_filesystem(
|
||||||
|
&self,
|
||||||
|
abs_path: &Path,
|
||||||
|
venv_settings: &terminal_settings::VenvSettingsContent,
|
||||||
|
cx: &App,
|
||||||
|
) -> Option<PathBuf> {
|
||||||
|
let (worktree, _) = self.find_worktree(abs_path, cx)?;
|
||||||
|
let fs = worktree.read(cx).as_local()?.fs();
|
||||||
|
venv_settings
|
||||||
|
.directories
|
||||||
|
.iter()
|
||||||
|
.map(|name| abs_path.join(name))
|
||||||
|
.find(|venv_path| {
|
||||||
|
let bin_path = venv_path.join(PYTHON_VENV_BIN_DIR);
|
||||||
|
// One-time synchronous check is acceptable for terminal/task initialization
|
||||||
|
smol::block_on(fs.metadata(&bin_path))
|
||||||
|
.ok()
|
||||||
|
.flatten()
|
||||||
|
.map_or(false, |meta| meta.is_dir)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn activate_script_kind(shell: Option<&str>) -> ActivateScript {
|
||||||
|
let shell_env = std::env::var("SHELL").ok();
|
||||||
|
let shell_path = shell.or_else(|| shell_env.as_deref());
|
||||||
|
let shell = std::path::Path::new(shell_path.unwrap_or(""))
|
||||||
|
.file_name()
|
||||||
|
.and_then(|name| name.to_str())
|
||||||
|
.unwrap_or("");
|
||||||
|
match shell {
|
||||||
|
"fish" => ActivateScript::Fish,
|
||||||
|
"tcsh" => ActivateScript::Csh,
|
||||||
|
"nu" => ActivateScript::Nushell,
|
||||||
|
"powershell" | "pwsh" => ActivateScript::PowerShell,
|
||||||
|
_ => ActivateScript::Default,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn python_activate_command(
|
||||||
|
&self,
|
||||||
|
venv_base_directory: &Path,
|
||||||
|
venv_settings: &VenvSettings,
|
||||||
|
shell: &Shell,
|
||||||
|
cx: &mut App,
|
||||||
|
) -> Task<Option<String>> {
|
||||||
|
let Some(venv_settings) = venv_settings.as_option() else {
|
||||||
|
return Task::ready(None);
|
||||||
|
};
|
||||||
|
let activate_keyword = match venv_settings.activate_script {
|
||||||
|
terminal_settings::ActivateScript::Default => match std::env::consts::OS {
|
||||||
|
"windows" => ".",
|
||||||
|
_ => ".",
|
||||||
|
},
|
||||||
|
terminal_settings::ActivateScript::Nushell => "overlay use",
|
||||||
|
terminal_settings::ActivateScript::PowerShell => ".",
|
||||||
|
terminal_settings::ActivateScript::Pyenv => "pyenv",
|
||||||
|
_ => "source",
|
||||||
|
};
|
||||||
|
let script_kind = if venv_settings.activate_script == terminal_settings::ActivateScript::Default
|
||||||
|
{
|
||||||
|
match shell {
|
||||||
|
Shell::Program(program) => Self::activate_script_kind(Some(program)),
|
||||||
|
Shell::WithArguments {
|
||||||
|
program,
|
||||||
|
args: _,
|
||||||
|
title_override: _,
|
||||||
|
} => Self::activate_script_kind(Some(program)),
|
||||||
|
Shell::System => Self::activate_script_kind(None),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
venv_settings.activate_script
|
||||||
|
};
|
||||||
|
|
||||||
|
let activate_script_name = match script_kind {
|
||||||
|
terminal_settings::ActivateScript::Default | terminal_settings::ActivateScript::Pyenv => {
|
||||||
|
"activate"
|
||||||
|
}
|
||||||
|
terminal_settings::ActivateScript::Csh => "activate.csh",
|
||||||
|
terminal_settings::ActivateScript::Fish => "activate.fish",
|
||||||
|
terminal_settings::ActivateScript::Nushell => "activate.nu",
|
||||||
|
terminal_settings::ActivateScript::PowerShell => "activate.ps1",
|
||||||
|
};
|
||||||
|
|
||||||
|
let line_ending = match std::env::consts::OS {
|
||||||
|
"windows" => "\r",
|
||||||
|
_ => "\n",
|
||||||
|
};
|
||||||
|
|
||||||
|
if venv_settings.venv_name.is_empty() {
|
||||||
|
let path = venv_base_directory
|
||||||
|
.join(PYTHON_VENV_BIN_DIR)
|
||||||
|
.join(activate_script_name)
|
||||||
|
.to_string_lossy()
|
||||||
|
.to_string();
|
||||||
|
|
||||||
|
let is_valid_path = self.resolve_abs_path(path.as_ref(), cx);
|
||||||
|
cx.background_spawn(async move {
|
||||||
|
let quoted = shlex::try_quote(&path).ok()?;
|
||||||
|
if is_valid_path.await.is_some_and(|meta| meta.is_file()) {
|
||||||
|
Some(format!(
|
||||||
|
"{} {} ; clear{}",
|
||||||
|
activate_keyword, quoted, line_ending
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Task::ready(Some(format!(
|
||||||
|
"{activate_keyword} {activate_script_name} {name}; clear{line_ending}",
|
||||||
|
name = venv_settings.venv_name
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
|
@ -9204,7 +9204,7 @@ fn python_lang(fs: Arc<FakeFs>) -> Arc<Language> {
|
||||||
path: venv_path.to_string_lossy().into_owned().into(),
|
path: venv_path.to_string_lossy().into_owned().into(),
|
||||||
language_name: LanguageName(SharedString::new_static("Python")),
|
language_name: LanguageName(SharedString::new_static("Python")),
|
||||||
as_json: serde_json::Value::Null,
|
as_json: serde_json::Value::Null,
|
||||||
startup_script: Default::default(),
|
activation_script: Default::default(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ use std::{
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
use task::{Shell, ShellBuilder, SpawnInTerminal, system_shell};
|
use task::{Shell, ShellBuilder, ShellKind, SpawnInTerminal, system_shell};
|
||||||
use terminal::{
|
use terminal::{
|
||||||
TaskState, TaskStatus, Terminal, TerminalBuilder, terminal_settings::TerminalSettings,
|
TaskState, TaskStatus, Terminal, TerminalBuilder, terminal_settings::TerminalSettings,
|
||||||
};
|
};
|
||||||
|
@ -293,10 +293,12 @@ impl Project {
|
||||||
|
|
||||||
let scripts = maybe!(async {
|
let scripts = maybe!(async {
|
||||||
let toolchain = toolchain?.await?;
|
let toolchain = toolchain?.await?;
|
||||||
Some(toolchain.startup_script)
|
Some(toolchain.activation_script)
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
let activation_script = scripts.as_ref().and_then(|it| it.get(&shell));
|
let activation_script = scripts
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|it| it.get(&ShellKind::new(&shell)));
|
||||||
let shell = {
|
let shell = {
|
||||||
match ssh_details {
|
match ssh_details {
|
||||||
Some(SshDetails {
|
Some(SshDetails {
|
||||||
|
|
|
@ -20,6 +20,7 @@ use rpc::{
|
||||||
proto::{self, FromProto, ToProto},
|
proto::{self, FromProto, ToProto},
|
||||||
};
|
};
|
||||||
use settings::WorktreeId;
|
use settings::WorktreeId;
|
||||||
|
use task::ShellKind;
|
||||||
use util::ResultExt as _;
|
use util::ResultExt as _;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -138,7 +139,11 @@ impl ToolchainStore {
|
||||||
// Do we need to convert path to native string?
|
// Do we need to convert path to native string?
|
||||||
path: PathBuf::from(toolchain.path).to_proto().into(),
|
path: PathBuf::from(toolchain.path).to_proto().into(),
|
||||||
as_json: serde_json::Value::from_str(&toolchain.raw_json)?,
|
as_json: serde_json::Value::from_str(&toolchain.raw_json)?,
|
||||||
startup_script: toolchain.activation_script.into_iter().collect(),
|
activation_script: toolchain
|
||||||
|
.activation_script
|
||||||
|
.into_iter()
|
||||||
|
.map(|(k, v)| (ShellKind::new(&k), v))
|
||||||
|
.collect(),
|
||||||
language_name,
|
language_name,
|
||||||
};
|
};
|
||||||
let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id);
|
let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id);
|
||||||
|
@ -179,7 +184,11 @@ impl ToolchainStore {
|
||||||
name: toolchain.name.into(),
|
name: toolchain.name.into(),
|
||||||
path: path.to_proto(),
|
path: path.to_proto(),
|
||||||
raw_json: toolchain.as_json.to_string(),
|
raw_json: toolchain.as_json.to_string(),
|
||||||
activation_script: toolchain.startup_script.into_iter().collect(),
|
activation_script: toolchain
|
||||||
|
.activation_script
|
||||||
|
.into_iter()
|
||||||
|
.map(|(k, v)| (k.to_string(), v))
|
||||||
|
.collect(),
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
@ -223,7 +232,11 @@ impl ToolchainStore {
|
||||||
name: toolchain.name.to_string(),
|
name: toolchain.name.to_string(),
|
||||||
path: path.to_proto(),
|
path: path.to_proto(),
|
||||||
raw_json: toolchain.as_json.to_string(),
|
raw_json: toolchain.as_json.to_string(),
|
||||||
activation_script: toolchain.startup_script.into_iter().collect(),
|
activation_script: toolchain
|
||||||
|
.activation_script
|
||||||
|
.into_iter()
|
||||||
|
.map(|(k, v)| (k.to_string(), v))
|
||||||
|
.collect(),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
@ -452,7 +465,11 @@ impl RemoteToolchainStore {
|
||||||
name: toolchain.name.into(),
|
name: toolchain.name.into(),
|
||||||
path: path.to_proto(),
|
path: path.to_proto(),
|
||||||
raw_json: toolchain.as_json.to_string(),
|
raw_json: toolchain.as_json.to_string(),
|
||||||
activation_script: toolchain.startup_script.into_iter().collect(),
|
activation_script: toolchain
|
||||||
|
.activation_script
|
||||||
|
.into_iter()
|
||||||
|
.map(|(k, v)| (k.to_string(), v))
|
||||||
|
.collect(),
|
||||||
}),
|
}),
|
||||||
path: Some(project_path.path.to_string_lossy().into_owned()),
|
path: Some(project_path.path.to_string_lossy().into_owned()),
|
||||||
})
|
})
|
||||||
|
@ -505,7 +522,11 @@ impl RemoteToolchainStore {
|
||||||
.to_string()
|
.to_string()
|
||||||
.into(),
|
.into(),
|
||||||
as_json: serde_json::Value::from_str(&toolchain.raw_json).ok()?,
|
as_json: serde_json::Value::from_str(&toolchain.raw_json).ok()?,
|
||||||
startup_script: toolchain.activation_script.into_iter().collect(),
|
activation_script: toolchain
|
||||||
|
.activation_script
|
||||||
|
.into_iter()
|
||||||
|
.map(|(k, v)| (ShellKind::new(&k), v))
|
||||||
|
.collect(),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -562,7 +583,11 @@ impl RemoteToolchainStore {
|
||||||
.to_string()
|
.to_string()
|
||||||
.into(),
|
.into(),
|
||||||
as_json: serde_json::Value::from_str(&toolchain.raw_json).ok()?,
|
as_json: serde_json::Value::from_str(&toolchain.raw_json).ok()?,
|
||||||
startup_script: toolchain.activation_script.into_iter().collect(),
|
activation_script: toolchain
|
||||||
|
.activation_script
|
||||||
|
.into_iter()
|
||||||
|
.map(|(k, v)| (ShellKind::new(&k), v))
|
||||||
|
.collect(),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
use crate::Shell;
|
use crate::Shell;
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
@ -11,6 +13,19 @@ pub enum ShellKind {
|
||||||
Cmd,
|
Cmd,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for ShellKind {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
ShellKind::Posix => write!(f, "sh"),
|
||||||
|
ShellKind::Csh => write!(f, "csh"),
|
||||||
|
ShellKind::Fish => write!(f, "fish"),
|
||||||
|
ShellKind::Powershell => write!(f, "powershell"),
|
||||||
|
ShellKind::Nushell => write!(f, "nu"),
|
||||||
|
ShellKind::Cmd => write!(f, "cmd"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ShellKind {
|
impl ShellKind {
|
||||||
pub fn system() -> Self {
|
pub fn system() -> Self {
|
||||||
Self::new(&system_shell())
|
Self::new(&system_shell())
|
||||||
|
|
|
@ -1,4 +1,11 @@
|
||||||
use std::{cmp, ops::ControlFlow, path::PathBuf, process::ExitStatus, sync::Arc, time::Duration};
|
use std::{
|
||||||
|
cmp,
|
||||||
|
ops::ControlFlow,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
process::ExitStatus,
|
||||||
|
sync::Arc,
|
||||||
|
time::Duration,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
TerminalView, default_working_directory,
|
TerminalView, default_working_directory,
|
||||||
|
@ -414,22 +421,36 @@ impl TerminalPanel {
|
||||||
let weak_workspace = self.workspace.clone();
|
let weak_workspace = self.workspace.clone();
|
||||||
let project = workspace.project().clone();
|
let project = workspace.project().clone();
|
||||||
let active_pane = &self.active_pane;
|
let active_pane = &self.active_pane;
|
||||||
let working_directory = active_pane
|
let terminal_view = active_pane
|
||||||
.read(cx)
|
.read(cx)
|
||||||
.active_item()
|
.active_item()
|
||||||
.and_then(|item| item.downcast::<TerminalView>())
|
.and_then(|item| item.downcast::<TerminalView>());
|
||||||
.map(|terminal_view| {
|
let working_directory = terminal_view.as_ref().and_then(|terminal_view| {
|
||||||
let terminal = terminal_view.read(cx).terminal().read(cx);
|
let terminal = terminal_view.read(cx).terminal().read(cx);
|
||||||
terminal
|
terminal
|
||||||
.working_directory()
|
.working_directory()
|
||||||
.or_else(|| default_working_directory(workspace, cx))
|
.or_else(|| default_working_directory(workspace, cx))
|
||||||
})
|
});
|
||||||
.unwrap_or(None);
|
|
||||||
let is_zoomed = active_pane.read(cx).is_zoomed();
|
let is_zoomed = active_pane.read(cx).is_zoomed();
|
||||||
cx.spawn_in(window, async move |panel, cx| {
|
cx.spawn_in(window, async move |panel, cx| {
|
||||||
let terminal = project
|
let terminal = project
|
||||||
.update(cx, |project, cx| {
|
.update(cx, |project, cx| match terminal_view {
|
||||||
project.create_terminal_shell(working_directory, cx, None)
|
Some(view) => Task::ready(project.clone_terminal(
|
||||||
|
&view.read(cx).terminal.clone(),
|
||||||
|
cx,
|
||||||
|
|| working_directory,
|
||||||
|
)),
|
||||||
|
None => project.create_terminal_shell(
|
||||||
|
working_directory,
|
||||||
|
cx,
|
||||||
|
project
|
||||||
|
.active_entry()
|
||||||
|
.and_then(|entry_id| project.worktree_id_for_entry(entry_id, cx))
|
||||||
|
.map(|worktree_id| project::ProjectPath {
|
||||||
|
worktree_id,
|
||||||
|
path: Arc::from(Path::new("")),
|
||||||
|
}),
|
||||||
|
),
|
||||||
})
|
})
|
||||||
.ok()?
|
.ok()?
|
||||||
.await
|
.await
|
||||||
|
@ -770,7 +791,17 @@ impl TerminalPanel {
|
||||||
let project = workspace.read_with(cx, |workspace, _| workspace.project().clone())?;
|
let project = workspace.read_with(cx, |workspace, _| workspace.project().clone())?;
|
||||||
let terminal = project
|
let terminal = project
|
||||||
.update(cx, |project, cx| {
|
.update(cx, |project, cx| {
|
||||||
project.create_terminal_shell(cwd, cx, None)
|
project.create_terminal_shell(
|
||||||
|
cwd,
|
||||||
|
cx,
|
||||||
|
project
|
||||||
|
.active_entry()
|
||||||
|
.and_then(|entry_id| project.worktree_id_for_entry(entry_id, cx))
|
||||||
|
.map(|worktree_id| project::ProjectPath {
|
||||||
|
worktree_id,
|
||||||
|
path: Arc::from(Path::new("")),
|
||||||
|
}),
|
||||||
|
)
|
||||||
})?
|
})?
|
||||||
.await?;
|
.await?;
|
||||||
let result = workspace.update_in(cx, |workspace, window, cx| {
|
let result = workspace.update_in(cx, |workspace, window, cx| {
|
||||||
|
|
|
@ -205,7 +205,17 @@ impl TerminalView {
|
||||||
) {
|
) {
|
||||||
let working_directory = default_working_directory(workspace, cx);
|
let working_directory = default_working_directory(workspace, cx);
|
||||||
TerminalPanel::add_center_terminal(workspace, window, cx, |project, cx| {
|
TerminalPanel::add_center_terminal(workspace, window, cx, |project, cx| {
|
||||||
project.create_terminal_shell(working_directory, cx, None)
|
project.create_terminal_shell(
|
||||||
|
working_directory,
|
||||||
|
cx,
|
||||||
|
project
|
||||||
|
.active_entry()
|
||||||
|
.and_then(|entry_id| project.worktree_id_for_entry(entry_id, cx))
|
||||||
|
.map(|worktree_id| project::ProjectPath {
|
||||||
|
worktree_id,
|
||||||
|
path: Arc::from(Path::new("")),
|
||||||
|
}),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
.detach_and_log_err(cx);
|
.detach_and_log_err(cx);
|
||||||
}
|
}
|
||||||
|
@ -1490,7 +1500,17 @@ impl SerializableItem for TerminalView {
|
||||||
|
|
||||||
let terminal = project
|
let terminal = project
|
||||||
.update(cx, |project, cx| {
|
.update(cx, |project, cx| {
|
||||||
project.create_terminal_shell(cwd, cx, None)
|
project.create_terminal_shell(
|
||||||
|
cwd,
|
||||||
|
cx,
|
||||||
|
project
|
||||||
|
.active_entry()
|
||||||
|
.and_then(|entry_id| project.worktree_id_for_entry(entry_id, cx))
|
||||||
|
.map(|worktree_id| project::ProjectPath {
|
||||||
|
worktree_id,
|
||||||
|
path: Arc::from(Path::new("")),
|
||||||
|
}),
|
||||||
|
)
|
||||||
})?
|
})?
|
||||||
.await?;
|
.await?;
|
||||||
cx.update(|window, cx| {
|
cx.update(|window, cx| {
|
||||||
|
|
|
@ -1389,6 +1389,7 @@ impl WorkspaceDb {
|
||||||
relative_path: String,
|
relative_path: String,
|
||||||
language_name: LanguageName,
|
language_name: LanguageName,
|
||||||
) -> Result<Option<Toolchain>> {
|
) -> Result<Option<Toolchain>> {
|
||||||
|
return Ok(None);
|
||||||
self.write(move |this| {
|
self.write(move |this| {
|
||||||
let mut select = this
|
let mut select = this
|
||||||
.select_bound(sql!(
|
.select_bound(sql!(
|
||||||
|
@ -1404,8 +1405,7 @@ impl WorkspaceDb {
|
||||||
path: path.into(),
|
path: path.into(),
|
||||||
language_name,
|
language_name,
|
||||||
as_json: serde_json::Value::from_str(&raw_json).ok()?,
|
as_json: serde_json::Value::from_str(&raw_json).ok()?,
|
||||||
// todo refresh?
|
activation_script: Default::default(),
|
||||||
startup_script: Default::default(),
|
|
||||||
})))
|
})))
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
@ -1415,6 +1415,7 @@ impl WorkspaceDb {
|
||||||
&self,
|
&self,
|
||||||
workspace_id: WorkspaceId,
|
workspace_id: WorkspaceId,
|
||||||
) -> Result<Vec<(Toolchain, WorktreeId, Arc<Path>)>> {
|
) -> Result<Vec<(Toolchain, WorktreeId, Arc<Path>)>> {
|
||||||
|
return Ok(vec![]);
|
||||||
self.write(move |this| {
|
self.write(move |this| {
|
||||||
let mut select = this
|
let mut select = this
|
||||||
.select_bound(sql!(
|
.select_bound(sql!(
|
||||||
|
@ -1430,8 +1431,7 @@ impl WorkspaceDb {
|
||||||
path: path.into(),
|
path: path.into(),
|
||||||
language_name: LanguageName::new(&language_name),
|
language_name: LanguageName::new(&language_name),
|
||||||
as_json: serde_json::Value::from_str(&raw_json).ok()?,
|
as_json: serde_json::Value::from_str(&raw_json).ok()?,
|
||||||
// todo refresh?
|
activation_script: Default::default(),
|
||||||
startup_script: Default::default(),
|
|
||||||
}, WorktreeId::from_proto(worktree_id), Arc::from(relative_worktree_path.as_ref())))).collect())
|
}, WorktreeId::from_proto(worktree_id), Arc::from(relative_worktree_path.as_ref())))).collect())
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue