Automatically install the HTML extension (#10867)
This PR makes it so the HTML extension will be installed in Zed by default. We feel we should keep HTML available out-of-the-box, but we want to do so while still keeping it as an extension (as opposed to built-in to Zed natively). There may be a world where we bundle the extension in with the Zed binary itself, but installing it on startup gets us 99% of the way there. The approach for making HTML available by default is quite general, and could be applied to any extension that we choose (likely other languages that we want to come out-of-the-box, but that could then be moved to extensions). If you do not want the HTML extension in Zed, you can disable the auto-installation in your `settings.json` and then uninstall the extension: ```json { "auto_install_extensions": { "html": false } } ``` Release Notes: - Added auto-installation for the HTML extension on startup. - This can be disabled by adding `{ "auto_install_extensions": { "html": false } }` to your settings.
This commit is contained in:
parent
c96a96b3ce
commit
63c529552c
3 changed files with 61 additions and 1 deletions
|
@ -590,6 +590,13 @@
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
"file_types": {},
|
"file_types": {},
|
||||||
|
// The extensions that Zed should automatically install on startup.
|
||||||
|
//
|
||||||
|
// If you don't want any of these extensions, add this field to your settings
|
||||||
|
// and change the value to `false`.
|
||||||
|
"auto_install_extensions": {
|
||||||
|
"html": true
|
||||||
|
},
|
||||||
// Different settings for specific languages.
|
// Different settings for specific languages.
|
||||||
"languages": {
|
"languages": {
|
||||||
"C++": {
|
"C++": {
|
||||||
|
|
|
@ -5,14 +5,29 @@ use schemars::JsonSchema;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use settings::{Settings, SettingsSources};
|
use settings::{Settings, SettingsSources};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use util::merge_non_null_json_value_into;
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug, Default, Clone, JsonSchema)]
|
#[derive(Deserialize, Serialize, Debug, Default, Clone, JsonSchema)]
|
||||||
pub struct ExtensionSettings {
|
pub struct ExtensionSettings {
|
||||||
|
/// The extensions that should be automatically installed by Zed.
|
||||||
|
///
|
||||||
|
/// This is used to make functionality provided by extensions (e.g., language support)
|
||||||
|
/// available out-of-the-box.
|
||||||
|
#[serde(default)]
|
||||||
|
pub auto_install_extensions: HashMap<Arc<str>, bool>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub auto_update_extensions: HashMap<Arc<str>, bool>,
|
pub auto_update_extensions: HashMap<Arc<str>, bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExtensionSettings {
|
impl ExtensionSettings {
|
||||||
|
/// Returns whether the given extension should be auto-installed.
|
||||||
|
pub fn should_auto_install(&self, extension_id: &str) -> bool {
|
||||||
|
self.auto_install_extensions
|
||||||
|
.get(extension_id)
|
||||||
|
.copied()
|
||||||
|
.unwrap_or(true)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn should_auto_update(&self, extension_id: &str) -> bool {
|
pub fn should_auto_update(&self, extension_id: &str) -> bool {
|
||||||
self.auto_update_extensions
|
self.auto_update_extensions
|
||||||
.get(extension_id)
|
.get(extension_id)
|
||||||
|
@ -27,6 +42,10 @@ impl Settings for ExtensionSettings {
|
||||||
type FileContent = Self;
|
type FileContent = Self;
|
||||||
|
|
||||||
fn load(sources: SettingsSources<Self::FileContent>, _cx: &mut AppContext) -> Result<Self> {
|
fn load(sources: SettingsSources<Self::FileContent>, _cx: &mut AppContext) -> Result<Self> {
|
||||||
Ok(sources.user.cloned().unwrap_or_default())
|
let mut merged = serde_json::Value::Null;
|
||||||
|
for value in [sources.default].into_iter().chain(sources.user) {
|
||||||
|
merge_non_null_json_value_into(serde_json::to_value(value).unwrap(), &mut merged);
|
||||||
|
}
|
||||||
|
Ok(serde_json::from_value(merged)?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -291,6 +291,8 @@ impl ExtensionStore {
|
||||||
if let Some(future) = reload_future {
|
if let Some(future) = reload_future {
|
||||||
future.await;
|
future.await;
|
||||||
}
|
}
|
||||||
|
this.update(&mut cx, |this, cx| this.auto_install_extensions(cx))
|
||||||
|
.ok();
|
||||||
this.update(&mut cx, |this, cx| this.check_for_updates(cx))
|
this.update(&mut cx, |this, cx| this.check_for_updates(cx))
|
||||||
.ok();
|
.ok();
|
||||||
})
|
})
|
||||||
|
@ -480,6 +482,38 @@ impl ExtensionStore {
|
||||||
self.fetch_extensions_from_api(&format!("/extensions/{extension_id}"), &[], cx)
|
self.fetch_extensions_from_api(&format!("/extensions/{extension_id}"), &[], cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Installs any extensions that should be included with Zed by default.
|
||||||
|
///
|
||||||
|
/// This can be used to make certain functionality provided by extensions
|
||||||
|
/// available out-of-the-box.
|
||||||
|
pub fn auto_install_extensions(&mut self, cx: &mut ModelContext<Self>) {
|
||||||
|
let extension_settings = ExtensionSettings::get_global(cx);
|
||||||
|
|
||||||
|
let extensions_to_install = extension_settings
|
||||||
|
.auto_install_extensions
|
||||||
|
.keys()
|
||||||
|
.filter(|extension_id| extension_settings.should_auto_install(extension_id))
|
||||||
|
.filter(|extension_id| {
|
||||||
|
let is_already_installed = self
|
||||||
|
.extension_index
|
||||||
|
.extensions
|
||||||
|
.contains_key(extension_id.as_ref());
|
||||||
|
!is_already_installed
|
||||||
|
})
|
||||||
|
.cloned()
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
cx.spawn(move |this, mut cx| async move {
|
||||||
|
for extension_id in extensions_to_install {
|
||||||
|
this.update(&mut cx, |this, cx| {
|
||||||
|
this.install_latest_extension(extension_id.clone(), cx);
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.detach();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn check_for_updates(&mut self, cx: &mut ModelContext<Self>) {
|
pub fn check_for_updates(&mut self, cx: &mut ModelContext<Self>) {
|
||||||
let task = self.fetch_extensions_with_update_available(cx);
|
let task = self.fetch_extensions_with_update_available(cx);
|
||||||
cx.spawn(move |this, mut cx| async move {
|
cx.spawn(move |this, mut cx| async move {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue