Merge branch 'main' into in-app-feedback

This commit is contained in:
Joseph Lyons 2023-01-23 01:20:10 -05:00
commit f2a5a4d0fd
135 changed files with 3316 additions and 2821 deletions

View file

@ -1,3 +1,4 @@
use anyhow::Context;
use gpui::executor::Background;
pub use language::*;
use lazy_static::lazy_static;
@ -145,7 +146,9 @@ pub(crate) fn language(
.unwrap()
.data,
)
.with_context(|| format!("failed to load config.toml for language {name:?}"))
.unwrap();
let mut language = Language::new(config, Some(grammar));
if let Some(query) = load_query(name, "/highlights") {
@ -173,6 +176,11 @@ pub(crate) fn language(
.with_injection_query(query.as_ref())
.expect("failed to load injection query");
}
if let Some(query) = load_query(name, "/overrides") {
language = language
.with_override_query(query.as_ref())
.expect("failed to load override query");
}
if let Some(lsp_adapter) = lsp_adapter {
language = language.with_lsp_adapter(lsp_adapter)
}

View file

@ -7,5 +7,20 @@ brackets = [
{ start = "[", end = "]", close = true, newline = true },
{ start = "(", end = ")", close = true, newline = true },
{ start = "\"", end = "\"", close = true, newline = false },
{ start = "'", end = "'", close = true, newline = false },
{ start = "/*", end = " */", close = true, newline = false },
]
[overrides.comment]
brackets = [
{ start = "{", end = "}", close = true, newline = true },
{ start = "[", end = "]", close = true, newline = true },
{ start = "(", end = ")", close = true, newline = true },
]
[overrides.string]
brackets = [
{ start = "{", end = "}", close = true, newline = true },
{ start = "[", end = "]", close = true, newline = true },
{ start = "(", end = ")", close = true, newline = true },
]

View file

@ -0,0 +1,2 @@
(comment) @comment
(string_literal) @string

View file

@ -7,5 +7,20 @@ brackets = [
{ start = "[", end = "]", close = true, newline = true },
{ start = "(", end = ")", close = true, newline = true },
{ start = "\"", end = "\"", close = true, newline = false },
{ start = "'", end = "'", close = true, newline = false },
{ start = "/*", end = " */", close = true, newline = false },
]
[overrides.comment]
brackets = [
{ start = "{", end = "}", close = true, newline = true },
{ start = "[", end = "]", close = true, newline = true },
{ start = "(", end = ")", close = true, newline = true },
]
[overrides.string]
brackets = [
{ start = "{", end = "}", close = true, newline = true },
{ start = "[", end = "]", close = true, newline = true },
{ start = "(", end = ")", close = true, newline = true },
]

View file

@ -0,0 +1,2 @@
(comment) @comment
(string_literal) @string

View file

@ -5,5 +5,20 @@ brackets = [
{ start = "{", end = "}", close = true, newline = true },
{ start = "[", end = "]", close = true, newline = true },
{ start = "(", end = ")", close = true, newline = true },
{ start = "\"", end = "\"", close = true, newline = false }
{ start = "\"", end = "\"", close = true, newline = false },
{ start = "'", end = "'", close = true, newline = false },
]
[overrides.comment]
brackets = [
{ start = "{", end = "}", close = true, newline = true },
{ start = "[", end = "]", close = true, newline = true },
{ start = "(", end = ")", close = true, newline = true },
]
[overrides.string]
brackets = [
{ start = "{", end = "}", close = true, newline = true },
{ start = "[", end = "]", close = true, newline = true },
{ start = "(", end = ")", close = true, newline = true },
]

View file

@ -0,0 +1,2 @@
(comment) @comment
(string_value) @string

View file

@ -6,5 +6,20 @@ brackets = [
{ start = "{", end = "}", close = true, newline = true },
{ start = "[", end = "]", close = true, newline = true },
{ start = "(", end = ")", close = true, newline = true },
{ start = "\"", end = "\"", close = true, newline = false }
{ start = "\"", end = "\"", close = true, newline = false },
{ start = "'", end = "'", close = true, newline = false },
]
[overrides.comment]
brackets = [
{ start = "{", end = "}", close = true, newline = true },
{ start = "[", end = "]", close = true, newline = true },
{ start = "(", end = ")", close = true, newline = true },
]
[overrides.string]
brackets = [
{ start = "{", end = "}", close = true, newline = true },
{ start = "[", end = "]", close = true, newline = true },
{ start = "(", end = ")", close = true, newline = true },
]

View file

@ -0,0 +1,2 @@
(comment) @comment
[(string) (charlist)] @string

View file

@ -4,5 +4,4 @@ autoclose_before = ">})"
brackets = [
{ start = "<", end = ">", close = true, newline = true },
]
block_comment = ["<%#", "%>"]
block_comment = ["<%#", "%>"]

View file

@ -7,5 +7,20 @@ brackets = [
{ start = "[", end = "]", close = true, newline = true },
{ start = "(", end = ")", close = true, newline = true },
{ start = "\"", end = "\"", close = true, newline = false },
{ start = "'", end = "'", close = true, newline = false },
{ start = "/*", end = " */", close = true, newline = false },
]
[overrides.comment]
brackets = [
{ start = "{", end = "}", close = true, newline = true },
{ start = "[", end = "]", close = true, newline = true },
{ start = "(", end = ")", close = true, newline = true },
]
[overrides.string]
brackets = [
{ start = "{", end = "}", close = true, newline = true },
{ start = "[", end = "]", close = true, newline = true },
{ start = "(", end = ")", close = true, newline = true },
]

View file

@ -40,5 +40,4 @@
")" @context)) @item
(field_declaration
name: (_) @name
type: (_) @context) @item
name: (_) @name) @item

View file

@ -0,0 +1,6 @@
(comment) @comment
[
(interpreted_string_literal)
(raw_string_literal)
(rune_literal)
] @string

View file

@ -9,4 +9,18 @@ brackets = [
{ start = "!--", end = " --", close = true, newline = false },
]
block_comment = ["<!-- ", " -->"]
block_comment = ["<!-- ", " -->"]
[overrides.comment]
brackets = [
{ start = "{", end = "}", close = true, newline = true },
{ start = "[", end = "]", close = true, newline = true },
{ start = "(", end = ")", close = true, newline = true },
]
[overrides.string]
brackets = [
{ start = "{", end = "}", close = true, newline = true },
{ start = "[", end = "]", close = true, newline = true },
{ start = "(", end = ")", close = true, newline = true },
]

View file

@ -0,0 +1,2 @@
(comment) @comment
(quoted_attribute_value) @string

View file

@ -37,6 +37,8 @@ pub(crate) struct GithubReleaseAsset {
pub async fn npm_package_latest_version(name: &str) -> Result<String> {
let output = smol::process::Command::new("npm")
.args(["-fetch-retry-mintimeout", "2000"])
.args(["-fetch-retry-maxtimeout", "5000"])
.args(["info", name, "--json"])
.output()
.await
@ -60,6 +62,8 @@ pub async fn npm_install_packages(
directory: &Path,
) -> Result<()> {
let output = smol::process::Command::new("npm")
.args(["-fetch-retry-mintimeout", "2000"])
.args(["-fetch-retry-maxtimeout", "5000"])
.arg("install")
.arg("--prefix")
.arg(directory)

View file

@ -12,3 +12,21 @@ brackets = [
{ start = "`", end = "`", close = true, newline = false },
{ start = "/*", end = " */", close = true, newline = false },
]
[overrides.comment]
brackets = [
{ start = "{", end = "}", close = true, newline = true },
{ start = "[", end = "]", close = true, newline = true },
{ start = "(", end = ")", close = true, newline = true },
]
[overrides.string]
brackets = [
{ start = "{", end = "}", close = true, newline = true },
{ start = "[", end = "]", close = true, newline = true },
{ start = "(", end = ")", close = true, newline = true },
]
[overrides.element]
line_comment = { remove = true }
block_comment = ["{/* ", " */}"]

View file

@ -0,0 +1,9 @@
(comment) @comment
(string) @string
[
(jsx_element)
(jsx_fragment)
(jsx_self_closing_element)
(jsx_expression)
] @element

View file

@ -7,3 +7,9 @@ brackets = [
{ start = "[", end = "]", close = true, newline = true },
{ start = "\"", end = "\"", close = true, newline = false },
]
[overrides.string]
brackets = [
{ start = "{", end = "}", close = true, newline = true },
{ start = "[", end = "]", close = true, newline = true },
]

View file

@ -0,0 +1 @@
(string) @string

View file

@ -12,4 +12,18 @@ brackets = [
auto_indent_using_last_non_empty_line = false
increase_indent_pattern = ":$"
decrease_indent_pattern = "^\\s*(else|elif|except|finally)\\b.*:"
decrease_indent_pattern = "^\\s*(else|elif|except|finally)\\b.*:"
[overrides.comment]
brackets = [
{ start = "{", end = "}", close = true, newline = true },
{ start = "[", end = "]", close = true, newline = true },
{ start = "(", end = ")", close = true, newline = true },
]
[overrides.string]
brackets = [
{ start = "{", end = "}", close = true, newline = true },
{ start = "[", end = "]", close = true, newline = true },
{ start = "(", end = ")", close = true, newline = true },
]

View file

@ -0,0 +1,2 @@
(comment) @comment
(string) @string

View file

@ -7,5 +7,19 @@ brackets = [
{ start = "[", end = "]", close = true, newline = true },
{ start = "(", end = ")", close = true, newline = true },
{ start = "\"", end = "\"", close = true, newline = false },
{ start = "'", end = "'", close = false, newline = false },
]
{ start = "'", end = "'", close = true, newline = false },
]
[overrides.comment]
brackets = [
{ start = "{", end = "}", close = true, newline = true },
{ start = "[", end = "]", close = true, newline = true },
{ start = "(", end = ")", close = true, newline = true },
]
[overrides.string]
brackets = [
{ start = "{", end = "}", close = true, newline = true },
{ start = "[", end = "]", close = true, newline = true },
{ start = "(", end = ")", close = true, newline = true },
]

View file

@ -0,0 +1,2 @@
(comment) @comment
(string) @string

View file

@ -11,3 +11,19 @@ brackets = [
{ start = "'", end = "'", close = false, newline = false },
{ start = "/*", end = " */", close = true, newline = false },
]
[overrides.comment]
brackets = [
{ start = "{", end = "}", close = true, newline = true },
{ start = "[", end = "]", close = true, newline = true },
{ start = "(", end = ")", close = true, newline = true },
{ start = "<", end = ">", close = false, newline = true },
]
[overrides.string]
brackets = [
{ start = "{", end = "}", close = true, newline = true },
{ start = "[", end = "]", close = true, newline = true },
{ start = "(", end = ")", close = true, newline = true },
{ start = "<", end = ">", close = false, newline = true },
]

View file

@ -52,6 +52,7 @@
[
"as"
"async"
"await"
"break"
"const"
"continue"

View file

@ -5,6 +5,7 @@
(assignment_expression)
(let_declaration)
(let_chain)
(await_expression)
] @indent
(_ "[" "]" @end) @indent

View file

@ -0,0 +1,8 @@
[
(string_literal)
(raw_string_literal)
] @string
[
(line_comment)
(block_comment)
] @comment

View file

@ -7,3 +7,15 @@ brackets = [
{ start = "(", end = ")", close = true, newline = false },
{ start = "\"", end = "\"", close = true, newline = false },
]
[overrides.comment]
brackets = [
{ start = "{", end = "}", close = true, newline = true },
{ start = "[", end = "]", close = true, newline = true },
]
[overrides.string]
brackets = [
{ start = "{", end = "}", close = true, newline = true },
{ start = "[", end = "]", close = true, newline = true },
]

View file

@ -0,0 +1,6 @@
[
(comment)
(block_comment)
(directive)
] @comment
(string) @string

View file

@ -6,4 +6,17 @@ brackets = [
{ start = "{", end = "}", close = true, newline = true },
{ start = "[", end = "]", close = true, newline = true },
{ start = "\"", end = "\"", close = true, newline = false },
{ start = "'", end = "'", close = true, newline = false },
]
[overrides.comment]
brackets = [
{ start = "{", end = "}", close = true, newline = true },
{ start = "[", end = "]", close = true, newline = true },
]
[overrides.string]
brackets = [
{ start = "{", end = "}", close = true, newline = true },
{ start = "[", end = "]", close = true, newline = true },
]

View file

@ -0,0 +1,2 @@
(comment) @comment
(string) @string

View file

@ -12,3 +12,12 @@ brackets = [
{ start = "`", end = "`", close = true, newline = false },
{ start = "/*", end = " */", close = true, newline = false },
]
[overrides.element]
line_comment = { remove = true }
block_comment = ["{/* ", " */}"]
[overrides.string]
brackets = [
{ start = "{", end = "}", close = true, newline = true },
]

View file

@ -0,0 +1,7 @@
[
(jsx_element)
(jsx_fragment)
(jsx_self_closing_element)
(jsx_expression)
] @element
(string) @string

View file

@ -12,7 +12,8 @@ use util::ResultExt;
pub struct TypeScriptLspAdapter;
impl TypeScriptLspAdapter {
const BIN_PATH: &'static str = "node_modules/typescript-language-server/lib/cli.js";
const OLD_BIN_PATH: &'static str = "node_modules/typescript-language-server/lib/cli.js";
const NEW_BIN_PATH: &'static str = "node_modules/typescript-language-server/lib/cli.mjs";
}
struct Versions {
@ -57,7 +58,7 @@ impl LspAdapter for TypeScriptLspAdapter {
fs::create_dir_all(&version_dir)
.await
.context("failed to create version directory")?;
let binary_path = version_dir.join(Self::BIN_PATH);
let binary_path = version_dir.join(Self::NEW_BIN_PATH);
if fs::metadata(&binary_path).await.is_err() {
npm_install_packages(
@ -98,9 +99,12 @@ impl LspAdapter for TypeScriptLspAdapter {
}
}
let last_version_dir = last_version_dir.ok_or_else(|| anyhow!("no cached binary"))?;
let bin_path = last_version_dir.join(Self::BIN_PATH);
if bin_path.exists() {
Ok(bin_path)
let old_bin_path = last_version_dir.join(Self::OLD_BIN_PATH);
let new_bin_path = last_version_dir.join(Self::NEW_BIN_PATH);
if new_bin_path.exists() {
Ok(new_bin_path)
} else if old_bin_path.exists() {
Ok(old_bin_path)
} else {
Err(anyhow!(
"missing executable in directory {:?}",

View file

@ -12,3 +12,17 @@ brackets = [
{ start = "`", end = "`", close = true, newline = false },
{ start = "/*", end = " */", close = true, newline = false },
]
[overrides.comment]
brackets = [
{ start = "{", end = "}", close = true, newline = true },
{ start = "[", end = "]", close = true, newline = true },
{ start = "(", end = ")", close = true, newline = true },
]
[overrides.string]
brackets = [
{ start = "{", end = "}", close = true, newline = true },
{ start = "[", end = "]", close = true, newline = true },
{ start = "(", end = ")", close = true, newline = true },
]

View file

@ -0,0 +1,2 @@
(comment) @comment
(string) @string

View file

@ -19,7 +19,7 @@ use futures::{
channel::{mpsc, oneshot},
FutureExt, SinkExt, StreamExt,
};
use gpui::{executor::Background, App, AssetSource, AsyncAppContext, Task, ViewContext};
use gpui::{App, AssetSource, AsyncAppContext, MutableAppContext, Task, ViewContext};
use isahc::{config::Configurable, Request};
use language::LanguageRegistry;
use log::LevelFilter;
@ -30,6 +30,7 @@ use settings::{
self, settings_file::SettingsFile, KeymapFileContent, Settings, SettingsFileContent,
WorkingDirectory,
};
use simplelog::ConfigBuilder;
use smol::process::Command;
use std::fs::OpenOptions;
use std::{env, ffi::OsStr, panic, path::PathBuf, sync::Arc, thread, time::Duration};
@ -51,10 +52,13 @@ fn main() {
log::info!("========== starting zed ==========");
let mut app = gpui::App::new(Assets).unwrap();
let app_version = ZED_APP_VERSION
.or_else(|| app.platform().app_version().ok())
.map_or("dev".to_string(), |v| v.to_string());
init_panic_hook(app_version, http.clone(), app.background());
init_panic_hook(app_version);
app.background();
load_embedded_fonts(&app);
@ -62,7 +66,6 @@ fn main() {
let themes = ThemeRegistry::new(Assets, app.font_cache());
let default_settings = Settings::defaults(Assets, &app.font_cache(), &themes);
let config_files = load_config_files(&app, fs.clone());
let login_shell_env_loaded = if stdout_is_a_pty() {
@ -74,6 +77,7 @@ fn main() {
};
let (cli_connections_tx, mut cli_connections_rx) = mpsc::unbounded();
let (open_paths_tx, open_paths_rx) = mpsc::unbounded();
app.on_open_urls(move |urls, _| {
if let Some(server_name) = urls.first().and_then(|url| url.strip_prefix("zed-cli://")) {
if let Some(cli_connection) = connect_to_cli(server_name).log_err() {
@ -82,6 +86,16 @@ fn main() {
.map_err(|_| anyhow!("no listener for cli connections"))
.log_err();
};
} else {
let paths: Vec<_> = urls
.iter()
.flat_map(|url| url.strip_prefix("file://"))
.map(|path| PathBuf::from(path))
.collect();
open_paths_tx
.unbounded_send(paths)
.map_err(|_| anyhow!("no listener for open urls requests"))
.log_err();
}
});
@ -89,6 +103,18 @@ fn main() {
cx.set_global(*RELEASE_CHANNEL);
cx.set_global(HomeDir(paths::HOME.to_path_buf()));
let (settings_file_content, keymap_file) = cx.background().block(config_files).unwrap();
//Setup settings global before binding actions
cx.set_global(SettingsFile::new(
&paths::SETTINGS,
settings_file_content.clone(),
fs.clone(),
));
watch_settings_file(default_settings, settings_file_content, themes.clone(), cx);
upload_previous_panics(http.clone(), cx);
let client = client::Client::new(http.clone(), cx);
let mut languages = LanguageRegistry::new(login_shell_env_loaded);
languages.set_language_server_download_dir(paths::LANGUAGES_DIR.clone());
@ -98,15 +124,6 @@ fn main() {
.spawn(languages::init(languages.clone(), cx.background().clone()));
let user_store = cx.add_model(|cx| UserStore::new(client.clone(), http.clone(), cx));
let (settings_file_content, keymap_file) = cx.background().block(config_files).unwrap();
//Setup settings global before binding actions
cx.set_global(SettingsFile::new(
&paths::SETTINGS,
settings_file_content.clone(),
fs.clone(),
));
watch_settings_file(default_settings, settings_file_content, themes.clone(), cx);
watch_keymap_file(keymap_file, cx);
cx.set_global(client.clone());
@ -147,7 +164,11 @@ fn main() {
.detach();
client.start_telemetry();
client.report_event("start app", Default::default());
client.report_event(
"start app",
Default::default(),
cx.global::<Settings>().telemetry(),
);
let app_state = Arc::new(AppState {
languages,
@ -170,11 +191,15 @@ fn main() {
cx.set_menus(menus::menus());
cx.spawn(|cx| handle_open_paths(open_paths_rx, app_state.clone(), cx))
.detach();
if stdout_is_a_pty() {
cx.platform().activate(true);
let paths = collect_path_args();
if paths.is_empty() {
restore_or_create_workspace(cx);
cx.spawn(|cx| async move { restore_or_create_workspace(cx).await })
.detach()
} else {
cx.dispatch_global_action(OpenPaths { paths });
}
@ -183,7 +208,8 @@ fn main() {
cx.spawn(|cx| handle_cli_connection(connection, app_state.clone(), cx))
.detach();
} else {
restore_or_create_workspace(cx);
cx.spawn(|cx| async move { restore_or_create_workspace(cx).await })
.detach()
}
cx.spawn(|cx| async move {
while let Some(connection) = cli_connections_rx.next().await {
@ -207,13 +233,17 @@ fn main() {
});
}
fn restore_or_create_workspace(cx: &mut gpui::MutableAppContext) {
if let Some(location) = workspace::last_opened_workspace_paths() {
cx.dispatch_global_action(OpenPaths {
paths: location.paths().as_ref().clone(),
})
async fn restore_or_create_workspace(mut cx: AsyncAppContext) {
if let Some(location) = workspace::last_opened_workspace_paths().await {
cx.update(|cx| {
cx.dispatch_global_action(OpenPaths {
paths: location.paths().as_ref().clone(),
})
});
} else {
cx.dispatch_global_action(NewFile);
cx.update(|cx| {
cx.dispatch_global_action(NewFile);
});
}
}
@ -244,70 +274,16 @@ fn init_logger() {
.append(true)
.open(&*paths::LOG)
.expect("could not open logfile");
simplelog::WriteLogger::init(level, simplelog::Config::default(), log_file)
.expect("could not initialize logger");
let config = ConfigBuilder::new()
.set_time_format_str("%Y-%m-%dT%T") //All timestamps are UTC
.build();
simplelog::WriteLogger::init(level, config, log_file).expect("could not initialize logger");
}
}
fn init_panic_hook(app_version: String, http: Arc<dyn HttpClient>, background: Arc<Background>) {
background
.spawn({
async move {
let panic_report_url = format!("{}/api/panic", &*client::ZED_SERVER_URL);
let mut children = smol::fs::read_dir(&*paths::LOGS_DIR).await?;
while let Some(child) = children.next().await {
let child = child?;
let child_path = child.path();
if child_path.extension() != Some(OsStr::new("panic")) {
continue;
}
let filename = if let Some(filename) = child_path.file_name() {
filename.to_string_lossy()
} else {
continue;
};
let mut components = filename.split('-');
if components.next() != Some("zed") {
continue;
}
let version = if let Some(version) = components.next() {
version
} else {
continue;
};
let text = smol::fs::read_to_string(&child_path)
.await
.context("error reading panic file")?;
let body = serde_json::to_string(&json!({
"text": text,
"version": version,
"token": ZED_SECRET_CLIENT_TOKEN,
}))
.unwrap();
let request = Request::post(&panic_report_url)
.redirect_policy(isahc::config::RedirectPolicy::Follow)
.header("Content-Type", "application/json")
.body(body.into())?;
let response = http.send(request).await.context("error sending panic")?;
if response.status().is_success() {
std::fs::remove_file(child_path)
.context("error removing panic after sending it successfully")
.log_err();
} else {
return Err(anyhow!(
"error uploading panic to server: {}",
response.status()
));
}
}
Ok::<_, anyhow::Error>(())
}
.log_err()
})
.detach();
fn init_panic_hook(app_version: String) {
let is_pty = stdout_is_a_pty();
panic::set_hook(Box::new(move |info| {
let backtrace = Backtrace::new();
@ -356,6 +332,69 @@ fn init_panic_hook(app_version: String, http: Arc<dyn HttpClient>, background: A
}));
}
fn upload_previous_panics(http: Arc<dyn HttpClient>, cx: &mut MutableAppContext) {
let diagnostics_telemetry = cx.global::<Settings>().telemetry_diagnostics();
cx.background()
.spawn({
async move {
let panic_report_url = format!("{}/api/panic", &*client::ZED_SERVER_URL);
let mut children = smol::fs::read_dir(&*paths::LOGS_DIR).await?;
while let Some(child) = children.next().await {
let child = child?;
let child_path = child.path();
if child_path.extension() != Some(OsStr::new("panic")) {
continue;
}
let filename = if let Some(filename) = child_path.file_name() {
filename.to_string_lossy()
} else {
continue;
};
let mut components = filename.split('-');
if components.next() != Some("zed") {
continue;
}
let version = if let Some(version) = components.next() {
version
} else {
continue;
};
if diagnostics_telemetry {
let text = smol::fs::read_to_string(&child_path)
.await
.context("error reading panic file")?;
let body = serde_json::to_string(&json!({
"text": text,
"version": version,
"token": ZED_SECRET_CLIENT_TOKEN,
}))
.unwrap();
let request = Request::post(&panic_report_url)
.redirect_policy(isahc::config::RedirectPolicy::Follow)
.header("Content-Type", "application/json")
.body(body.into())?;
let response = http.send(request).await.context("error sending panic")?;
if !response.status().is_success() {
log::error!("Error uploading panic to server: {}", response.status());
}
}
// We've done what we can, delete the file
std::fs::remove_file(child_path)
.context("error removing panic")
.log_err();
}
Ok::<_, anyhow::Error>(())
}
.log_err()
})
.detach();
}
async fn load_login_shell_environment() -> Result<()> {
let marker = "ZED_LOGIN_SHELL_START";
let shell = env::var("SHELL").context(
@ -484,6 +523,17 @@ fn load_config_files(
rx
}
async fn handle_open_paths(
mut rx: mpsc::UnboundedReceiver<Vec<PathBuf>>,
app_state: Arc<AppState>,
mut cx: AsyncAppContext,
) {
while let Some(paths) = rx.next().await {
cx.update(|cx| workspace::open_paths(&paths, &app_state, cx))
.detach();
}
}
fn connect_to_cli(
server_name: &str,
) -> Result<(mpsc::Receiver<CliRequest>, IpcSender<CliResponse>)> {

View file

@ -11,6 +11,7 @@ use collections::VecDeque;
pub use editor;
use editor::{Editor, MultiBuffer};
use futures::StreamExt;
use gpui::{
actions,
geometry::{
@ -19,7 +20,8 @@ use gpui::{
},
impl_actions,
platform::{WindowBounds, WindowOptions},
AssetSource, AsyncAppContext, TitlebarOptions, ViewContext, WindowKind,
AssetSource, AsyncAppContext, ClipboardItem, PromptLevel, TitlebarOptions, ViewContext,
WindowKind,
};
use language::Rope;
use lazy_static::lazy_static;
@ -379,7 +381,23 @@ fn quit(_: &Quit, cx: &mut gpui::MutableAppContext) {
// prompt in the active window before switching to a different window.
workspaces.sort_by_key(|workspace| !cx.window_is_active(workspace.window_id()));
let should_confirm = cx.global::<Settings>().confirm_quit;
cx.spawn(|mut cx| async move {
if let (true, Some(workspace)) = (should_confirm, workspaces.first()) {
let answer = cx
.prompt(
workspace.window_id(),
PromptLevel::Info,
"Are you sure you want to quit?",
&["Quit", "Cancel"],
)
.next()
.await;
if answer != Some(0) {
return Ok(());
}
}
// If the user cancels any save prompt, then keep the app open.
for workspace in workspaces {
if !workspace