Merge branch 'main' into collab-panel2
This commit is contained in:
commit
01d3432a40
41 changed files with 646 additions and 361 deletions
13
Cargo.lock
generated
13
Cargo.lock
generated
|
@ -9930,7 +9930,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tree-sitter"
|
name = "tree-sitter"
|
||||||
version = "0.20.10"
|
version = "0.20.10"
|
||||||
source = "git+https://github.com/tree-sitter/tree-sitter?rev=35a6052fbcafc5e5fc0f9415b8652be7dcaf7222#35a6052fbcafc5e5fc0f9415b8652be7dcaf7222"
|
source = "git+https://github.com/tree-sitter/tree-sitter?rev=3b0159d25559b603af566ade3c83d930bf466db1#3b0159d25559b603af566ade3c83d930bf466db1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"regex",
|
"regex",
|
||||||
|
@ -10178,6 +10178,15 @@ dependencies = [
|
||||||
"tree-sitter",
|
"tree-sitter",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tree-sitter-uiua"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "git+https://github.com/shnarazk/tree-sitter-uiua?rev=9260f11be5900beda4ee6d1a24ab8ddfaf5a19b2#9260f11be5900beda4ee6d1a24ab8ddfaf5a19b2"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"tree-sitter",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tree-sitter-vue"
|
name = "tree-sitter-vue"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
|
@ -11616,6 +11625,7 @@ dependencies = [
|
||||||
"tree-sitter-svelte",
|
"tree-sitter-svelte",
|
||||||
"tree-sitter-toml",
|
"tree-sitter-toml",
|
||||||
"tree-sitter-typescript",
|
"tree-sitter-typescript",
|
||||||
|
"tree-sitter-uiua",
|
||||||
"tree-sitter-vue",
|
"tree-sitter-vue",
|
||||||
"tree-sitter-yaml",
|
"tree-sitter-yaml",
|
||||||
"unindent",
|
"unindent",
|
||||||
|
@ -11739,6 +11749,7 @@ dependencies = [
|
||||||
"tree-sitter-svelte",
|
"tree-sitter-svelte",
|
||||||
"tree-sitter-toml",
|
"tree-sitter-toml",
|
||||||
"tree-sitter-typescript",
|
"tree-sitter-typescript",
|
||||||
|
"tree-sitter-uiua",
|
||||||
"tree-sitter-vue",
|
"tree-sitter-vue",
|
||||||
"tree-sitter-yaml",
|
"tree-sitter-yaml",
|
||||||
"unindent",
|
"unindent",
|
||||||
|
|
|
@ -195,8 +195,10 @@ tree-sitter-lua = "0.0.14"
|
||||||
tree-sitter-nix = { git = "https://github.com/nix-community/tree-sitter-nix", rev = "66e3e9ce9180ae08fc57372061006ef83f0abde7" }
|
tree-sitter-nix = { git = "https://github.com/nix-community/tree-sitter-nix", rev = "66e3e9ce9180ae08fc57372061006ef83f0abde7" }
|
||||||
tree-sitter-nu = { git = "https://github.com/nushell/tree-sitter-nu", rev = "786689b0562b9799ce53e824cb45a1a2a04dc673"}
|
tree-sitter-nu = { git = "https://github.com/nushell/tree-sitter-nu", rev = "786689b0562b9799ce53e824cb45a1a2a04dc673"}
|
||||||
tree-sitter-vue = {git = "https://github.com/zed-industries/tree-sitter-vue", rev = "9b6cb221ccb8d0b956fcb17e9a1efac2feefeb58"}
|
tree-sitter-vue = {git = "https://github.com/zed-industries/tree-sitter-vue", rev = "9b6cb221ccb8d0b956fcb17e9a1efac2feefeb58"}
|
||||||
|
tree-sitter-uiua = {git = "https://github.com/shnarazk/tree-sitter-uiua", rev = "9260f11be5900beda4ee6d1a24ab8ddfaf5a19b2"}
|
||||||
|
|
||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
tree-sitter = { git = "https://github.com/tree-sitter/tree-sitter", rev = "35a6052fbcafc5e5fc0f9415b8652be7dcaf7222" }
|
tree-sitter = { git = "https://github.com/tree-sitter/tree-sitter", rev = "3b0159d25559b603af566ade3c83d930bf466db1" }
|
||||||
async-task = { git = "https://github.com/zed-industries/async-task", rev = "341b57d6de98cdfd7b418567b8de2022ca993a6e" }
|
async-task = { git = "https://github.com/zed-industries/async-task", rev = "341b57d6de98cdfd7b418567b8de2022ca993a6e" }
|
||||||
|
|
||||||
# TODO - Remove when a version is released with this PR: https://github.com/servo/core-foundation-rs/pull/457
|
# TODO - Remove when a version is released with this PR: https://github.com/servo/core-foundation-rs/pull/457
|
||||||
|
|
|
@ -84,8 +84,8 @@ impl Settings for AutoUpdateSetting {
|
||||||
pub fn init(http_client: Arc<dyn HttpClient>, server_url: String, cx: &mut AppContext) {
|
pub fn init(http_client: Arc<dyn HttpClient>, server_url: String, cx: &mut AppContext) {
|
||||||
AutoUpdateSetting::register(cx);
|
AutoUpdateSetting::register(cx);
|
||||||
|
|
||||||
cx.observe_new_views(|wokrspace: &mut Workspace, _cx| {
|
cx.observe_new_views(|workspace: &mut Workspace, _cx| {
|
||||||
wokrspace
|
workspace
|
||||||
.register_action(|_, action: &Check, cx| check(action, cx))
|
.register_action(|_, action: &Check, cx| check(action, cx))
|
||||||
.register_action(|_, _action: &CheckThatAutoUpdaterWorks, cx| {
|
.register_action(|_, _action: &CheckThatAutoUpdaterWorks, cx| {
|
||||||
let prompt = cx.prompt(gpui::PromptLevel::Info, "It does!", &["Ok"]);
|
let prompt = cx.prompt(gpui::PromptLevel::Info, "It does!", &["Ok"]);
|
||||||
|
@ -94,6 +94,11 @@ pub fn init(http_client: Arc<dyn HttpClient>, server_url: String, cx: &mut AppCo
|
||||||
})
|
})
|
||||||
.detach();
|
.detach();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// @nate - code to trigger update notification on launch
|
||||||
|
// workspace.show_notification(0, _cx, |cx| {
|
||||||
|
// cx.build_view(|_| UpdateNotification::new(SemanticVersion::from_str("1.1.1").unwrap()))
|
||||||
|
// });
|
||||||
})
|
})
|
||||||
.detach();
|
.detach();
|
||||||
|
|
||||||
|
@ -131,7 +136,7 @@ pub fn check(_: &Check, cx: &mut AppContext) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _view_release_notes(_: &ViewReleaseNotes, cx: &mut AppContext) {
|
pub fn view_release_notes(_: &ViewReleaseNotes, cx: &mut AppContext) {
|
||||||
if let Some(auto_updater) = AutoUpdater::get(cx) {
|
if let Some(auto_updater) = AutoUpdater::get(cx) {
|
||||||
let auto_updater = auto_updater.read(cx);
|
let auto_updater = auto_updater.read(cx);
|
||||||
let server_url = &auto_updater.server_url;
|
let server_url = &auto_updater.server_url;
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
use gpui::{
|
use gpui::{
|
||||||
div, DismissEvent, Div, EventEmitter, ParentElement, Render, SemanticVersion, ViewContext,
|
div, DismissEvent, Div, EventEmitter, InteractiveElement, ParentElement, Render,
|
||||||
|
SemanticVersion, StatefulInteractiveElement, Styled, ViewContext,
|
||||||
};
|
};
|
||||||
use menu::Cancel;
|
use util::channel::ReleaseChannel;
|
||||||
|
use workspace::ui::{h_stack, v_stack, Icon, IconElement, Label, StyledExt};
|
||||||
|
|
||||||
pub struct UpdateNotification {
|
pub struct UpdateNotification {
|
||||||
_version: SemanticVersion,
|
version: SemanticVersion,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EventEmitter<DismissEvent> for UpdateNotification {}
|
impl EventEmitter<DismissEvent> for UpdateNotification {}
|
||||||
|
@ -12,77 +14,43 @@ impl EventEmitter<DismissEvent> for UpdateNotification {}
|
||||||
impl Render for UpdateNotification {
|
impl Render for UpdateNotification {
|
||||||
type Element = Div;
|
type Element = Div;
|
||||||
|
|
||||||
fn render(&mut self, _cx: &mut gpui::ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> Self::Element {
|
||||||
div().child("Updated zed!")
|
let app_name = cx.global::<ReleaseChannel>().display_name();
|
||||||
// let theme = theme::current(cx).clone();
|
|
||||||
// let theme = &theme.update_notification;
|
|
||||||
|
|
||||||
// let app_name = cx.global::<ReleaseChannel>().display_name();
|
v_stack()
|
||||||
|
.elevation_3(cx)
|
||||||
// MouseEventHandler::new::<ViewReleaseNotes, _>(0, cx, |state, cx| {
|
.p_4()
|
||||||
// Flex::column()
|
.child(
|
||||||
// .with_child(
|
h_stack()
|
||||||
// Flex::row()
|
.justify_between()
|
||||||
// .with_child(
|
.child(Label::new(format!(
|
||||||
// Text::new(
|
"Updated to {app_name} {}",
|
||||||
// format!("Updated to {app_name} {}", self.version),
|
self.version
|
||||||
// theme.message.text.clone(),
|
)))
|
||||||
// )
|
.child(
|
||||||
// .contained()
|
div()
|
||||||
// .with_style(theme.message.container)
|
.id("cancel")
|
||||||
// .aligned()
|
.child(IconElement::new(Icon::Close))
|
||||||
// .top()
|
.cursor_pointer()
|
||||||
// .left()
|
.on_click(cx.listener(|this, _, cx| this.dismiss(cx))),
|
||||||
// .flex(1., true),
|
),
|
||||||
// )
|
)
|
||||||
// .with_child(
|
.child(
|
||||||
// MouseEventHandler::new::<Cancel, _>(0, cx, |state, _| {
|
div()
|
||||||
// let style = theme.dismiss_button.style_for(state);
|
.id("notes")
|
||||||
// Svg::new("icons/x.svg")
|
.child(Label::new("View the release notes"))
|
||||||
// .with_color(style.color)
|
.cursor_pointer()
|
||||||
// .constrained()
|
.on_click(|_, cx| crate::view_release_notes(&Default::default(), cx)),
|
||||||
// .with_width(style.icon_width)
|
)
|
||||||
// .aligned()
|
|
||||||
// .contained()
|
|
||||||
// .with_style(style.container)
|
|
||||||
// .constrained()
|
|
||||||
// .with_width(style.button_width)
|
|
||||||
// .with_height(style.button_width)
|
|
||||||
// })
|
|
||||||
// .with_padding(Padding::uniform(5.))
|
|
||||||
// .on_click(MouseButton::Left, move |_, this, cx| {
|
|
||||||
// this.dismiss(&Default::default(), cx)
|
|
||||||
// })
|
|
||||||
// .aligned()
|
|
||||||
// .constrained()
|
|
||||||
// .with_height(cx.font_cache().line_height(theme.message.text.font_size))
|
|
||||||
// .aligned()
|
|
||||||
// .top()
|
|
||||||
// .flex_float(),
|
|
||||||
// ),
|
|
||||||
// )
|
|
||||||
// .with_child({
|
|
||||||
// let style = theme.action_message.style_for(state);
|
|
||||||
// Text::new("View the release notes", style.text.clone())
|
|
||||||
// .contained()
|
|
||||||
// .with_style(style.container)
|
|
||||||
// })
|
|
||||||
// .contained()
|
|
||||||
// })
|
|
||||||
// .with_cursor_style(CursorStyle::PointingHand)
|
|
||||||
// .on_click(MouseButton::Left, |_, _, cx| {
|
|
||||||
// crate::view_release_notes(&Default::default(), cx)
|
|
||||||
// })
|
|
||||||
// .into_any_named("update notification")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UpdateNotification {
|
impl UpdateNotification {
|
||||||
pub fn new(version: SemanticVersion) -> Self {
|
pub fn new(version: SemanticVersion) -> Self {
|
||||||
Self { _version: version }
|
Self { version }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _dismiss(&mut self, _: &Cancel, cx: &mut ViewContext<Self>) {
|
pub fn dismiss(&mut self, cx: &mut ViewContext<Self>) {
|
||||||
cx.emit(DismissEvent::Dismiss);
|
cx.emit(DismissEvent::Dismiss);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -170,7 +170,7 @@ impl PickerDelegate for ContactFinderDelegate {
|
||||||
ix: usize,
|
ix: usize,
|
||||||
selected: bool,
|
selected: bool,
|
||||||
cx: &mut ViewContext<Picker<Self>>,
|
cx: &mut ViewContext<Picker<Self>>,
|
||||||
) -> Self::ListItem {
|
) -> Option<Self::ListItem> {
|
||||||
let user = &self.potential_contacts[ix];
|
let user = &self.potential_contacts[ix];
|
||||||
let request_status = self.user_store.read(cx).contact_request_status(user);
|
let request_status = self.user_store.read(cx).contact_request_status(user);
|
||||||
|
|
||||||
|
@ -182,12 +182,14 @@ impl PickerDelegate for ContactFinderDelegate {
|
||||||
ContactRequestStatus::RequestAccepted => None,
|
ContactRequestStatus::RequestAccepted => None,
|
||||||
};
|
};
|
||||||
dbg!(icon_path);
|
dbg!(icon_path);
|
||||||
div()
|
Some(
|
||||||
.flex_1()
|
div()
|
||||||
.justify_between()
|
.flex_1()
|
||||||
.children(user.avatar.clone().map(|avatar| img().data(avatar)))
|
.justify_between()
|
||||||
.child(Label::new(user.github_login.clone()))
|
.children(user.avatar.clone().map(|avatar| img().data(avatar)))
|
||||||
.children(icon_path.map(|icon_path| svg().path(icon_path)))
|
.child(Label::new(user.github_login.clone()))
|
||||||
|
.children(icon_path.map(|icon_path| svg().path(icon_path))),
|
||||||
|
)
|
||||||
// Flex::row()
|
// Flex::row()
|
||||||
// .with_children(user.avatar.clone().map(|avatar| {
|
// .with_children(user.avatar.clone().map(|avatar| {
|
||||||
// Image::from_data(avatar)
|
// Image::from_data(avatar)
|
||||||
|
|
|
@ -1,17 +1,15 @@
|
||||||
use collections::{CommandPaletteFilter, HashMap};
|
use collections::{CommandPaletteFilter, HashMap};
|
||||||
use fuzzy::{StringMatch, StringMatchCandidate};
|
use fuzzy::{StringMatch, StringMatchCandidate};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, div, prelude::*, Action, AppContext, DismissEvent, Div, EventEmitter, FocusHandle,
|
actions, Action, AppContext, DismissEvent, Div, EventEmitter, FocusHandle, FocusableView,
|
||||||
FocusableView, Keystroke, ParentElement, Render, Styled, View, ViewContext, VisualContext,
|
Keystroke, ParentElement, Render, Styled, View, ViewContext, VisualContext, WeakView,
|
||||||
WeakView,
|
|
||||||
};
|
};
|
||||||
use picker::{Picker, PickerDelegate};
|
use picker::{Picker, PickerDelegate};
|
||||||
use std::{
|
use std::{
|
||||||
cmp::{self, Reverse},
|
cmp::{self, Reverse},
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
use theme::ActiveTheme;
|
use ui::{h_stack, v_stack, HighlightedLabel, KeyBinding, ListItem};
|
||||||
use ui::{h_stack, v_stack, HighlightedLabel, KeyBinding, StyledExt};
|
|
||||||
use util::{
|
use util::{
|
||||||
channel::{parse_zed_link, ReleaseChannel, RELEASE_CHANNEL},
|
channel::{parse_zed_link, ReleaseChannel, RELEASE_CHANNEL},
|
||||||
ResultExt,
|
ResultExt,
|
||||||
|
@ -141,7 +139,7 @@ impl CommandPaletteDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PickerDelegate for CommandPaletteDelegate {
|
impl PickerDelegate for CommandPaletteDelegate {
|
||||||
type ListItem = Div;
|
type ListItem = ListItem;
|
||||||
|
|
||||||
fn placeholder_text(&self) -> Arc<str> {
|
fn placeholder_text(&self) -> Arc<str> {
|
||||||
"Execute a command...".into()
|
"Execute a command...".into()
|
||||||
|
@ -294,24 +292,16 @@ impl PickerDelegate for CommandPaletteDelegate {
|
||||||
ix: usize,
|
ix: usize,
|
||||||
selected: bool,
|
selected: bool,
|
||||||
cx: &mut ViewContext<Picker<Self>>,
|
cx: &mut ViewContext<Picker<Self>>,
|
||||||
) -> Self::ListItem {
|
) -> Option<Self::ListItem> {
|
||||||
let colors = cx.theme().colors();
|
|
||||||
let Some(r#match) = self.matches.get(ix) else {
|
let Some(r#match) = self.matches.get(ix) else {
|
||||||
return div();
|
return None;
|
||||||
};
|
};
|
||||||
let Some(command) = self.commands.get(r#match.candidate_id) else {
|
let Some(command) = self.commands.get(r#match.candidate_id) else {
|
||||||
return div();
|
return None;
|
||||||
};
|
};
|
||||||
|
|
||||||
div()
|
Some(
|
||||||
.px_1()
|
ListItem::new(ix).selected(selected).child(
|
||||||
.text_color(colors.text)
|
|
||||||
.text_ui()
|
|
||||||
.bg(colors.ghost_element_background)
|
|
||||||
.rounded_md()
|
|
||||||
.when(selected, |this| this.bg(colors.ghost_element_selected))
|
|
||||||
.hover(|this| this.bg(colors.ghost_element_hover))
|
|
||||||
.child(
|
|
||||||
h_stack()
|
h_stack()
|
||||||
.justify_between()
|
.justify_between()
|
||||||
.child(HighlightedLabel::new(
|
.child(HighlightedLabel::new(
|
||||||
|
@ -319,7 +309,8 @@ impl PickerDelegate for CommandPaletteDelegate {
|
||||||
r#match.positions.clone(),
|
r#match.positions.clone(),
|
||||||
))
|
))
|
||||||
.children(KeyBinding::for_action(&*command.action, cx)),
|
.children(KeyBinding::for_action(&*command.action, cx)),
|
||||||
)
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1273,6 +1273,13 @@ impl CompletionsMenu {
|
||||||
multiline_docs.map(|div| {
|
multiline_docs.map(|div| {
|
||||||
div.id("multiline_docs")
|
div.id("multiline_docs")
|
||||||
.max_h(max_height)
|
.max_h(max_height)
|
||||||
|
.flex_1()
|
||||||
|
.px_1p5()
|
||||||
|
.py_1()
|
||||||
|
.min_w(px(260.))
|
||||||
|
.max_w(px(640.))
|
||||||
|
.w(px(500.))
|
||||||
|
.text_ui()
|
||||||
.overflow_y_scroll()
|
.overflow_y_scroll()
|
||||||
// Prevent a mouse down on documentation from being propagated to the editor,
|
// Prevent a mouse down on documentation from being propagated to the editor,
|
||||||
// because that would move the cursor.
|
// because that would move the cursor.
|
||||||
|
@ -1327,13 +1334,18 @@ impl CompletionsMenu {
|
||||||
|
|
||||||
div()
|
div()
|
||||||
.id(mat.candidate_id)
|
.id(mat.candidate_id)
|
||||||
.min_w(px(300.))
|
.min_w(px(220.))
|
||||||
.max_w(px(700.))
|
.max_w(px(540.))
|
||||||
.whitespace_nowrap()
|
.whitespace_nowrap()
|
||||||
.overflow_hidden()
|
.overflow_hidden()
|
||||||
.bg(gpui::green())
|
.text_ui()
|
||||||
.hover(|style| style.bg(gpui::blue()))
|
.px_1()
|
||||||
.when(item_ix == selected_item, |div| div.bg(gpui::red()))
|
.rounded(px(4.))
|
||||||
|
.bg(cx.theme().colors().ghost_element_background)
|
||||||
|
.hover(|style| style.bg(cx.theme().colors().ghost_element_hover))
|
||||||
|
.when(item_ix == selected_item, |div| {
|
||||||
|
div.bg(cx.theme().colors().ghost_element_selected)
|
||||||
|
})
|
||||||
.on_mouse_down(
|
.on_mouse_down(
|
||||||
MouseButton::Left,
|
MouseButton::Left,
|
||||||
cx.listener(move |editor, event, cx| {
|
cx.listener(move |editor, event, cx| {
|
||||||
|
|
|
@ -2,9 +2,8 @@ use collections::HashMap;
|
||||||
use editor::{scroll::autoscroll::Autoscroll, Bias, Editor};
|
use editor::{scroll::autoscroll::Autoscroll, Bias, Editor};
|
||||||
use fuzzy::{CharBag, PathMatch, PathMatchCandidate};
|
use fuzzy::{CharBag, PathMatch, PathMatchCandidate};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, div, AppContext, DismissEvent, Div, EventEmitter, FocusHandle, FocusableView,
|
actions, AppContext, DismissEvent, Div, EventEmitter, FocusHandle, FocusableView, Model,
|
||||||
InteractiveElement, IntoElement, Model, ParentElement, Render, Styled, Task, View, ViewContext,
|
ParentElement, Render, Styled, Task, View, ViewContext, VisualContext, WeakView,
|
||||||
VisualContext, WeakView,
|
|
||||||
};
|
};
|
||||||
use picker::{Picker, PickerDelegate};
|
use picker::{Picker, PickerDelegate};
|
||||||
use project::{PathMatchCandidateSet, Project, ProjectPath, WorktreeId};
|
use project::{PathMatchCandidateSet, Project, ProjectPath, WorktreeId};
|
||||||
|
@ -16,8 +15,7 @@ use std::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use text::Point;
|
use text::Point;
|
||||||
use theme::ActiveTheme;
|
use ui::{v_stack, HighlightedLabel, ListItem};
|
||||||
use ui::{v_stack, HighlightedLabel, StyledExt};
|
|
||||||
use util::{paths::PathLikeWithPosition, post_inc, ResultExt};
|
use util::{paths::PathLikeWithPosition, post_inc, ResultExt};
|
||||||
use workspace::Workspace;
|
use workspace::Workspace;
|
||||||
|
|
||||||
|
@ -530,7 +528,7 @@ impl FileFinderDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PickerDelegate for FileFinderDelegate {
|
impl PickerDelegate for FileFinderDelegate {
|
||||||
type ListItem = Div;
|
type ListItem = ListItem;
|
||||||
|
|
||||||
fn placeholder_text(&self) -> Arc<str> {
|
fn placeholder_text(&self) -> Arc<str> {
|
||||||
"Search project files...".into()
|
"Search project files...".into()
|
||||||
|
@ -711,30 +709,22 @@ impl PickerDelegate for FileFinderDelegate {
|
||||||
ix: usize,
|
ix: usize,
|
||||||
selected: bool,
|
selected: bool,
|
||||||
cx: &mut ViewContext<Picker<Self>>,
|
cx: &mut ViewContext<Picker<Self>>,
|
||||||
) -> Self::ListItem {
|
) -> Option<Self::ListItem> {
|
||||||
let path_match = self
|
let path_match = self
|
||||||
.matches
|
.matches
|
||||||
.get(ix)
|
.get(ix)
|
||||||
.expect("Invalid matches state: no element for index {ix}");
|
.expect("Invalid matches state: no element for index {ix}");
|
||||||
let theme = cx.theme();
|
|
||||||
let colors = theme.colors();
|
|
||||||
|
|
||||||
let (file_name, file_name_positions, full_path, full_path_positions) =
|
let (file_name, file_name_positions, full_path, full_path_positions) =
|
||||||
self.labels_for_match(path_match, cx, ix);
|
self.labels_for_match(path_match, cx, ix);
|
||||||
|
|
||||||
div()
|
Some(
|
||||||
.px_1()
|
ListItem::new(ix).selected(selected).child(
|
||||||
.text_color(colors.text)
|
|
||||||
.text_ui()
|
|
||||||
.bg(colors.ghost_element_background)
|
|
||||||
.rounded_md()
|
|
||||||
.when(selected, |this| this.bg(colors.ghost_element_selected))
|
|
||||||
.hover(|this| this.bg(colors.ghost_element_hover))
|
|
||||||
.child(
|
|
||||||
v_stack()
|
v_stack()
|
||||||
.child(HighlightedLabel::new(file_name, file_name_positions))
|
.child(HighlightedLabel::new(file_name, file_name_positions))
|
||||||
.child(HighlightedLabel::new(full_path, full_path_positions)),
|
.child(HighlightedLabel::new(full_path, full_path_positions)),
|
||||||
)
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -105,6 +105,7 @@ impl Element for Overlay {
|
||||||
origin: Point::zero(),
|
origin: Point::zero(),
|
||||||
size: cx.viewport_size(),
|
size: cx.viewport_size(),
|
||||||
};
|
};
|
||||||
|
dbg!(limits);
|
||||||
|
|
||||||
match self.fit_mode {
|
match self.fit_mode {
|
||||||
OverlayFitMode::SnapToWindow => {
|
OverlayFitMode::SnapToWindow => {
|
||||||
|
|
|
@ -11,7 +11,7 @@ pub struct HighlightId(pub u32);
|
||||||
const DEFAULT_SYNTAX_HIGHLIGHT_ID: HighlightId = HighlightId(u32::MAX);
|
const DEFAULT_SYNTAX_HIGHLIGHT_ID: HighlightId = HighlightId(u32::MAX);
|
||||||
|
|
||||||
impl HighlightMap {
|
impl HighlightMap {
|
||||||
pub fn new(capture_names: &[String], theme: &SyntaxTheme) -> Self {
|
pub fn new(capture_names: &[&str], theme: &SyntaxTheme) -> Self {
|
||||||
// For each capture name in the highlight query, find the longest
|
// For each capture name in the highlight query, find the longest
|
||||||
// key in the theme's syntax styles that matches all of the
|
// key in the theme's syntax styles that matches all of the
|
||||||
// dot-separated components of the capture name.
|
// dot-separated components of the capture name.
|
||||||
|
@ -98,9 +98,9 @@ mod tests {
|
||||||
);
|
);
|
||||||
|
|
||||||
let capture_names = &[
|
let capture_names = &[
|
||||||
"function.special".to_string(),
|
"function.special",
|
||||||
"function.async.rust".to_string(),
|
"function.async.rust",
|
||||||
"variable.builtin.self".to_string(),
|
"variable.builtin.self",
|
||||||
];
|
];
|
||||||
|
|
||||||
let map = HighlightMap::new(capture_names, &theme);
|
let map = HighlightMap::new(capture_names, &theme);
|
||||||
|
|
|
@ -1383,7 +1383,7 @@ impl Language {
|
||||||
let query = Query::new(self.grammar_mut().ts_language, source)?;
|
let query = Query::new(self.grammar_mut().ts_language, source)?;
|
||||||
|
|
||||||
let mut override_configs_by_id = HashMap::default();
|
let mut override_configs_by_id = HashMap::default();
|
||||||
for (ix, name) in query.capture_names().iter().enumerate() {
|
for (ix, name) in query.capture_names().iter().copied().enumerate() {
|
||||||
if !name.starts_with('_') {
|
if !name.starts_with('_') {
|
||||||
let value = self.config.overrides.remove(name).unwrap_or_default();
|
let value = self.config.overrides.remove(name).unwrap_or_default();
|
||||||
for server_name in &value.opt_into_language_servers {
|
for server_name in &value.opt_into_language_servers {
|
||||||
|
@ -1396,7 +1396,7 @@ impl Language {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override_configs_by_id.insert(ix as u32, (name.clone(), value));
|
override_configs_by_id.insert(ix as u32, (name.into(), value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1300,7 +1300,7 @@ fn assert_capture_ranges(
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
for capture in captures {
|
for capture in captures {
|
||||||
let name = &queries[capture.grammar_index].capture_names()[capture.index as usize];
|
let name = &queries[capture.grammar_index].capture_names()[capture.index as usize];
|
||||||
if highlight_query_capture_names.contains(&name.as_str()) {
|
if highlight_query_capture_names.contains(&name) {
|
||||||
actual_ranges.push(capture.node.byte_range());
|
actual_ranges.push(capture.node.byte_range());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ pub struct HighlightId(pub u32);
|
||||||
const DEFAULT_SYNTAX_HIGHLIGHT_ID: HighlightId = HighlightId(u32::MAX);
|
const DEFAULT_SYNTAX_HIGHLIGHT_ID: HighlightId = HighlightId(u32::MAX);
|
||||||
|
|
||||||
impl HighlightMap {
|
impl HighlightMap {
|
||||||
pub fn new(capture_names: &[String], theme: &SyntaxTheme) -> Self {
|
pub fn new(capture_names: &[&str], theme: &SyntaxTheme) -> Self {
|
||||||
// For each capture name in the highlight query, find the longest
|
// For each capture name in the highlight query, find the longest
|
||||||
// key in the theme's syntax styles that matches all of the
|
// key in the theme's syntax styles that matches all of the
|
||||||
// dot-separated components of the capture name.
|
// dot-separated components of the capture name.
|
||||||
|
@ -100,9 +100,9 @@ mod tests {
|
||||||
};
|
};
|
||||||
|
|
||||||
let capture_names = &[
|
let capture_names = &[
|
||||||
"function.special".to_string(),
|
"function.special",
|
||||||
"function.async.rust".to_string(),
|
"function.async.rust",
|
||||||
"variable.builtin.self".to_string(),
|
"variable.builtin.self",
|
||||||
];
|
];
|
||||||
|
|
||||||
let map = HighlightMap::new(capture_names, &theme);
|
let map = HighlightMap::new(capture_names, &theme);
|
||||||
|
|
|
@ -1391,7 +1391,7 @@ impl Language {
|
||||||
let mut override_configs_by_id = HashMap::default();
|
let mut override_configs_by_id = HashMap::default();
|
||||||
for (ix, name) in query.capture_names().iter().enumerate() {
|
for (ix, name) in query.capture_names().iter().enumerate() {
|
||||||
if !name.starts_with('_') {
|
if !name.starts_with('_') {
|
||||||
let value = self.config.overrides.remove(name).unwrap_or_default();
|
let value = self.config.overrides.remove(*name).unwrap_or_default();
|
||||||
for server_name in &value.opt_into_language_servers {
|
for server_name in &value.opt_into_language_servers {
|
||||||
if !self
|
if !self
|
||||||
.config
|
.config
|
||||||
|
@ -1402,7 +1402,7 @@ impl Language {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override_configs_by_id.insert(ix as u32, (name.clone(), value));
|
override_configs_by_id.insert(ix as u32, (name.to_string(), value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1300,7 +1300,7 @@ fn assert_capture_ranges(
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
for capture in captures {
|
for capture in captures {
|
||||||
let name = &queries[capture.grammar_index].capture_names()[capture.index as usize];
|
let name = &queries[capture.grammar_index].capture_names()[capture.index as usize];
|
||||||
if highlight_query_capture_names.contains(&name.as_str()) {
|
if highlight_query_capture_names.contains(&name) {
|
||||||
actual_ranges.push(capture.node.byte_range());
|
actual_ranges.push(capture.node.byte_range());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,6 +73,7 @@ impl RealNodeRuntime {
|
||||||
let npm_file = node_dir.join("bin/npm");
|
let npm_file = node_dir.join("bin/npm");
|
||||||
|
|
||||||
let result = Command::new(&node_binary)
|
let result = Command::new(&node_binary)
|
||||||
|
.env_clear()
|
||||||
.arg(npm_file)
|
.arg(npm_file)
|
||||||
.arg("--version")
|
.arg("--version")
|
||||||
.stdin(Stdio::null())
|
.stdin(Stdio::null())
|
||||||
|
@ -149,6 +150,7 @@ impl NodeRuntime for RealNodeRuntime {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut command = Command::new(node_binary);
|
let mut command = Command::new(node_binary);
|
||||||
|
command.env_clear();
|
||||||
command.env("PATH", env_path);
|
command.env("PATH", env_path);
|
||||||
command.arg(npm_file).arg(subcommand);
|
command.arg(npm_file).arg(subcommand);
|
||||||
command.args(["--cache".into(), installation_path.join("cache")]);
|
command.args(["--cache".into(), installation_path.join("cache")]);
|
||||||
|
@ -200,11 +202,11 @@ impl NodeRuntime for RealNodeRuntime {
|
||||||
&[
|
&[
|
||||||
name,
|
name,
|
||||||
"--json",
|
"--json",
|
||||||
"-fetch-retry-mintimeout",
|
"--fetch-retry-mintimeout",
|
||||||
"2000",
|
"2000",
|
||||||
"-fetch-retry-maxtimeout",
|
"--fetch-retry-maxtimeout",
|
||||||
"5000",
|
"5000",
|
||||||
"-fetch-timeout",
|
"--fetch-timeout",
|
||||||
"5000",
|
"5000",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -229,11 +231,11 @@ impl NodeRuntime for RealNodeRuntime {
|
||||||
|
|
||||||
let mut arguments: Vec<_> = packages.iter().map(|p| p.as_str()).collect();
|
let mut arguments: Vec<_> = packages.iter().map(|p| p.as_str()).collect();
|
||||||
arguments.extend_from_slice(&[
|
arguments.extend_from_slice(&[
|
||||||
"-fetch-retry-mintimeout",
|
"--fetch-retry-mintimeout",
|
||||||
"2000",
|
"2000",
|
||||||
"-fetch-retry-maxtimeout",
|
"--fetch-retry-maxtimeout",
|
||||||
"5000",
|
"5000",
|
||||||
"-fetch-timeout",
|
"--fetch-timeout",
|
||||||
"5000",
|
"5000",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ pub trait PickerDelegate: Sized + 'static {
|
||||||
ix: usize,
|
ix: usize,
|
||||||
selected: bool,
|
selected: bool,
|
||||||
cx: &mut ViewContext<Picker<Self>>,
|
cx: &mut ViewContext<Picker<Self>>,
|
||||||
) -> Self::ListItem;
|
) -> Option<Self::ListItem>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D: PickerDelegate> FocusableView for Picker<D> {
|
impl<D: PickerDelegate> FocusableView for Picker<D> {
|
||||||
|
@ -230,7 +230,7 @@ impl<D: PickerDelegate> Render for Picker<D> {
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.child(picker.delegate.render_match(
|
.children(picker.delegate.render_match(
|
||||||
ix,
|
ix,
|
||||||
ix == selected_index,
|
ix == selected_index,
|
||||||
cx,
|
cx,
|
||||||
|
|
|
@ -10,9 +10,8 @@ use anyhow::{anyhow, Result};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, div, px, uniform_list, Action, AppContext, AssetSource, AsyncWindowContext,
|
actions, div, px, uniform_list, Action, AppContext, AssetSource, AsyncWindowContext,
|
||||||
ClipboardItem, Div, EventEmitter, FocusHandle, Focusable, FocusableView, InteractiveElement,
|
ClipboardItem, Div, EventEmitter, FocusHandle, Focusable, FocusableView, InteractiveElement,
|
||||||
IntoElement, Model, MouseButton, MouseDownEvent, ParentElement, Pixels, Point, PromptLevel,
|
Model, MouseDownEvent, ParentElement, Pixels, Point, PromptLevel, Render, Stateful, Styled,
|
||||||
Render, Stateful, StatefulInteractiveElement, Styled, Task, UniformListScrollHandle, View,
|
Task, UniformListScrollHandle, View, ViewContext, VisualContext as _, WeakView, WindowContext,
|
||||||
ViewContext, VisualContext as _, WeakView, WindowContext,
|
|
||||||
};
|
};
|
||||||
use menu::{Confirm, SelectNext, SelectPrev};
|
use menu::{Confirm, SelectNext, SelectPrev};
|
||||||
use project::{
|
use project::{
|
||||||
|
@ -30,7 +29,7 @@ use std::{
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
use theme::ActiveTheme as _;
|
use theme::ActiveTheme as _;
|
||||||
use ui::{h_stack, v_stack, IconElement, Label};
|
use ui::{v_stack, IconElement, Label, ListItem};
|
||||||
use unicase::UniCase;
|
use unicase::UniCase;
|
||||||
use util::{maybe, ResultExt, TryFutureExt};
|
use util::{maybe, ResultExt, TryFutureExt};
|
||||||
use workspace::{
|
use workspace::{
|
||||||
|
@ -1335,13 +1334,19 @@ impl ProjectPanel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_entry_visual_element(
|
fn render_entry(
|
||||||
details: &EntryDetails,
|
&self,
|
||||||
editor: Option<&View<Editor>>,
|
entry_id: ProjectEntryId,
|
||||||
padding: Pixels,
|
details: EntryDetails,
|
||||||
|
// dragged_entry_destination: &mut Option<Arc<Path>>,
|
||||||
cx: &mut ViewContext<Self>,
|
cx: &mut ViewContext<Self>,
|
||||||
) -> Div {
|
) -> ListItem {
|
||||||
|
let kind = details.kind;
|
||||||
|
let settings = ProjectPanelSettings::get_global(cx);
|
||||||
let show_editor = details.is_editing && !details.is_processing;
|
let show_editor = details.is_editing && !details.is_processing;
|
||||||
|
let is_selected = self
|
||||||
|
.selection
|
||||||
|
.map_or(false, |selection| selection.entry_id == entry_id);
|
||||||
|
|
||||||
let theme = cx.theme();
|
let theme = cx.theme();
|
||||||
let filename_text_color = details
|
let filename_text_color = details
|
||||||
|
@ -1354,14 +1359,17 @@ impl ProjectPanel {
|
||||||
})
|
})
|
||||||
.unwrap_or(theme.status().info);
|
.unwrap_or(theme.status().info);
|
||||||
|
|
||||||
h_stack()
|
ListItem::new(entry_id.to_proto() as usize)
|
||||||
|
.indent_level(details.depth)
|
||||||
|
.indent_step_size(px(settings.indent_size))
|
||||||
|
.selected(is_selected)
|
||||||
.child(if let Some(icon) = &details.icon {
|
.child(if let Some(icon) = &details.icon {
|
||||||
div().child(IconElement::from_path(icon.to_string()))
|
div().child(IconElement::from_path(icon.to_string()))
|
||||||
} else {
|
} else {
|
||||||
div()
|
div()
|
||||||
})
|
})
|
||||||
.child(
|
.child(
|
||||||
if let (Some(editor), true) = (editor, show_editor) {
|
if let (Some(editor), true) = (Some(&self.filename_editor), show_editor) {
|
||||||
div().w_full().child(editor.clone())
|
div().w_full().child(editor.clone())
|
||||||
} else {
|
} else {
|
||||||
div()
|
div()
|
||||||
|
@ -1370,33 +1378,6 @@ impl ProjectPanel {
|
||||||
}
|
}
|
||||||
.ml_1(),
|
.ml_1(),
|
||||||
)
|
)
|
||||||
.pl(padding)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn render_entry(
|
|
||||||
&self,
|
|
||||||
entry_id: ProjectEntryId,
|
|
||||||
details: EntryDetails,
|
|
||||||
// dragged_entry_destination: &mut Option<Arc<Path>>,
|
|
||||||
cx: &mut ViewContext<Self>,
|
|
||||||
) -> Stateful<Div> {
|
|
||||||
let kind = details.kind;
|
|
||||||
let settings = ProjectPanelSettings::get_global(cx);
|
|
||||||
const INDENT_SIZE: Pixels = px(16.0);
|
|
||||||
let padding = INDENT_SIZE + details.depth as f32 * px(settings.indent_size);
|
|
||||||
let show_editor = details.is_editing && !details.is_processing;
|
|
||||||
let is_selected = self
|
|
||||||
.selection
|
|
||||||
.map_or(false, |selection| selection.entry_id == entry_id);
|
|
||||||
|
|
||||||
Self::render_entry_visual_element(&details, Some(&self.filename_editor), padding, cx)
|
|
||||||
.id(entry_id.to_proto() as usize)
|
|
||||||
.w_full()
|
|
||||||
.cursor_pointer()
|
|
||||||
.when(is_selected, |this| {
|
|
||||||
this.bg(cx.theme().colors().element_selected)
|
|
||||||
})
|
|
||||||
.hover(|style| style.bg(cx.theme().colors().element_hover))
|
|
||||||
.on_click(cx.listener(move |this, event: &gpui::ClickEvent, cx| {
|
.on_click(cx.listener(move |this, event: &gpui::ClickEvent, cx| {
|
||||||
if !show_editor {
|
if !show_editor {
|
||||||
if kind.is_dir() {
|
if kind.is_dir() {
|
||||||
|
@ -1410,12 +1391,9 @@ impl ProjectPanel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
.on_mouse_down(
|
.on_secondary_mouse_down(cx.listener(move |this, event: &MouseDownEvent, cx| {
|
||||||
MouseButton::Right,
|
this.deploy_context_menu(event.position, entry_id, cx);
|
||||||
cx.listener(move |this, event: &MouseDownEvent, cx| {
|
}))
|
||||||
this.deploy_context_menu(event.position, entry_id, cx);
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
// .on_drop::<ProjectEntryId>(|this, event, cx| {
|
// .on_drop::<ProjectEntryId>(|this, event, cx| {
|
||||||
// this.move_entry(
|
// this.move_entry(
|
||||||
// *dragged_entry,
|
// *dragged_entry,
|
||||||
|
|
|
@ -1659,13 +1659,13 @@ fn elixir_lang() -> Arc<Language> {
|
||||||
target: (identifier) @name)
|
target: (identifier) @name)
|
||||||
operator: "when")
|
operator: "when")
|
||||||
])
|
])
|
||||||
(#match? @name "^(def|defp|defdelegate|defguard|defguardp|defmacro|defmacrop|defn|defnp)$")) @item
|
(#any-match? @name "^(def|defp|defdelegate|defguard|defguardp|defmacro|defmacrop|defn|defnp)$")) @item
|
||||||
)
|
)
|
||||||
|
|
||||||
(call
|
(call
|
||||||
target: (identifier) @name
|
target: (identifier) @name
|
||||||
(arguments (alias) @name)
|
(arguments (alias) @name)
|
||||||
(#match? @name "^(defmodule|defprotocol)$")) @item
|
(#any-match? @name "^(defmodule|defprotocol)$")) @item
|
||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
|
|
|
@ -5,6 +5,7 @@ use gpui::{
|
||||||
use picker::{Picker, PickerDelegate};
|
use picker::{Picker, PickerDelegate};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use theme2::ActiveTheme;
|
use theme2::ActiveTheme;
|
||||||
|
use ui::{Label, ListItem};
|
||||||
|
|
||||||
pub struct PickerStory {
|
pub struct PickerStory {
|
||||||
picker: View<Picker<Delegate>>,
|
picker: View<Picker<Delegate>>,
|
||||||
|
@ -36,7 +37,7 @@ impl Delegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PickerDelegate for Delegate {
|
impl PickerDelegate for Delegate {
|
||||||
type ListItem = Div;
|
type ListItem = ListItem;
|
||||||
|
|
||||||
fn match_count(&self) -> usize {
|
fn match_count(&self) -> usize {
|
||||||
self.candidates.len()
|
self.candidates.len()
|
||||||
|
@ -51,25 +52,18 @@ impl PickerDelegate for Delegate {
|
||||||
ix: usize,
|
ix: usize,
|
||||||
selected: bool,
|
selected: bool,
|
||||||
cx: &mut gpui::ViewContext<Picker<Self>>,
|
cx: &mut gpui::ViewContext<Picker<Self>>,
|
||||||
) -> Self::ListItem {
|
) -> Option<Self::ListItem> {
|
||||||
let colors = cx.theme().colors();
|
|
||||||
let Some(candidate_ix) = self.matches.get(ix) else {
|
let Some(candidate_ix) = self.matches.get(ix) else {
|
||||||
return div();
|
return None;
|
||||||
};
|
};
|
||||||
// TASK: Make StringMatchCandidate::string a SharedString
|
// TASK: Make StringMatchCandidate::string a SharedString
|
||||||
let candidate = SharedString::from(self.candidates[*candidate_ix].string.clone());
|
let candidate = SharedString::from(self.candidates[*candidate_ix].string.clone());
|
||||||
|
|
||||||
div()
|
Some(
|
||||||
.text_color(colors.text)
|
ListItem::new(ix)
|
||||||
.when(selected, |s| {
|
.selected(selected)
|
||||||
s.border_l_10().border_color(colors.terminal_ansi_yellow)
|
.child(Label::new(candidate)),
|
||||||
})
|
)
|
||||||
.hover(|style| {
|
|
||||||
style
|
|
||||||
.bg(colors.element_active)
|
|
||||||
.text_color(colors.text_accent)
|
|
||||||
})
|
|
||||||
.child(candidate)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn selected_index(&self) -> usize {
|
fn selected_index(&self) -> usize {
|
||||||
|
|
|
@ -4,18 +4,15 @@ use std::rc::Rc;
|
||||||
use crate::{prelude::*, v_stack, Label, List};
|
use crate::{prelude::*, v_stack, Label, List};
|
||||||
use crate::{ListItem, ListSeparator, ListSubHeader};
|
use crate::{ListItem, ListSeparator, ListSubHeader};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
overlay, px, Action, AnchorCorner, AnyElement, AppContext, Bounds, DismissEvent, DispatchPhase,
|
overlay, px, Action, AnchorCorner, AnyElement, AppContext, Bounds, ClickEvent, DismissEvent,
|
||||||
Div, EventEmitter, FocusHandle, FocusableView, IntoElement, LayoutId, ManagedView, MouseButton,
|
DispatchPhase, Div, EventEmitter, FocusHandle, FocusableView, IntoElement, LayoutId,
|
||||||
MouseDownEvent, Pixels, Point, Render, View, VisualContext,
|
ManagedView, MouseButton, MouseDownEvent, Pixels, Point, Render, View, VisualContext,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub enum ContextMenuItem {
|
pub enum ContextMenuItem {
|
||||||
Separator,
|
Separator,
|
||||||
Header(SharedString),
|
Header(SharedString),
|
||||||
Entry(
|
Entry(SharedString, Rc<dyn Fn(&ClickEvent, &mut WindowContext)>),
|
||||||
SharedString,
|
|
||||||
Rc<dyn Fn(&MouseDownEvent, &mut WindowContext)>,
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ContextMenu {
|
pub struct ContextMenu {
|
||||||
|
@ -61,7 +58,7 @@ impl ContextMenu {
|
||||||
pub fn entry(
|
pub fn entry(
|
||||||
mut self,
|
mut self,
|
||||||
label: impl Into<SharedString>,
|
label: impl Into<SharedString>,
|
||||||
on_click: impl Fn(&MouseDownEvent, &mut WindowContext) + 'static,
|
on_click: impl Fn(&ClickEvent, &mut WindowContext) + 'static,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
self.items
|
self.items
|
||||||
.push(ContextMenuItem::Entry(label.into(), Rc::new(on_click)));
|
.push(ContextMenuItem::Entry(label.into(), Rc::new(on_click)));
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
use gpui::{
|
use gpui::{
|
||||||
div, px, AnyElement, Div, ImageSource, IntoElement, MouseButton, MouseDownEvent, Stateful,
|
div, px, AnyElement, ClickEvent, Div, ImageSource, IntoElement, MouseButton, MouseDownEvent,
|
||||||
|
Pixels, Stateful, StatefulInteractiveElement,
|
||||||
};
|
};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
disclosure_control, h_stack, v_stack, Avatar, Icon, IconButton, IconElement, IconSize, Label,
|
disclosure_control, h_stack, v_stack, Avatar, Icon, IconButton, IconElement, IconSize, Label,
|
||||||
|
@ -117,66 +119,6 @@ impl ListHeader {
|
||||||
self.meta = meta;
|
self.meta = meta;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
// before_ship!("delete")
|
|
||||||
// fn render<V: 'static>(self, cx: &mut WindowContext) -> impl Element<V> {
|
|
||||||
// let disclosure_control = disclosure_control(self.toggle);
|
|
||||||
|
|
||||||
// let meta = match self.meta {
|
|
||||||
// Some(ListHeaderMeta::Tools(icons)) => div().child(
|
|
||||||
// h_stack()
|
|
||||||
// .gap_2()
|
|
||||||
// .items_center()
|
|
||||||
// .children(icons.into_iter().map(|i| {
|
|
||||||
// IconElement::new(i)
|
|
||||||
// .color(TextColor::Muted)
|
|
||||||
// .size(IconSize::Small)
|
|
||||||
// })),
|
|
||||||
// ),
|
|
||||||
// Some(ListHeaderMeta::Button(label)) => div().child(label),
|
|
||||||
// Some(ListHeaderMeta::Text(label)) => div().child(label),
|
|
||||||
// None => div(),
|
|
||||||
// };
|
|
||||||
|
|
||||||
// h_stack()
|
|
||||||
// .w_full()
|
|
||||||
// .bg(cx.theme().colors().surface_background)
|
|
||||||
// // TODO: Add focus state
|
|
||||||
// // .when(self.state == InteractionState::Focused, |this| {
|
|
||||||
// // this.border()
|
|
||||||
// // .border_color(cx.theme().colors().border_focused)
|
|
||||||
// // })
|
|
||||||
// .relative()
|
|
||||||
// .child(
|
|
||||||
// div()
|
|
||||||
// .h_5()
|
|
||||||
// .when(self.variant == ListItemVariant::Inset, |this| this.px_2())
|
|
||||||
// .flex()
|
|
||||||
// .flex_1()
|
|
||||||
// .items_center()
|
|
||||||
// .justify_between()
|
|
||||||
// .w_full()
|
|
||||||
// .gap_1()
|
|
||||||
// .child(
|
|
||||||
// h_stack()
|
|
||||||
// .gap_1()
|
|
||||||
// .child(
|
|
||||||
// div()
|
|
||||||
// .flex()
|
|
||||||
// .gap_1()
|
|
||||||
// .items_center()
|
|
||||||
// .children(self.left_icon.map(|i| {
|
|
||||||
// IconElement::new(i)
|
|
||||||
// .color(TextColor::Muted)
|
|
||||||
// .size(IconSize::Small)
|
|
||||||
// }))
|
|
||||||
// .child(Label::new(self.label.clone()).color(TextColor::Muted)),
|
|
||||||
// )
|
|
||||||
// .child(disclosure_control),
|
|
||||||
// )
|
|
||||||
// .child(meta),
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(IntoElement, Clone)]
|
#[derive(IntoElement, Clone)]
|
||||||
|
@ -231,26 +173,21 @@ impl RenderOnce for ListSubHeader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, PartialEq, Copy, Clone)]
|
|
||||||
pub enum ListEntrySize {
|
|
||||||
#[default]
|
|
||||||
Small,
|
|
||||||
Medium,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(IntoElement)]
|
#[derive(IntoElement)]
|
||||||
pub struct ListItem {
|
pub struct ListItem {
|
||||||
id: ElementId,
|
id: ElementId,
|
||||||
disabled: bool,
|
disabled: bool,
|
||||||
|
selected: bool,
|
||||||
// TODO: Reintroduce this
|
// TODO: Reintroduce this
|
||||||
// disclosure_control_style: DisclosureControlVisibility,
|
// disclosure_control_style: DisclosureControlVisibility,
|
||||||
indent_level: u32,
|
indent_level: usize,
|
||||||
|
indent_step_size: Pixels,
|
||||||
left_slot: Option<GraphicSlot>,
|
left_slot: Option<GraphicSlot>,
|
||||||
overflow: OverflowStyle,
|
overflow: OverflowStyle,
|
||||||
size: ListEntrySize,
|
|
||||||
toggle: Toggle,
|
toggle: Toggle,
|
||||||
variant: ListItemVariant,
|
variant: ListItemVariant,
|
||||||
on_click: Option<Rc<dyn Fn(&MouseDownEvent, &mut WindowContext) + 'static>>,
|
on_click: Option<Rc<dyn Fn(&ClickEvent, &mut WindowContext) + 'static>>,
|
||||||
|
on_secondary_mouse_down: Option<Rc<dyn Fn(&MouseDownEvent, &mut WindowContext) + 'static>>,
|
||||||
children: SmallVec<[AnyElement; 2]>,
|
children: SmallVec<[AnyElement; 2]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,22 +196,29 @@ impl ListItem {
|
||||||
Self {
|
Self {
|
||||||
id: id.into(),
|
id: id.into(),
|
||||||
disabled: false,
|
disabled: false,
|
||||||
|
selected: false,
|
||||||
indent_level: 0,
|
indent_level: 0,
|
||||||
|
indent_step_size: px(12.),
|
||||||
left_slot: None,
|
left_slot: None,
|
||||||
overflow: OverflowStyle::Hidden,
|
overflow: OverflowStyle::Hidden,
|
||||||
size: ListEntrySize::default(),
|
|
||||||
toggle: Toggle::NotToggleable,
|
toggle: Toggle::NotToggleable,
|
||||||
variant: ListItemVariant::default(),
|
variant: ListItemVariant::default(),
|
||||||
on_click: Default::default(),
|
on_click: None,
|
||||||
|
on_secondary_mouse_down: None,
|
||||||
children: SmallVec::new(),
|
children: SmallVec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_click(
|
pub fn on_click(mut self, handler: impl Fn(&ClickEvent, &mut WindowContext) + 'static) -> Self {
|
||||||
|
self.on_click = Some(Rc::new(handler));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn on_secondary_mouse_down(
|
||||||
mut self,
|
mut self,
|
||||||
handler: impl Fn(&MouseDownEvent, &mut WindowContext) + 'static,
|
handler: impl Fn(&MouseDownEvent, &mut WindowContext) + 'static,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
self.on_click = Some(Rc::new(handler));
|
self.on_secondary_mouse_down = Some(Rc::new(handler));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,16 +227,26 @@ impl ListItem {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn indent_level(mut self, indent_level: u32) -> Self {
|
pub fn indent_level(mut self, indent_level: usize) -> Self {
|
||||||
self.indent_level = indent_level;
|
self.indent_level = indent_level;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn indent_step_size(mut self, indent_step_size: Pixels) -> Self {
|
||||||
|
self.indent_step_size = indent_step_size;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn toggle(mut self, toggle: Toggle) -> Self {
|
pub fn toggle(mut self, toggle: Toggle) -> Self {
|
||||||
self.toggle = toggle;
|
self.toggle = toggle;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn selected(mut self, selected: bool) -> Self {
|
||||||
|
self.selected = selected;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn left_content(mut self, left_content: GraphicSlot) -> Self {
|
pub fn left_content(mut self, left_content: GraphicSlot) -> Self {
|
||||||
self.left_slot = Some(left_content);
|
self.left_slot = Some(left_content);
|
||||||
self
|
self
|
||||||
|
@ -307,11 +261,6 @@ impl ListItem {
|
||||||
self.left_slot = Some(GraphicSlot::Avatar(left_avatar.into()));
|
self.left_slot = Some(GraphicSlot::Avatar(left_avatar.into()));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn size(mut self, size: ListEntrySize) -> Self {
|
|
||||||
self.size = size;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RenderOnce for ListItem {
|
impl RenderOnce for ListItem {
|
||||||
|
@ -331,42 +280,32 @@ impl RenderOnce for ListItem {
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let sized_item = match self.size {
|
|
||||||
ListEntrySize::Small => div().h_6(),
|
|
||||||
ListEntrySize::Medium => div().h_7(),
|
|
||||||
};
|
|
||||||
div()
|
div()
|
||||||
.id(self.id)
|
.id(self.id)
|
||||||
.relative()
|
.relative()
|
||||||
.bg(cx.theme().colors().editor_background.clone())
|
.hover(|mut style| {
|
||||||
// .hover(|mut style| {
|
style.background = Some(cx.theme().colors().editor_background.into());
|
||||||
// style.background = Some(cx.theme().colors().editor_background.into());
|
style
|
||||||
// style
|
})
|
||||||
// })
|
|
||||||
// TODO: Add focus state
|
// TODO: Add focus state
|
||||||
// .when(self.state == InteractionState::Focused, |this| {
|
// .when(self.state == InteractionState::Focused, |this| {
|
||||||
// this.border()
|
// this.border()
|
||||||
// .border_color(cx.theme().colors().border_focused)
|
// .border_color(cx.theme().colors().border_focused)
|
||||||
// })
|
// })
|
||||||
//.hover(|style| style.bg(cx.theme().colors().ghost_element_hover))
|
.hover(|style| style.bg(cx.theme().colors().ghost_element_hover))
|
||||||
//.active(|style| style.bg(cx.theme().colors().ghost_element_active))
|
.active(|style| style.bg(cx.theme().colors().ghost_element_active))
|
||||||
|
.when(self.selected, |this| {
|
||||||
|
this.bg(cx.theme().colors().ghost_element_selected)
|
||||||
|
})
|
||||||
|
.when_some(self.on_secondary_mouse_down, |this, on_mouse_down| {
|
||||||
|
this.on_mouse_down(MouseButton::Right, move |event, cx| {
|
||||||
|
(on_mouse_down)(event, cx)
|
||||||
|
})
|
||||||
|
})
|
||||||
.child(
|
.child(
|
||||||
sized_item
|
div()
|
||||||
.when(self.variant == ListItemVariant::Inset, |this| this.px_2())
|
.when(self.variant == ListItemVariant::Inset, |this| this.px_2())
|
||||||
// .ml(rems(0.75 * self.indent_level as f32))
|
.ml(self.indent_level as f32 * self.indent_step_size)
|
||||||
.children((0..self.indent_level).map(|_| {
|
|
||||||
div()
|
|
||||||
.w(px(4.))
|
|
||||||
.h_full()
|
|
||||||
.flex()
|
|
||||||
.justify_center()
|
|
||||||
.group_hover("", |style| style.bg(cx.theme().colors().border_focused))
|
|
||||||
.child(
|
|
||||||
h_stack()
|
|
||||||
.child(div().w_px().h_full())
|
|
||||||
.child(div().w_px().h_full().bg(cx.theme().colors().border)),
|
|
||||||
)
|
|
||||||
}))
|
|
||||||
.flex()
|
.flex()
|
||||||
.gap_1()
|
.gap_1()
|
||||||
.items_center()
|
.items_center()
|
||||||
|
@ -374,13 +313,19 @@ impl RenderOnce for ListItem {
|
||||||
.child(disclosure_control(self.toggle))
|
.child(disclosure_control(self.toggle))
|
||||||
.children(left_content)
|
.children(left_content)
|
||||||
.children(self.children)
|
.children(self.children)
|
||||||
.on_mouse_down(MouseButton::Left, {
|
// HACK: We need to attach the `on_click` handler to the child element in order to have the click
|
||||||
let on_click = self.on_click.clone();
|
// event actually fire.
|
||||||
move |event, cx| {
|
// Once this is fixed in GPUI we can remove this and rely on the `on_click` handler set above on the
|
||||||
if let Some(on_click) = &on_click {
|
// outer `div`.
|
||||||
|
.id("on_click_hack")
|
||||||
|
.when_some(self.on_click, |this, on_click| {
|
||||||
|
this.on_click(move |event, cx| {
|
||||||
|
// HACK: GPUI currently fires `on_click` with any mouse button,
|
||||||
|
// but we only care about the left button.
|
||||||
|
if event.down.button == MouseButton::Left {
|
||||||
(on_click)(event, cx)
|
(on_click)(event, cx)
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
use gpui::{
|
use gpui::{
|
||||||
AnyElement, Div, Element, ElementId, IntoElement, ParentElement, RenderOnce, Styled,
|
div, AnyElement, Div, Element, ElementId, IntoElement, ParentElement, RenderOnce, Styled,
|
||||||
WindowContext,
|
WindowContext,
|
||||||
};
|
};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
use theme2::ActiveTheme;
|
||||||
|
|
||||||
use crate::{v_stack, StyledExt};
|
use crate::{v_stack, StyledExt};
|
||||||
|
|
||||||
|
@ -43,22 +44,16 @@ impl RenderOnce for Popover {
|
||||||
type Rendered = Div;
|
type Rendered = Div;
|
||||||
|
|
||||||
fn render(self, cx: &mut WindowContext) -> Self::Rendered {
|
fn render(self, cx: &mut WindowContext) -> Self::Rendered {
|
||||||
v_stack()
|
div()
|
||||||
.relative()
|
.flex()
|
||||||
.elevation_2(cx)
|
.gap_1()
|
||||||
.p_1()
|
.child(v_stack().elevation_2(cx).px_1().children(self.children))
|
||||||
.children(self.children)
|
|
||||||
.when_some(self.aside, |this, aside| {
|
.when_some(self.aside, |this, aside| {
|
||||||
// TODO: This will statically position the aside to the top right of the popover.
|
|
||||||
// We should update this to use gpui2::overlay avoid collisions with the window edges.
|
|
||||||
this.child(
|
this.child(
|
||||||
v_stack()
|
v_stack()
|
||||||
.top_0()
|
|
||||||
.left_full()
|
|
||||||
.ml_1()
|
|
||||||
.absolute()
|
|
||||||
.elevation_2(cx)
|
.elevation_2(cx)
|
||||||
.p_1()
|
.bg(cx.theme().colors().surface_background)
|
||||||
|
.px_1()
|
||||||
.child(aside),
|
.child(aside),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
|
@ -22,5 +22,13 @@ impl Render for ListItemStory {
|
||||||
println!("Clicked!");
|
println!("Clicked!");
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
.child(Story::label("With `on_secondary_mouse_down`"))
|
||||||
|
.child(
|
||||||
|
ListItem::new("with_on_secondary_mouse_down").on_secondary_mouse_down(
|
||||||
|
|_event, _cx| {
|
||||||
|
println!("Right mouse down!");
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use gpui::{Styled, WindowContext};
|
use gpui::{px, Styled, WindowContext};
|
||||||
use theme2::ActiveTheme;
|
use theme2::ActiveTheme;
|
||||||
|
|
||||||
use crate::{ElevationIndex, UITextSize};
|
use crate::{ElevationIndex, UITextSize};
|
||||||
|
@ -6,7 +6,7 @@ use crate::{ElevationIndex, UITextSize};
|
||||||
fn elevated<E: Styled>(this: E, cx: &mut WindowContext, index: ElevationIndex) -> E {
|
fn elevated<E: Styled>(this: E, cx: &mut WindowContext, index: ElevationIndex) -> E {
|
||||||
this.bg(cx.theme().colors().elevated_surface_background)
|
this.bg(cx.theme().colors().elevated_surface_background)
|
||||||
.z_index(index.z_index())
|
.z_index(index.z_index())
|
||||||
.rounded_lg()
|
.rounded(px(8.))
|
||||||
.border()
|
.border()
|
||||||
.border_color(cx.theme().colors().border_variant)
|
.border_color(cx.theme().colors().border_variant)
|
||||||
.shadow(index.shadow())
|
.shadow(index.shadow())
|
||||||
|
|
|
@ -56,14 +56,16 @@ use std::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
notifications::{simple_message_notification::MessageNotification, NotificationTracker},
|
notifications::NotificationTracker,
|
||||||
persistence::model::{
|
persistence::model::{
|
||||||
DockData, DockStructure, SerializedPane, SerializedPaneGroup, SerializedWorkspace,
|
DockData, DockStructure, SerializedPane, SerializedPaneGroup, SerializedWorkspace,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use dock::{Dock, DockPosition, Panel, PanelButtons, PanelHandle};
|
use dock::{Dock, DockPosition, Panel, PanelButtons, PanelHandle};
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use notifications::{simple_message_notification, NotificationHandle, NotifyResultExt};
|
use notifications::{
|
||||||
|
simple_message_notification::MessageNotification, NotificationHandle, NotifyResultExt,
|
||||||
|
};
|
||||||
pub use pane::*;
|
pub use pane::*;
|
||||||
pub use pane_group::*;
|
pub use pane_group::*;
|
||||||
use persistence::{model::SerializedItem, DB};
|
use persistence::{model::SerializedItem, DB};
|
||||||
|
@ -778,20 +780,6 @@ impl Workspace {
|
||||||
|
|
||||||
cx.defer(|this, cx| {
|
cx.defer(|this, cx| {
|
||||||
this.update_window_title(cx);
|
this.update_window_title(cx);
|
||||||
|
|
||||||
this.show_notification(0, cx, |cx| {
|
|
||||||
cx.add_view(|_cx| {
|
|
||||||
simple_message_notification::MessageNotification::new(format!(
|
|
||||||
"Error: what happens if this message is very very very very very long "
|
|
||||||
))
|
|
||||||
.with_click_message("Click here because!")
|
|
||||||
})
|
|
||||||
});
|
|
||||||
this.show_notification(1, cx, |cx| {
|
|
||||||
cx.add_view(|_cx| {
|
|
||||||
simple_message_notification::MessageNotification::new(format!("Nope"))
|
|
||||||
})
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
Workspace {
|
Workspace {
|
||||||
weak_self: weak_handle.clone(),
|
weak_self: weak_handle.clone(),
|
||||||
|
|
|
@ -140,6 +140,7 @@ tree-sitter-lua.workspace = true
|
||||||
tree-sitter-nix.workspace = true
|
tree-sitter-nix.workspace = true
|
||||||
tree-sitter-nu.workspace = true
|
tree-sitter-nu.workspace = true
|
||||||
tree-sitter-vue.workspace = true
|
tree-sitter-vue.workspace = true
|
||||||
|
tree-sitter-uiua.workspace = true
|
||||||
|
|
||||||
url = "2.2"
|
url = "2.2"
|
||||||
urlencoding = "2.1.2"
|
urlencoding = "2.1.2"
|
||||||
|
|
|
@ -17,6 +17,7 @@ mod json;
|
||||||
#[cfg(feature = "plugin_runtime")]
|
#[cfg(feature = "plugin_runtime")]
|
||||||
mod language_plugin;
|
mod language_plugin;
|
||||||
mod lua;
|
mod lua;
|
||||||
|
mod nu;
|
||||||
mod php;
|
mod php;
|
||||||
mod python;
|
mod python;
|
||||||
mod ruby;
|
mod ruby;
|
||||||
|
@ -24,6 +25,7 @@ mod rust;
|
||||||
mod svelte;
|
mod svelte;
|
||||||
mod tailwind;
|
mod tailwind;
|
||||||
mod typescript;
|
mod typescript;
|
||||||
|
mod uiua;
|
||||||
mod vue;
|
mod vue;
|
||||||
mod yaml;
|
mod yaml;
|
||||||
|
|
||||||
|
@ -210,12 +212,21 @@ pub fn init(
|
||||||
language("elm", tree_sitter_elm::language(), vec![]);
|
language("elm", tree_sitter_elm::language(), vec![]);
|
||||||
language("glsl", tree_sitter_glsl::language(), vec![]);
|
language("glsl", tree_sitter_glsl::language(), vec![]);
|
||||||
language("nix", tree_sitter_nix::language(), vec![]);
|
language("nix", tree_sitter_nix::language(), vec![]);
|
||||||
language("nu", tree_sitter_nu::language(), vec![]);
|
language(
|
||||||
|
"nu",
|
||||||
|
tree_sitter_nu::language(),
|
||||||
|
vec![Arc::new(nu::NuLanguageServer {})],
|
||||||
|
);
|
||||||
language(
|
language(
|
||||||
"vue",
|
"vue",
|
||||||
tree_sitter_vue::language(),
|
tree_sitter_vue::language(),
|
||||||
vec![Arc::new(vue::VueLspAdapter::new(node_runtime))],
|
vec![Arc::new(vue::VueLspAdapter::new(node_runtime))],
|
||||||
);
|
);
|
||||||
|
language(
|
||||||
|
"uiua",
|
||||||
|
tree_sitter_uiua::language(),
|
||||||
|
vec![Arc::new(uiua::UiuaLanguageServer {})],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(test, feature = "test-support"))]
|
#[cfg(any(test, feature = "test-support"))]
|
||||||
|
|
|
@ -18,10 +18,10 @@
|
||||||
target: (identifier) @name)
|
target: (identifier) @name)
|
||||||
operator: "when")
|
operator: "when")
|
||||||
])
|
])
|
||||||
(#match? @name "^(def|defp|defdelegate|defguard|defguardp|defmacro|defmacrop|defn|defnp)$")) @item
|
(#any-match? @name "^(def|defp|defdelegate|defguard|defguardp|defmacro|defmacrop|defn|defnp)$")) @item
|
||||||
)
|
)
|
||||||
|
|
||||||
(call
|
(call
|
||||||
target: (identifier) @name
|
target: (identifier) @name
|
||||||
(arguments (alias) @name)
|
(arguments (alias) @name)
|
||||||
(#match? @name "^(defmodule|defprotocol)$")) @item
|
(#any-match? @name "^(defmodule|defprotocol)$")) @item
|
||||||
|
|
81
crates/zed/src/languages/nu.rs
Normal file
81
crates/zed/src/languages/nu.rs
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
use anyhow::{anyhow, Result};
|
||||||
|
use async_trait::async_trait;
|
||||||
|
use language::{CodeLabel, Language, LanguageServerName, LspAdapter, LspAdapterDelegate};
|
||||||
|
use lsp::LanguageServerBinary;
|
||||||
|
use std::{any::Any, path::PathBuf, sync::Arc};
|
||||||
|
|
||||||
|
pub struct NuLanguageServer;
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl LspAdapter for NuLanguageServer {
|
||||||
|
async fn name(&self) -> LanguageServerName {
|
||||||
|
LanguageServerName("nu".into())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn short_name(&self) -> &'static str {
|
||||||
|
"nu"
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn fetch_latest_server_version(
|
||||||
|
&self,
|
||||||
|
_: &dyn LspAdapterDelegate,
|
||||||
|
) -> Result<Box<dyn 'static + Any + Send>> {
|
||||||
|
Ok(Box::new(()))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn fetch_server_binary(
|
||||||
|
&self,
|
||||||
|
_version: Box<dyn 'static + Send + Any>,
|
||||||
|
_container_dir: PathBuf,
|
||||||
|
_: &dyn LspAdapterDelegate,
|
||||||
|
) -> Result<LanguageServerBinary> {
|
||||||
|
Err(anyhow!(
|
||||||
|
"nu v0.87.0 or greater must be installed and available in your $PATH"
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn cached_server_binary(
|
||||||
|
&self,
|
||||||
|
_: PathBuf,
|
||||||
|
_: &dyn LspAdapterDelegate,
|
||||||
|
) -> Option<LanguageServerBinary> {
|
||||||
|
Some(LanguageServerBinary {
|
||||||
|
path: "nu".into(),
|
||||||
|
arguments: vec!["--lsp".into()],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn can_be_reinstalled(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn installation_test_binary(&self, _: PathBuf) -> Option<LanguageServerBinary> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn label_for_completion(
|
||||||
|
&self,
|
||||||
|
completion: &lsp::CompletionItem,
|
||||||
|
language: &Arc<Language>,
|
||||||
|
) -> Option<CodeLabel> {
|
||||||
|
return Some(CodeLabel {
|
||||||
|
runs: language
|
||||||
|
.highlight_text(&completion.label.clone().into(), 0..completion.label.len()),
|
||||||
|
text: completion.label.clone(),
|
||||||
|
filter_range: 0..completion.label.len(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn label_for_symbol(
|
||||||
|
&self,
|
||||||
|
name: &str,
|
||||||
|
_: lsp::SymbolKind,
|
||||||
|
language: &Arc<Language>,
|
||||||
|
) -> Option<CodeLabel> {
|
||||||
|
Some(CodeLabel {
|
||||||
|
runs: language.highlight_text(&name.into(), 0..name.len()),
|
||||||
|
text: name.to_string(),
|
||||||
|
filter_range: 0..name.len(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
55
crates/zed/src/languages/uiua.rs
Normal file
55
crates/zed/src/languages/uiua.rs
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
use anyhow::{anyhow, Result};
|
||||||
|
use async_trait::async_trait;
|
||||||
|
use language::{LanguageServerName, LspAdapter, LspAdapterDelegate};
|
||||||
|
use lsp::LanguageServerBinary;
|
||||||
|
use std::{any::Any, path::PathBuf};
|
||||||
|
|
||||||
|
pub struct UiuaLanguageServer;
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl LspAdapter for UiuaLanguageServer {
|
||||||
|
async fn name(&self) -> LanguageServerName {
|
||||||
|
LanguageServerName("uiua".into())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn short_name(&self) -> &'static str {
|
||||||
|
"uiua"
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn fetch_latest_server_version(
|
||||||
|
&self,
|
||||||
|
_: &dyn LspAdapterDelegate,
|
||||||
|
) -> Result<Box<dyn 'static + Any + Send>> {
|
||||||
|
Ok(Box::new(()))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn fetch_server_binary(
|
||||||
|
&self,
|
||||||
|
_version: Box<dyn 'static + Send + Any>,
|
||||||
|
_container_dir: PathBuf,
|
||||||
|
_: &dyn LspAdapterDelegate,
|
||||||
|
) -> Result<LanguageServerBinary> {
|
||||||
|
Err(anyhow!(
|
||||||
|
"uiua must be installed and available in your $PATH"
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn cached_server_binary(
|
||||||
|
&self,
|
||||||
|
_: PathBuf,
|
||||||
|
_: &dyn LspAdapterDelegate,
|
||||||
|
) -> Option<LanguageServerBinary> {
|
||||||
|
Some(LanguageServerBinary {
|
||||||
|
path: "uiua".into(),
|
||||||
|
arguments: vec!["lsp".into()],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn can_be_reinstalled(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn installation_test_binary(&self, _: PathBuf) -> Option<LanguageServerBinary> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
10
crates/zed/src/languages/uiua/config.toml
Normal file
10
crates/zed/src/languages/uiua/config.toml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
name = "Uiua"
|
||||||
|
path_suffixes = ["ua"]
|
||||||
|
line_comment = "# "
|
||||||
|
autoclose_before = ")]}\""
|
||||||
|
brackets = [
|
||||||
|
{ start = "{", end = "}", close = true, newline = false },
|
||||||
|
{ start = "[", end = "]", close = true, newline = false },
|
||||||
|
{ start = "(", end = ")", close = true, newline = false },
|
||||||
|
{ start = "\"", end = "\"", close = true, newline = false, not_in = ["string"] },
|
||||||
|
]
|
50
crates/zed/src/languages/uiua/highlights.scm
Normal file
50
crates/zed/src/languages/uiua/highlights.scm
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
[
|
||||||
|
(openParen)
|
||||||
|
(closeParen)
|
||||||
|
(openCurly)
|
||||||
|
(closeCurly)
|
||||||
|
(openBracket)
|
||||||
|
(closeBracket)
|
||||||
|
] @punctuation.bracket
|
||||||
|
|
||||||
|
[
|
||||||
|
(branchSeparator)
|
||||||
|
(underscore)
|
||||||
|
] @constructor
|
||||||
|
; ] @punctuation.delimiter
|
||||||
|
|
||||||
|
[ (character) ] @constant.character
|
||||||
|
[ (comment) ] @comment
|
||||||
|
[ (constant) ] @constant.numeric
|
||||||
|
[ (identifier) ] @variable
|
||||||
|
[ (leftArrow) ] @keyword
|
||||||
|
[ (function) ] @function
|
||||||
|
[ (modifier1) ] @operator
|
||||||
|
[ (modifier2) ] @operator
|
||||||
|
[ (number) ] @constant.numeric
|
||||||
|
[ (placeHolder) ] @special
|
||||||
|
[ (otherConstant) ] @string.special
|
||||||
|
[ (signature) ] @type
|
||||||
|
[ (system) ] @function.builtin
|
||||||
|
[ (tripleMinus) ] @module
|
||||||
|
|
||||||
|
; planet
|
||||||
|
[
|
||||||
|
"id"
|
||||||
|
"identity"
|
||||||
|
"∘"
|
||||||
|
"dip"
|
||||||
|
"⊙"
|
||||||
|
"gap"
|
||||||
|
"⋅"
|
||||||
|
] @tag
|
||||||
|
|
||||||
|
[
|
||||||
|
(string)
|
||||||
|
(multiLineString)
|
||||||
|
] @string
|
||||||
|
|
||||||
|
; [
|
||||||
|
; (deprecated)
|
||||||
|
; (identifierDeprecated)
|
||||||
|
; ] @warning
|
3
crates/zed/src/languages/uiua/indents.scm
Normal file
3
crates/zed/src/languages/uiua/indents.scm
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
[
|
||||||
|
(array)
|
||||||
|
] @indent
|
|
@ -136,6 +136,7 @@ tree-sitter-lua.workspace = true
|
||||||
tree-sitter-nix.workspace = true
|
tree-sitter-nix.workspace = true
|
||||||
tree-sitter-nu.workspace = true
|
tree-sitter-nu.workspace = true
|
||||||
tree-sitter-vue.workspace = true
|
tree-sitter-vue.workspace = true
|
||||||
|
tree-sitter-uiua.workspace = true
|
||||||
|
|
||||||
url = "2.2"
|
url = "2.2"
|
||||||
urlencoding = "2.1.2"
|
urlencoding = "2.1.2"
|
||||||
|
|
|
@ -18,6 +18,7 @@ mod json;
|
||||||
#[cfg(feature = "plugin_runtime")]
|
#[cfg(feature = "plugin_runtime")]
|
||||||
mod language_plugin;
|
mod language_plugin;
|
||||||
mod lua;
|
mod lua;
|
||||||
|
mod nu;
|
||||||
mod php;
|
mod php;
|
||||||
mod python;
|
mod python;
|
||||||
mod ruby;
|
mod ruby;
|
||||||
|
@ -25,6 +26,7 @@ mod rust;
|
||||||
mod svelte;
|
mod svelte;
|
||||||
mod tailwind;
|
mod tailwind;
|
||||||
mod typescript;
|
mod typescript;
|
||||||
|
mod uiua;
|
||||||
mod vue;
|
mod vue;
|
||||||
mod yaml;
|
mod yaml;
|
||||||
|
|
||||||
|
@ -211,12 +213,21 @@ pub fn init(
|
||||||
language("elm", tree_sitter_elm::language(), vec![]);
|
language("elm", tree_sitter_elm::language(), vec![]);
|
||||||
language("glsl", tree_sitter_glsl::language(), vec![]);
|
language("glsl", tree_sitter_glsl::language(), vec![]);
|
||||||
language("nix", tree_sitter_nix::language(), vec![]);
|
language("nix", tree_sitter_nix::language(), vec![]);
|
||||||
language("nu", tree_sitter_nu::language(), vec![]);
|
language(
|
||||||
|
"nu",
|
||||||
|
tree_sitter_nu::language(),
|
||||||
|
vec![Arc::new(nu::NuLanguageServer {})],
|
||||||
|
);
|
||||||
language(
|
language(
|
||||||
"vue",
|
"vue",
|
||||||
tree_sitter_vue::language(),
|
tree_sitter_vue::language(),
|
||||||
vec![Arc::new(vue::VueLspAdapter::new(node_runtime))],
|
vec![Arc::new(vue::VueLspAdapter::new(node_runtime))],
|
||||||
);
|
);
|
||||||
|
language(
|
||||||
|
"uiua",
|
||||||
|
tree_sitter_uiua::language(),
|
||||||
|
vec![Arc::new(uiua::UiuaLanguageServer {})],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(test, feature = "test-support"))]
|
#[cfg(any(test, feature = "test-support"))]
|
||||||
|
|
55
crates/zed2/src/languages/nu.rs
Normal file
55
crates/zed2/src/languages/nu.rs
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
use anyhow::{anyhow, Result};
|
||||||
|
use async_trait::async_trait;
|
||||||
|
use language::{LanguageServerName, LspAdapter, LspAdapterDelegate};
|
||||||
|
use lsp::LanguageServerBinary;
|
||||||
|
use std::{any::Any, path::PathBuf};
|
||||||
|
|
||||||
|
pub struct NuLanguageServer;
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl LspAdapter for NuLanguageServer {
|
||||||
|
async fn name(&self) -> LanguageServerName {
|
||||||
|
LanguageServerName("nu".into())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn short_name(&self) -> &'static str {
|
||||||
|
"nu"
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn fetch_latest_server_version(
|
||||||
|
&self,
|
||||||
|
_: &dyn LspAdapterDelegate,
|
||||||
|
) -> Result<Box<dyn 'static + Any + Send>> {
|
||||||
|
Ok(Box::new(()))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn fetch_server_binary(
|
||||||
|
&self,
|
||||||
|
_version: Box<dyn 'static + Send + Any>,
|
||||||
|
_container_dir: PathBuf,
|
||||||
|
_: &dyn LspAdapterDelegate,
|
||||||
|
) -> Result<LanguageServerBinary> {
|
||||||
|
Err(anyhow!(
|
||||||
|
"nu v0.87.0 or greater must be installed and available in your $PATH"
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn cached_server_binary(
|
||||||
|
&self,
|
||||||
|
_: PathBuf,
|
||||||
|
_: &dyn LspAdapterDelegate,
|
||||||
|
) -> Option<LanguageServerBinary> {
|
||||||
|
Some(LanguageServerBinary {
|
||||||
|
path: "nu".into(),
|
||||||
|
arguments: vec!["--lsp".into()],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn can_be_reinstalled(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn installation_test_binary(&self, _: PathBuf) -> Option<LanguageServerBinary> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
55
crates/zed2/src/languages/uiua.rs
Normal file
55
crates/zed2/src/languages/uiua.rs
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
use anyhow::{anyhow, Result};
|
||||||
|
use async_trait::async_trait;
|
||||||
|
use language::{LanguageServerName, LspAdapter, LspAdapterDelegate};
|
||||||
|
use lsp::LanguageServerBinary;
|
||||||
|
use std::{any::Any, path::PathBuf};
|
||||||
|
|
||||||
|
pub struct UiuaLanguageServer;
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl LspAdapter for UiuaLanguageServer {
|
||||||
|
async fn name(&self) -> LanguageServerName {
|
||||||
|
LanguageServerName("uiua".into())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn short_name(&self) -> &'static str {
|
||||||
|
"uiua"
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn fetch_latest_server_version(
|
||||||
|
&self,
|
||||||
|
_: &dyn LspAdapterDelegate,
|
||||||
|
) -> Result<Box<dyn 'static + Any + Send>> {
|
||||||
|
Ok(Box::new(()))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn fetch_server_binary(
|
||||||
|
&self,
|
||||||
|
_version: Box<dyn 'static + Send + Any>,
|
||||||
|
_container_dir: PathBuf,
|
||||||
|
_: &dyn LspAdapterDelegate,
|
||||||
|
) -> Result<LanguageServerBinary> {
|
||||||
|
Err(anyhow!(
|
||||||
|
"uiua must be installed and available in your $PATH"
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn cached_server_binary(
|
||||||
|
&self,
|
||||||
|
_: PathBuf,
|
||||||
|
_: &dyn LspAdapterDelegate,
|
||||||
|
) -> Option<LanguageServerBinary> {
|
||||||
|
Some(LanguageServerBinary {
|
||||||
|
path: "uiua".into(),
|
||||||
|
arguments: vec!["lsp".into()],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn can_be_reinstalled(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn installation_test_binary(&self, _: PathBuf) -> Option<LanguageServerBinary> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
10
crates/zed2/src/languages/uiua/config.toml
Normal file
10
crates/zed2/src/languages/uiua/config.toml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
name = "Uiua"
|
||||||
|
path_suffixes = ["ua"]
|
||||||
|
line_comment = "# "
|
||||||
|
autoclose_before = ")]}\""
|
||||||
|
brackets = [
|
||||||
|
{ start = "{", end = "}", close = true, newline = false},
|
||||||
|
{ start = "[", end = "]", close = true, newline = false },
|
||||||
|
{ start = "(", end = ")", close = true, newline = false },
|
||||||
|
{ start = "\"", end = "\"", close = true, newline = false, not_in = ["string"] },
|
||||||
|
]
|
50
crates/zed2/src/languages/uiua/highlights.scm
Normal file
50
crates/zed2/src/languages/uiua/highlights.scm
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
[
|
||||||
|
(openParen)
|
||||||
|
(closeParen)
|
||||||
|
(openCurly)
|
||||||
|
(closeCurly)
|
||||||
|
(openBracket)
|
||||||
|
(closeBracket)
|
||||||
|
] @punctuation.bracket
|
||||||
|
|
||||||
|
[
|
||||||
|
(branchSeparator)
|
||||||
|
(underscore)
|
||||||
|
] @constructor
|
||||||
|
; ] @punctuation.delimiter
|
||||||
|
|
||||||
|
[ (character) ] @constant.character
|
||||||
|
[ (comment) ] @comment
|
||||||
|
[ (constant) ] @constant.numeric
|
||||||
|
[ (identifier) ] @variable
|
||||||
|
[ (leftArrow) ] @keyword
|
||||||
|
[ (function) ] @function
|
||||||
|
[ (modifier1) ] @operator
|
||||||
|
[ (modifier2) ] @operator
|
||||||
|
[ (number) ] @constant.numeric
|
||||||
|
[ (placeHolder) ] @special
|
||||||
|
[ (otherConstant) ] @string.special
|
||||||
|
[ (signature) ] @type
|
||||||
|
[ (system) ] @function.builtin
|
||||||
|
[ (tripleMinus) ] @module
|
||||||
|
|
||||||
|
; planet
|
||||||
|
[
|
||||||
|
"id"
|
||||||
|
"identity"
|
||||||
|
"∘"
|
||||||
|
"dip"
|
||||||
|
"⊙"
|
||||||
|
"gap"
|
||||||
|
"⋅"
|
||||||
|
] @tag
|
||||||
|
|
||||||
|
[
|
||||||
|
(string)
|
||||||
|
(multiLineString)
|
||||||
|
] @string
|
||||||
|
|
||||||
|
; [
|
||||||
|
; (deprecated)
|
||||||
|
; (identifierDeprecated)
|
||||||
|
; ] @warning
|
3
crates/zed2/src/languages/uiua/indents.scm
Normal file
3
crates/zed2/src/languages/uiua/indents.scm
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
[
|
||||||
|
(array)
|
||||||
|
] @indent
|
Loading…
Add table
Add a link
Reference in a new issue