Merge branch 'main' into feedback-submit-button

This commit is contained in:
Joseph Lyons
2023-02-07 12:55:53 -05:00
19 changed files with 619 additions and 154 deletions
Generated
+109
View File
@@ -259,6 +259,21 @@ dependencies = [
"futures-lite",
]
[[package]]
name = "async-global-executor"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1b6f5d7df27bd294849f8eec66ecfc63d11814df7a4f5d74168a2394467b776"
dependencies = [
"async-channel",
"async-executor",
"async-io",
"async-lock",
"blocking",
"futures-lite",
"once_cell",
]
[[package]]
name = "async-io"
version = "1.12.0"
@@ -350,6 +365,32 @@ dependencies = [
"syn",
]
[[package]]
name = "async-std"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d"
dependencies = [
"async-channel",
"async-global-executor",
"async-io",
"async-lock",
"crossbeam-utils 0.8.14",
"futures-channel",
"futures-core",
"futures-io",
"futures-lite",
"gloo-timers",
"kv-log-macro",
"log",
"memchr",
"once_cell",
"pin-project-lite 0.2.9",
"pin-utils",
"slab",
"wasm-bindgen-futures",
]
[[package]]
name = "async-stream"
version = "0.3.3"
@@ -371,6 +412,20 @@ dependencies = [
"syn",
]
[[package]]
name = "async-tar"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c49359998a76e32ef6e870dbc079ebad8f1e53e8441c5dd39d27b44493fe331"
dependencies = [
"async-std",
"filetime",
"libc",
"pin-project",
"redox_syscall",
"xattr",
]
[[package]]
name = "async-task"
version = "4.0.3"
@@ -2080,6 +2135,18 @@ dependencies = [
"workspace",
]
[[package]]
name = "filetime"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e884668cd0c7480504233e951174ddc3b382f7c2666e3b7310b5c4e7b0c37f9"
dependencies = [
"cfg-if 1.0.0",
"libc",
"redox_syscall",
"windows-sys 0.42.0",
]
[[package]]
name = "fixedbitset"
version = "0.4.2"
@@ -2528,6 +2595,18 @@ dependencies = [
"regex",
]
[[package]]
name = "gloo-timers"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c"
dependencies = [
"futures-channel",
"futures-core",
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "go_to_line"
version = "0.1.0"
@@ -3144,6 +3223,15 @@ dependencies = [
"arrayvec 0.7.2",
]
[[package]]
name = "kv-log-macro"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f"
dependencies = [
"log",
]
[[package]]
name = "language"
version = "0.1.0"
@@ -7017,6 +7105,16 @@ dependencies = [
"tree-sitter",
]
[[package]]
name = "tree-sitter-lua"
version = "0.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d489873fd1a2fa6d5f04930bfc5c081c96f0c038c1437104518b5b842c69b282"
dependencies = [
"cc",
"tree-sitter",
]
[[package]]
name = "tree-sitter-markdown"
version = "0.0.1"
@@ -8194,6 +8292,15 @@ dependencies = [
"winapi-build",
]
[[package]]
name = "xattr"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d1526bbe5aaeb5eb06885f4d987bcdfa5e23187055de9b83fe00156a821fabc"
dependencies = [
"libc",
]
[[package]]
name = "xml-rs"
version = "0.8.4"
@@ -8236,6 +8343,7 @@ dependencies = [
"assets",
"async-compression",
"async-recursion 0.3.2",
"async-tar",
"async-trait",
"auto_update",
"backtrace",
@@ -8313,6 +8421,7 @@ dependencies = [
"tree-sitter-go",
"tree-sitter-html",
"tree-sitter-json 0.20.0",
"tree-sitter-lua",
"tree-sitter-markdown",
"tree-sitter-python",
"tree-sitter-racket",
+3 -38
View File
@@ -1,4 +1,3 @@
mod indicator;
pub mod participant;
pub mod room;
@@ -10,22 +9,17 @@ use collections::HashSet;
use postage::watch;
use gpui::{
actions, AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle, MutableAppContext,
Subscription, Task, ViewHandle, WeakModelHandle,
AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle, MutableAppContext,
Subscription, Task, WeakModelHandle,
};
use project::Project;
use settings::Settings;
use indicator::SharingStatusIndicator;
pub use participant::ParticipantLocation;
pub use room::Room;
actions!(collab, [ToggleScreenSharing]);
pub fn init(client: Arc<Client>, user_store: ModelHandle<UserStore>, cx: &mut MutableAppContext) {
let active_call = cx.add_model(|cx| ActiveCall::new(client, user_store, cx));
cx.set_global(active_call);
cx.add_global_action(toggle_screen_sharing);
}
#[derive(Clone)]
@@ -36,6 +30,7 @@ pub struct IncomingCall {
pub initial_project: Option<proto::ParticipantProject>,
}
/// Singleton global maintaining the user's participation in a room across workspaces.
pub struct ActiveCall {
room: Option<(ModelHandle<Room>, Vec<Subscription>)>,
location: Option<WeakModelHandle<Project>>,
@@ -46,7 +41,6 @@ pub struct ActiveCall {
),
client: Arc<Client>,
user_store: ModelHandle<UserStore>,
sharing_status_indicator: Option<(usize, ViewHandle<SharingStatusIndicator>)>,
_subscriptions: Vec<client::Subscription>,
}
@@ -71,7 +65,6 @@ impl ActiveCall {
],
client,
user_store,
sharing_status_indicator: None,
}
}
@@ -290,8 +283,6 @@ impl ActiveCall {
this.set_room(None, cx).detach_and_log_err(cx);
}
this.set_sharing_status(room.read(cx).is_screen_sharing(), cx);
cx.notify();
}),
cx.subscribe(&room, |_, _, event, cx| cx.emit(event.clone())),
@@ -316,30 +307,4 @@ impl ActiveCall {
pub fn pending_invites(&self) -> &HashSet<u64> {
&self.pending_invites
}
pub fn set_sharing_status(&mut self, is_screen_sharing: bool, cx: &mut MutableAppContext) {
if is_screen_sharing {
if self.sharing_status_indicator.is_none()
&& cx.global::<Settings>().show_call_status_icon
{
self.sharing_status_indicator =
Some(cx.add_status_bar_item(|_| SharingStatusIndicator));
}
} else if let Some((window_id, _)) = self.sharing_status_indicator.take() {
cx.remove_status_bar_item(window_id);
}
}
}
pub fn toggle_screen_sharing(_: &ToggleScreenSharing, cx: &mut MutableAppContext) {
if let Some(room) = ActiveCall::global(cx).read(cx).room().cloned() {
let toggle_screen_sharing = room.update(cx, |room, cx| {
if room.is_screen_sharing() {
Task::ready(room.unshare_screen(cx))
} else {
room.share_screen(cx)
}
});
toggle_screen_sharing.detach_and_log_err(cx);
}
}
+2 -2
View File
@@ -1,5 +1,5 @@
use crate::{contact_notification::ContactNotification, contacts_popover};
use call::{ActiveCall, ParticipantLocation, ToggleScreenSharing};
use crate::{contact_notification::ContactNotification, contacts_popover, ToggleScreenSharing};
use call::{ActiveCall, ParticipantLocation};
use client::{proto::PeerId, Authenticate, ContactEventKind, User, UserStore};
use clock::ReplicaId;
use contacts_popover::ContactsPopover;
+104 -83
View File
@@ -6,14 +6,17 @@ mod contacts_popover;
mod incoming_call_notification;
mod notifications;
mod project_shared_notification;
mod sharing_status_indicator;
use anyhow::anyhow;
use call::ActiveCall;
pub use collab_titlebar_item::{CollabTitlebarItem, ToggleCollaborationMenu};
use gpui::MutableAppContext;
use gpui::{actions, MutableAppContext, Task};
use std::sync::Arc;
use workspace::{AppState, JoinProject, ToggleFollow, Workspace};
actions!(collab, [ToggleScreenSharing]);
pub fn init(app_state: Arc<AppState>, cx: &mut MutableAppContext) {
collab_titlebar_item::init(cx);
contact_notification::init(cx);
@@ -22,89 +25,107 @@ pub fn init(app_state: Arc<AppState>, cx: &mut MutableAppContext) {
contacts_popover::init(cx);
incoming_call_notification::init(cx);
project_shared_notification::init(cx);
sharing_status_indicator::init(cx);
cx.add_global_action(toggle_screen_sharing);
cx.add_global_action(move |action: &JoinProject, cx| {
let project_id = action.project_id;
let follow_user_id = action.follow_user_id;
let app_state = app_state.clone();
cx.spawn(|mut cx| async move {
let existing_workspace = cx.update(|cx| {
cx.window_ids()
.filter_map(|window_id| cx.root_view::<Workspace>(window_id))
.find(|workspace| {
workspace.read(cx).project().read(cx).remote_id() == Some(project_id)
})
});
let workspace = if let Some(existing_workspace) = existing_workspace {
existing_workspace
} else {
let active_call = cx.read(ActiveCall::global);
let room = active_call
.read_with(&cx, |call, _| call.room().cloned())
.ok_or_else(|| anyhow!("not in a call"))?;
let project = room
.update(&mut cx, |room, cx| {
room.join_project(
project_id,
app_state.languages.clone(),
app_state.fs.clone(),
cx,
)
})
.await?;
let (_, workspace) = cx.add_window(
(app_state.build_window_options)(None, None, cx.platform().as_ref()),
|cx| {
let mut workspace = Workspace::new(
Default::default(),
0,
project,
app_state.dock_default_item_factory,
cx,
);
(app_state.initialize_workspace)(&mut workspace, &app_state, cx);
workspace
},
);
workspace
};
cx.activate_window(workspace.window_id());
cx.platform().activate(true);
workspace.update(&mut cx, |workspace, cx| {
if let Some(room) = ActiveCall::global(cx).read(cx).room().cloned() {
let follow_peer_id = room
.read(cx)
.remote_participants()
.iter()
.find(|(_, participant)| participant.user.id == follow_user_id)
.map(|(_, p)| p.peer_id)
.or_else(|| {
// If we couldn't follow the given user, follow the host instead.
let collaborator = workspace
.project()
.read(cx)
.collaborators()
.values()
.find(|collaborator| collaborator.replica_id == 0)?;
Some(collaborator.peer_id)
});
if let Some(follow_peer_id) = follow_peer_id {
if !workspace.is_following(follow_peer_id) {
workspace
.toggle_follow(&ToggleFollow(follow_peer_id), cx)
.map(|follow| follow.detach_and_log_err(cx));
}
}
}
});
anyhow::Ok(())
})
.detach_and_log_err(cx);
join_project(action, app_state.clone(), cx);
});
}
pub fn toggle_screen_sharing(_: &ToggleScreenSharing, cx: &mut MutableAppContext) {
if let Some(room) = ActiveCall::global(cx).read(cx).room().cloned() {
let toggle_screen_sharing = room.update(cx, |room, cx| {
if room.is_screen_sharing() {
Task::ready(room.unshare_screen(cx))
} else {
room.share_screen(cx)
}
});
toggle_screen_sharing.detach_and_log_err(cx);
}
}
fn join_project(action: &JoinProject, app_state: Arc<AppState>, cx: &mut MutableAppContext) {
let project_id = action.project_id;
let follow_user_id = action.follow_user_id;
cx.spawn(|mut cx| async move {
let existing_workspace = cx.update(|cx| {
cx.window_ids()
.filter_map(|window_id| cx.root_view::<Workspace>(window_id))
.find(|workspace| {
workspace.read(cx).project().read(cx).remote_id() == Some(project_id)
})
});
let workspace = if let Some(existing_workspace) = existing_workspace {
existing_workspace
} else {
let active_call = cx.read(ActiveCall::global);
let room = active_call
.read_with(&cx, |call, _| call.room().cloned())
.ok_or_else(|| anyhow!("not in a call"))?;
let project = room
.update(&mut cx, |room, cx| {
room.join_project(
project_id,
app_state.languages.clone(),
app_state.fs.clone(),
cx,
)
})
.await?;
let (_, workspace) = cx.add_window(
(app_state.build_window_options)(None, None, cx.platform().as_ref()),
|cx| {
let mut workspace = Workspace::new(
Default::default(),
0,
project,
app_state.dock_default_item_factory,
cx,
);
(app_state.initialize_workspace)(&mut workspace, &app_state, cx);
workspace
},
);
workspace
};
cx.activate_window(workspace.window_id());
cx.platform().activate(true);
workspace.update(&mut cx, |workspace, cx| {
if let Some(room) = ActiveCall::global(cx).read(cx).room().cloned() {
let follow_peer_id = room
.read(cx)
.remote_participants()
.iter()
.find(|(_, participant)| participant.user.id == follow_user_id)
.map(|(_, p)| p.peer_id)
.or_else(|| {
// If we couldn't follow the given user, follow the host instead.
let collaborator = workspace
.project()
.read(cx)
.collaborators()
.values()
.find(|collaborator| collaborator.replica_id == 0)?;
Some(collaborator.peer_id)
});
if let Some(follow_peer_id) = follow_peer_id {
if !workspace.is_following(follow_peer_id) {
workspace
.toggle_follow(&ToggleFollow(follow_peer_id), cx)
.map(|follow| follow.detach_and_log_err(cx));
}
}
}
});
anyhow::Ok(())
})
.detach_and_log_err(cx);
}
@@ -1,11 +1,31 @@
use call::ActiveCall;
use gpui::{
color::Color,
elements::{MouseEventHandler, Svg},
Appearance, Element, ElementBox, Entity, MouseButton, RenderContext, View,
Appearance, Element, ElementBox, Entity, MouseButton, MutableAppContext, RenderContext, View,
};
use settings::Settings;
use crate::ToggleScreenSharing;
pub fn init(cx: &mut MutableAppContext) {
let active_call = ActiveCall::global(cx);
let mut status_indicator = None;
cx.observe(&active_call, move |call, cx| {
if let Some(room) = call.read(cx).room() {
if room.read(cx).is_screen_sharing() {
if status_indicator.is_none() && cx.global::<Settings>().show_call_status_icon {
status_indicator = Some(cx.add_status_bar_item(|_| SharingStatusIndicator));
}
} else if let Some((window_id, _)) = status_indicator.take() {
cx.remove_status_bar_item(window_id);
}
}
})
.detach();
}
pub struct SharingStatusIndicator;
impl Entity for SharingStatusIndicator {
+2 -2
View File
@@ -52,8 +52,8 @@ pub fn deploy_context_menu(
AnchorCorner::TopLeft,
vec![
ContextMenuItem::item("Rename Symbol", Rename),
ContextMenuItem::item("Go To Definition", GoToDefinition),
ContextMenuItem::item("Go To Type Definition", GoToTypeDefinition),
ContextMenuItem::item("Go to Definition", GoToDefinition),
ContextMenuItem::item("Go to Type Definition", GoToTypeDefinition),
ContextMenuItem::item("Find All References", FindAllReferences),
ContextMenuItem::item(
"Code Actions",
+13 -14
View File
@@ -910,15 +910,14 @@ impl MutableAppContext {
.map_or(false, |window| window.is_fullscreen)
}
pub fn window_bounds(&self, window_id: usize) -> WindowBounds {
self.presenters_and_platform_windows[&window_id].1.bounds()
pub fn window_bounds(&self, window_id: usize) -> Option<WindowBounds> {
let (_, window) = self.presenters_and_platform_windows.get(&window_id)?;
Some(window.bounds())
}
pub fn window_display_uuid(&self, window_id: usize) -> Option<Uuid> {
self.presenters_and_platform_windows[&window_id]
.1
.screen()
.display_uuid()
let (_, window) = self.presenters_and_platform_windows.get(&window_id)?;
window.screen().display_uuid()
}
pub fn render_view(&mut self, params: RenderParams) -> Result<ElementBox> {
@@ -2375,8 +2374,10 @@ impl MutableAppContext {
callback(is_fullscreen, this)
});
if let Some(uuid) = this.window_display_uuid(window_id) {
let bounds = this.window_bounds(window_id);
if let Some((uuid, bounds)) = this
.window_display_uuid(window_id)
.zip(this.window_bounds(window_id))
{
let mut bounds_observations = this.window_bounds_observations.clone();
bounds_observations.emit(window_id, this, |callback, this| {
callback(bounds, uuid, this)
@@ -2560,8 +2561,10 @@ impl MutableAppContext {
}
fn handle_window_moved(&mut self, window_id: usize) {
if let Some(display) = self.window_display_uuid(window_id) {
let bounds = self.window_bounds(window_id);
if let Some((display, bounds)) = self
.window_display_uuid(window_id)
.zip(self.window_bounds(window_id))
{
self.window_bounds_observations
.clone()
.emit(window_id, self, move |callback, this| {
@@ -3733,10 +3736,6 @@ impl<'a, T: View> ViewContext<'a, T> {
self.app.toggle_window_full_screen(self.window_id)
}
pub fn window_bounds(&self) -> WindowBounds {
self.app.window_bounds(self.window_id)
}
pub fn prompt(
&self,
level: PromptLevel,
+4 -3
View File
@@ -1,3 +1,4 @@
use log::warn;
pub use lsp_types::request::*;
pub use lsp_types::*;
@@ -220,10 +221,10 @@ impl LanguageServer {
}
}
} else {
return Err(anyhow!(
"failed to deserialize message:\n{}",
warn!(
"Failed to deserialize message:\n{}",
std::str::from_utf8(&buffer)?
));
);
}
// Don't starve the main thread when receiving lots of messages at once.
+19 -8
View File
@@ -11,7 +11,10 @@ use highlighted_workspace_location::HighlightedWorkspaceLocation;
use ordered_float::OrderedFloat;
use picker::{Picker, PickerDelegate};
use settings::Settings;
use workspace::{OpenPaths, Workspace, WorkspaceLocation, WORKSPACE_DB};
use workspace::{
notifications::simple_message_notification::MessageNotification, OpenPaths, Workspace,
WorkspaceLocation, WORKSPACE_DB,
};
actions!(projects, [OpenRecent]);
@@ -42,7 +45,7 @@ impl RecentProjectsView {
fn toggle(_: &mut Workspace, _: &OpenRecent, cx: &mut ViewContext<Workspace>) {
cx.spawn(|workspace, mut cx| async move {
let workspace_locations = cx
let workspace_locations: Vec<_> = cx
.background()
.spawn(async {
WORKSPACE_DB
@@ -56,12 +59,20 @@ impl RecentProjectsView {
.await;
workspace.update(&mut cx, |workspace, cx| {
workspace.toggle_modal(cx, |_, cx| {
let view = cx.add_view(|cx| Self::new(workspace_locations, cx));
cx.subscribe(&view, Self::on_event).detach();
view
});
})
if !workspace_locations.is_empty() {
workspace.toggle_modal(cx, |_, cx| {
let view = cx.add_view(|cx| Self::new(workspace_locations, cx));
cx.subscribe(&view, Self::on_event).detach();
view
});
} else {
workspace.show_notification(0, cx, |cx| {
cx.add_view(|_| {
MessageNotification::new_message("No recent projects to open.")
})
})
}
});
})
.detach();
}
+2 -2
View File
@@ -174,7 +174,7 @@ pub mod simple_message_notification {
}
impl MessageNotification {
pub fn new_messsage<S: AsRef<str>>(message: S) -> MessageNotification {
pub fn new_message<S: AsRef<str>>(message: S) -> MessageNotification {
Self {
message: message.as_ref().to_string(),
click_action: None,
@@ -320,7 +320,7 @@ where
Err(err) => {
workspace.show_notification(0, cx, |cx| {
cx.add_view(|_cx| {
simple_message_notification::MessageNotification::new_messsage(format!(
simple_message_notification::MessageNotification::new_message(format!(
"Error: {:?}",
err,
))
+2
View File
@@ -60,6 +60,7 @@ vim = { path = "../vim" }
workspace = { path = "../workspace" }
anyhow = "1.0.38"
async-compression = { version = "0.3", features = ["gzip", "futures-bufread"] }
async-tar = "0.4.2"
async-recursion = "0.3"
async-trait = "0.1"
backtrace = "0.3"
@@ -109,6 +110,7 @@ tree-sitter-ruby = "0.20.0"
tree-sitter-html = "0.19.0"
tree-sitter-scheme = { git = "https://github.com/6cdh/tree-sitter-scheme", rev = "af0fd1fa452cb2562dc7b5c8a8c55551c39273b9"}
tree-sitter-racket = { git = "https://github.com/zed-industries/tree-sitter-racket", rev = "eb010cf2c674c6fd9a6316a84e28ef90190fe51a"}
tree-sitter-lua = "0.0.14"
url = "2.2"
urlencoding = "2.1.2"
uuid = { version = "1.1.2", features = ["v4"] }
+6
View File
@@ -10,6 +10,7 @@ mod html;
mod installation;
mod json;
mod language_plugin;
mod lua;
mod python;
mod ruby;
mod rust;
@@ -122,6 +123,11 @@ pub fn init(languages: Arc<LanguageRegistry>) {
tree_sitter_racket::language(),
None, //
),
(
"lua",
tree_sitter_lua::language(),
Some(Box::new(lua::LuaLspAdapter)),
),
] {
languages.register(name, load_config(name), grammar, lsp_adapter, load_queries);
}
+108
View File
@@ -0,0 +1,108 @@
use std::{any::Any, env::consts, path::PathBuf, sync::Arc};
use anyhow::{anyhow, bail, Result};
use async_compression::futures::bufread::GzipDecoder;
use async_tar::Archive;
use async_trait::async_trait;
use client::http::HttpClient;
use futures::{io::BufReader, StreamExt};
use language::LanguageServerName;
use smol::fs;
use util::{async_iife, ResultExt};
use super::installation::{latest_github_release, GitHubLspBinaryVersion};
#[derive(Copy, Clone)]
pub struct LuaLspAdapter;
#[async_trait]
impl super::LspAdapter for LuaLspAdapter {
async fn name(&self) -> LanguageServerName {
LanguageServerName("lua-language-server".into())
}
async fn server_args(&self) -> Vec<String> {
vec![
"--logpath=~/lua-language-server.log".into(),
"--loglevel=trace".into(),
]
}
async fn fetch_latest_server_version(
&self,
http: Arc<dyn HttpClient>,
) -> Result<Box<dyn 'static + Send + Any>> {
let release = latest_github_release("LuaLS/lua-language-server", http).await?;
let version = release.name.clone();
let platform = match consts::ARCH {
"x86_64" => "x64",
"aarch64" => "arm64",
other => bail!("Running on unsupported platform: {other}"),
};
let asset_name = format!("lua-language-server-{version}-darwin-{platform}.tar.gz");
let asset = release
.assets
.iter()
.find(|asset| asset.name == asset_name)
.ok_or_else(|| anyhow!("no asset found matching {:?}", asset_name))?;
let version = GitHubLspBinaryVersion {
name: release.name.clone(),
url: asset.browser_download_url.clone(),
};
Ok(Box::new(version) as Box<_>)
}
async fn fetch_server_binary(
&self,
version: Box<dyn 'static + Send + Any>,
http: Arc<dyn HttpClient>,
container_dir: PathBuf,
) -> Result<PathBuf> {
let version = version.downcast::<GitHubLspBinaryVersion>().unwrap();
let binary_path = container_dir.join("bin/lua-language-server");
if fs::metadata(&binary_path).await.is_err() {
let mut response = http
.get(&version.url, Default::default(), true)
.await
.map_err(|err| anyhow!("error downloading release: {}", err))?;
let decompressed_bytes = GzipDecoder::new(BufReader::new(response.body_mut()));
let archive = Archive::new(decompressed_bytes);
archive.unpack(container_dir).await?;
}
fs::set_permissions(
&binary_path,
<fs::Permissions as fs::unix::PermissionsExt>::from_mode(0o755),
)
.await?;
Ok(binary_path)
}
async fn cached_server_binary(&self, container_dir: PathBuf) -> Option<PathBuf> {
async_iife!({
let mut last_binary_path = 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_file()
&& entry
.file_name()
.to_str()
.map_or(false, |name| name == "lua-language-server")
{
last_binary_path = Some(entry.path());
}
}
if let Some(path) = last_binary_path {
Ok(path)
} else {
Err(anyhow!("no cached binary"))
}
})
.await
.log_err()
}
}
@@ -0,0 +1,3 @@
("[" @open "]" @close)
("{" @open "}" @close)
("(" @open ")" @close)
+15
View File
@@ -0,0 +1,15 @@
name = "Lua"
path_suffixes = ["lua"]
line_comment = "-- "
autoclose_before = ",]}"
brackets = [
{ start = "{", end = "}", close = true, newline = true },
{ 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 },
]
+192
View File
@@ -0,0 +1,192 @@
;; Keywords
"return" @keyword
[
"goto"
"in"
"local"
] @keyword
(break_statement) @keyword
(do_statement
[
"do"
"end"
] @keyword)
(while_statement
[
"while"
"do"
"end"
] @keyword)
(repeat_statement
[
"repeat"
"until"
] @keyword)
(if_statement
[
"if"
"elseif"
"else"
"then"
"end"
] @keyword)
(elseif_statement
[
"elseif"
"then"
"end"
] @keyword)
(else_statement
[
"else"
"end"
] @keyword)
(for_statement
[
"for"
"do"
"end"
] @keyword)
(function_declaration
[
"function"
"end"
] @keyword)
(function_definition
[
"function"
"end"
] @keyword)
;; Operators
[
"and"
"not"
"or"
] @operator
[
"+"
"-"
"*"
"/"
"%"
"^"
"#"
"=="
"~="
"<="
">="
"<"
">"
"="
"&"
"~"
"|"
"<<"
">>"
"//"
".."
] @operator
;; Punctuations
[
";"
":"
","
"."
] @punctuation.delimiter
;; Brackets
[
"("
")"
"["
"]"
"{"
"}"
] @punctuation.bracket
;; Variables
(identifier) @variable
((identifier) @variable.special
(#eq? @variable.special "self"))
(variable_list
attribute: (attribute
(["<" ">"] @punctuation.bracket
(identifier) @attribute)))
;; Constants
((identifier) @constant
(#lua-match? @constant "^[A-Z][A-Z_0-9]*$"))
(vararg_expression) @constant
(nil) @constant.builtin
[
(false)
(true)
] @boolean
;; Tables
(field name: (identifier) @field)
(dot_index_expression field: (identifier) @field)
(table_constructor
[
"{"
"}"
] @constructor)
;; Functions
(parameters (identifier) @parameter)
(function_call name: (identifier) @function.call)
(function_declaration name: (identifier) @function)
(function_call name: (dot_index_expression field: (identifier) @function.call))
(function_declaration name: (dot_index_expression field: (identifier) @function))
(method_index_expression method: (identifier) @method)
(function_call
(identifier) @function.builtin
(#any-of? @function.builtin
;; built-in functions in Lua 5.1
"assert" "collectgarbage" "dofile" "error" "getfenv" "getmetatable" "ipairs"
"load" "loadfile" "loadstring" "module" "next" "pairs" "pcall" "print"
"rawequal" "rawget" "rawset" "require" "select" "setfenv" "setmetatable"
"tonumber" "tostring" "type" "unpack" "xpcall"))
;; Others
(comment) @comment
(hash_bang_line) @preproc
(number) @number
(string) @string
+10
View File
@@ -0,0 +1,10 @@
(if_statement "end" @end) @indent
(do_statement "end" @end) @indent
(while_statement "end" @end) @indent
(for_statement "end" @end) @indent
(repeat_statement "until" @end) @indent
(function_declaration "end" @end) @indent
(_ "[" "]" @end) @indent
(_ "{" "}" @end) @indent
(_ "(" ")" @end) @indent
+3
View File
@@ -0,0 +1,3 @@
(function_declaration
"function" @context
name: (_) @name) @item
+1 -1
View File
@@ -293,7 +293,7 @@ pub fn menus() -> Vec<Menu<'static>> {
action: Box::new(editor::GoToTypeDefinition),
},
MenuItem::Action {
name: "Go to References",
name: "Find All References",
action: Box::new(editor::FindAllReferences),
},
MenuItem::Action {