Detailed changes
@@ -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;
-
- // 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")
+ fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> Self::Element {
+ let app_name = cx.global::<ReleaseChannel>().display_name();
+
+ 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
@@ -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(),
+ })
+ }
+}
@@ -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
+ }
+}
@@ -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"] },
+]
@@ -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
@@ -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"))]
@@ -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
+ }
+}
@@ -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
+ }
+}
@@ -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"] },
+]
@@ -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
@@ -0,0 +1,3 @@
+[
+ (array)
+] @indent