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]]
|
||||
name = "tree-sitter"
|
||||
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 = [
|
||||
"cc",
|
||||
"regex",
|
||||
|
@ -10178,6 +10178,15 @@ dependencies = [
|
|||
"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]]
|
||||
name = "tree-sitter-vue"
|
||||
version = "0.0.1"
|
||||
|
@ -11616,6 +11625,7 @@ dependencies = [
|
|||
"tree-sitter-svelte",
|
||||
"tree-sitter-toml",
|
||||
"tree-sitter-typescript",
|
||||
"tree-sitter-uiua",
|
||||
"tree-sitter-vue",
|
||||
"tree-sitter-yaml",
|
||||
"unindent",
|
||||
|
@ -11739,6 +11749,7 @@ dependencies = [
|
|||
"tree-sitter-svelte",
|
||||
"tree-sitter-toml",
|
||||
"tree-sitter-typescript",
|
||||
"tree-sitter-uiua",
|
||||
"tree-sitter-vue",
|
||||
"tree-sitter-yaml",
|
||||
"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-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-uiua = {git = "https://github.com/shnarazk/tree-sitter-uiua", rev = "9260f11be5900beda4ee6d1a24ab8ddfaf5a19b2"}
|
||||
|
||||
[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" }
|
||||
|
||||
# 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) {
|
||||
AutoUpdateSetting::register(cx);
|
||||
|
||||
cx.observe_new_views(|wokrspace: &mut Workspace, _cx| {
|
||||
wokrspace
|
||||
cx.observe_new_views(|workspace: &mut Workspace, _cx| {
|
||||
workspace
|
||||
.register_action(|_, action: &Check, cx| check(action, cx))
|
||||
.register_action(|_, _action: &CheckThatAutoUpdaterWorks, cx| {
|
||||
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();
|
||||
});
|
||||
|
||||
// @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();
|
||||
|
||||
|
@ -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) {
|
||||
let auto_updater = auto_updater.read(cx);
|
||||
let server_url = &auto_updater.server_url;
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
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 {
|
||||
_version: SemanticVersion,
|
||||
version: SemanticVersion,
|
||||
}
|
||||
|
||||
impl EventEmitter<DismissEvent> for UpdateNotification {}
|
||||
|
@ -12,77 +14,43 @@ impl EventEmitter<DismissEvent> for UpdateNotification {}
|
|||
impl Render for UpdateNotification {
|
||||
type Element = Div;
|
||||
|
||||
fn render(&mut self, _cx: &mut gpui::ViewContext<Self>) -> Self::Element {
|
||||
div().child("Updated zed!")
|
||||
// let theme = theme::current(cx).clone();
|
||||
// let theme = &theme.update_notification;
|
||||
fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> Self::Element {
|
||||
let app_name = cx.global::<ReleaseChannel>().display_name();
|
||||
|
||||
// let app_name = cx.global::<ReleaseChannel>().display_name();
|
||||
|
||||
// MouseEventHandler::new::<ViewReleaseNotes, _>(0, cx, |state, cx| {
|
||||
// Flex::column()
|
||||
// .with_child(
|
||||
// Flex::row()
|
||||
// .with_child(
|
||||
// Text::new(
|
||||
// format!("Updated to {app_name} {}", self.version),
|
||||
// theme.message.text.clone(),
|
||||
// )
|
||||
// .contained()
|
||||
// .with_style(theme.message.container)
|
||||
// .aligned()
|
||||
// .top()
|
||||
// .left()
|
||||
// .flex(1., true),
|
||||
// )
|
||||
// .with_child(
|
||||
// MouseEventHandler::new::<Cancel, _>(0, cx, |state, _| {
|
||||
// let style = theme.dismiss_button.style_for(state);
|
||||
// Svg::new("icons/x.svg")
|
||||
// .with_color(style.color)
|
||||
// .constrained()
|
||||
// .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")
|
||||
v_stack()
|
||||
.elevation_3(cx)
|
||||
.p_4()
|
||||
.child(
|
||||
h_stack()
|
||||
.justify_between()
|
||||
.child(Label::new(format!(
|
||||
"Updated to {app_name} {}",
|
||||
self.version
|
||||
)))
|
||||
.child(
|
||||
div()
|
||||
.id("cancel")
|
||||
.child(IconElement::new(Icon::Close))
|
||||
.cursor_pointer()
|
||||
.on_click(cx.listener(|this, _, cx| this.dismiss(cx))),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.id("notes")
|
||||
.child(Label::new("View the release notes"))
|
||||
.cursor_pointer()
|
||||
.on_click(|_, cx| crate::view_release_notes(&Default::default(), cx)),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl UpdateNotification {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -170,7 +170,7 @@ impl PickerDelegate for ContactFinderDelegate {
|
|||
ix: usize,
|
||||
selected: bool,
|
||||
cx: &mut ViewContext<Picker<Self>>,
|
||||
) -> Self::ListItem {
|
||||
) -> Option<Self::ListItem> {
|
||||
let user = &self.potential_contacts[ix];
|
||||
let request_status = self.user_store.read(cx).contact_request_status(user);
|
||||
|
||||
|
@ -182,12 +182,14 @@ impl PickerDelegate for ContactFinderDelegate {
|
|||
ContactRequestStatus::RequestAccepted => None,
|
||||
};
|
||||
dbg!(icon_path);
|
||||
div()
|
||||
.flex_1()
|
||||
.justify_between()
|
||||
.children(user.avatar.clone().map(|avatar| img().data(avatar)))
|
||||
.child(Label::new(user.github_login.clone()))
|
||||
.children(icon_path.map(|icon_path| svg().path(icon_path)))
|
||||
Some(
|
||||
div()
|
||||
.flex_1()
|
||||
.justify_between()
|
||||
.children(user.avatar.clone().map(|avatar| img().data(avatar)))
|
||||
.child(Label::new(user.github_login.clone()))
|
||||
.children(icon_path.map(|icon_path| svg().path(icon_path))),
|
||||
)
|
||||
// Flex::row()
|
||||
// .with_children(user.avatar.clone().map(|avatar| {
|
||||
// Image::from_data(avatar)
|
||||
|
|
|
@ -1,17 +1,15 @@
|
|||
use collections::{CommandPaletteFilter, HashMap};
|
||||
use fuzzy::{StringMatch, StringMatchCandidate};
|
||||
use gpui::{
|
||||
actions, div, prelude::*, Action, AppContext, DismissEvent, Div, EventEmitter, FocusHandle,
|
||||
FocusableView, Keystroke, ParentElement, Render, Styled, View, ViewContext, VisualContext,
|
||||
WeakView,
|
||||
actions, Action, AppContext, DismissEvent, Div, EventEmitter, FocusHandle, FocusableView,
|
||||
Keystroke, ParentElement, Render, Styled, View, ViewContext, VisualContext, WeakView,
|
||||
};
|
||||
use picker::{Picker, PickerDelegate};
|
||||
use std::{
|
||||
cmp::{self, Reverse},
|
||||
sync::Arc,
|
||||
};
|
||||
use theme::ActiveTheme;
|
||||
use ui::{h_stack, v_stack, HighlightedLabel, KeyBinding, StyledExt};
|
||||
use ui::{h_stack, v_stack, HighlightedLabel, KeyBinding, ListItem};
|
||||
use util::{
|
||||
channel::{parse_zed_link, ReleaseChannel, RELEASE_CHANNEL},
|
||||
ResultExt,
|
||||
|
@ -141,7 +139,7 @@ impl CommandPaletteDelegate {
|
|||
}
|
||||
|
||||
impl PickerDelegate for CommandPaletteDelegate {
|
||||
type ListItem = Div;
|
||||
type ListItem = ListItem;
|
||||
|
||||
fn placeholder_text(&self) -> Arc<str> {
|
||||
"Execute a command...".into()
|
||||
|
@ -294,24 +292,16 @@ impl PickerDelegate for CommandPaletteDelegate {
|
|||
ix: usize,
|
||||
selected: bool,
|
||||
cx: &mut ViewContext<Picker<Self>>,
|
||||
) -> Self::ListItem {
|
||||
let colors = cx.theme().colors();
|
||||
) -> Option<Self::ListItem> {
|
||||
let Some(r#match) = self.matches.get(ix) else {
|
||||
return div();
|
||||
return None;
|
||||
};
|
||||
let Some(command) = self.commands.get(r#match.candidate_id) else {
|
||||
return div();
|
||||
return None;
|
||||
};
|
||||
|
||||
div()
|
||||
.px_1()
|
||||
.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(
|
||||
Some(
|
||||
ListItem::new(ix).selected(selected).child(
|
||||
h_stack()
|
||||
.justify_between()
|
||||
.child(HighlightedLabel::new(
|
||||
|
@ -319,7 +309,8 @@ impl PickerDelegate for CommandPaletteDelegate {
|
|||
r#match.positions.clone(),
|
||||
))
|
||||
.children(KeyBinding::for_action(&*command.action, cx)),
|
||||
)
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1273,6 +1273,13 @@ impl CompletionsMenu {
|
|||
multiline_docs.map(|div| {
|
||||
div.id("multiline_docs")
|
||||
.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()
|
||||
// Prevent a mouse down on documentation from being propagated to the editor,
|
||||
// because that would move the cursor.
|
||||
|
@ -1327,13 +1334,18 @@ impl CompletionsMenu {
|
|||
|
||||
div()
|
||||
.id(mat.candidate_id)
|
||||
.min_w(px(300.))
|
||||
.max_w(px(700.))
|
||||
.min_w(px(220.))
|
||||
.max_w(px(540.))
|
||||
.whitespace_nowrap()
|
||||
.overflow_hidden()
|
||||
.bg(gpui::green())
|
||||
.hover(|style| style.bg(gpui::blue()))
|
||||
.when(item_ix == selected_item, |div| div.bg(gpui::red()))
|
||||
.text_ui()
|
||||
.px_1()
|
||||
.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(
|
||||
MouseButton::Left,
|
||||
cx.listener(move |editor, event, cx| {
|
||||
|
|
|
@ -2,9 +2,8 @@ use collections::HashMap;
|
|||
use editor::{scroll::autoscroll::Autoscroll, Bias, Editor};
|
||||
use fuzzy::{CharBag, PathMatch, PathMatchCandidate};
|
||||
use gpui::{
|
||||
actions, div, AppContext, DismissEvent, Div, EventEmitter, FocusHandle, FocusableView,
|
||||
InteractiveElement, IntoElement, Model, ParentElement, Render, Styled, Task, View, ViewContext,
|
||||
VisualContext, WeakView,
|
||||
actions, AppContext, DismissEvent, Div, EventEmitter, FocusHandle, FocusableView, Model,
|
||||
ParentElement, Render, Styled, Task, View, ViewContext, VisualContext, WeakView,
|
||||
};
|
||||
use picker::{Picker, PickerDelegate};
|
||||
use project::{PathMatchCandidateSet, Project, ProjectPath, WorktreeId};
|
||||
|
@ -16,8 +15,7 @@ use std::{
|
|||
},
|
||||
};
|
||||
use text::Point;
|
||||
use theme::ActiveTheme;
|
||||
use ui::{v_stack, HighlightedLabel, StyledExt};
|
||||
use ui::{v_stack, HighlightedLabel, ListItem};
|
||||
use util::{paths::PathLikeWithPosition, post_inc, ResultExt};
|
||||
use workspace::Workspace;
|
||||
|
||||
|
@ -530,7 +528,7 @@ impl FileFinderDelegate {
|
|||
}
|
||||
|
||||
impl PickerDelegate for FileFinderDelegate {
|
||||
type ListItem = Div;
|
||||
type ListItem = ListItem;
|
||||
|
||||
fn placeholder_text(&self) -> Arc<str> {
|
||||
"Search project files...".into()
|
||||
|
@ -711,30 +709,22 @@ impl PickerDelegate for FileFinderDelegate {
|
|||
ix: usize,
|
||||
selected: bool,
|
||||
cx: &mut ViewContext<Picker<Self>>,
|
||||
) -> Self::ListItem {
|
||||
) -> Option<Self::ListItem> {
|
||||
let path_match = self
|
||||
.matches
|
||||
.get(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) =
|
||||
self.labels_for_match(path_match, cx, ix);
|
||||
|
||||
div()
|
||||
.px_1()
|
||||
.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(
|
||||
Some(
|
||||
ListItem::new(ix).selected(selected).child(
|
||||
v_stack()
|
||||
.child(HighlightedLabel::new(file_name, file_name_positions))
|
||||
.child(HighlightedLabel::new(full_path, full_path_positions)),
|
||||
)
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -105,6 +105,7 @@ impl Element for Overlay {
|
|||
origin: Point::zero(),
|
||||
size: cx.viewport_size(),
|
||||
};
|
||||
dbg!(limits);
|
||||
|
||||
match self.fit_mode {
|
||||
OverlayFitMode::SnapToWindow => {
|
||||
|
|
|
@ -11,7 +11,7 @@ pub struct HighlightId(pub u32);
|
|||
const DEFAULT_SYNTAX_HIGHLIGHT_ID: HighlightId = HighlightId(u32::MAX);
|
||||
|
||||
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
|
||||
// key in the theme's syntax styles that matches all of the
|
||||
// dot-separated components of the capture name.
|
||||
|
@ -98,9 +98,9 @@ mod tests {
|
|||
);
|
||||
|
||||
let capture_names = &[
|
||||
"function.special".to_string(),
|
||||
"function.async.rust".to_string(),
|
||||
"variable.builtin.self".to_string(),
|
||||
"function.special",
|
||||
"function.async.rust",
|
||||
"variable.builtin.self",
|
||||
];
|
||||
|
||||
let map = HighlightMap::new(capture_names, &theme);
|
||||
|
|
|
@ -1383,7 +1383,7 @@ impl Language {
|
|||
let query = Query::new(self.grammar_mut().ts_language, source)?;
|
||||
|
||||
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('_') {
|
||||
let value = self.config.overrides.remove(name).unwrap_or_default();
|
||||
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<_>>();
|
||||
for capture in captures {
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ pub struct HighlightId(pub u32);
|
|||
const DEFAULT_SYNTAX_HIGHLIGHT_ID: HighlightId = HighlightId(u32::MAX);
|
||||
|
||||
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
|
||||
// key in the theme's syntax styles that matches all of the
|
||||
// dot-separated components of the capture name.
|
||||
|
@ -100,9 +100,9 @@ mod tests {
|
|||
};
|
||||
|
||||
let capture_names = &[
|
||||
"function.special".to_string(),
|
||||
"function.async.rust".to_string(),
|
||||
"variable.builtin.self".to_string(),
|
||||
"function.special",
|
||||
"function.async.rust",
|
||||
"variable.builtin.self",
|
||||
];
|
||||
|
||||
let map = HighlightMap::new(capture_names, &theme);
|
||||
|
|
|
@ -1391,7 +1391,7 @@ impl Language {
|
|||
let mut override_configs_by_id = HashMap::default();
|
||||
for (ix, name) in query.capture_names().iter().enumerate() {
|
||||
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 {
|
||||
if !self
|
||||
.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<_>>();
|
||||
for capture in captures {
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,6 +73,7 @@ impl RealNodeRuntime {
|
|||
let npm_file = node_dir.join("bin/npm");
|
||||
|
||||
let result = Command::new(&node_binary)
|
||||
.env_clear()
|
||||
.arg(npm_file)
|
||||
.arg("--version")
|
||||
.stdin(Stdio::null())
|
||||
|
@ -149,6 +150,7 @@ impl NodeRuntime for RealNodeRuntime {
|
|||
}
|
||||
|
||||
let mut command = Command::new(node_binary);
|
||||
command.env_clear();
|
||||
command.env("PATH", env_path);
|
||||
command.arg(npm_file).arg(subcommand);
|
||||
command.args(["--cache".into(), installation_path.join("cache")]);
|
||||
|
@ -200,11 +202,11 @@ impl NodeRuntime for RealNodeRuntime {
|
|||
&[
|
||||
name,
|
||||
"--json",
|
||||
"-fetch-retry-mintimeout",
|
||||
"--fetch-retry-mintimeout",
|
||||
"2000",
|
||||
"-fetch-retry-maxtimeout",
|
||||
"--fetch-retry-maxtimeout",
|
||||
"5000",
|
||||
"-fetch-timeout",
|
||||
"--fetch-timeout",
|
||||
"5000",
|
||||
],
|
||||
)
|
||||
|
@ -229,11 +231,11 @@ impl NodeRuntime for RealNodeRuntime {
|
|||
|
||||
let mut arguments: Vec<_> = packages.iter().map(|p| p.as_str()).collect();
|
||||
arguments.extend_from_slice(&[
|
||||
"-fetch-retry-mintimeout",
|
||||
"--fetch-retry-mintimeout",
|
||||
"2000",
|
||||
"-fetch-retry-maxtimeout",
|
||||
"--fetch-retry-maxtimeout",
|
||||
"5000",
|
||||
"-fetch-timeout",
|
||||
"--fetch-timeout",
|
||||
"5000",
|
||||
]);
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ pub trait PickerDelegate: Sized + 'static {
|
|||
ix: usize,
|
||||
selected: bool,
|
||||
cx: &mut ViewContext<Picker<Self>>,
|
||||
) -> Self::ListItem;
|
||||
) -> Option<Self::ListItem>;
|
||||
}
|
||||
|
||||
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 == selected_index,
|
||||
cx,
|
||||
|
|
|
@ -10,9 +10,8 @@ use anyhow::{anyhow, Result};
|
|||
use gpui::{
|
||||
actions, div, px, uniform_list, Action, AppContext, AssetSource, AsyncWindowContext,
|
||||
ClipboardItem, Div, EventEmitter, FocusHandle, Focusable, FocusableView, InteractiveElement,
|
||||
IntoElement, Model, MouseButton, MouseDownEvent, ParentElement, Pixels, Point, PromptLevel,
|
||||
Render, Stateful, StatefulInteractiveElement, Styled, Task, UniformListScrollHandle, View,
|
||||
ViewContext, VisualContext as _, WeakView, WindowContext,
|
||||
Model, MouseDownEvent, ParentElement, Pixels, Point, PromptLevel, Render, Stateful, Styled,
|
||||
Task, UniformListScrollHandle, View, ViewContext, VisualContext as _, WeakView, WindowContext,
|
||||
};
|
||||
use menu::{Confirm, SelectNext, SelectPrev};
|
||||
use project::{
|
||||
|
@ -30,7 +29,7 @@ use std::{
|
|||
sync::Arc,
|
||||
};
|
||||
use theme::ActiveTheme as _;
|
||||
use ui::{h_stack, v_stack, IconElement, Label};
|
||||
use ui::{v_stack, IconElement, Label, ListItem};
|
||||
use unicase::UniCase;
|
||||
use util::{maybe, ResultExt, TryFutureExt};
|
||||
use workspace::{
|
||||
|
@ -1335,13 +1334,19 @@ impl ProjectPanel {
|
|||
}
|
||||
}
|
||||
|
||||
fn render_entry_visual_element(
|
||||
details: &EntryDetails,
|
||||
editor: Option<&View<Editor>>,
|
||||
padding: Pixels,
|
||||
fn render_entry(
|
||||
&self,
|
||||
entry_id: ProjectEntryId,
|
||||
details: EntryDetails,
|
||||
// dragged_entry_destination: &mut Option<Arc<Path>>,
|
||||
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 is_selected = self
|
||||
.selection
|
||||
.map_or(false, |selection| selection.entry_id == entry_id);
|
||||
|
||||
let theme = cx.theme();
|
||||
let filename_text_color = details
|
||||
|
@ -1354,14 +1359,17 @@ impl ProjectPanel {
|
|||
})
|
||||
.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 {
|
||||
div().child(IconElement::from_path(icon.to_string()))
|
||||
} else {
|
||||
div()
|
||||
})
|
||||
.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())
|
||||
} else {
|
||||
div()
|
||||
|
@ -1370,33 +1378,6 @@ impl ProjectPanel {
|
|||
}
|
||||
.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| {
|
||||
if !show_editor {
|
||||
if kind.is_dir() {
|
||||
|
@ -1410,12 +1391,9 @@ impl ProjectPanel {
|
|||
}
|
||||
}
|
||||
}))
|
||||
.on_mouse_down(
|
||||
MouseButton::Right,
|
||||
cx.listener(move |this, event: &MouseDownEvent, cx| {
|
||||
this.deploy_context_menu(event.position, entry_id, cx);
|
||||
}),
|
||||
)
|
||||
.on_secondary_mouse_down(cx.listener(move |this, event: &MouseDownEvent, cx| {
|
||||
this.deploy_context_menu(event.position, entry_id, cx);
|
||||
}))
|
||||
// .on_drop::<ProjectEntryId>(|this, event, cx| {
|
||||
// this.move_entry(
|
||||
// *dragged_entry,
|
||||
|
|
|
@ -1659,13 +1659,13 @@ fn elixir_lang() -> Arc<Language> {
|
|||
target: (identifier) @name)
|
||||
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
|
||||
target: (identifier) @name
|
||||
(arguments (alias) @name)
|
||||
(#match? @name "^(defmodule|defprotocol)$")) @item
|
||||
(#any-match? @name "^(defmodule|defprotocol)$")) @item
|
||||
"#,
|
||||
)
|
||||
.unwrap(),
|
||||
|
|
|
@ -5,6 +5,7 @@ use gpui::{
|
|||
use picker::{Picker, PickerDelegate};
|
||||
use std::sync::Arc;
|
||||
use theme2::ActiveTheme;
|
||||
use ui::{Label, ListItem};
|
||||
|
||||
pub struct PickerStory {
|
||||
picker: View<Picker<Delegate>>,
|
||||
|
@ -36,7 +37,7 @@ impl Delegate {
|
|||
}
|
||||
|
||||
impl PickerDelegate for Delegate {
|
||||
type ListItem = Div;
|
||||
type ListItem = ListItem;
|
||||
|
||||
fn match_count(&self) -> usize {
|
||||
self.candidates.len()
|
||||
|
@ -51,25 +52,18 @@ impl PickerDelegate for Delegate {
|
|||
ix: usize,
|
||||
selected: bool,
|
||||
cx: &mut gpui::ViewContext<Picker<Self>>,
|
||||
) -> Self::ListItem {
|
||||
let colors = cx.theme().colors();
|
||||
) -> Option<Self::ListItem> {
|
||||
let Some(candidate_ix) = self.matches.get(ix) else {
|
||||
return div();
|
||||
return None;
|
||||
};
|
||||
// TASK: Make StringMatchCandidate::string a SharedString
|
||||
let candidate = SharedString::from(self.candidates[*candidate_ix].string.clone());
|
||||
|
||||
div()
|
||||
.text_color(colors.text)
|
||||
.when(selected, |s| {
|
||||
s.border_l_10().border_color(colors.terminal_ansi_yellow)
|
||||
})
|
||||
.hover(|style| {
|
||||
style
|
||||
.bg(colors.element_active)
|
||||
.text_color(colors.text_accent)
|
||||
})
|
||||
.child(candidate)
|
||||
Some(
|
||||
ListItem::new(ix)
|
||||
.selected(selected)
|
||||
.child(Label::new(candidate)),
|
||||
)
|
||||
}
|
||||
|
||||
fn selected_index(&self) -> usize {
|
||||
|
|
|
@ -4,18 +4,15 @@ use std::rc::Rc;
|
|||
use crate::{prelude::*, v_stack, Label, List};
|
||||
use crate::{ListItem, ListSeparator, ListSubHeader};
|
||||
use gpui::{
|
||||
overlay, px, Action, AnchorCorner, AnyElement, AppContext, Bounds, DismissEvent, DispatchPhase,
|
||||
Div, EventEmitter, FocusHandle, FocusableView, IntoElement, LayoutId, ManagedView, MouseButton,
|
||||
MouseDownEvent, Pixels, Point, Render, View, VisualContext,
|
||||
overlay, px, Action, AnchorCorner, AnyElement, AppContext, Bounds, ClickEvent, DismissEvent,
|
||||
DispatchPhase, Div, EventEmitter, FocusHandle, FocusableView, IntoElement, LayoutId,
|
||||
ManagedView, MouseButton, MouseDownEvent, Pixels, Point, Render, View, VisualContext,
|
||||
};
|
||||
|
||||
pub enum ContextMenuItem {
|
||||
Separator,
|
||||
Header(SharedString),
|
||||
Entry(
|
||||
SharedString,
|
||||
Rc<dyn Fn(&MouseDownEvent, &mut WindowContext)>,
|
||||
),
|
||||
Entry(SharedString, Rc<dyn Fn(&ClickEvent, &mut WindowContext)>),
|
||||
}
|
||||
|
||||
pub struct ContextMenu {
|
||||
|
@ -61,7 +58,7 @@ impl ContextMenu {
|
|||
pub fn entry(
|
||||
mut self,
|
||||
label: impl Into<SharedString>,
|
||||
on_click: impl Fn(&MouseDownEvent, &mut WindowContext) + 'static,
|
||||
on_click: impl Fn(&ClickEvent, &mut WindowContext) + 'static,
|
||||
) -> Self {
|
||||
self.items
|
||||
.push(ContextMenuItem::Entry(label.into(), Rc::new(on_click)));
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
use std::rc::Rc;
|
||||
|
||||
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 std::rc::Rc;
|
||||
|
||||
use crate::{
|
||||
disclosure_control, h_stack, v_stack, Avatar, Icon, IconButton, IconElement, IconSize, Label,
|
||||
|
@ -117,66 +119,6 @@ impl ListHeader {
|
|||
self.meta = meta;
|
||||
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)]
|
||||
|
@ -231,26 +173,21 @@ impl RenderOnce for ListSubHeader {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Default, PartialEq, Copy, Clone)]
|
||||
pub enum ListEntrySize {
|
||||
#[default]
|
||||
Small,
|
||||
Medium,
|
||||
}
|
||||
|
||||
#[derive(IntoElement)]
|
||||
pub struct ListItem {
|
||||
id: ElementId,
|
||||
disabled: bool,
|
||||
selected: bool,
|
||||
// TODO: Reintroduce this
|
||||
// disclosure_control_style: DisclosureControlVisibility,
|
||||
indent_level: u32,
|
||||
indent_level: usize,
|
||||
indent_step_size: Pixels,
|
||||
left_slot: Option<GraphicSlot>,
|
||||
overflow: OverflowStyle,
|
||||
size: ListEntrySize,
|
||||
toggle: Toggle,
|
||||
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]>,
|
||||
}
|
||||
|
||||
|
@ -259,22 +196,29 @@ impl ListItem {
|
|||
Self {
|
||||
id: id.into(),
|
||||
disabled: false,
|
||||
selected: false,
|
||||
indent_level: 0,
|
||||
indent_step_size: px(12.),
|
||||
left_slot: None,
|
||||
overflow: OverflowStyle::Hidden,
|
||||
size: ListEntrySize::default(),
|
||||
toggle: Toggle::NotToggleable,
|
||||
variant: ListItemVariant::default(),
|
||||
on_click: Default::default(),
|
||||
on_click: None,
|
||||
on_secondary_mouse_down: None,
|
||||
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,
|
||||
handler: impl Fn(&MouseDownEvent, &mut WindowContext) + 'static,
|
||||
) -> Self {
|
||||
self.on_click = Some(Rc::new(handler));
|
||||
self.on_secondary_mouse_down = Some(Rc::new(handler));
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -283,16 +227,26 @@ impl ListItem {
|
|||
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
|
||||
}
|
||||
|
||||
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 {
|
||||
self.toggle = toggle;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn selected(mut self, selected: bool) -> Self {
|
||||
self.selected = selected;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn left_content(mut self, left_content: GraphicSlot) -> Self {
|
||||
self.left_slot = Some(left_content);
|
||||
self
|
||||
|
@ -307,11 +261,6 @@ impl ListItem {
|
|||
self.left_slot = Some(GraphicSlot::Avatar(left_avatar.into()));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn size(mut self, size: ListEntrySize) -> Self {
|
||||
self.size = size;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderOnce for ListItem {
|
||||
|
@ -331,42 +280,32 @@ impl RenderOnce for ListItem {
|
|||
None => None,
|
||||
};
|
||||
|
||||
let sized_item = match self.size {
|
||||
ListEntrySize::Small => div().h_6(),
|
||||
ListEntrySize::Medium => div().h_7(),
|
||||
};
|
||||
div()
|
||||
.id(self.id)
|
||||
.relative()
|
||||
.bg(cx.theme().colors().editor_background.clone())
|
||||
// .hover(|mut style| {
|
||||
// style.background = Some(cx.theme().colors().editor_background.into());
|
||||
// style
|
||||
// })
|
||||
.hover(|mut style| {
|
||||
style.background = Some(cx.theme().colors().editor_background.into());
|
||||
style
|
||||
})
|
||||
// TODO: Add focus state
|
||||
// .when(self.state == InteractionState::Focused, |this| {
|
||||
// this.border()
|
||||
// .border_color(cx.theme().colors().border_focused)
|
||||
// })
|
||||
//.hover(|style| style.bg(cx.theme().colors().ghost_element_hover))
|
||||
//.active(|style| style.bg(cx.theme().colors().ghost_element_active))
|
||||
.hover(|style| style.bg(cx.theme().colors().ghost_element_hover))
|
||||
.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(
|
||||
sized_item
|
||||
div()
|
||||
.when(self.variant == ListItemVariant::Inset, |this| this.px_2())
|
||||
// .ml(rems(0.75 * self.indent_level as f32))
|
||||
.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)),
|
||||
)
|
||||
}))
|
||||
.ml(self.indent_level as f32 * self.indent_step_size)
|
||||
.flex()
|
||||
.gap_1()
|
||||
.items_center()
|
||||
|
@ -374,13 +313,19 @@ impl RenderOnce for ListItem {
|
|||
.child(disclosure_control(self.toggle))
|
||||
.children(left_content)
|
||||
.children(self.children)
|
||||
.on_mouse_down(MouseButton::Left, {
|
||||
let on_click = self.on_click.clone();
|
||||
move |event, cx| {
|
||||
if let Some(on_click) = &on_click {
|
||||
// HACK: We need to attach the `on_click` handler to the child element in order to have the click
|
||||
// event actually fire.
|
||||
// Once this is fixed in GPUI we can remove this and rely on the `on_click` handler set above on the
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
})
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
use gpui::{
|
||||
AnyElement, Div, Element, ElementId, IntoElement, ParentElement, RenderOnce, Styled,
|
||||
div, AnyElement, Div, Element, ElementId, IntoElement, ParentElement, RenderOnce, Styled,
|
||||
WindowContext,
|
||||
};
|
||||
use smallvec::SmallVec;
|
||||
use theme2::ActiveTheme;
|
||||
|
||||
use crate::{v_stack, StyledExt};
|
||||
|
||||
|
@ -43,22 +44,16 @@ impl RenderOnce for Popover {
|
|||
type Rendered = Div;
|
||||
|
||||
fn render(self, cx: &mut WindowContext) -> Self::Rendered {
|
||||
v_stack()
|
||||
.relative()
|
||||
.elevation_2(cx)
|
||||
.p_1()
|
||||
.children(self.children)
|
||||
div()
|
||||
.flex()
|
||||
.gap_1()
|
||||
.child(v_stack().elevation_2(cx).px_1().children(self.children))
|
||||
.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(
|
||||
v_stack()
|
||||
.top_0()
|
||||
.left_full()
|
||||
.ml_1()
|
||||
.absolute()
|
||||
.elevation_2(cx)
|
||||
.p_1()
|
||||
.bg(cx.theme().colors().surface_background)
|
||||
.px_1()
|
||||
.child(aside),
|
||||
)
|
||||
})
|
||||
|
|
|
@ -22,5 +22,13 @@ impl Render for ListItemStory {
|
|||
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 crate::{ElevationIndex, UITextSize};
|
||||
|
@ -6,7 +6,7 @@ use crate::{ElevationIndex, UITextSize};
|
|||
fn elevated<E: Styled>(this: E, cx: &mut WindowContext, index: ElevationIndex) -> E {
|
||||
this.bg(cx.theme().colors().elevated_surface_background)
|
||||
.z_index(index.z_index())
|
||||
.rounded_lg()
|
||||
.rounded(px(8.))
|
||||
.border()
|
||||
.border_color(cx.theme().colors().border_variant)
|
||||
.shadow(index.shadow())
|
||||
|
|
|
@ -56,14 +56,16 @@ use std::{
|
|||
};
|
||||
|
||||
use crate::{
|
||||
notifications::{simple_message_notification::MessageNotification, NotificationTracker},
|
||||
notifications::NotificationTracker,
|
||||
persistence::model::{
|
||||
DockData, DockStructure, SerializedPane, SerializedPaneGroup, SerializedWorkspace,
|
||||
},
|
||||
};
|
||||
use dock::{Dock, DockPosition, Panel, PanelButtons, PanelHandle};
|
||||
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_group::*;
|
||||
use persistence::{model::SerializedItem, DB};
|
||||
|
@ -778,20 +780,6 @@ impl Workspace {
|
|||
|
||||
cx.defer(|this, 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 {
|
||||
weak_self: weak_handle.clone(),
|
||||
|
|
|
@ -140,6 +140,7 @@ tree-sitter-lua.workspace = true
|
|||
tree-sitter-nix.workspace = true
|
||||
tree-sitter-nu.workspace = true
|
||||
tree-sitter-vue.workspace = true
|
||||
tree-sitter-uiua.workspace = true
|
||||
|
||||
url = "2.2"
|
||||
urlencoding = "2.1.2"
|
||||
|
|
|
@ -17,6 +17,7 @@ mod json;
|
|||
#[cfg(feature = "plugin_runtime")]
|
||||
mod language_plugin;
|
||||
mod lua;
|
||||
mod nu;
|
||||
mod php;
|
||||
mod python;
|
||||
mod ruby;
|
||||
|
@ -24,6 +25,7 @@ mod rust;
|
|||
mod svelte;
|
||||
mod tailwind;
|
||||
mod typescript;
|
||||
mod uiua;
|
||||
mod vue;
|
||||
mod yaml;
|
||||
|
||||
|
@ -210,12 +212,21 @@ pub fn init(
|
|||
language("elm", tree_sitter_elm::language(), vec![]);
|
||||
language("glsl", tree_sitter_glsl::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(
|
||||
"vue",
|
||||
tree_sitter_vue::language(),
|
||||
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"))]
|
||||
|
|
|
@ -18,10 +18,10 @@
|
|||
target: (identifier) @name)
|
||||
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
|
||||
target: (identifier) @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-nu.workspace = true
|
||||
tree-sitter-vue.workspace = true
|
||||
tree-sitter-uiua.workspace = true
|
||||
|
||||
url = "2.2"
|
||||
urlencoding = "2.1.2"
|
||||
|
|
|
@ -18,6 +18,7 @@ mod json;
|
|||
#[cfg(feature = "plugin_runtime")]
|
||||
mod language_plugin;
|
||||
mod lua;
|
||||
mod nu;
|
||||
mod php;
|
||||
mod python;
|
||||
mod ruby;
|
||||
|
@ -25,6 +26,7 @@ mod rust;
|
|||
mod svelte;
|
||||
mod tailwind;
|
||||
mod typescript;
|
||||
mod uiua;
|
||||
mod vue;
|
||||
mod yaml;
|
||||
|
||||
|
@ -211,12 +213,21 @@ pub fn init(
|
|||
language("elm", tree_sitter_elm::language(), vec![]);
|
||||
language("glsl", tree_sitter_glsl::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(
|
||||
"vue",
|
||||
tree_sitter_vue::language(),
|
||||
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"))]
|
||||
|
|
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