Merge branch 'main' into theme-improvements

This commit is contained in:
Nate Butler 2022-07-19 20:12:02 -04:00
commit bcc554a3db
76 changed files with 4053 additions and 1557 deletions

View file

@ -2,7 +2,7 @@ use crate::OpenBrowser;
use gpui::{
elements::{MouseEventHandler, Text},
platform::CursorStyle,
Element, Entity, RenderContext, View,
Element, Entity, MouseButton, RenderContext, View,
};
use settings::Settings;
use workspace::StatusItemView;
@ -32,7 +32,7 @@ impl View for FeedbackLink {
.boxed()
})
.with_cursor_style(CursorStyle::PointingHand)
.on_click(|_, _, cx| {
.on_click(MouseButton::Left, |_, cx| {
cx.dispatch_action(OpenBrowser {
url: NEW_ISSUE_URL.into(),
})

View file

@ -1,12 +1,13 @@
use gpui::executor::Background;
pub use language::*;
use lazy_static::lazy_static;
use rust_embed::RustEmbed;
use std::{borrow::Cow, str, sync::Arc};
use util::ResultExt;
mod c;
mod go;
mod installation;
mod json;
mod language_plugin;
mod python;
mod rust;
@ -17,7 +18,22 @@ mod typescript;
#[exclude = "*.rs"]
struct LanguageDir;
pub async fn init(languages: Arc<LanguageRegistry>, executor: Arc<Background>) {
// TODO - Remove this once the `init` function is synchronous again.
lazy_static! {
pub static ref LANGUAGE_NAMES: Vec<String> = LanguageDir::iter()
.filter_map(|path| {
if path.ends_with("config.toml") {
let config = LanguageDir::get(&path)?;
let config = toml::from_slice::<LanguageConfig>(&config.data).ok()?;
Some(config.name.to_string())
} else {
None
}
})
.collect();
}
pub async fn init(languages: Arc<LanguageRegistry>, _executor: Arc<Background>) {
for (name, grammar, lsp_adapter) in [
(
"c",
@ -37,10 +53,7 @@ pub async fn init(languages: Arc<LanguageRegistry>, executor: Arc<Background>) {
(
"json",
tree_sitter_json::language(),
match language_plugin::new_json(executor).await.log_err() {
Some(lang) => Some(CachedLspAdapter::new(lang).await),
None => None,
},
Some(CachedLspAdapter::new(json::JsonLspAdapter).await),
),
(
"markdown",

View file

@ -0,0 +1,106 @@
use super::installation::{npm_install_packages, npm_package_latest_version};
use anyhow::{anyhow, Context, Result};
use async_trait::async_trait;
use client::http::HttpClient;
use collections::HashMap;
use futures::StreamExt;
use language::{LanguageServerName, LspAdapter};
use serde_json::json;
use smol::fs;
use std::{any::Any, path::PathBuf, sync::Arc};
use util::ResultExt;
pub struct JsonLspAdapter;
impl JsonLspAdapter {
const BIN_PATH: &'static str =
"node_modules/vscode-json-languageserver/bin/vscode-json-languageserver";
}
#[async_trait]
impl LspAdapter for JsonLspAdapter {
async fn name(&self) -> LanguageServerName {
LanguageServerName("vscode-json-languageserver".into())
}
async fn server_args(&self) -> Vec<String> {
vec!["--stdio".into()]
}
async fn fetch_latest_server_version(
&self,
_: Arc<dyn HttpClient>,
) -> Result<Box<dyn 'static + Any + Send>> {
Ok(Box::new(npm_package_latest_version("vscode-json-languageserver").await?) as Box<_>)
}
async fn fetch_server_binary(
&self,
version: Box<dyn 'static + Send + Any>,
_: Arc<dyn HttpClient>,
container_dir: PathBuf,
) -> Result<PathBuf> {
let version = version.downcast::<String>().unwrap();
let version_dir = container_dir.join(version.as_str());
fs::create_dir_all(&version_dir)
.await
.context("failed to create version directory")?;
let binary_path = version_dir.join(Self::BIN_PATH);
if fs::metadata(&binary_path).await.is_err() {
npm_install_packages(
[("vscode-json-languageserver", version.as_str())],
&version_dir,
)
.await?;
if let Some(mut entries) = fs::read_dir(&container_dir).await.log_err() {
while let Some(entry) = entries.next().await {
if let Some(entry) = entry.log_err() {
let entry_path = entry.path();
if entry_path.as_path() != version_dir {
fs::remove_dir_all(&entry_path).await.log_err();
}
}
}
}
}
Ok(binary_path)
}
async fn cached_server_binary(&self, container_dir: PathBuf) -> Option<PathBuf> {
(|| async move {
let mut last_version_dir = None;
let mut entries = fs::read_dir(&container_dir).await?;
while let Some(entry) = entries.next().await {
let entry = entry?;
if entry.file_type().await?.is_dir() {
last_version_dir = Some(entry.path());
}
}
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)
} else {
Err(anyhow!(
"missing executable in directory {:?}",
last_version_dir
))
}
})()
.await
.log_err()
}
async fn initialization_options(&self) -> Option<serde_json::Value> {
Some(json!({
"provideFormatter": true
}))
}
async fn language_ids(&self) -> HashMap<String, String> {
[("JSON".into(), "jsonc".into())].into_iter().collect()
}
}

View file

@ -5,16 +5,13 @@ use collections::HashMap;
use futures::lock::Mutex;
use gpui::executor::Background;
use language::{LanguageServerName, LspAdapter};
use plugin_runtime::{Plugin, PluginBinary, PluginBuilder, PluginYield, WasiFn};
use plugin_runtime::{Plugin, PluginBinary, PluginBuilder, WasiFn};
use std::{any::Any, path::PathBuf, sync::Arc};
use util::ResultExt;
#[allow(dead_code)]
pub async fn new_json(executor: Arc<Background>) -> Result<PluginLspAdapter> {
let executor_ref = executor.clone();
let plugin =
PluginBuilder::new_epoch_with_default_ctx(PluginYield::default_epoch(), move |future| {
executor_ref.spawn(future).detach()
})?
let plugin = PluginBuilder::new_default()?
.host_function_async("command", |command: String| async move {
let mut args = command.split(' ');
let command = args.next().unwrap();
@ -26,7 +23,7 @@ pub async fn new_json(executor: Arc<Background>) -> Result<PluginLspAdapter> {
.map(|output| output.stdout)
})?
.init(PluginBinary::Precompiled(include_bytes!(
"../../../../plugins/bin/json_language.wasm.pre"
"../../../../plugins/bin/json_language.wasm.pre",
)))
.await?;
@ -46,6 +43,7 @@ pub struct PluginLspAdapter {
}
impl PluginLspAdapter {
#[allow(unused)]
pub async fn new(mut plugin: Plugin, executor: Arc<Background>) -> Result<Self> {
Ok(Self {
name: plugin.function("name")?,

View file

@ -39,15 +39,20 @@ where
Self(rx)
}
///Loads the given watched JSON file. In the special case that the file is
///empty (ignoring whitespace) or is not a file, this will return T::default()
async fn load(fs: Arc<dyn Fs>, path: &Path) -> Option<T> {
if fs.is_file(&path).await {
fs.load(&path)
.await
.log_err()
.and_then(|data| parse_json_with_comments(&data).log_err())
} else {
Some(T::default())
if !fs.is_file(&path).await {
return Some(T::default());
}
fs.load(&path).await.log_err().and_then(|data| {
if data.trim().is_empty() {
Some(T::default())
} else {
parse_json_with_comments(&data).log_err()
}
})
}
}

View file

@ -79,18 +79,25 @@ pub fn init(app_state: &Arc<AppState>, cx: &mut gpui::MutableAppContext) {
cx.add_global_action(move |_: &IncreaseBufferFontSize, cx| {
cx.update_global::<Settings, _, _>(|settings, cx| {
settings.buffer_font_size = (settings.buffer_font_size + 1.0).max(MIN_FONT_SIZE);
if let Some(terminal_font_size) = settings.terminal_overrides.font_size.as_mut() {
*terminal_font_size = (*terminal_font_size + 1.0).max(MIN_FONT_SIZE);
}
cx.refresh_windows();
});
});
cx.add_global_action(move |_: &DecreaseBufferFontSize, cx| {
cx.update_global::<Settings, _, _>(|settings, cx| {
settings.buffer_font_size = (settings.buffer_font_size - 1.0).max(MIN_FONT_SIZE);
if let Some(terminal_font_size) = settings.terminal_overrides.font_size.as_mut() {
*terminal_font_size = (*terminal_font_size - 1.0).max(MIN_FONT_SIZE);
}
cx.refresh_windows();
});
});
cx.add_global_action(move |_: &ResetBufferFontSize, cx| {
cx.update_global::<Settings, _, _>(|settings, cx| {
settings.buffer_font_size = settings.default_buffer_font_size;
settings.terminal_overrides.font_size = settings.terminal_defaults.font_size;
cx.refresh_windows();
});
});
@ -102,14 +109,14 @@ pub fn init(app_state: &Arc<AppState>, cx: &mut gpui::MutableAppContext) {
let app_state = app_state.clone();
move |_: &mut Workspace, _: &OpenSettings, cx: &mut ViewContext<Workspace>| {
open_config_file(&SETTINGS_PATH, app_state.clone(), cx, || {
let header = Assets.load("settings/header-comments.json").unwrap();
let json = Assets.load("settings/default.json").unwrap();
let header = str::from_utf8(header.as_ref()).unwrap();
let json = str::from_utf8(json.as_ref()).unwrap();
let mut content = Rope::new();
content.push(header);
content.push(json);
content
str::from_utf8(
Assets
.load("settings/initial_user_settings.json")
.unwrap()
.as_ref(),
)
.unwrap()
.into()
});
}
});
@ -209,7 +216,7 @@ pub fn initialize_workspace(
cx.emit(workspace::Event::PaneAdded(workspace.active_pane().clone()));
let theme_names = app_state.themes.list().collect();
let language_names = app_state.languages.language_names();
let language_names = &languages::LANGUAGE_NAMES;
workspace.project().update(cx, |project, cx| {
let action_names = cx.all_action_names().collect::<Vec<_>>();