From fd4b81c8fc07f57ebb8aea6c47292d5f91af45b1 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 8 Apr 2022 15:32:56 -0700 Subject: [PATCH 01/22] Allow actions to be deserialized from JSON Introduce separate macro for implementing 'internal' actions which are not intended to be loaded from keymaps. --- Cargo.lock | 3 + crates/editor/src/editor.rs | 241 +++++++++++--------- crates/file_finder/src/file_finder.rs | 4 +- crates/gpui/src/app.rs | 147 ++++++++---- crates/gpui/src/app/action.rs | 117 +++++++--- crates/gpui/src/gpui.rs | 3 + crates/gpui/src/keymap.rs | 64 +++--- crates/gpui/src/views/select.rs | 4 +- crates/project_panel/src/project_panel.rs | 4 +- crates/search/Cargo.toml | 1 + crates/search/src/buffer_search.rs | 116 ++++++---- crates/search/src/project_search.rs | 37 +-- crates/search/src/search.rs | 8 +- crates/server/Cargo.toml | 1 + crates/server/src/rpc.rs | 2 + crates/theme_selector/src/theme_selector.rs | 30 ++- crates/vim/Cargo.toml | 1 + crates/vim/src/mode.rs | 5 +- crates/vim/src/normal.rs | 7 +- crates/vim/src/vim.rs | 3 +- crates/workspace/src/pane.rs | 29 ++- crates/workspace/src/pane_group.rs | 4 +- crates/workspace/src/sidebar.rs | 6 +- crates/workspace/src/workspace.rs | 13 +- crates/zed/src/main.rs | 2 +- crates/zed/src/zed.rs | 42 ++-- 26 files changed, 559 insertions(+), 335 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5e5c046ab9..d32a21d201 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4269,6 +4269,7 @@ dependencies = [ "log", "postage", "project", + "serde", "serde_json", "settings", "theme", @@ -5748,6 +5749,7 @@ dependencies = [ "language", "log", "project", + "serde", "settings", "util", "workspace", @@ -6133,6 +6135,7 @@ dependencies = [ "sha-1 0.9.6", "sqlx 0.5.5", "surf", + "theme", "tide", "tide-compress", "time 0.2.27", diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index e10fe9c17c..4d3265f8fa 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -22,7 +22,7 @@ use gpui::{ executor, fonts::{self, HighlightStyle, TextStyle}, geometry::vector::{vec2f, Vector2F}, - impl_actions, + impl_actions, impl_internal_actions, keymap::Binding, platform::CursorStyle, text_layout, AppContext, AsyncAppContext, ClipboardItem, Element, ElementBox, Entity, @@ -66,8 +66,11 @@ const MAX_LINE_LEN: usize = 1024; const MIN_NAVIGATION_HISTORY_ROW_DELTA: i64 = 10; const MAX_SELECTION_HISTORY_LEN: usize = 1024; -#[derive(Clone)] -pub struct SelectNext(pub bool); +#[derive(Clone, Deserialize)] +pub struct SelectNext { + #[serde(default)] + pub replace_newest: bool, +} #[derive(Clone)] pub struct GoToDiagnostic(pub Direction); @@ -81,44 +84,26 @@ pub struct Select(pub SelectPhase); #[derive(Clone)] pub struct Input(pub String); -#[derive(Clone)] -pub struct Tab(pub Direction); - -#[derive(Clone)] +#[derive(Clone, Deserialize)] pub struct SelectToBeginningOfLine { + #[serde(default)] stop_at_soft_wraps: bool, } -#[derive(Clone)] +#[derive(Clone, Deserialize)] pub struct SelectToEndOfLine { + #[serde(default)] stop_at_soft_wraps: bool, } -#[derive(Clone)] -pub struct ToggleCodeActions(pub bool); +#[derive(Clone, Deserialize)] +pub struct ToggleCodeActions(#[serde(default)] pub bool); -#[derive(Clone)] -pub struct ConfirmCompletion(pub Option); +#[derive(Clone, Deserialize)] +pub struct ConfirmCompletion(#[serde(default)] pub Option); -#[derive(Clone)] -pub struct ConfirmCodeAction(pub Option); - -impl_actions!( - editor, - [ - SelectNext, - GoToDiagnostic, - Scroll, - Select, - Input, - Tab, - SelectToBeginningOfLine, - SelectToEndOfLine, - ToggleCodeActions, - ConfirmCompletion, - ConfirmCodeAction, - ] -); +#[derive(Clone, Deserialize)] +pub struct ConfirmCodeAction(#[serde(default)] pub Option); actions!( editor, @@ -127,6 +112,8 @@ actions!( Backspace, Delete, Newline, + GoToNextDiagnostic, + GoToPrevDiagnostic, Indent, Outdent, DeleteLine, @@ -172,6 +159,8 @@ actions!( SplitSelectionIntoLines, AddSelectionAbove, AddSelectionBelow, + Tab, + TabPrev, ToggleComments, SelectLargerSyntaxNode, SelectSmallerSyntaxNode, @@ -193,6 +182,20 @@ actions!( ] ); +impl_actions!( + editor, + [ + SelectNext, + SelectToBeginningOfLine, + SelectToEndOfLine, + ToggleCodeActions, + ConfirmCompletion, + ConfirmCodeAction, + ] +); + +impl_internal_actions!(editor, [Scroll, Select, Input]); + enum DocumentHighlightRead {} enum DocumentHighlightWrite {} @@ -226,8 +229,8 @@ pub fn init(cx: &mut MutableAppContext) { Some("Editor && showing_code_actions"), ), Binding::new("enter", ConfirmRename, Some("Editor && renaming")), - Binding::new("tab", Tab(Direction::Next), Some("Editor")), - Binding::new("shift-tab", Tab(Direction::Prev), Some("Editor")), + Binding::new("tab", Tab, Some("Editor")), + Binding::new("shift-tab", TabPrev, Some("Editor")), Binding::new( "tab", ConfirmCompletion(None), @@ -346,8 +349,20 @@ pub fn init(cx: &mut MutableAppContext) { Binding::new("cmd-ctrl-p", AddSelectionAbove, Some("Editor")), Binding::new("cmd-alt-down", AddSelectionBelow, Some("Editor")), Binding::new("cmd-ctrl-n", AddSelectionBelow, Some("Editor")), - Binding::new("cmd-d", SelectNext(false), Some("Editor")), - Binding::new("cmd-k cmd-d", SelectNext(true), Some("Editor")), + Binding::new( + "cmd-d", + SelectNext { + replace_newest: false, + }, + Some("Editor"), + ), + Binding::new( + "cmd-k cmd-d", + SelectNext { + replace_newest: true, + }, + Some("Editor"), + ), Binding::new("cmd-/", ToggleComments, Some("Editor")), Binding::new("alt-up", SelectLargerSyntaxNode, Some("Editor")), Binding::new("ctrl-w", SelectLargerSyntaxNode, Some("Editor")), @@ -355,8 +370,8 @@ pub fn init(cx: &mut MutableAppContext) { Binding::new("ctrl-shift-W", SelectSmallerSyntaxNode, Some("Editor")), Binding::new("cmd-u", UndoSelection, Some("Editor")), Binding::new("cmd-shift-U", RedoSelection, Some("Editor")), - Binding::new("f8", GoToDiagnostic(Direction::Next), Some("Editor")), - Binding::new("shift-f8", GoToDiagnostic(Direction::Prev), Some("Editor")), + Binding::new("f8", GoToNextDiagnostic, Some("Editor")), + Binding::new("shift-f8", GoToPrevDiagnostic, Some("Editor")), Binding::new("f2", Rename, Some("Editor")), Binding::new("f12", GoToDefinition, Some("Editor")), Binding::new("alt-shift-f12", FindAllReferences, Some("Editor")), @@ -435,7 +450,8 @@ pub fn init(cx: &mut MutableAppContext) { cx.add_action(Editor::move_to_enclosing_bracket); cx.add_action(Editor::undo_selection); cx.add_action(Editor::redo_selection); - cx.add_action(Editor::go_to_diagnostic); + cx.add_action(Editor::go_to_next_diagnostic); + cx.add_action(Editor::go_to_prev_diagnostic); cx.add_action(Editor::go_to_definition); cx.add_action(Editor::page_up); cx.add_action(Editor::page_down); @@ -2940,8 +2956,8 @@ impl Editor { self.move_to_snippet_tabstop(Bias::Right, cx) } - pub fn move_to_prev_snippet_tabstop(&mut self, cx: &mut ViewContext) { - self.move_to_snippet_tabstop(Bias::Left, cx); + pub fn move_to_prev_snippet_tabstop(&mut self, cx: &mut ViewContext) -> bool { + self.move_to_snippet_tabstop(Bias::Left, cx) } pub fn move_to_snippet_tabstop(&mut self, bias: Bias, cx: &mut ViewContext) -> bool { @@ -3046,54 +3062,46 @@ impl Editor { }); } - pub fn tab(&mut self, &Tab(direction): &Tab, cx: &mut ViewContext) { - match direction { - Direction::Prev => { - if !self.snippet_stack.is_empty() { - self.move_to_prev_snippet_tabstop(cx); - return; - } + pub fn tab_prev(&mut self, _: &TabPrev, cx: &mut ViewContext) { + if self.move_to_prev_snippet_tabstop(cx) { + return; + } - self.outdent(&Outdent, cx); - } - Direction::Next => { - if self.move_to_next_snippet_tabstop(cx) { - return; - } + self.outdent(&Outdent, cx); + } - let mut selections = self.local_selections::(cx); - if selections.iter().all(|s| s.is_empty()) { - self.transact(cx, |this, cx| { - this.buffer.update(cx, |buffer, cx| { - for selection in &mut selections { - let language_name = - buffer.language_at(selection.start, cx).map(|l| l.name()); - let tab_size = - cx.global::().tab_size(language_name.as_deref()); - let char_column = buffer - .read(cx) - .text_for_range( - Point::new(selection.start.row, 0)..selection.start, - ) - .flat_map(str::chars) - .count(); - let chars_to_next_tab_stop = - tab_size - (char_column as u32 % tab_size); - buffer.edit( - [selection.start..selection.start], - " ".repeat(chars_to_next_tab_stop as usize), - cx, - ); - selection.start.column += chars_to_next_tab_stop; - selection.end = selection.start; - } - }); - this.update_selections(selections, Some(Autoscroll::Fit), cx); - }); - } else { - self.indent(&Indent, cx); - } - } + pub fn tab(&mut self, _: &Tab, cx: &mut ViewContext) { + if self.move_to_next_snippet_tabstop(cx) { + return; + } + + let mut selections = self.local_selections::(cx); + if selections.iter().all(|s| s.is_empty()) { + self.transact(cx, |this, cx| { + this.buffer.update(cx, |buffer, cx| { + for selection in &mut selections { + let language_name = + buffer.language_at(selection.start, cx).map(|l| l.name()); + let tab_size = cx.global::().tab_size(language_name.as_deref()); + let char_column = buffer + .read(cx) + .text_for_range(Point::new(selection.start.row, 0)..selection.start) + .flat_map(str::chars) + .count(); + let chars_to_next_tab_stop = tab_size - (char_column as u32 % tab_size); + buffer.edit( + [selection.start..selection.start], + " ".repeat(chars_to_next_tab_stop as usize), + cx, + ); + selection.start.column += chars_to_next_tab_stop; + selection.end = selection.start; + } + }); + this.update_selections(selections, Some(Autoscroll::Fit), cx); + }); + } else { + self.indent(&Indent, cx); } } @@ -4237,7 +4245,6 @@ impl Editor { pub fn select_next(&mut self, action: &SelectNext, cx: &mut ViewContext) { self.push_to_selection_history(); - let replace_newest = action.0; let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); let buffer = &display_map.buffer_snapshot; let mut selections = self.local_selections::(cx); @@ -4276,7 +4283,7 @@ impl Editor { } if let Some(next_selected_range) = next_selected_range { - if replace_newest { + if action.replace_newest { if let Some(newest_id) = selections.iter().max_by_key(|s| s.id).map(|s| s.id) { @@ -4547,11 +4554,15 @@ impl Editor { self.selection_history.mode = SelectionHistoryMode::Normal; } - pub fn go_to_diagnostic( - &mut self, - &GoToDiagnostic(direction): &GoToDiagnostic, - cx: &mut ViewContext, - ) { + fn go_to_next_diagnostic(&mut self, _: &GoToNextDiagnostic, cx: &mut ViewContext) { + self.go_to_diagnostic(Direction::Next, cx) + } + + fn go_to_prev_diagnostic(&mut self, _: &GoToNextDiagnostic, cx: &mut ViewContext) { + self.go_to_diagnostic(Direction::Prev, cx) + } + + pub fn go_to_diagnostic(&mut self, direction: Direction, cx: &mut ViewContext) { let buffer = self.buffer.read(cx).snapshot(cx); let selection = self.newest_selection_with_snapshot::(&buffer); let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| { @@ -7771,7 +7782,7 @@ mod tests { ); // indent from mid-tabstop to full tabstop - view.tab(&Tab(Direction::Next), cx); + view.tab(&Tab, cx); assert_text_with_selections( view, indoc! {" @@ -7782,7 +7793,7 @@ mod tests { ); // outdent from 1 tabstop to 0 tabstops - view.tab(&Tab(Direction::Prev), cx); + view.tab_prev(&TabPrev, cx); assert_text_with_selections( view, indoc! {" @@ -7803,7 +7814,7 @@ mod tests { ); // indent and outdent affect only the preceding line - view.tab(&Tab(Direction::Next), cx); + view.tab(&Tab, cx); assert_text_with_selections( view, indoc! {" @@ -7812,7 +7823,7 @@ mod tests { ] four"}, cx, ); - view.tab(&Tab(Direction::Prev), cx); + view.tab_prev(&TabPrev, cx); assert_text_with_selections( view, indoc! {" @@ -7831,7 +7842,7 @@ mod tests { four"}, cx, ); - view.tab(&Tab(Direction::Next), cx); + view.tab(&Tab, cx); assert_text_with_selections( view, indoc! {" @@ -7849,7 +7860,7 @@ mod tests { four"}, cx, ); - view.tab(&Tab(Direction::Prev), cx); + view.tab_prev(&TabPrev, cx); assert_text_with_selections( view, indoc! {" @@ -7939,7 +7950,7 @@ mod tests { cx, ); - editor.tab(&Tab(Direction::Next), cx); + editor.tab(&Tab, cx); assert_text_with_selections( &mut editor, indoc! {" @@ -7950,7 +7961,7 @@ mod tests { "}, cx, ); - editor.tab(&Tab(Direction::Prev), cx); + editor.tab_prev(&TabPrev, cx); assert_text_with_selections( &mut editor, indoc! {" @@ -8693,10 +8704,20 @@ mod tests { view.update(cx, |view, cx| { view.select_ranges([ranges[1].start + 1..ranges[1].start + 1], None, cx); - view.select_next(&SelectNext(false), cx); + view.select_next( + &SelectNext { + replace_newest: false, + }, + cx, + ); assert_eq!(view.selected_ranges(cx), &ranges[1..2]); - view.select_next(&SelectNext(false), cx); + view.select_next( + &SelectNext { + replace_newest: false, + }, + cx, + ); assert_eq!(view.selected_ranges(cx), &ranges[1..3]); view.undo_selection(&UndoSelection, cx); @@ -8705,10 +8726,20 @@ mod tests { view.redo_selection(&RedoSelection, cx); assert_eq!(view.selected_ranges(cx), &ranges[1..3]); - view.select_next(&SelectNext(false), cx); + view.select_next( + &SelectNext { + replace_newest: false, + }, + cx, + ); assert_eq!(view.selected_ranges(cx), &ranges[1..4]); - view.select_next(&SelectNext(false), cx); + view.select_next( + &SelectNext { + replace_newest: false, + }, + cx, + ); assert_eq!(view.selected_ranges(cx), &ranges[0..4]); }); } diff --git a/crates/file_finder/src/file_finder.rs b/crates/file_finder/src/file_finder.rs index af9fd910b5..659dde7c5b 100644 --- a/crates/file_finder/src/file_finder.rs +++ b/crates/file_finder/src/file_finder.rs @@ -3,7 +3,7 @@ use fuzzy::PathMatch; use gpui::{ actions, elements::*, - impl_actions, + impl_internal_actions, keymap::{self, Binding}, AppContext, Axis, Entity, ModelHandle, MutableAppContext, RenderContext, Task, View, ViewContext, ViewHandle, WeakViewHandle, @@ -41,8 +41,8 @@ pub struct FileFinder { #[derive(Clone)] pub struct Select(pub ProjectPath); -impl_actions!(file_finder, [Select]); actions!(file_finder, [Toggle]); +impl_internal_actions!(file_finder, [Select]); pub fn init(cx: &mut MutableAppContext) { cx.add_action(FileFinder::toggle); diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index 3fc5652791..f7417f6663 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -715,12 +715,14 @@ type GlobalSubscriptionCallback = Box bool>; type GlobalObservationCallback = Box; type ReleaseObservationCallback = Box; +type DeserializeActionCallback = fn(json: &str) -> anyhow::Result>; pub struct MutableAppContext { weak_self: Option>>, foreground_platform: Rc, assets: Arc, cx: AppContext, + action_deserializers: HashMap<&'static str, DeserializeActionCallback>, capture_actions: HashMap>>>, actions: HashMap>>>, global_actions: HashMap>, @@ -773,6 +775,7 @@ impl MutableAppContext { font_cache, platform, }, + action_deserializers: HashMap::new(), capture_actions: HashMap::new(), actions: HashMap::new(), global_actions: HashMap::new(), @@ -857,6 +860,18 @@ impl MutableAppContext { .and_then(|(presenter, _)| presenter.borrow().debug_elements(self)) } + pub fn deserialize_action( + &self, + name: &str, + argument: Option<&str>, + ) -> Result> { + let callback = self + .action_deserializers + .get(name) + .ok_or_else(|| anyhow!("unknown action {}", name))?; + callback(argument.unwrap_or("{}")) + } + pub fn add_action(&mut self, handler: F) where A: Action, @@ -899,6 +914,10 @@ impl MutableAppContext { }, ); + self.action_deserializers + .entry(A::qualified_name()) + .or_insert(A::from_json_str); + let actions = if capture { &mut self.capture_actions } else { @@ -934,6 +953,10 @@ impl MutableAppContext { handler(action, cx); }); + self.action_deserializers + .entry(A::qualified_name()) + .or_insert(A::from_json_str); + if self .global_actions .insert(TypeId::of::(), handler) @@ -4575,7 +4598,8 @@ impl RefCounts { #[cfg(test)] mod tests { use super::*; - use crate::{elements::*, impl_actions}; + use crate::{actions, elements::*, impl_actions}; + use serde::Deserialize; use smol::future::poll_once; use std::{ cell::Cell, @@ -5683,6 +5707,42 @@ mod tests { ); } + #[crate::test(self)] + fn test_deserialize_actions(cx: &mut MutableAppContext) { + #[derive(Clone, Debug, Deserialize, PartialEq, Eq)] + pub struct ComplexAction { + arg: String, + count: usize, + } + + actions!(test::something, [SimpleAction]); + impl_actions!(test::something, [ComplexAction]); + + cx.add_global_action(move |_: &SimpleAction, _: &mut MutableAppContext| {}); + cx.add_global_action(move |_: &ComplexAction, _: &mut MutableAppContext| {}); + + let action1 = cx + .deserialize_action( + "test::something::ComplexAction", + Some(r#"{"arg": "a", "count": 5}"#), + ) + .unwrap(); + let action2 = cx + .deserialize_action("test::something::SimpleAction", None) + .unwrap(); + assert_eq!( + action1.as_any().downcast_ref::().unwrap(), + &ComplexAction { + arg: "a".to_string(), + count: 5, + } + ); + assert_eq!( + action2.as_any().downcast_ref::().unwrap(), + &SimpleAction + ); + } + #[crate::test(self)] fn test_dispatch_action(cx: &mut MutableAppContext) { struct ViewA { @@ -5721,32 +5781,32 @@ mod tests { } } - #[derive(Clone)] - pub struct Action(pub &'static str); + #[derive(Clone, Deserialize)] + pub struct Action(pub String); impl_actions!(test, [Action]); let actions = Rc::new(RefCell::new(Vec::new())); - { + cx.add_global_action({ let actions = actions.clone(); - cx.add_global_action(move |_: &Action, _: &mut MutableAppContext| { + move |_: &Action, _: &mut MutableAppContext| { actions.borrow_mut().push("global".to_string()); - }); - } + } + }); - { + cx.add_action({ let actions = actions.clone(); - cx.add_action(move |view: &mut ViewA, action: &Action, cx| { + move |view: &mut ViewA, action: &Action, cx| { assert_eq!(action.0, "bar"); cx.propagate_action(); actions.borrow_mut().push(format!("{} a", view.id)); - }); - } + } + }); - { + cx.add_action({ let actions = actions.clone(); - cx.add_action(move |view: &mut ViewA, _: &Action, cx| { + move |view: &mut ViewA, _: &Action, cx| { if view.id != 1 { cx.add_view(|cx| { cx.propagate_action(); // Still works on a nested ViewContext @@ -5754,32 +5814,32 @@ mod tests { }); } actions.borrow_mut().push(format!("{} b", view.id)); - }); - } + } + }); - { + cx.add_action({ let actions = actions.clone(); - cx.add_action(move |view: &mut ViewB, _: &Action, cx| { + move |view: &mut ViewB, _: &Action, cx| { cx.propagate_action(); actions.borrow_mut().push(format!("{} c", view.id)); - }); - } + } + }); - { + cx.add_action({ let actions = actions.clone(); - cx.add_action(move |view: &mut ViewB, _: &Action, cx| { + move |view: &mut ViewB, _: &Action, cx| { cx.propagate_action(); actions.borrow_mut().push(format!("{} d", view.id)); - }); - } + } + }); - { + cx.capture_action({ let actions = actions.clone(); - cx.capture_action(move |view: &mut ViewA, _: &Action, cx| { + move |view: &mut ViewA, _: &Action, cx| { cx.propagate_action(); actions.borrow_mut().push(format!("{} capture", view.id)); - }); - } + } + }); let (window_id, view_1) = cx.add_window(Default::default(), |_| ViewA { id: 1 }); let view_2 = cx.add_view(window_id, |_| ViewB { id: 2 }); @@ -5789,7 +5849,7 @@ mod tests { cx.dispatch_action( window_id, vec![view_1.id(), view_2.id(), view_3.id(), view_4.id()], - &Action("bar"), + &Action("bar".to_string()), ); assert_eq!( @@ -5812,7 +5872,7 @@ mod tests { cx.dispatch_action( window_id, vec![view_2.id(), view_3.id(), view_4.id()], - &Action("bar"), + &Action("bar".to_string()), ); assert_eq!( @@ -5832,8 +5892,8 @@ mod tests { #[crate::test(self)] fn test_dispatch_keystroke(cx: &mut MutableAppContext) { - #[derive(Clone)] - pub struct Action(pub &'static str); + #[derive(Clone, Deserialize)] + pub struct Action(String); impl_actions!(test, [Action]); @@ -5887,16 +5947,20 @@ mod tests { // "a" and "b" in its context, but not "c". cx.add_bindings(vec![keymap::Binding::new( "a", - Action("a"), + Action("a".to_string()), Some("a && b && !c"), )]); - cx.add_bindings(vec![keymap::Binding::new("b", Action("b"), None)]); + cx.add_bindings(vec![keymap::Binding::new( + "b", + Action("b".to_string()), + None, + )]); let actions = Rc::new(RefCell::new(Vec::new())); - { + cx.add_action({ let actions = actions.clone(); - cx.add_action(move |view: &mut View, action: &Action, cx| { + move |view: &mut View, action: &Action, cx| { if action.0 == "a" { actions.borrow_mut().push(format!("{} a", view.id)); } else { @@ -5905,14 +5969,15 @@ mod tests { .push(format!("{} {}", view.id, action.0)); cx.propagate_action(); } - }); - } - { + } + }); + + cx.add_global_action({ let actions = actions.clone(); - cx.add_global_action(move |action: &Action, _| { + move |action: &Action, _| { actions.borrow_mut().push(format!("global {}", action.0)); - }); - } + } + }); cx.dispatch_keystroke( window_id, diff --git a/crates/gpui/src/app/action.rs b/crates/gpui/src/app/action.rs index 79606feee7..fc5bd616ee 100644 --- a/crates/gpui/src/app/action.rs +++ b/crates/gpui/src/app/action.rs @@ -2,55 +2,108 @@ use std::any::{Any, TypeId}; pub trait Action: 'static { fn id(&self) -> TypeId; - fn namespace(&self) -> &'static str; fn name(&self) -> &'static str; fn as_any(&self) -> &dyn Any; fn boxed_clone(&self) -> Box; - fn boxed_clone_as_any(&self) -> Box; + + fn qualified_name() -> &'static str + where + Self: Sized; + fn from_json_str(json: &str) -> anyhow::Result> + where + Self: Sized; } +/// Define a set of unit struct types that all implement the `Action` trait. +/// +/// The first argument is a namespace that will be associated with each of +/// the given action types, to ensure that they have globally unique +/// qualified names for use in keymap files. #[macro_export] -macro_rules! impl_actions { +macro_rules! actions { ($namespace:path, [ $($name:ident),* $(,)? ]) => { $( - impl $crate::action::Action for $name { - fn id(&self) -> std::any::TypeId { - std::any::TypeId::of::<$name>() - } - - fn namespace(&self) -> &'static str { - stringify!($namespace) - } - - fn name(&self) -> &'static str { - stringify!($name) - } - - fn as_any(&self) -> &dyn std::any::Any { - self - } - - fn boxed_clone(&self) -> Box { - Box::new(self.clone()) - } - - fn boxed_clone_as_any(&self) -> Box { - Box::new(self.clone()) + #[derive(Clone, Debug, Default, PartialEq, Eq)] + pub struct $name; + $crate::__impl_action! { + $namespace, + $name, + fn from_json_str(_: &str) -> $crate::anyhow::Result> { + Ok(Box::new(Self)) } } )* }; } +/// Implement the `Action` trait for a set of existing types. +/// +/// The first argument is a namespace that will be associated with each of +/// the given action types, to ensure that they have globally unique +/// qualified names for use in keymap files. #[macro_export] -macro_rules! actions { +macro_rules! impl_actions { ($namespace:path, [ $($name:ident),* $(,)? ]) => { - $( - #[derive(Clone, Debug, Default, PartialEq, Eq)] - pub struct $name; + $crate::__impl_action! { + $namespace, + $name, + fn from_json_str(json: &str) -> $crate::anyhow::Result> { + Ok(Box::new($crate::serde_json::from_str::(json)?)) + } + } )* - - $crate::impl_actions!($namespace, [ $($name),* ]); + }; +} + +/// Implement the `Action` trait for a set of existing types that are +/// not intended to be constructed via a keymap file, but only dispatched +/// internally. +#[macro_export] +macro_rules! impl_internal_actions { + ($namespace:path, [ $($name:ident),* $(,)? ]) => { + $( + $crate::__impl_action! { + $namespace, + $name, + fn from_json_str(_: &str) -> $crate::anyhow::Result> { + Err($crate::anyhow::anyhow!("internal action")) + } + } + )* + }; +} + +#[doc(hidden)] +#[macro_export] +macro_rules! __impl_action { + ($namespace:path, $name:ident, $from_json_fn:item) => { + impl $crate::action::Action for $name { + fn name(&self) -> &'static str { + stringify!($name) + } + + fn qualified_name() -> &'static str { + concat!( + stringify!($namespace), + "::", + stringify!($name), + ) + } + + fn id(&self) -> std::any::TypeId { + std::any::TypeId::of::<$name>() + } + + fn as_any(&self) -> &dyn std::any::Any { + self + } + + fn boxed_clone(&self) -> Box { + Box::new(self.clone()) + } + + $from_json_fn + } }; } diff --git a/crates/gpui/src/gpui.rs b/crates/gpui/src/gpui.rs index 9803a2aa2f..e58bbec1c6 100644 --- a/crates/gpui/src/gpui.rs +++ b/crates/gpui/src/gpui.rs @@ -33,3 +33,6 @@ pub use platform::{Event, NavigationDirection, PathPromptOptions, Platform, Prom pub use presenter::{ Axis, DebugContext, EventContext, LayoutContext, PaintContext, SizeConstraint, Vector2FExt, }; + +pub use anyhow; +pub use serde_json; diff --git a/crates/gpui/src/keymap.rs b/crates/gpui/src/keymap.rs index f286265964..a94abb8252 100644 --- a/crates/gpui/src/keymap.rs +++ b/crates/gpui/src/keymap.rs @@ -328,6 +328,8 @@ impl ContextPredicate { #[cfg(test)] mod tests { + use serde::Deserialize; + use crate::{actions, impl_actions}; use super::*; @@ -419,30 +421,18 @@ mod tests { #[test] fn test_matcher() -> anyhow::Result<()> { - #[derive(Clone)] - pub struct A(pub &'static str); + #[derive(Clone, Deserialize, PartialEq, Eq, Debug)] + pub struct A(pub String); impl_actions!(test, [A]); actions!(test, [B, Ab]); - impl PartialEq for A { - fn eq(&self, other: &Self) -> bool { - self.0 == other.0 - } - } - impl Eq for A {} - impl Debug for A { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "A({:?})", &self.0) - } - } - #[derive(Clone, Debug, Eq, PartialEq)] struct ActionArg { a: &'static str, } let keymap = Keymap(vec![ - Binding::new("a", A("x"), Some("a")), + Binding::new("a", A("x".to_string()), Some("a")), Binding::new("b", B, Some("a")), Binding::new("a b", Ab, Some("a || b")), ]); @@ -456,40 +446,54 @@ mod tests { let mut matcher = Matcher::new(keymap); // Basic match - assert_eq!(matcher.test_keystroke("a", 1, &ctx_a), Some(A("x"))); + assert_eq!( + downcast(&matcher.test_keystroke("a", 1, &ctx_a)), + Some(&A("x".to_string())) + ); // Multi-keystroke match - assert_eq!(matcher.test_keystroke::("a", 1, &ctx_b), None); - assert_eq!(matcher.test_keystroke("b", 1, &ctx_b), Some(Ab)); + assert!(matcher.test_keystroke("a", 1, &ctx_b).is_none()); + assert_eq!(downcast(&matcher.test_keystroke("b", 1, &ctx_b)), Some(&Ab)); // Failed matches don't interfere with matching subsequent keys - assert_eq!(matcher.test_keystroke::("x", 1, &ctx_a), None); - assert_eq!(matcher.test_keystroke("a", 1, &ctx_a), Some(A("x"))); + assert!(matcher.test_keystroke("x", 1, &ctx_a).is_none()); + assert_eq!( + downcast(&matcher.test_keystroke("a", 1, &ctx_a)), + Some(&A("x".to_string())) + ); // Pending keystrokes are cleared when the context changes - assert_eq!(matcher.test_keystroke::("a", 1, &ctx_b), None); - assert_eq!(matcher.test_keystroke("b", 1, &ctx_a), Some(B)); + assert!(&matcher.test_keystroke("a", 1, &ctx_b).is_none()); + assert_eq!(downcast(&matcher.test_keystroke("b", 1, &ctx_a)), Some(&B)); let mut ctx_c = Context::default(); ctx_c.set.insert("c".into()); // Pending keystrokes are maintained per-view - assert_eq!(matcher.test_keystroke::("a", 1, &ctx_b), None); - assert_eq!(matcher.test_keystroke::("a", 2, &ctx_c), None); - assert_eq!(matcher.test_keystroke("b", 1, &ctx_b), Some(Ab)); + assert!(matcher.test_keystroke("a", 1, &ctx_b).is_none()); + assert!(matcher.test_keystroke("a", 2, &ctx_c).is_none()); + assert_eq!(downcast(&matcher.test_keystroke("b", 1, &ctx_b)), Some(&Ab)); Ok(()) } + fn downcast<'a, A: Action>(action: &'a Option>) -> Option<&'a A> { + action + .as_ref() + .and_then(|action| action.as_any().downcast_ref()) + } + impl Matcher { - fn test_keystroke(&mut self, keystroke: &str, view_id: usize, cx: &Context) -> Option - where - A: Action + Debug + Eq, - { + fn test_keystroke( + &mut self, + keystroke: &str, + view_id: usize, + cx: &Context, + ) -> Option> { if let MatchResult::Action(action) = self.push_keystroke(Keystroke::parse(keystroke).unwrap(), view_id, cx) { - Some(*action.boxed_clone_as_any().downcast().unwrap()) + Some(action.boxed_clone()) } else { None } diff --git a/crates/gpui/src/views/select.rs b/crates/gpui/src/views/select.rs index 14b098c472..10cd0cd5a2 100644 --- a/crates/gpui/src/views/select.rs +++ b/crates/gpui/src/views/select.rs @@ -1,3 +1,5 @@ +use serde::Deserialize; + use crate::{ actions, elements::*, impl_actions, AppContext, Entity, MutableAppContext, RenderContext, View, ViewContext, WeakViewHandle, @@ -25,7 +27,7 @@ pub enum ItemType { Unselected, } -#[derive(Clone)] +#[derive(Clone, Deserialize)] pub struct SelectItem(pub usize); actions!(select, [ToggleSelect]); diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index 3534fa186f..a14e03d27d 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -4,7 +4,7 @@ use gpui::{ Align, ConstrainedBox, Empty, Flex, Label, MouseEventHandler, ParentElement, ScrollTarget, Svg, UniformList, UniformListState, }, - impl_actions, + impl_internal_actions, keymap::{self, Binding}, platform::CursorStyle, AppContext, Element, ElementBox, Entity, ModelHandle, MutableAppContext, View, ViewContext, @@ -54,7 +54,7 @@ pub struct ToggleExpanded(pub ProjectEntryId); pub struct Open(pub ProjectEntryId); actions!(project_panel, [ExpandSelectedEntry, CollapseSelectedEntry]); -impl_actions!(project_panel, [Open, ToggleExpanded]); +impl_internal_actions!(project_panel, [Open, ToggleExpanded]); pub fn init(cx: &mut MutableAppContext) { cx.add_action(ProjectPanel::expand_selected_entry); diff --git a/crates/search/Cargo.toml b/crates/search/Cargo.toml index 77961de01f..967b50c270 100644 --- a/crates/search/Cargo.toml +++ b/crates/search/Cargo.toml @@ -20,6 +20,7 @@ workspace = { path = "../workspace" } anyhow = "1.0" log = "0.4" postage = { version = "0.4.1", features = ["futures-traits"] } +serde = { version = "1", features = ["derive"] } [dev-dependencies] editor = { path = "../editor", features = ["test-support"] } diff --git a/crates/search/src/buffer_search.rs b/crates/search/src/buffer_search.rs index ffaf8e368d..71e9a90970 100644 --- a/crates/search/src/buffer_search.rs +++ b/crates/search/src/buffer_search.rs @@ -1,25 +1,32 @@ -use crate::{active_match_index, match_index_for_direction, Direction, SearchOption, SelectMatch}; +use crate::{ + active_match_index, match_index_for_direction, Direction, SearchOption, SelectNextMatch, + SelectPrevMatch, +}; use collections::HashMap; use editor::{display_map::ToDisplayPoint, Anchor, Autoscroll, Bias, Editor}; use gpui::{ - actions, elements::*, impl_actions, keymap::Binding, platform::CursorStyle, AppContext, Entity, - MutableAppContext, RenderContext, Subscription, Task, View, ViewContext, ViewHandle, - WeakViewHandle, + actions, elements::*, impl_actions, impl_internal_actions, keymap::Binding, + platform::CursorStyle, AppContext, Entity, MutableAppContext, RenderContext, Subscription, + Task, View, ViewContext, ViewHandle, WeakViewHandle, }; use language::OffsetRangeExt; use project::search::SearchQuery; +use serde::Deserialize; use settings::Settings; use std::ops::Range; use workspace::{ItemHandle, Pane, ToolbarItemLocation, ToolbarItemView}; -#[derive(Clone)] -pub struct Deploy(pub bool); +#[derive(Clone, Deserialize)] +pub struct Deploy { + pub focus: bool, +} #[derive(Clone)] pub struct ToggleSearchOption(pub SearchOption); actions!(buffer_search, [Dismiss, FocusEditor]); -impl_actions!(buffer_search, [Deploy, ToggleSearchOption]); +impl_actions!(buffer_search, [Deploy]); +impl_internal_actions!(buffer_search, [ToggleSearchOption]); pub enum Event { UpdateLocation, @@ -27,29 +34,31 @@ pub enum Event { pub fn init(cx: &mut MutableAppContext) { cx.add_bindings([ - Binding::new("cmd-f", Deploy(true), Some("Editor && mode == full")), - Binding::new("cmd-e", Deploy(false), Some("Editor && mode == full")), + Binding::new( + "cmd-f", + Deploy { focus: true }, + Some("Editor && mode == full"), + ), + Binding::new( + "cmd-e", + Deploy { focus: false }, + Some("Editor && mode == full"), + ), Binding::new("escape", Dismiss, Some("BufferSearchBar")), Binding::new("cmd-f", FocusEditor, Some("BufferSearchBar")), - Binding::new( - "enter", - SelectMatch(Direction::Next), - Some("BufferSearchBar"), - ), - Binding::new( - "shift-enter", - SelectMatch(Direction::Prev), - Some("BufferSearchBar"), - ), - Binding::new("cmd-g", SelectMatch(Direction::Next), Some("Pane")), - Binding::new("cmd-shift-G", SelectMatch(Direction::Prev), Some("Pane")), + Binding::new("enter", SelectNextMatch, Some("BufferSearchBar")), + Binding::new("shift-enter", SelectPrevMatch, Some("BufferSearchBar")), + Binding::new("cmd-g", SelectNextMatch, Some("Pane")), + Binding::new("cmd-shift-G", SelectPrevMatch, Some("Pane")), ]); cx.add_action(BufferSearchBar::deploy); cx.add_action(BufferSearchBar::dismiss); cx.add_action(BufferSearchBar::focus_editor); cx.add_action(BufferSearchBar::toggle_search_option); - cx.add_action(BufferSearchBar::select_match); - cx.add_action(BufferSearchBar::select_match_on_pane); + cx.add_action(BufferSearchBar::select_next_match); + cx.add_action(BufferSearchBar::select_prev_match); + cx.add_action(BufferSearchBar::select_next_match_on_pane); + cx.add_action(BufferSearchBar::select_prev_match_on_pane); } pub struct BufferSearchBar { @@ -325,14 +334,17 @@ impl BufferSearchBar { .with_style(style.container) .boxed() }) - .on_click(move |cx| cx.dispatch_action(SelectMatch(direction))) + .on_click(move |cx| match direction { + Direction::Prev => cx.dispatch_action(SelectPrevMatch), + Direction::Next => cx.dispatch_action(SelectNextMatch), + }) .with_cursor_style(CursorStyle::PointingHand) .boxed() } - fn deploy(pane: &mut Pane, Deploy(focus): &Deploy, cx: &mut ViewContext) { + fn deploy(pane: &mut Pane, action: &Deploy, cx: &mut ViewContext) { if let Some(search_bar) = pane.toolbar().read(cx).item_of_type::() { - if search_bar.update(cx, |search_bar, cx| search_bar.show(*focus, cx)) { + if search_bar.update(cx, |search_bar, cx| search_bar.show(action.focus, cx)) { return; } } @@ -368,7 +380,15 @@ impl BufferSearchBar { cx.notify(); } - fn select_match(&mut self, &SelectMatch(direction): &SelectMatch, cx: &mut ViewContext) { + fn select_next_match(&mut self, _: &SelectNextMatch, cx: &mut ViewContext) { + self.select_match(Direction::Next, cx); + } + + fn select_prev_match(&mut self, _: &SelectPrevMatch, cx: &mut ViewContext) { + self.select_match(Direction::Prev, cx); + } + + fn select_match(&mut self, direction: Direction, cx: &mut ViewContext) { if let Some(index) = self.active_match_index { if let Some(editor) = self.active_editor.as_ref() { editor.update(cx, |editor, cx| { @@ -389,9 +409,23 @@ impl BufferSearchBar { } } - fn select_match_on_pane(pane: &mut Pane, action: &SelectMatch, cx: &mut ViewContext) { + fn select_next_match_on_pane( + pane: &mut Pane, + action: &SelectNextMatch, + cx: &mut ViewContext, + ) { if let Some(search_bar) = pane.toolbar().read(cx).item_of_type::() { - search_bar.update(cx, |search_bar, cx| search_bar.select_match(action, cx)); + search_bar.update(cx, |bar, cx| bar.select_next_match(action, cx)); + } + } + + fn select_prev_match_on_pane( + pane: &mut Pane, + action: &SelectPrevMatch, + cx: &mut ViewContext, + ) { + if let Some(search_bar) = pane.toolbar().read(cx).item_of_type::() { + search_bar.update(cx, |bar, cx| bar.select_prev_match(action, cx)); } } @@ -699,7 +733,7 @@ mod tests { }); search_bar.update(cx, |search_bar, cx| { assert_eq!(search_bar.active_match_index, Some(0)); - search_bar.select_match(&SelectMatch(Direction::Next), cx); + search_bar.select_next_match(&SelectNextMatch, cx); assert_eq!( editor.update(cx, |editor, cx| editor.selected_display_ranges(cx)), [DisplayPoint::new(0, 41)..DisplayPoint::new(0, 43)] @@ -710,7 +744,7 @@ mod tests { }); search_bar.update(cx, |search_bar, cx| { - search_bar.select_match(&SelectMatch(Direction::Next), cx); + search_bar.select_next_match(&SelectNextMatch, cx); assert_eq!( editor.update(cx, |editor, cx| editor.selected_display_ranges(cx)), [DisplayPoint::new(3, 11)..DisplayPoint::new(3, 13)] @@ -721,7 +755,7 @@ mod tests { }); search_bar.update(cx, |search_bar, cx| { - search_bar.select_match(&SelectMatch(Direction::Next), cx); + search_bar.select_next_match(&SelectNextMatch, cx); assert_eq!( editor.update(cx, |editor, cx| editor.selected_display_ranges(cx)), [DisplayPoint::new(3, 56)..DisplayPoint::new(3, 58)] @@ -732,7 +766,7 @@ mod tests { }); search_bar.update(cx, |search_bar, cx| { - search_bar.select_match(&SelectMatch(Direction::Next), cx); + search_bar.select_next_match(&SelectNextMatch, cx); assert_eq!( editor.update(cx, |editor, cx| editor.selected_display_ranges(cx)), [DisplayPoint::new(0, 41)..DisplayPoint::new(0, 43)] @@ -743,7 +777,7 @@ mod tests { }); search_bar.update(cx, |search_bar, cx| { - search_bar.select_match(&SelectMatch(Direction::Prev), cx); + search_bar.select_prev_match(&SelectPrevMatch, cx); assert_eq!( editor.update(cx, |editor, cx| editor.selected_display_ranges(cx)), [DisplayPoint::new(3, 56)..DisplayPoint::new(3, 58)] @@ -754,7 +788,7 @@ mod tests { }); search_bar.update(cx, |search_bar, cx| { - search_bar.select_match(&SelectMatch(Direction::Prev), cx); + search_bar.select_prev_match(&SelectPrevMatch, cx); assert_eq!( editor.update(cx, |editor, cx| editor.selected_display_ranges(cx)), [DisplayPoint::new(3, 11)..DisplayPoint::new(3, 13)] @@ -765,7 +799,7 @@ mod tests { }); search_bar.update(cx, |search_bar, cx| { - search_bar.select_match(&SelectMatch(Direction::Prev), cx); + search_bar.select_prev_match(&SelectPrevMatch, cx); assert_eq!( editor.update(cx, |editor, cx| editor.selected_display_ranges(cx)), [DisplayPoint::new(0, 41)..DisplayPoint::new(0, 43)] @@ -782,7 +816,7 @@ mod tests { }); search_bar.update(cx, |search_bar, cx| { assert_eq!(search_bar.active_match_index, Some(1)); - search_bar.select_match(&SelectMatch(Direction::Prev), cx); + search_bar.select_prev_match(&SelectPrevMatch, cx); assert_eq!( editor.update(cx, |editor, cx| editor.selected_display_ranges(cx)), [DisplayPoint::new(0, 41)..DisplayPoint::new(0, 43)] @@ -799,7 +833,7 @@ mod tests { }); search_bar.update(cx, |search_bar, cx| { assert_eq!(search_bar.active_match_index, Some(1)); - search_bar.select_match(&SelectMatch(Direction::Next), cx); + search_bar.select_next_match(&SelectNextMatch, cx); assert_eq!( editor.update(cx, |editor, cx| editor.selected_display_ranges(cx)), [DisplayPoint::new(3, 11)..DisplayPoint::new(3, 13)] @@ -816,7 +850,7 @@ mod tests { }); search_bar.update(cx, |search_bar, cx| { assert_eq!(search_bar.active_match_index, Some(2)); - search_bar.select_match(&SelectMatch(Direction::Prev), cx); + search_bar.select_prev_match(&SelectPrevMatch, cx); assert_eq!( editor.update(cx, |editor, cx| editor.selected_display_ranges(cx)), [DisplayPoint::new(3, 56)..DisplayPoint::new(3, 58)] @@ -833,7 +867,7 @@ mod tests { }); search_bar.update(cx, |search_bar, cx| { assert_eq!(search_bar.active_match_index, Some(2)); - search_bar.select_match(&SelectMatch(Direction::Next), cx); + search_bar.select_next_match(&SelectNextMatch, cx); assert_eq!( editor.update(cx, |editor, cx| editor.selected_display_ranges(cx)), [DisplayPoint::new(0, 41)..DisplayPoint::new(0, 43)] @@ -850,7 +884,7 @@ mod tests { }); search_bar.update(cx, |search_bar, cx| { assert_eq!(search_bar.active_match_index, Some(0)); - search_bar.select_match(&SelectMatch(Direction::Prev), cx); + search_bar.select_prev_match(&SelectPrevMatch, cx); assert_eq!( editor.update(cx, |editor, cx| editor.selected_display_ranges(cx)), [DisplayPoint::new(3, 56)..DisplayPoint::new(3, 58)] diff --git a/crates/search/src/project_search.rs b/crates/search/src/project_search.rs index f96e3c84d1..39ff1a09ea 100644 --- a/crates/search/src/project_search.rs +++ b/crates/search/src/project_search.rs @@ -1,6 +1,6 @@ use crate::{ - active_match_index, match_index_for_direction, Direction, SearchOption, SelectMatch, - ToggleSearchOption, + active_match_index, match_index_for_direction, Direction, SearchOption, SelectNextMatch, + SelectPrevMatch, ToggleSearchOption, }; use collections::HashMap; use editor::{Anchor, Autoscroll, Editor, MultiBuffer, SelectAll}; @@ -34,14 +34,15 @@ pub fn init(cx: &mut MutableAppContext) { Binding::new("cmd-shift-F", Deploy, Some("Workspace")), Binding::new("enter", Search, Some("ProjectSearchBar")), Binding::new("cmd-enter", SearchInNew, Some("ProjectSearchBar")), - Binding::new("cmd-g", SelectMatch(Direction::Next), Some("Pane")), - Binding::new("cmd-shift-G", SelectMatch(Direction::Prev), Some("Pane")), + Binding::new("cmd-g", SelectNextMatch, Some("Pane")), + Binding::new("cmd-shift-G", SelectPrevMatch, Some("Pane")), ]); cx.add_action(ProjectSearchView::deploy); cx.add_action(ProjectSearchBar::search); cx.add_action(ProjectSearchBar::search_in_new); cx.add_action(ProjectSearchBar::toggle_search_option); - cx.add_action(ProjectSearchBar::select_match); + cx.add_action(ProjectSearchBar::select_next_match); + cx.add_action(ProjectSearchBar::select_prev_match); cx.add_action(ProjectSearchBar::toggle_focus); cx.capture_action(ProjectSearchBar::tab); } @@ -545,18 +546,23 @@ impl ProjectSearchBar { } } - fn select_match( - pane: &mut Pane, - &SelectMatch(direction): &SelectMatch, - cx: &mut ViewContext, - ) { + fn select_next_match(pane: &mut Pane, _: &SelectNextMatch, cx: &mut ViewContext) { if let Some(search_view) = pane .active_item() .and_then(|item| item.downcast::()) { - search_view.update(cx, |search_view, cx| { - search_view.select_match(direction, cx); - }); + search_view.update(cx, |view, cx| view.select_match(Direction::Next, cx)); + } else { + cx.propagate_action(); + } + } + + fn select_prev_match(pane: &mut Pane, _: &SelectPrevMatch, cx: &mut ViewContext) { + if let Some(search_view) = pane + .active_item() + .and_then(|item| item.downcast::()) + { + search_view.update(cx, |view, cx| view.select_match(Direction::Prev, cx)); } else { cx.propagate_action(); } @@ -635,7 +641,10 @@ impl ProjectSearchBar { .with_style(style.container) .boxed() }) - .on_click(move |cx| cx.dispatch_action(SelectMatch(direction))) + .on_click(move |cx| match direction { + Direction::Prev => cx.dispatch_action(SelectPrevMatch), + Direction::Next => cx.dispatch_action(SelectNextMatch), + }) .with_cursor_style(CursorStyle::PointingHand) .boxed() } diff --git a/crates/search/src/search.rs b/crates/search/src/search.rs index 83e5a259d2..48cf24b1f3 100644 --- a/crates/search/src/search.rs +++ b/crates/search/src/search.rs @@ -1,6 +1,6 @@ pub use buffer_search::BufferSearchBar; use editor::{Anchor, MultiBufferSnapshot}; -use gpui::{impl_actions, MutableAppContext}; +use gpui::{actions, impl_internal_actions, MutableAppContext}; pub use project_search::{ProjectSearchBar, ProjectSearchView}; use std::{ cmp::{self, Ordering}, @@ -18,10 +18,8 @@ pub fn init(cx: &mut MutableAppContext) { #[derive(Clone)] pub struct ToggleSearchOption(pub SearchOption); -#[derive(Clone)] -pub struct SelectMatch(pub Direction); - -impl_actions!(search, [ToggleSearchOption, SelectMatch]); +actions!(search, [SelectNextMatch, SelectPrevMatch]); +impl_internal_actions!(search, [ToggleSearchOption]); #[derive(Clone, Copy)] pub enum SearchOption { diff --git a/crates/server/Cargo.toml b/crates/server/Cargo.toml index fe1a63f5f1..8aafcd6a30 100644 --- a/crates/server/Cargo.toml +++ b/crates/server/Cargo.toml @@ -64,6 +64,7 @@ language = { path = "../language", features = ["test-support"] } lsp = { path = "../lsp", features = ["test-support"] } project = { path = "../project", features = ["test-support"] } settings = { path = "../settings", features = ["test-support"] } +theme = { path = "../theme" } workspace = { path = "../workspace", features = ["test-support"] } ctor = "0.1" env_logger = "0.8" diff --git a/crates/server/src/rpc.rs b/crates/server/src/rpc.rs index efa19653ae..5ebe36e824 100644 --- a/crates/server/src/rpc.rs +++ b/crates/server/src/rpc.rs @@ -1117,6 +1117,7 @@ mod tests { }, time::Duration, }; + use theme::ThemeRegistry; use util::TryFutureExt; use workspace::{Item, SplitDirection, ToggleFollow, Workspace, WorkspaceParams}; @@ -5633,6 +5634,7 @@ mod tests { project: project.clone(), user_store: self.user_store.clone(), languages: self.language_registry.clone(), + themes: ThemeRegistry::new((), cx.font_cache().clone()), channel_list: cx.add_model(|cx| { ChannelList::new(self.user_store.clone(), self.client.clone(), cx) }), diff --git a/crates/theme_selector/src/theme_selector.rs b/crates/theme_selector/src/theme_selector.rs index b69552d02b..733df65b82 100644 --- a/crates/theme_selector/src/theme_selector.rs +++ b/crates/theme_selector/src/theme_selector.rs @@ -1,8 +1,8 @@ use editor::Editor; use fuzzy::{match_strings, StringMatch, StringMatchCandidate}; use gpui::{ + actions, elements::*, - impl_actions, keymap::{self, Binding}, AppContext, Axis, Element, ElementBox, Entity, MutableAppContext, RenderContext, View, ViewContext, ViewHandle, @@ -25,15 +25,9 @@ pub struct ThemeSelector { selection_completed: bool, } -#[derive(Clone)] -pub struct Toggle(pub Arc); +actions!(theme_selector, [Toggle, Reload]); -#[derive(Clone)] -pub struct Reload(pub Arc); - -impl_actions!(theme_selector, [Toggle, Reload]); - -pub fn init(themes: Arc, cx: &mut MutableAppContext) { +pub fn init(cx: &mut MutableAppContext) { cx.add_action(ThemeSelector::confirm); cx.add_action(ThemeSelector::select_prev); cx.add_action(ThemeSelector::select_next); @@ -41,9 +35,9 @@ pub fn init(themes: Arc, cx: &mut MutableAppContext) { cx.add_action(ThemeSelector::reload); cx.add_bindings(vec![ - Binding::new("cmd-k cmd-t", Toggle(themes.clone()), None), - Binding::new("cmd-k t", Reload(themes.clone()), None), - Binding::new("escape", Toggle(themes.clone()), Some("ThemeSelector")), + Binding::new("cmd-k cmd-t", Toggle, None), + Binding::new("cmd-k t", Reload, None), + Binding::new("escape", Toggle, Some("ThemeSelector")), ]); } @@ -79,18 +73,20 @@ impl ThemeSelector { this } - fn toggle(workspace: &mut Workspace, action: &Toggle, cx: &mut ViewContext) { + fn toggle(workspace: &mut Workspace, _: &Toggle, cx: &mut ViewContext) { + let themes = workspace.themes(); workspace.toggle_modal(cx, |cx, _| { - let selector = cx.add_view(|cx| Self::new(action.0.clone(), cx)); + let selector = cx.add_view(|cx| Self::new(themes, cx)); cx.subscribe(&selector, Self::on_event).detach(); selector }); } - fn reload(_: &mut Workspace, action: &Reload, cx: &mut ViewContext) { + fn reload(workspace: &mut Workspace, _: &Reload, cx: &mut ViewContext) { let current_theme_name = cx.global::().theme.name.clone(); - action.0.clear(); - match action.0.get(¤t_theme_name) { + let themes = workspace.themes(); + themes.clear(); + match themes.get(¤t_theme_name) { Ok(theme) => { Self::set_theme(theme, cx); log::info!("reloaded theme {}", current_theme_name); diff --git a/crates/vim/Cargo.toml b/crates/vim/Cargo.toml index 4ffa6a4363..f1413d7c51 100644 --- a/crates/vim/Cargo.toml +++ b/crates/vim/Cargo.toml @@ -12,6 +12,7 @@ collections = { path = "../collections" } editor = { path = "../editor" } gpui = { path = "../gpui" } language = { path = "../language" } +serde = { version = "1", features = ["derive"] } settings = { path = "../settings" } workspace = { path = "../workspace" } log = "0.4" diff --git a/crates/vim/src/mode.rs b/crates/vim/src/mode.rs index f00c14e2e8..ccebf0ad68 100644 --- a/crates/vim/src/mode.rs +++ b/crates/vim/src/mode.rs @@ -1,7 +1,8 @@ use editor::CursorShape; use gpui::keymap::Context; +use serde::Deserialize; -#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize)] pub enum Mode { Normal(NormalState), Insert, @@ -44,7 +45,7 @@ impl Default for Mode { } } -#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize)] pub enum NormalState { None, GPrefix, diff --git a/crates/vim/src/normal.rs b/crates/vim/src/normal.rs index ce5305e8bf..0a49d2c8fd 100644 --- a/crates/vim/src/normal.rs +++ b/crates/vim/src/normal.rs @@ -4,15 +4,16 @@ use crate::{mode::NormalState, Mode, SwitchMode, VimState}; use editor::{char_kind, movement, Bias}; use gpui::{actions, impl_actions, keymap::Binding, MutableAppContext, ViewContext}; use language::SelectionGoal; +use serde::Deserialize; use workspace::Workspace; -#[derive(Clone)] +#[derive(Clone, Deserialize)] struct MoveToNextWordStart(pub bool); -#[derive(Clone)] +#[derive(Clone, Deserialize)] struct MoveToNextWordEnd(pub bool); -#[derive(Clone)] +#[derive(Clone, Deserialize)] struct MoveToPreviousWordStart(pub bool); impl_actions!( diff --git a/crates/vim/src/vim.rs b/crates/vim/src/vim.rs index 2d76831076..adcf2fb130 100644 --- a/crates/vim/src/vim.rs +++ b/crates/vim/src/vim.rs @@ -8,12 +8,13 @@ mod vim_test_context; use collections::HashMap; use editor::{CursorShape, Editor}; use gpui::{impl_actions, MutableAppContext, ViewContext, WeakViewHandle}; +use serde::Deserialize; use mode::Mode; use settings::Settings; use workspace::{self, Workspace}; -#[derive(Clone)] +#[derive(Clone, Deserialize)] pub struct SwitchMode(pub Mode); impl_actions!(vim, [SwitchMode]); diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index 6459e46fca..a60e2ff9db 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -7,13 +7,14 @@ use gpui::{ actions, elements::*, geometry::{rect::RectF, vector::vec2f}, - impl_actions, + impl_actions, impl_internal_actions, keymap::Binding, platform::{CursorStyle, NavigationDirection}, AppContext, Entity, MutableAppContext, PromptLevel, Quad, RenderContext, Task, View, ViewContext, ViewHandle, WeakViewHandle, }; use project::{ProjectEntryId, ProjectPath}; +use serde::Deserialize; use settings::Settings; use std::{any::Any, cell::RefCell, cmp, mem, path::Path, rc::Rc}; use util::ResultExt; @@ -28,13 +29,16 @@ actions!( ] ); -#[derive(Clone)] +#[derive(Clone, Deserialize)] pub struct Split(pub SplitDirection); #[derive(Clone)] -pub struct CloseItem(pub CloseItemParams); +pub struct CloseItem { + pub item_id: usize, + pub pane: WeakViewHandle, +} -#[derive(Clone)] +#[derive(Clone, Deserialize)] pub struct ActivateItem(pub usize); #[derive(Clone)] @@ -43,13 +47,8 @@ pub struct GoBack(pub Option>); #[derive(Clone)] pub struct GoForward(pub Option>); -impl_actions!(pane, [Split, CloseItem, ActivateItem, GoBack, GoForward,]); - -#[derive(Clone)] -pub struct CloseItemParams { - pub item_id: usize, - pub pane: WeakViewHandle, -} +impl_actions!(pane, [Split]); +impl_internal_actions!(pane, [CloseItem, ActivateItem, GoBack, GoForward]); const MAX_NAVIGATION_HISTORY_LEN: usize = 1024; @@ -66,8 +65,8 @@ pub fn init(cx: &mut MutableAppContext) { cx.add_async_action(Pane::close_active_item); cx.add_async_action(Pane::close_inactive_items); cx.add_async_action(|workspace: &mut Workspace, action: &CloseItem, cx| { - let pane = action.0.pane.upgrade(cx)?; - Some(Pane::close_item(workspace, pane, action.0.item_id, cx)) + let pane = action.pane.upgrade(cx)?; + Some(Pane::close_item(workspace, pane, action.item_id, cx)) }); cx.add_action(|pane: &mut Pane, action: &Split, cx| { pane.split(action.0, cx); @@ -747,10 +746,10 @@ impl Pane { .on_click({ let pane = pane.clone(); move |cx| { - cx.dispatch_action(CloseItem(CloseItemParams { + cx.dispatch_action(CloseItem { item_id, pane: pane.clone(), - })) + }) } }) .named("close-tab-icon") diff --git a/crates/workspace/src/pane_group.rs b/crates/workspace/src/pane_group.rs index 258d644148..d5661ba2c9 100644 --- a/crates/workspace/src/pane_group.rs +++ b/crates/workspace/src/pane_group.rs @@ -4,6 +4,7 @@ use client::PeerId; use collections::HashMap; use gpui::{elements::*, Axis, Border, ViewHandle}; use project::Collaborator; +use serde::Deserialize; use theme::Theme; #[derive(Clone, Debug, Eq, PartialEq)] @@ -254,7 +255,8 @@ impl PaneAxis { } } -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Copy, Debug, Deserialize)] +#[serde(rename_all = "snake_case")] pub enum SplitDirection { Up, Down, diff --git a/crates/workspace/src/sidebar.rs b/crates/workspace/src/sidebar.rs index 49852d16f2..78b1d4a6ea 100644 --- a/crates/workspace/src/sidebar.rs +++ b/crates/workspace/src/sidebar.rs @@ -1,5 +1,7 @@ use super::Workspace; -use gpui::{elements::*, impl_actions, platform::CursorStyle, AnyViewHandle, RenderContext}; +use gpui::{ + elements::*, impl_internal_actions, platform::CursorStyle, AnyViewHandle, RenderContext, +}; use std::{cell::RefCell, rc::Rc}; use theme::Theme; @@ -27,7 +29,7 @@ pub struct ToggleSidebarItem(pub SidebarItemId); #[derive(Clone)] pub struct ToggleSidebarItemFocus(pub SidebarItemId); -impl_actions!(workspace, [ToggleSidebarItem, ToggleSidebarItemFocus]); +impl_internal_actions!(workspace, [ToggleSidebarItem, ToggleSidebarItemFocus]); #[derive(Clone)] pub struct SidebarItemId { diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 6b6761b1f7..475913d9db 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -17,7 +17,7 @@ use gpui::{ color::Color, elements::*, geometry::{rect::RectF, vector::vec2f, PathBuilder}, - impl_actions, + impl_internal_actions, json::{self, to_string_pretty, ToJson}, keymap::Binding, platform::{CursorStyle, WindowOptions}, @@ -101,7 +101,7 @@ pub struct ToggleFollow(pub PeerId); #[derive(Clone)] pub struct JoinProject(pub JoinProjectParams); -impl_actions!( +impl_internal_actions!( workspace, [Open, OpenNew, OpenPaths, ToggleFollow, JoinProject] ); @@ -630,6 +630,7 @@ pub struct WorkspaceParams { pub client: Arc, pub fs: Arc, pub languages: Arc, + pub themes: Arc, pub user_store: ModelHandle, pub channel_list: ModelHandle, } @@ -659,6 +660,7 @@ impl WorkspaceParams { channel_list: cx .add_model(|cx| ChannelList::new(user_store.clone(), client.clone(), cx)), client, + themes: ThemeRegistry::new((), cx.font_cache().clone()), fs, languages, user_store, @@ -677,6 +679,7 @@ impl WorkspaceParams { ), client: app_state.client.clone(), fs: app_state.fs.clone(), + themes: app_state.themes.clone(), languages: app_state.languages.clone(), user_store: app_state.user_store.clone(), channel_list: app_state.channel_list.clone(), @@ -694,6 +697,7 @@ pub struct Workspace { user_store: ModelHandle, remote_entity_subscription: Option, fs: Arc, + themes: Arc, modal: Option, center: PaneGroup, left_sidebar: Sidebar, @@ -802,6 +806,7 @@ impl Workspace { remote_entity_subscription: None, user_store: params.user_store.clone(), fs: params.fs.clone(), + themes: params.themes.clone(), left_sidebar: Sidebar::new(Side::Left), right_sidebar: Sidebar::new(Side::Right), project: params.project.clone(), @@ -834,6 +839,10 @@ impl Workspace { &self.project } + pub fn themes(&self) -> Arc { + self.themes.clone() + } + pub fn worktrees<'a>( &self, cx: &'a AppContext, diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index 8633005899..abdf68e6ab 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -146,7 +146,7 @@ fn main() { }); journal::init(app_state.clone(), cx); zed::init(&app_state, cx); - theme_selector::init(app_state.themes.clone(), cx); + theme_selector::init(cx); cx.set_menus(menus::menus(&app_state.clone())); diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 6fca5247fc..6465c9b253 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -14,7 +14,6 @@ pub use editor; use gpui::{ actions, geometry::vector::vec2f, - impl_actions, keymap::Binding, platform::{WindowBounds, WindowOptions}, ModelHandle, ViewContext, @@ -30,12 +29,16 @@ use std::{path::PathBuf, sync::Arc}; pub use workspace; use workspace::{AppState, Workspace, WorkspaceParams}; -actions!(zed, [About, Quit, OpenSettings]); - -#[derive(Clone)] -pub struct AdjustBufferFontSize(pub f32); - -impl_actions!(zed, [AdjustBufferFontSize]); +actions!( + zed, + [ + About, + Quit, + OpenSettings, + IncreaseBufferFontSize, + DecreaseBufferFontSize + ] +); const MIN_FONT_SIZE: f32 = 6.0; @@ -48,16 +51,18 @@ lazy_static! { pub fn init(app_state: &Arc, cx: &mut gpui::MutableAppContext) { cx.add_global_action(quit); - cx.add_global_action({ - move |action: &AdjustBufferFontSize, cx| { - cx.update_global::(|settings, cx| { - settings.buffer_font_size = - (settings.buffer_font_size + action.0).max(MIN_FONT_SIZE); - cx.refresh_windows(); - }); - } + cx.add_global_action(move |_: &IncreaseBufferFontSize, cx| { + cx.update_global::(|settings, cx| { + settings.buffer_font_size = (settings.buffer_font_size + 1.0).max(MIN_FONT_SIZE); + cx.refresh_windows(); + }); + }); + cx.add_global_action(move |_: &DecreaseBufferFontSize, cx| { + cx.update_global::(|settings, cx| { + settings.buffer_font_size = (settings.buffer_font_size - 1.0).max(MIN_FONT_SIZE); + cx.refresh_windows(); + }); }); - cx.add_action({ let app_state = app_state.clone(); move |_: &mut Workspace, _: &OpenSettings, cx: &mut ViewContext| { @@ -100,8 +105,8 @@ pub fn init(app_state: &Arc, cx: &mut gpui::MutableAppContext) { workspace::lsp_status::init(cx); cx.add_bindings(vec![ - Binding::new("cmd-=", AdjustBufferFontSize(1.), None), - Binding::new("cmd--", AdjustBufferFontSize(-1.), None), + Binding::new("cmd-=", IncreaseBufferFontSize, None), + Binding::new("cmd--", DecreaseBufferFontSize, None), Binding::new("cmd-,", OpenSettings, None), ]) } @@ -134,6 +139,7 @@ pub fn build_workspace( client: app_state.client.clone(), fs: app_state.fs.clone(), languages: app_state.languages.clone(), + themes: app_state.themes.clone(), user_store: app_state.user_store.clone(), channel_list: app_state.channel_list.clone(), }; From ab8204368c291b690c87c0e2ef377145e51d1e77 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Sat, 9 Apr 2022 08:30:42 -0600 Subject: [PATCH 02/22] Rename zed-server to collab Over time, I think we may end up having multiple services, so it seems like a good opportunity to name this one more specifically while the cost is low. It just seems like naming it "zed" and "zed-server" leaves it a bit open ended. --- .gitignore | 4 +- Cargo.lock | 106 +++++++++--------- Dockerfile | 14 +-- Dockerfile.migrator | 2 +- Procfile | 2 +- README.md | 2 +- crates/{server => collab}/.env.template.toml | 0 crates/{server => collab}/Cargo.toml | 6 +- crates/{server => collab}/Procfile | 2 +- crates/{server => collab}/README.md | 0 crates/{server => collab}/basic.conf | 0 crates/{server => collab}/favicon.ico | Bin .../k8s/environments/production.sh | 0 .../k8s/environments/staging.sh | 0 .../k8s/manifest.template.yml | 0 .../k8s/migrate.template.yml | 0 .../20210527024318_initial_schema.sql | 0 .../20210607190313_create_access_tokens.sql | 0 .../20210805175147_create_chat_tables.sql | 0 ...16123647_add_nonce_to_channel_messages.sql | 0 ...0210920192001_add_interests_to_signups.sql | 0 crates/{server => collab}/src/admin.rs | 0 crates/{server => collab}/src/api.rs | 0 crates/{server => collab}/src/assets.rs | 0 crates/{server => collab}/src/auth.rs | 0 crates/{server => collab}/src/bin/dotenv.rs | 0 crates/{server => collab}/src/bin/seed.rs | 0 crates/{server => collab}/src/careers.rs | 0 crates/{server => collab}/src/community.rs | 0 crates/{server => collab}/src/db.rs | 0 crates/{server => collab}/src/env.rs | 0 crates/{server => collab}/src/errors.rs | 0 crates/{server => collab}/src/expiring.rs | 0 crates/{server => collab}/src/github.rs | 0 crates/{server => collab}/src/home.rs | 0 crates/{server => collab}/src/main.rs | 0 crates/{server => collab}/src/releases.rs | 0 crates/{server => collab}/src/rpc.rs | 0 crates/{server => collab}/src/rpc/store.rs | 0 crates/{server => collab}/src/team.rs | 0 .../static/browserconfig.xml | 0 .../static/fonts/VisbyCF-Bold.eot | Bin .../static/fonts/VisbyCF-Bold.woff | Bin .../static/fonts/VisbyCF-Bold.woff2 | Bin .../static/fonts/VisbyCF-BoldOblique.eot | Bin .../static/fonts/VisbyCF-BoldOblique.woff | Bin .../static/fonts/VisbyCF-BoldOblique.woff2 | Bin .../static/fonts/VisbyCF-DemiBold.eot | Bin .../static/fonts/VisbyCF-DemiBold.woff | Bin .../static/fonts/VisbyCF-DemiBold.woff2 | Bin .../static/fonts/VisbyCF-DemiBoldOblique.eot | Bin .../static/fonts/VisbyCF-DemiBoldOblique.woff | Bin .../fonts/VisbyCF-DemiBoldOblique.woff2 | Bin .../static/fonts/VisbyCF-ExtraBold.eot | Bin .../static/fonts/VisbyCF-ExtraBold.woff | Bin .../static/fonts/VisbyCF-ExtraBold.woff2 | Bin .../static/fonts/VisbyCF-ExtraBoldOblique.eot | Bin .../fonts/VisbyCF-ExtraBoldOblique.woff | Bin .../fonts/VisbyCF-ExtraBoldOblique.woff2 | Bin .../static/fonts/VisbyCF-Heavy.eot | Bin .../static/fonts/VisbyCF-Heavy.woff | Bin .../static/fonts/VisbyCF-Heavy.woff2 | Bin .../static/fonts/VisbyCF-HeavyOblique.eot | Bin .../static/fonts/VisbyCF-HeavyOblique.woff | Bin .../static/fonts/VisbyCF-HeavyOblique.woff2 | Bin .../static/fonts/VisbyCF-Light.eot | Bin .../static/fonts/VisbyCF-Light.woff | Bin .../static/fonts/VisbyCF-Light.woff2 | Bin .../static/fonts/VisbyCF-LightOblique.eot | Bin .../static/fonts/VisbyCF-LightOblique.woff | Bin .../static/fonts/VisbyCF-LightOblique.woff2 | Bin .../static/fonts/VisbyCF-Medium.eot | Bin .../static/fonts/VisbyCF-Medium.woff | Bin .../static/fonts/VisbyCF-Medium.woff2 | Bin .../static/fonts/VisbyCF-MediumOblique.eot | Bin .../static/fonts/VisbyCF-MediumOblique.woff | Bin .../static/fonts/VisbyCF-MediumOblique.woff2 | Bin .../static/fonts/VisbyCF-Regular.eot | Bin .../static/fonts/VisbyCF-Regular.woff | Bin .../static/fonts/VisbyCF-Regular.woff2 | Bin .../static/fonts/VisbyCF-RegularOblique.eot | Bin .../static/fonts/VisbyCF-RegularOblique.woff | Bin .../static/fonts/VisbyCF-RegularOblique.woff2 | Bin .../static/fonts/VisbyCF-Thin.eot | Bin .../static/fonts/VisbyCF-Thin.woff | Bin .../static/fonts/VisbyCF-Thin.woff2 | Bin .../static/fonts/VisbyCF-ThinOblique.eot | Bin .../static/fonts/VisbyCF-ThinOblique.woff | Bin .../static/fonts/VisbyCF-ThinOblique.woff2 | Bin .../static/images/android-chrome-192x192.png | Bin .../static/images/android-chrome-512x512.png | Bin .../static/images/apple-touch-icon.png | Bin .../static/images/favicon-16x16.png | Bin .../static/images/favicon-32x32.png | Bin .../static/images/favicon.png | Bin .../static/images/favicon.svg | 0 .../static/images/mstile-144x144.png | Bin .../static/images/mstile-150x150.png | Bin .../static/images/mstile-310x150.png | Bin .../static/images/mstile-310x310.png | Bin .../static/images/mstile-70x70.png | Bin .../static/images/safari-pinned-tab.svg | 0 .../static/images/zed-og-image.png | Bin .../static/images/zed-twitter-image.png | Bin crates/{server => collab}/static/prism.js | 0 crates/{server => collab}/static/prose.css | 0 .../{server => collab}/static/prose.css.map | 0 crates/{server => collab}/static/prose.scss | 0 .../static/site.webmanifest | 0 crates/{server => collab}/static/svg/hero.svg | 0 crates/{server => collab}/styles.css | 0 crates/{server => collab}/templates/admin.hbs | 0 .../{server => collab}/templates/careers.hbs | 0 .../templates/community.hbs | 0 crates/{server => collab}/templates/docs.hbs | 0 crates/{server => collab}/templates/error.hbs | 0 crates/{server => collab}/templates/home.hbs | 0 .../templates/partials/layout.hbs | 0 .../{server => collab}/templates/releases.hbs | 0 .../{server => collab}/templates/signup.hbs | 0 crates/{server => collab}/templates/team.hbs | 0 crates/server/.env.toml | 42 ------- script/deploy | 2 +- script/seed-db | 2 +- 124 files changed, 71 insertions(+), 113 deletions(-) rename crates/{server => collab}/.env.template.toml (100%) rename crates/{server => collab}/Cargo.toml (96%) rename crates/{server => collab}/Procfile (56%) rename crates/{server => collab}/README.md (100%) rename crates/{server => collab}/basic.conf (100%) rename crates/{server => collab}/favicon.ico (100%) rename crates/{server => collab}/k8s/environments/production.sh (100%) rename crates/{server => collab}/k8s/environments/staging.sh (100%) rename crates/{server => collab}/k8s/manifest.template.yml (100%) rename crates/{server => collab}/k8s/migrate.template.yml (100%) rename crates/{server => collab}/migrations/20210527024318_initial_schema.sql (100%) rename crates/{server => collab}/migrations/20210607190313_create_access_tokens.sql (100%) rename crates/{server => collab}/migrations/20210805175147_create_chat_tables.sql (100%) rename crates/{server => collab}/migrations/20210916123647_add_nonce_to_channel_messages.sql (100%) rename crates/{server => collab}/migrations/20210920192001_add_interests_to_signups.sql (100%) rename crates/{server => collab}/src/admin.rs (100%) rename crates/{server => collab}/src/api.rs (100%) rename crates/{server => collab}/src/assets.rs (100%) rename crates/{server => collab}/src/auth.rs (100%) rename crates/{server => collab}/src/bin/dotenv.rs (100%) rename crates/{server => collab}/src/bin/seed.rs (100%) rename crates/{server => collab}/src/careers.rs (100%) rename crates/{server => collab}/src/community.rs (100%) rename crates/{server => collab}/src/db.rs (100%) rename crates/{server => collab}/src/env.rs (100%) rename crates/{server => collab}/src/errors.rs (100%) rename crates/{server => collab}/src/expiring.rs (100%) rename crates/{server => collab}/src/github.rs (100%) rename crates/{server => collab}/src/home.rs (100%) rename crates/{server => collab}/src/main.rs (100%) rename crates/{server => collab}/src/releases.rs (100%) rename crates/{server => collab}/src/rpc.rs (100%) rename crates/{server => collab}/src/rpc/store.rs (100%) rename crates/{server => collab}/src/team.rs (100%) rename crates/{server => collab}/static/browserconfig.xml (100%) rename crates/{server => collab}/static/fonts/VisbyCF-Bold.eot (100%) rename crates/{server => collab}/static/fonts/VisbyCF-Bold.woff (100%) rename crates/{server => collab}/static/fonts/VisbyCF-Bold.woff2 (100%) rename crates/{server => collab}/static/fonts/VisbyCF-BoldOblique.eot (100%) rename crates/{server => collab}/static/fonts/VisbyCF-BoldOblique.woff (100%) rename crates/{server => collab}/static/fonts/VisbyCF-BoldOblique.woff2 (100%) rename crates/{server => collab}/static/fonts/VisbyCF-DemiBold.eot (100%) rename crates/{server => collab}/static/fonts/VisbyCF-DemiBold.woff (100%) rename crates/{server => collab}/static/fonts/VisbyCF-DemiBold.woff2 (100%) rename crates/{server => collab}/static/fonts/VisbyCF-DemiBoldOblique.eot (100%) rename crates/{server => collab}/static/fonts/VisbyCF-DemiBoldOblique.woff (100%) rename crates/{server => collab}/static/fonts/VisbyCF-DemiBoldOblique.woff2 (100%) rename crates/{server => collab}/static/fonts/VisbyCF-ExtraBold.eot (100%) rename crates/{server => collab}/static/fonts/VisbyCF-ExtraBold.woff (100%) rename crates/{server => collab}/static/fonts/VisbyCF-ExtraBold.woff2 (100%) rename crates/{server => collab}/static/fonts/VisbyCF-ExtraBoldOblique.eot (100%) rename crates/{server => collab}/static/fonts/VisbyCF-ExtraBoldOblique.woff (100%) rename crates/{server => collab}/static/fonts/VisbyCF-ExtraBoldOblique.woff2 (100%) rename crates/{server => collab}/static/fonts/VisbyCF-Heavy.eot (100%) rename crates/{server => collab}/static/fonts/VisbyCF-Heavy.woff (100%) rename crates/{server => collab}/static/fonts/VisbyCF-Heavy.woff2 (100%) rename crates/{server => collab}/static/fonts/VisbyCF-HeavyOblique.eot (100%) rename crates/{server => collab}/static/fonts/VisbyCF-HeavyOblique.woff (100%) rename crates/{server => collab}/static/fonts/VisbyCF-HeavyOblique.woff2 (100%) rename crates/{server => collab}/static/fonts/VisbyCF-Light.eot (100%) rename crates/{server => collab}/static/fonts/VisbyCF-Light.woff (100%) rename crates/{server => collab}/static/fonts/VisbyCF-Light.woff2 (100%) rename crates/{server => collab}/static/fonts/VisbyCF-LightOblique.eot (100%) rename crates/{server => collab}/static/fonts/VisbyCF-LightOblique.woff (100%) rename crates/{server => collab}/static/fonts/VisbyCF-LightOblique.woff2 (100%) rename crates/{server => collab}/static/fonts/VisbyCF-Medium.eot (100%) rename crates/{server => collab}/static/fonts/VisbyCF-Medium.woff (100%) rename crates/{server => collab}/static/fonts/VisbyCF-Medium.woff2 (100%) rename crates/{server => collab}/static/fonts/VisbyCF-MediumOblique.eot (100%) rename crates/{server => collab}/static/fonts/VisbyCF-MediumOblique.woff (100%) rename crates/{server => collab}/static/fonts/VisbyCF-MediumOblique.woff2 (100%) rename crates/{server => collab}/static/fonts/VisbyCF-Regular.eot (100%) rename crates/{server => collab}/static/fonts/VisbyCF-Regular.woff (100%) rename crates/{server => collab}/static/fonts/VisbyCF-Regular.woff2 (100%) rename crates/{server => collab}/static/fonts/VisbyCF-RegularOblique.eot (100%) rename crates/{server => collab}/static/fonts/VisbyCF-RegularOblique.woff (100%) rename crates/{server => collab}/static/fonts/VisbyCF-RegularOblique.woff2 (100%) rename crates/{server => collab}/static/fonts/VisbyCF-Thin.eot (100%) rename crates/{server => collab}/static/fonts/VisbyCF-Thin.woff (100%) rename crates/{server => collab}/static/fonts/VisbyCF-Thin.woff2 (100%) rename crates/{server => collab}/static/fonts/VisbyCF-ThinOblique.eot (100%) rename crates/{server => collab}/static/fonts/VisbyCF-ThinOblique.woff (100%) rename crates/{server => collab}/static/fonts/VisbyCF-ThinOblique.woff2 (100%) rename crates/{server => collab}/static/images/android-chrome-192x192.png (100%) rename crates/{server => collab}/static/images/android-chrome-512x512.png (100%) rename crates/{server => collab}/static/images/apple-touch-icon.png (100%) rename crates/{server => collab}/static/images/favicon-16x16.png (100%) rename crates/{server => collab}/static/images/favicon-32x32.png (100%) rename crates/{server => collab}/static/images/favicon.png (100%) rename crates/{server => collab}/static/images/favicon.svg (100%) rename crates/{server => collab}/static/images/mstile-144x144.png (100%) rename crates/{server => collab}/static/images/mstile-150x150.png (100%) rename crates/{server => collab}/static/images/mstile-310x150.png (100%) rename crates/{server => collab}/static/images/mstile-310x310.png (100%) rename crates/{server => collab}/static/images/mstile-70x70.png (100%) rename crates/{server => collab}/static/images/safari-pinned-tab.svg (100%) rename crates/{server => collab}/static/images/zed-og-image.png (100%) rename crates/{server => collab}/static/images/zed-twitter-image.png (100%) rename crates/{server => collab}/static/prism.js (100%) rename crates/{server => collab}/static/prose.css (100%) rename crates/{server => collab}/static/prose.css.map (100%) rename crates/{server => collab}/static/prose.scss (100%) rename crates/{server => collab}/static/site.webmanifest (100%) rename crates/{server => collab}/static/svg/hero.svg (100%) rename crates/{server => collab}/styles.css (100%) rename crates/{server => collab}/templates/admin.hbs (100%) rename crates/{server => collab}/templates/careers.hbs (100%) rename crates/{server => collab}/templates/community.hbs (100%) rename crates/{server => collab}/templates/docs.hbs (100%) rename crates/{server => collab}/templates/error.hbs (100%) rename crates/{server => collab}/templates/home.hbs (100%) rename crates/{server => collab}/templates/partials/layout.hbs (100%) rename crates/{server => collab}/templates/releases.hbs (100%) rename crates/{server => collab}/templates/signup.hbs (100%) rename crates/{server => collab}/templates/team.hbs (100%) delete mode 100644 crates/server/.env.toml diff --git a/.gitignore b/.gitignore index 140053fc2c..a733bb3bb7 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,6 @@ .DS_Store /script/node_modules /styles/node_modules -/crates/server/.env.toml -/crates/server/static/styles.css +/crates/collab/.env.toml +/crates/collab/static/styles.css /vendor/bin diff --git a/Cargo.lock b/Cargo.lock index 92aaa62c6e..7e74f4c964 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1067,6 +1067,59 @@ dependencies = [ "objc", ] +[[package]] +name = "collab" +version = "0.1.0" +dependencies = [ + "anyhow", + "async-io", + "async-sqlx-session", + "async-std", + "async-trait", + "async-tungstenite", + "base64 0.13.0", + "clap 3.0.0-beta.2", + "client", + "collections", + "comrak", + "ctor", + "editor", + "either", + "env_logger 0.8.3", + "envy", + "futures", + "gpui", + "handlebars", + "http-auth-basic", + "json_env_logger", + "jwt-simple", + "language", + "lazy_static", + "lipsum", + "log", + "lsp", + "oauth2", + "oauth2-surf", + "parking_lot", + "project", + "rand 0.8.3", + "rpc", + "rust-embed", + "scrypt", + "serde", + "serde_json", + "settings", + "sha-1 0.9.6", + "sqlx 0.5.5", + "surf", + "tide", + "tide-compress", + "time 0.2.27", + "toml", + "util", + "workspace", +] + [[package]] name = "collections" version = "0.1.0" @@ -6136,59 +6189,6 @@ dependencies = [ "workspace", ] -[[package]] -name = "zed-server" -version = "0.1.0" -dependencies = [ - "anyhow", - "async-io", - "async-sqlx-session", - "async-std", - "async-trait", - "async-tungstenite", - "base64 0.13.0", - "clap 3.0.0-beta.2", - "client", - "collections", - "comrak", - "ctor", - "editor", - "either", - "env_logger 0.8.3", - "envy", - "futures", - "gpui", - "handlebars", - "http-auth-basic", - "json_env_logger", - "jwt-simple", - "language", - "lazy_static", - "lipsum", - "log", - "lsp", - "oauth2", - "oauth2-surf", - "parking_lot", - "project", - "rand 0.8.3", - "rpc", - "rust-embed", - "scrypt", - "serde", - "serde_json", - "settings", - "sha-1 0.9.6", - "sqlx 0.5.5", - "surf", - "tide", - "tide-compress", - "time 0.2.27", - "toml", - "util", - "workspace", -] - [[package]] name = "zeroize" version = "1.3.0" diff --git a/Dockerfile b/Dockerfile index af4365649f..544d9eae86 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,20 +14,20 @@ RUN --mount=type=cache,target=./script/node_modules \ RUN --mount=type=cache,target=./script/node_modules \ script/build-css --release -# Compile server +# Compile collab server RUN --mount=type=cache,target=./script/node_modules \ --mount=type=cache,target=/usr/local/cargo/registry \ --mount=type=cache,target=./target \ - cargo build --release --package zed-server --bin zed-server + cargo build --release --package collab --bin collab -# Copy server binary out of cached directory +# Copy collab server binary out of cached directory RUN --mount=type=cache,target=./target \ - cp /app/target/release/zed-server /app/zed-server + cp /app/target/release/collab /app/collab -# Copy server binary to the runtime image +# Copy collab server binary to the runtime image FROM debian:bullseye-slim as runtime RUN apt-get update; \ apt-get install -y --no-install-recommends libcurl4-openssl-dev ca-certificates WORKDIR app -COPY --from=builder /app/zed-server /app -ENTRYPOINT ["/app/zed-server"] +COPY --from=builder /app/collab /app +ENTRYPOINT ["/app/collab"] diff --git a/Dockerfile.migrator b/Dockerfile.migrator index 1b7a0adf3a..72e4e41d27 100644 --- a/Dockerfile.migrator +++ b/Dockerfile.migrator @@ -11,5 +11,5 @@ RUN apt-get update; \ apt-get install -y --no-install-recommends libssl1.1 WORKDIR app COPY --from=builder /app/bin/sqlx /app -COPY ./server/migrations /app/migrations +COPY ./collab/migrations /app/migrations ENTRYPOINT ["/app/sqlx", "migrate", "run"] diff --git a/Procfile b/Procfile index 08bff5acc2..a64b411ef3 100644 --- a/Procfile +++ b/Procfile @@ -1,2 +1,2 @@ web: cd ../zed.dev && PORT=3000 npx next dev -collab: cd crates/server && cargo run +collab: cd crates/collab && cargo run diff --git a/README.md b/README.md index c380115100..1bac43b694 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ script/sqlx migrate run script/seed-db ``` -Run `zed.dev` and the collaboration server. +Run the web frontend and the collaboration server. ``` brew install foreman diff --git a/crates/server/.env.template.toml b/crates/collab/.env.template.toml similarity index 100% rename from crates/server/.env.template.toml rename to crates/collab/.env.template.toml diff --git a/crates/server/Cargo.toml b/crates/collab/Cargo.toml similarity index 96% rename from crates/server/Cargo.toml rename to crates/collab/Cargo.toml index e0834b76c5..96df2ae4ec 100644 --- a/crates/server/Cargo.toml +++ b/crates/collab/Cargo.toml @@ -1,12 +1,12 @@ [package] authors = ["Nathan Sobo "] -default-run = "zed-server" +default-run = "collab" edition = "2021" -name = "zed-server" +name = "collab" version = "0.1.0" [[bin]] -name = "zed-server" +name = "collab" [[bin]] name = "seed" diff --git a/crates/server/Procfile b/crates/collab/Procfile similarity index 56% rename from crates/server/Procfile rename to crates/collab/Procfile index 74cb9a094b..ef8914fcc0 100644 --- a/crates/server/Procfile +++ b/crates/collab/Procfile @@ -1,2 +1,2 @@ -web: ./target/release/zed-server +collab: ./target/release/collab release: ./target/release/sqlx migrate run diff --git a/crates/server/README.md b/crates/collab/README.md similarity index 100% rename from crates/server/README.md rename to crates/collab/README.md diff --git a/crates/server/basic.conf b/crates/collab/basic.conf similarity index 100% rename from crates/server/basic.conf rename to crates/collab/basic.conf diff --git a/crates/server/favicon.ico b/crates/collab/favicon.ico similarity index 100% rename from crates/server/favicon.ico rename to crates/collab/favicon.ico diff --git a/crates/server/k8s/environments/production.sh b/crates/collab/k8s/environments/production.sh similarity index 100% rename from crates/server/k8s/environments/production.sh rename to crates/collab/k8s/environments/production.sh diff --git a/crates/server/k8s/environments/staging.sh b/crates/collab/k8s/environments/staging.sh similarity index 100% rename from crates/server/k8s/environments/staging.sh rename to crates/collab/k8s/environments/staging.sh diff --git a/crates/server/k8s/manifest.template.yml b/crates/collab/k8s/manifest.template.yml similarity index 100% rename from crates/server/k8s/manifest.template.yml rename to crates/collab/k8s/manifest.template.yml diff --git a/crates/server/k8s/migrate.template.yml b/crates/collab/k8s/migrate.template.yml similarity index 100% rename from crates/server/k8s/migrate.template.yml rename to crates/collab/k8s/migrate.template.yml diff --git a/crates/server/migrations/20210527024318_initial_schema.sql b/crates/collab/migrations/20210527024318_initial_schema.sql similarity index 100% rename from crates/server/migrations/20210527024318_initial_schema.sql rename to crates/collab/migrations/20210527024318_initial_schema.sql diff --git a/crates/server/migrations/20210607190313_create_access_tokens.sql b/crates/collab/migrations/20210607190313_create_access_tokens.sql similarity index 100% rename from crates/server/migrations/20210607190313_create_access_tokens.sql rename to crates/collab/migrations/20210607190313_create_access_tokens.sql diff --git a/crates/server/migrations/20210805175147_create_chat_tables.sql b/crates/collab/migrations/20210805175147_create_chat_tables.sql similarity index 100% rename from crates/server/migrations/20210805175147_create_chat_tables.sql rename to crates/collab/migrations/20210805175147_create_chat_tables.sql diff --git a/crates/server/migrations/20210916123647_add_nonce_to_channel_messages.sql b/crates/collab/migrations/20210916123647_add_nonce_to_channel_messages.sql similarity index 100% rename from crates/server/migrations/20210916123647_add_nonce_to_channel_messages.sql rename to crates/collab/migrations/20210916123647_add_nonce_to_channel_messages.sql diff --git a/crates/server/migrations/20210920192001_add_interests_to_signups.sql b/crates/collab/migrations/20210920192001_add_interests_to_signups.sql similarity index 100% rename from crates/server/migrations/20210920192001_add_interests_to_signups.sql rename to crates/collab/migrations/20210920192001_add_interests_to_signups.sql diff --git a/crates/server/src/admin.rs b/crates/collab/src/admin.rs similarity index 100% rename from crates/server/src/admin.rs rename to crates/collab/src/admin.rs diff --git a/crates/server/src/api.rs b/crates/collab/src/api.rs similarity index 100% rename from crates/server/src/api.rs rename to crates/collab/src/api.rs diff --git a/crates/server/src/assets.rs b/crates/collab/src/assets.rs similarity index 100% rename from crates/server/src/assets.rs rename to crates/collab/src/assets.rs diff --git a/crates/server/src/auth.rs b/crates/collab/src/auth.rs similarity index 100% rename from crates/server/src/auth.rs rename to crates/collab/src/auth.rs diff --git a/crates/server/src/bin/dotenv.rs b/crates/collab/src/bin/dotenv.rs similarity index 100% rename from crates/server/src/bin/dotenv.rs rename to crates/collab/src/bin/dotenv.rs diff --git a/crates/server/src/bin/seed.rs b/crates/collab/src/bin/seed.rs similarity index 100% rename from crates/server/src/bin/seed.rs rename to crates/collab/src/bin/seed.rs diff --git a/crates/server/src/careers.rs b/crates/collab/src/careers.rs similarity index 100% rename from crates/server/src/careers.rs rename to crates/collab/src/careers.rs diff --git a/crates/server/src/community.rs b/crates/collab/src/community.rs similarity index 100% rename from crates/server/src/community.rs rename to crates/collab/src/community.rs diff --git a/crates/server/src/db.rs b/crates/collab/src/db.rs similarity index 100% rename from crates/server/src/db.rs rename to crates/collab/src/db.rs diff --git a/crates/server/src/env.rs b/crates/collab/src/env.rs similarity index 100% rename from crates/server/src/env.rs rename to crates/collab/src/env.rs diff --git a/crates/server/src/errors.rs b/crates/collab/src/errors.rs similarity index 100% rename from crates/server/src/errors.rs rename to crates/collab/src/errors.rs diff --git a/crates/server/src/expiring.rs b/crates/collab/src/expiring.rs similarity index 100% rename from crates/server/src/expiring.rs rename to crates/collab/src/expiring.rs diff --git a/crates/server/src/github.rs b/crates/collab/src/github.rs similarity index 100% rename from crates/server/src/github.rs rename to crates/collab/src/github.rs diff --git a/crates/server/src/home.rs b/crates/collab/src/home.rs similarity index 100% rename from crates/server/src/home.rs rename to crates/collab/src/home.rs diff --git a/crates/server/src/main.rs b/crates/collab/src/main.rs similarity index 100% rename from crates/server/src/main.rs rename to crates/collab/src/main.rs diff --git a/crates/server/src/releases.rs b/crates/collab/src/releases.rs similarity index 100% rename from crates/server/src/releases.rs rename to crates/collab/src/releases.rs diff --git a/crates/server/src/rpc.rs b/crates/collab/src/rpc.rs similarity index 100% rename from crates/server/src/rpc.rs rename to crates/collab/src/rpc.rs diff --git a/crates/server/src/rpc/store.rs b/crates/collab/src/rpc/store.rs similarity index 100% rename from crates/server/src/rpc/store.rs rename to crates/collab/src/rpc/store.rs diff --git a/crates/server/src/team.rs b/crates/collab/src/team.rs similarity index 100% rename from crates/server/src/team.rs rename to crates/collab/src/team.rs diff --git a/crates/server/static/browserconfig.xml b/crates/collab/static/browserconfig.xml similarity index 100% rename from crates/server/static/browserconfig.xml rename to crates/collab/static/browserconfig.xml diff --git a/crates/server/static/fonts/VisbyCF-Bold.eot b/crates/collab/static/fonts/VisbyCF-Bold.eot similarity index 100% rename from crates/server/static/fonts/VisbyCF-Bold.eot rename to crates/collab/static/fonts/VisbyCF-Bold.eot diff --git a/crates/server/static/fonts/VisbyCF-Bold.woff b/crates/collab/static/fonts/VisbyCF-Bold.woff similarity index 100% rename from crates/server/static/fonts/VisbyCF-Bold.woff rename to crates/collab/static/fonts/VisbyCF-Bold.woff diff --git a/crates/server/static/fonts/VisbyCF-Bold.woff2 b/crates/collab/static/fonts/VisbyCF-Bold.woff2 similarity index 100% rename from crates/server/static/fonts/VisbyCF-Bold.woff2 rename to crates/collab/static/fonts/VisbyCF-Bold.woff2 diff --git a/crates/server/static/fonts/VisbyCF-BoldOblique.eot b/crates/collab/static/fonts/VisbyCF-BoldOblique.eot similarity index 100% rename from crates/server/static/fonts/VisbyCF-BoldOblique.eot rename to crates/collab/static/fonts/VisbyCF-BoldOblique.eot diff --git a/crates/server/static/fonts/VisbyCF-BoldOblique.woff b/crates/collab/static/fonts/VisbyCF-BoldOblique.woff similarity index 100% rename from crates/server/static/fonts/VisbyCF-BoldOblique.woff rename to crates/collab/static/fonts/VisbyCF-BoldOblique.woff diff --git a/crates/server/static/fonts/VisbyCF-BoldOblique.woff2 b/crates/collab/static/fonts/VisbyCF-BoldOblique.woff2 similarity index 100% rename from crates/server/static/fonts/VisbyCF-BoldOblique.woff2 rename to crates/collab/static/fonts/VisbyCF-BoldOblique.woff2 diff --git a/crates/server/static/fonts/VisbyCF-DemiBold.eot b/crates/collab/static/fonts/VisbyCF-DemiBold.eot similarity index 100% rename from crates/server/static/fonts/VisbyCF-DemiBold.eot rename to crates/collab/static/fonts/VisbyCF-DemiBold.eot diff --git a/crates/server/static/fonts/VisbyCF-DemiBold.woff b/crates/collab/static/fonts/VisbyCF-DemiBold.woff similarity index 100% rename from crates/server/static/fonts/VisbyCF-DemiBold.woff rename to crates/collab/static/fonts/VisbyCF-DemiBold.woff diff --git a/crates/server/static/fonts/VisbyCF-DemiBold.woff2 b/crates/collab/static/fonts/VisbyCF-DemiBold.woff2 similarity index 100% rename from crates/server/static/fonts/VisbyCF-DemiBold.woff2 rename to crates/collab/static/fonts/VisbyCF-DemiBold.woff2 diff --git a/crates/server/static/fonts/VisbyCF-DemiBoldOblique.eot b/crates/collab/static/fonts/VisbyCF-DemiBoldOblique.eot similarity index 100% rename from crates/server/static/fonts/VisbyCF-DemiBoldOblique.eot rename to crates/collab/static/fonts/VisbyCF-DemiBoldOblique.eot diff --git a/crates/server/static/fonts/VisbyCF-DemiBoldOblique.woff b/crates/collab/static/fonts/VisbyCF-DemiBoldOblique.woff similarity index 100% rename from crates/server/static/fonts/VisbyCF-DemiBoldOblique.woff rename to crates/collab/static/fonts/VisbyCF-DemiBoldOblique.woff diff --git a/crates/server/static/fonts/VisbyCF-DemiBoldOblique.woff2 b/crates/collab/static/fonts/VisbyCF-DemiBoldOblique.woff2 similarity index 100% rename from crates/server/static/fonts/VisbyCF-DemiBoldOblique.woff2 rename to crates/collab/static/fonts/VisbyCF-DemiBoldOblique.woff2 diff --git a/crates/server/static/fonts/VisbyCF-ExtraBold.eot b/crates/collab/static/fonts/VisbyCF-ExtraBold.eot similarity index 100% rename from crates/server/static/fonts/VisbyCF-ExtraBold.eot rename to crates/collab/static/fonts/VisbyCF-ExtraBold.eot diff --git a/crates/server/static/fonts/VisbyCF-ExtraBold.woff b/crates/collab/static/fonts/VisbyCF-ExtraBold.woff similarity index 100% rename from crates/server/static/fonts/VisbyCF-ExtraBold.woff rename to crates/collab/static/fonts/VisbyCF-ExtraBold.woff diff --git a/crates/server/static/fonts/VisbyCF-ExtraBold.woff2 b/crates/collab/static/fonts/VisbyCF-ExtraBold.woff2 similarity index 100% rename from crates/server/static/fonts/VisbyCF-ExtraBold.woff2 rename to crates/collab/static/fonts/VisbyCF-ExtraBold.woff2 diff --git a/crates/server/static/fonts/VisbyCF-ExtraBoldOblique.eot b/crates/collab/static/fonts/VisbyCF-ExtraBoldOblique.eot similarity index 100% rename from crates/server/static/fonts/VisbyCF-ExtraBoldOblique.eot rename to crates/collab/static/fonts/VisbyCF-ExtraBoldOblique.eot diff --git a/crates/server/static/fonts/VisbyCF-ExtraBoldOblique.woff b/crates/collab/static/fonts/VisbyCF-ExtraBoldOblique.woff similarity index 100% rename from crates/server/static/fonts/VisbyCF-ExtraBoldOblique.woff rename to crates/collab/static/fonts/VisbyCF-ExtraBoldOblique.woff diff --git a/crates/server/static/fonts/VisbyCF-ExtraBoldOblique.woff2 b/crates/collab/static/fonts/VisbyCF-ExtraBoldOblique.woff2 similarity index 100% rename from crates/server/static/fonts/VisbyCF-ExtraBoldOblique.woff2 rename to crates/collab/static/fonts/VisbyCF-ExtraBoldOblique.woff2 diff --git a/crates/server/static/fonts/VisbyCF-Heavy.eot b/crates/collab/static/fonts/VisbyCF-Heavy.eot similarity index 100% rename from crates/server/static/fonts/VisbyCF-Heavy.eot rename to crates/collab/static/fonts/VisbyCF-Heavy.eot diff --git a/crates/server/static/fonts/VisbyCF-Heavy.woff b/crates/collab/static/fonts/VisbyCF-Heavy.woff similarity index 100% rename from crates/server/static/fonts/VisbyCF-Heavy.woff rename to crates/collab/static/fonts/VisbyCF-Heavy.woff diff --git a/crates/server/static/fonts/VisbyCF-Heavy.woff2 b/crates/collab/static/fonts/VisbyCF-Heavy.woff2 similarity index 100% rename from crates/server/static/fonts/VisbyCF-Heavy.woff2 rename to crates/collab/static/fonts/VisbyCF-Heavy.woff2 diff --git a/crates/server/static/fonts/VisbyCF-HeavyOblique.eot b/crates/collab/static/fonts/VisbyCF-HeavyOblique.eot similarity index 100% rename from crates/server/static/fonts/VisbyCF-HeavyOblique.eot rename to crates/collab/static/fonts/VisbyCF-HeavyOblique.eot diff --git a/crates/server/static/fonts/VisbyCF-HeavyOblique.woff b/crates/collab/static/fonts/VisbyCF-HeavyOblique.woff similarity index 100% rename from crates/server/static/fonts/VisbyCF-HeavyOblique.woff rename to crates/collab/static/fonts/VisbyCF-HeavyOblique.woff diff --git a/crates/server/static/fonts/VisbyCF-HeavyOblique.woff2 b/crates/collab/static/fonts/VisbyCF-HeavyOblique.woff2 similarity index 100% rename from crates/server/static/fonts/VisbyCF-HeavyOblique.woff2 rename to crates/collab/static/fonts/VisbyCF-HeavyOblique.woff2 diff --git a/crates/server/static/fonts/VisbyCF-Light.eot b/crates/collab/static/fonts/VisbyCF-Light.eot similarity index 100% rename from crates/server/static/fonts/VisbyCF-Light.eot rename to crates/collab/static/fonts/VisbyCF-Light.eot diff --git a/crates/server/static/fonts/VisbyCF-Light.woff b/crates/collab/static/fonts/VisbyCF-Light.woff similarity index 100% rename from crates/server/static/fonts/VisbyCF-Light.woff rename to crates/collab/static/fonts/VisbyCF-Light.woff diff --git a/crates/server/static/fonts/VisbyCF-Light.woff2 b/crates/collab/static/fonts/VisbyCF-Light.woff2 similarity index 100% rename from crates/server/static/fonts/VisbyCF-Light.woff2 rename to crates/collab/static/fonts/VisbyCF-Light.woff2 diff --git a/crates/server/static/fonts/VisbyCF-LightOblique.eot b/crates/collab/static/fonts/VisbyCF-LightOblique.eot similarity index 100% rename from crates/server/static/fonts/VisbyCF-LightOblique.eot rename to crates/collab/static/fonts/VisbyCF-LightOblique.eot diff --git a/crates/server/static/fonts/VisbyCF-LightOblique.woff b/crates/collab/static/fonts/VisbyCF-LightOblique.woff similarity index 100% rename from crates/server/static/fonts/VisbyCF-LightOblique.woff rename to crates/collab/static/fonts/VisbyCF-LightOblique.woff diff --git a/crates/server/static/fonts/VisbyCF-LightOblique.woff2 b/crates/collab/static/fonts/VisbyCF-LightOblique.woff2 similarity index 100% rename from crates/server/static/fonts/VisbyCF-LightOblique.woff2 rename to crates/collab/static/fonts/VisbyCF-LightOblique.woff2 diff --git a/crates/server/static/fonts/VisbyCF-Medium.eot b/crates/collab/static/fonts/VisbyCF-Medium.eot similarity index 100% rename from crates/server/static/fonts/VisbyCF-Medium.eot rename to crates/collab/static/fonts/VisbyCF-Medium.eot diff --git a/crates/server/static/fonts/VisbyCF-Medium.woff b/crates/collab/static/fonts/VisbyCF-Medium.woff similarity index 100% rename from crates/server/static/fonts/VisbyCF-Medium.woff rename to crates/collab/static/fonts/VisbyCF-Medium.woff diff --git a/crates/server/static/fonts/VisbyCF-Medium.woff2 b/crates/collab/static/fonts/VisbyCF-Medium.woff2 similarity index 100% rename from crates/server/static/fonts/VisbyCF-Medium.woff2 rename to crates/collab/static/fonts/VisbyCF-Medium.woff2 diff --git a/crates/server/static/fonts/VisbyCF-MediumOblique.eot b/crates/collab/static/fonts/VisbyCF-MediumOblique.eot similarity index 100% rename from crates/server/static/fonts/VisbyCF-MediumOblique.eot rename to crates/collab/static/fonts/VisbyCF-MediumOblique.eot diff --git a/crates/server/static/fonts/VisbyCF-MediumOblique.woff b/crates/collab/static/fonts/VisbyCF-MediumOblique.woff similarity index 100% rename from crates/server/static/fonts/VisbyCF-MediumOblique.woff rename to crates/collab/static/fonts/VisbyCF-MediumOblique.woff diff --git a/crates/server/static/fonts/VisbyCF-MediumOblique.woff2 b/crates/collab/static/fonts/VisbyCF-MediumOblique.woff2 similarity index 100% rename from crates/server/static/fonts/VisbyCF-MediumOblique.woff2 rename to crates/collab/static/fonts/VisbyCF-MediumOblique.woff2 diff --git a/crates/server/static/fonts/VisbyCF-Regular.eot b/crates/collab/static/fonts/VisbyCF-Regular.eot similarity index 100% rename from crates/server/static/fonts/VisbyCF-Regular.eot rename to crates/collab/static/fonts/VisbyCF-Regular.eot diff --git a/crates/server/static/fonts/VisbyCF-Regular.woff b/crates/collab/static/fonts/VisbyCF-Regular.woff similarity index 100% rename from crates/server/static/fonts/VisbyCF-Regular.woff rename to crates/collab/static/fonts/VisbyCF-Regular.woff diff --git a/crates/server/static/fonts/VisbyCF-Regular.woff2 b/crates/collab/static/fonts/VisbyCF-Regular.woff2 similarity index 100% rename from crates/server/static/fonts/VisbyCF-Regular.woff2 rename to crates/collab/static/fonts/VisbyCF-Regular.woff2 diff --git a/crates/server/static/fonts/VisbyCF-RegularOblique.eot b/crates/collab/static/fonts/VisbyCF-RegularOblique.eot similarity index 100% rename from crates/server/static/fonts/VisbyCF-RegularOblique.eot rename to crates/collab/static/fonts/VisbyCF-RegularOblique.eot diff --git a/crates/server/static/fonts/VisbyCF-RegularOblique.woff b/crates/collab/static/fonts/VisbyCF-RegularOblique.woff similarity index 100% rename from crates/server/static/fonts/VisbyCF-RegularOblique.woff rename to crates/collab/static/fonts/VisbyCF-RegularOblique.woff diff --git a/crates/server/static/fonts/VisbyCF-RegularOblique.woff2 b/crates/collab/static/fonts/VisbyCF-RegularOblique.woff2 similarity index 100% rename from crates/server/static/fonts/VisbyCF-RegularOblique.woff2 rename to crates/collab/static/fonts/VisbyCF-RegularOblique.woff2 diff --git a/crates/server/static/fonts/VisbyCF-Thin.eot b/crates/collab/static/fonts/VisbyCF-Thin.eot similarity index 100% rename from crates/server/static/fonts/VisbyCF-Thin.eot rename to crates/collab/static/fonts/VisbyCF-Thin.eot diff --git a/crates/server/static/fonts/VisbyCF-Thin.woff b/crates/collab/static/fonts/VisbyCF-Thin.woff similarity index 100% rename from crates/server/static/fonts/VisbyCF-Thin.woff rename to crates/collab/static/fonts/VisbyCF-Thin.woff diff --git a/crates/server/static/fonts/VisbyCF-Thin.woff2 b/crates/collab/static/fonts/VisbyCF-Thin.woff2 similarity index 100% rename from crates/server/static/fonts/VisbyCF-Thin.woff2 rename to crates/collab/static/fonts/VisbyCF-Thin.woff2 diff --git a/crates/server/static/fonts/VisbyCF-ThinOblique.eot b/crates/collab/static/fonts/VisbyCF-ThinOblique.eot similarity index 100% rename from crates/server/static/fonts/VisbyCF-ThinOblique.eot rename to crates/collab/static/fonts/VisbyCF-ThinOblique.eot diff --git a/crates/server/static/fonts/VisbyCF-ThinOblique.woff b/crates/collab/static/fonts/VisbyCF-ThinOblique.woff similarity index 100% rename from crates/server/static/fonts/VisbyCF-ThinOblique.woff rename to crates/collab/static/fonts/VisbyCF-ThinOblique.woff diff --git a/crates/server/static/fonts/VisbyCF-ThinOblique.woff2 b/crates/collab/static/fonts/VisbyCF-ThinOblique.woff2 similarity index 100% rename from crates/server/static/fonts/VisbyCF-ThinOblique.woff2 rename to crates/collab/static/fonts/VisbyCF-ThinOblique.woff2 diff --git a/crates/server/static/images/android-chrome-192x192.png b/crates/collab/static/images/android-chrome-192x192.png similarity index 100% rename from crates/server/static/images/android-chrome-192x192.png rename to crates/collab/static/images/android-chrome-192x192.png diff --git a/crates/server/static/images/android-chrome-512x512.png b/crates/collab/static/images/android-chrome-512x512.png similarity index 100% rename from crates/server/static/images/android-chrome-512x512.png rename to crates/collab/static/images/android-chrome-512x512.png diff --git a/crates/server/static/images/apple-touch-icon.png b/crates/collab/static/images/apple-touch-icon.png similarity index 100% rename from crates/server/static/images/apple-touch-icon.png rename to crates/collab/static/images/apple-touch-icon.png diff --git a/crates/server/static/images/favicon-16x16.png b/crates/collab/static/images/favicon-16x16.png similarity index 100% rename from crates/server/static/images/favicon-16x16.png rename to crates/collab/static/images/favicon-16x16.png diff --git a/crates/server/static/images/favicon-32x32.png b/crates/collab/static/images/favicon-32x32.png similarity index 100% rename from crates/server/static/images/favicon-32x32.png rename to crates/collab/static/images/favicon-32x32.png diff --git a/crates/server/static/images/favicon.png b/crates/collab/static/images/favicon.png similarity index 100% rename from crates/server/static/images/favicon.png rename to crates/collab/static/images/favicon.png diff --git a/crates/server/static/images/favicon.svg b/crates/collab/static/images/favicon.svg similarity index 100% rename from crates/server/static/images/favicon.svg rename to crates/collab/static/images/favicon.svg diff --git a/crates/server/static/images/mstile-144x144.png b/crates/collab/static/images/mstile-144x144.png similarity index 100% rename from crates/server/static/images/mstile-144x144.png rename to crates/collab/static/images/mstile-144x144.png diff --git a/crates/server/static/images/mstile-150x150.png b/crates/collab/static/images/mstile-150x150.png similarity index 100% rename from crates/server/static/images/mstile-150x150.png rename to crates/collab/static/images/mstile-150x150.png diff --git a/crates/server/static/images/mstile-310x150.png b/crates/collab/static/images/mstile-310x150.png similarity index 100% rename from crates/server/static/images/mstile-310x150.png rename to crates/collab/static/images/mstile-310x150.png diff --git a/crates/server/static/images/mstile-310x310.png b/crates/collab/static/images/mstile-310x310.png similarity index 100% rename from crates/server/static/images/mstile-310x310.png rename to crates/collab/static/images/mstile-310x310.png diff --git a/crates/server/static/images/mstile-70x70.png b/crates/collab/static/images/mstile-70x70.png similarity index 100% rename from crates/server/static/images/mstile-70x70.png rename to crates/collab/static/images/mstile-70x70.png diff --git a/crates/server/static/images/safari-pinned-tab.svg b/crates/collab/static/images/safari-pinned-tab.svg similarity index 100% rename from crates/server/static/images/safari-pinned-tab.svg rename to crates/collab/static/images/safari-pinned-tab.svg diff --git a/crates/server/static/images/zed-og-image.png b/crates/collab/static/images/zed-og-image.png similarity index 100% rename from crates/server/static/images/zed-og-image.png rename to crates/collab/static/images/zed-og-image.png diff --git a/crates/server/static/images/zed-twitter-image.png b/crates/collab/static/images/zed-twitter-image.png similarity index 100% rename from crates/server/static/images/zed-twitter-image.png rename to crates/collab/static/images/zed-twitter-image.png diff --git a/crates/server/static/prism.js b/crates/collab/static/prism.js similarity index 100% rename from crates/server/static/prism.js rename to crates/collab/static/prism.js diff --git a/crates/server/static/prose.css b/crates/collab/static/prose.css similarity index 100% rename from crates/server/static/prose.css rename to crates/collab/static/prose.css diff --git a/crates/server/static/prose.css.map b/crates/collab/static/prose.css.map similarity index 100% rename from crates/server/static/prose.css.map rename to crates/collab/static/prose.css.map diff --git a/crates/server/static/prose.scss b/crates/collab/static/prose.scss similarity index 100% rename from crates/server/static/prose.scss rename to crates/collab/static/prose.scss diff --git a/crates/server/static/site.webmanifest b/crates/collab/static/site.webmanifest similarity index 100% rename from crates/server/static/site.webmanifest rename to crates/collab/static/site.webmanifest diff --git a/crates/server/static/svg/hero.svg b/crates/collab/static/svg/hero.svg similarity index 100% rename from crates/server/static/svg/hero.svg rename to crates/collab/static/svg/hero.svg diff --git a/crates/server/styles.css b/crates/collab/styles.css similarity index 100% rename from crates/server/styles.css rename to crates/collab/styles.css diff --git a/crates/server/templates/admin.hbs b/crates/collab/templates/admin.hbs similarity index 100% rename from crates/server/templates/admin.hbs rename to crates/collab/templates/admin.hbs diff --git a/crates/server/templates/careers.hbs b/crates/collab/templates/careers.hbs similarity index 100% rename from crates/server/templates/careers.hbs rename to crates/collab/templates/careers.hbs diff --git a/crates/server/templates/community.hbs b/crates/collab/templates/community.hbs similarity index 100% rename from crates/server/templates/community.hbs rename to crates/collab/templates/community.hbs diff --git a/crates/server/templates/docs.hbs b/crates/collab/templates/docs.hbs similarity index 100% rename from crates/server/templates/docs.hbs rename to crates/collab/templates/docs.hbs diff --git a/crates/server/templates/error.hbs b/crates/collab/templates/error.hbs similarity index 100% rename from crates/server/templates/error.hbs rename to crates/collab/templates/error.hbs diff --git a/crates/server/templates/home.hbs b/crates/collab/templates/home.hbs similarity index 100% rename from crates/server/templates/home.hbs rename to crates/collab/templates/home.hbs diff --git a/crates/server/templates/partials/layout.hbs b/crates/collab/templates/partials/layout.hbs similarity index 100% rename from crates/server/templates/partials/layout.hbs rename to crates/collab/templates/partials/layout.hbs diff --git a/crates/server/templates/releases.hbs b/crates/collab/templates/releases.hbs similarity index 100% rename from crates/server/templates/releases.hbs rename to crates/collab/templates/releases.hbs diff --git a/crates/server/templates/signup.hbs b/crates/collab/templates/signup.hbs similarity index 100% rename from crates/server/templates/signup.hbs rename to crates/collab/templates/signup.hbs diff --git a/crates/server/templates/team.hbs b/crates/collab/templates/team.hbs similarity index 100% rename from crates/server/templates/team.hbs rename to crates/collab/templates/team.hbs diff --git a/crates/server/.env.toml b/crates/server/.env.toml deleted file mode 100644 index 931f7c4df2..0000000000 --- a/crates/server/.env.toml +++ /dev/null @@ -1,42 +0,0 @@ -# Prod database: CAREFUL! -# DATABASE_URL = "postgres://postgres:f71db7645055488d666f3c26392113104706af1f24d2cf15@zed-db.internal:5432/zed" - -HTTP_PORT = 8080 - -DATABASE_URL = "postgres://postgres@localhost/zed" -SESSION_SECRET = "6E1GS6IQNOLIBKWMEVWF1AFO4H78KNU8" -API_TOKEN = "secret" - -# Available at https://github.com/organizations/zed-industries/settings/apps/zed-local-development -GITHUB_APP_ID = 115633 -GITHUB_CLIENT_ID = "Iv1.768076c9becc75c4" -GITHUB_CLIENT_SECRET = "3592ffff1ecda9773a3df7b0e75375bfbe7992fc" -GITHUB_PRIVATE_KEY = """\ ------BEGIN RSA PRIVATE KEY----- -MIIEowIBAAKCAQEAtt0O2t69ksn2zX5ucHpflNRoqdh342OOwrazLA6GS8Kp2hWM -NwLzymm2s8k1e2F7sAVYNHJvUPZCvM/xYuVMNpx33fVr00Tni2ATNJKS2lvCEBC0 -nTUKxXQImF82IQadg41o+81gofR3zt2UM7iDRMPbmn/aZe7K8vvFEERawSfKEMv3 -RqAzqt0fBDYvwHonje0Y7/5IAO5GDMd9kDE3w034ckwtyFAJDjRGYN5kVoRlua+Q -aIHoBkJ/jUAsS4kWqZt/r6hbrAcgok7Iv2RoapfgNTPeJKEe0pAagz1orqbrm9Qk -WBeAToTXl4YTfQruMNVyN2/5azqLnS8Urg2jHQIDAQABAoIBAF9TVY8bVk/TIOl2 -4zOXV4RKRlVkFvtexukSPMzWtYOA8vJREUsMKvJ1sVx/o3WyF7xmzNhqX0UhWyD6 -dadMSTKe1o3Khm8YGGw7pUdesVdLRhsB2mWpZPgRyPlFiP4maK5PZU7+fUVwH5Sj -RcLAiQ2r3CrqQ3unw/xu6wfT2kueBMJz6DBCx3y5wwEyrR7b+8ZGrjUy9BelzKti -yIT3OLWhilwho8l03Dg72SCSskotVMcywtc7SMr5PCILL7QANdJDhEO8FP4BysHx -6wlFwpfIPnNHN/RN1Dnnut5F64nPu//6vUs9DR9c34FzDp0SR2hJ98PLYn3uyD5b -6oOcZrECgYEA3QXrezpLwkZN2wS6r6vmNyEKSIevjpQpuFEzGSapJRJbGiP5/C+l -DfTmYud6Ld5YrL7xIQuf6SQWyO8WZkKA6D15VBdsFzM0pzhNGNGUgZYiTQ6rdh83 -5mL8l9IqzT5LD5RRXTj2CO7SB5iuyp8PrPyGCCVhILYJP+a4e4kHwEsCgYEA0803 -oF/QBhfKC3n/7xbRTeT4PcAHra+X84rY+KkyP1/qJXMRbCumpvTL6kZg7Jv2I3hG -SaRK7mGhi0/omVn9aEgn4E7UKmE2ZhVbigTiqnPdYoH/hmrbQ5Z7SVaT/MNzGuKQ -QZOmASgsZEjqSX7extXDzKOGD/AzMp3iWElUGTcCgYAOoT+vDnLJT0IEB1IcIrLA -X22A04ppU6FXU/if55E2pPpmxo7bhIPWYqmFTnEl7BvOg20OlOhm1D612i2PY0OJ -G9iWGl7LQlZv4ygnRmggE8H9e8UZsoNOuqqhmgW/RCpPw6+HDigq+zPn0NFxFApD -lwuAKok9Uw9VrX30n2Nl9QKBgAG7c/ED15e1Khnd7ZHvBdc1QDKBF478GKoNQKkH -+Tk7d5bG0iWoVbyX0/MekDxfKiwwF6MSjOpWMhQJm0VlzwTDUlArVODj2qYLFqyS -TahHOlBL7+MRjKmI2YlIA/3VO2PE5pkitADeaz6GuiPPvdKyfN93lukaddC8KdW/ -A8kRAoGBAJdU+sTC1zfP+tbgArzf4rU5qEknserAH+GE6C/Otn134WBEyqSgd2Jb -JpJsl2l/X/8Wfwh+SJQbhvDoY4ApMKlgLFBAIY/p2UcpEdUL2juec/F6+qGnBncQ -4I+MKiVfixBM9p66Afybiskh3a/RvXK+/6NNOVtVYaSd7aSIrq9W ------END RSA PRIVATE KEY----- -""" diff --git a/script/deploy b/script/deploy index ca32576281..4ba674766b 100755 --- a/script/deploy +++ b/script/deploy @@ -28,7 +28,7 @@ if [[ $ZED_KUBE_NAMESPACE == "production" && -n $(git status --short) ]]; then fi git_sha=$(git rev-parse HEAD) -export ZED_IMAGE_ID="registry.digitalocean.com/zed/zed-server:${ZED_KUBE_NAMESPACE}-${git_sha}" +export ZED_IMAGE_ID="registry.digitalocean.com/zed/collab:${ZED_KUBE_NAMESPACE}-${git_sha}" export $(cat $ENV_FILE) docker build . --tag "$ZED_IMAGE_ID" diff --git a/script/seed-db b/script/seed-db index 437d1bcac8..9da6ba2933 100755 --- a/script/seed-db +++ b/script/seed-db @@ -6,4 +6,4 @@ cd crates/server # Export contents of .env.toml eval "$(cargo run --bin dotenv)" -cargo run --package=zed-server --features seed-support --bin seed +cargo run --package=collab --features seed-support --bin seed From 3636c9ec2500132c89ee1a0ef2dccbbcadf63ca1 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 8 Apr 2022 17:32:58 -0700 Subject: [PATCH 03/22] Load workspace and editor key bindings from a JSON file --- crates/editor/src/editor.rs | 240 ++++--------------------- crates/gpui/src/app.rs | 3 +- crates/gpui/src/keymap.rs | 24 ++- crates/server/src/rpc.rs | 11 +- crates/workspace/src/menu.rs | 18 +- crates/workspace/src/pane.rs | 40 ++--- crates/workspace/src/pane_group.rs | 1 - crates/workspace/src/workspace.rs | 27 +-- crates/zed/assets/keymaps/default.json | 199 ++++++++++++++++++++ crates/zed/src/keymap_file.rs | 38 ++++ crates/zed/src/main.rs | 2 +- crates/zed/src/zed.rs | 16 +- 12 files changed, 326 insertions(+), 293 deletions(-) create mode 100644 crates/zed/assets/keymaps/default.json create mode 100644 crates/zed/src/keymap_file.rs diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 4d3265f8fa..bda5cda412 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -23,7 +23,6 @@ use gpui::{ fonts::{self, HighlightStyle, TextStyle}, geometry::vector::{vec2f, Vector2F}, impl_actions, impl_internal_actions, - keymap::Binding, platform::CursorStyle, text_layout, AppContext, AsyncAppContext, ClipboardItem, Element, ElementBox, Entity, ModelHandle, MutableAppContext, RenderContext, Task, View, ViewContext, ViewHandle, @@ -81,7 +80,7 @@ pub struct Scroll(pub Vector2F); #[derive(Clone)] pub struct Select(pub SelectPhase); -#[derive(Clone)] +#[derive(Clone, Deserialize)] pub struct Input(pub String); #[derive(Clone, Deserialize)] @@ -97,13 +96,22 @@ pub struct SelectToEndOfLine { } #[derive(Clone, Deserialize)] -pub struct ToggleCodeActions(#[serde(default)] pub bool); +pub struct ToggleCodeActions { + #[serde(default)] + pub deployed_from_indicator: bool, +} -#[derive(Clone, Deserialize)] -pub struct ConfirmCompletion(#[serde(default)] pub Option); +#[derive(Clone, Default, Deserialize)] +pub struct ConfirmCompletion { + #[serde(default)] + pub item_ix: Option, +} -#[derive(Clone, Deserialize)] -pub struct ConfirmCodeAction(#[serde(default)] pub Option); +#[derive(Clone, Default, Deserialize)] +pub struct ConfirmCodeAction { + #[serde(default)] + pub item_ix: Option, +} actions!( editor, @@ -185,6 +193,7 @@ actions!( impl_actions!( editor, [ + Input, SelectNext, SelectToBeginningOfLine, SelectToEndOfLine, @@ -194,7 +203,7 @@ impl_actions!( ] ); -impl_internal_actions!(editor, [Scroll, Select, Input]); +impl_internal_actions!(editor, [Scroll, Select]); enum DocumentHighlightRead {} enum DocumentHighlightWrite {} @@ -206,187 +215,6 @@ pub enum Direction { } pub fn init(cx: &mut MutableAppContext) { - cx.add_bindings(vec![ - Binding::new("escape", Cancel, Some("Editor")), - Binding::new("backspace", Backspace, Some("Editor")), - Binding::new("ctrl-h", Backspace, Some("Editor")), - Binding::new("delete", Delete, Some("Editor")), - Binding::new("ctrl-d", Delete, Some("Editor")), - Binding::new("enter", Newline, Some("Editor && mode == full")), - Binding::new( - "alt-enter", - Input("\n".into()), - Some("Editor && mode == auto_height"), - ), - Binding::new( - "enter", - ConfirmCompletion(None), - Some("Editor && showing_completions"), - ), - Binding::new( - "enter", - ConfirmCodeAction(None), - Some("Editor && showing_code_actions"), - ), - Binding::new("enter", ConfirmRename, Some("Editor && renaming")), - Binding::new("tab", Tab, Some("Editor")), - Binding::new("shift-tab", TabPrev, Some("Editor")), - Binding::new( - "tab", - ConfirmCompletion(None), - Some("Editor && showing_completions"), - ), - Binding::new("cmd-[", Outdent, Some("Editor")), - Binding::new("cmd-]", Indent, Some("Editor")), - Binding::new("ctrl-shift-K", DeleteLine, Some("Editor")), - Binding::new("alt-backspace", DeleteToPreviousWordStart, Some("Editor")), - Binding::new("alt-h", DeleteToPreviousWordStart, Some("Editor")), - Binding::new( - "ctrl-alt-backspace", - DeleteToPreviousSubwordStart, - Some("Editor"), - ), - Binding::new("ctrl-alt-h", DeleteToPreviousSubwordStart, Some("Editor")), - Binding::new("alt-delete", DeleteToNextWordEnd, Some("Editor")), - Binding::new("alt-d", DeleteToNextWordEnd, Some("Editor")), - Binding::new("ctrl-alt-delete", DeleteToNextSubwordEnd, Some("Editor")), - Binding::new("ctrl-alt-d", DeleteToNextSubwordEnd, Some("Editor")), - Binding::new("cmd-backspace", DeleteToBeginningOfLine, Some("Editor")), - Binding::new("cmd-delete", DeleteToEndOfLine, Some("Editor")), - Binding::new("ctrl-k", CutToEndOfLine, Some("Editor")), - Binding::new("cmd-shift-D", DuplicateLine, Some("Editor")), - Binding::new("ctrl-cmd-up", MoveLineUp, Some("Editor")), - Binding::new("ctrl-cmd-down", MoveLineDown, Some("Editor")), - Binding::new("cmd-x", Cut, Some("Editor")), - Binding::new("cmd-c", Copy, Some("Editor")), - Binding::new("cmd-v", Paste, Some("Editor")), - Binding::new("cmd-z", Undo, Some("Editor")), - Binding::new("cmd-shift-Z", Redo, Some("Editor")), - Binding::new("up", MoveUp, Some("Editor")), - Binding::new("down", MoveDown, Some("Editor")), - Binding::new("left", MoveLeft, Some("Editor")), - Binding::new("right", MoveRight, Some("Editor")), - Binding::new("ctrl-p", MoveUp, Some("Editor")), - Binding::new("ctrl-n", MoveDown, Some("Editor")), - Binding::new("ctrl-b", MoveLeft, Some("Editor")), - Binding::new("ctrl-f", MoveRight, Some("Editor")), - Binding::new("alt-left", MoveToPreviousWordStart, Some("Editor")), - Binding::new("alt-b", MoveToPreviousWordStart, Some("Editor")), - Binding::new("ctrl-alt-left", MoveToPreviousSubwordStart, Some("Editor")), - Binding::new("ctrl-alt-b", MoveToPreviousSubwordStart, Some("Editor")), - Binding::new("alt-right", MoveToNextWordEnd, Some("Editor")), - Binding::new("alt-f", MoveToNextWordEnd, Some("Editor")), - Binding::new("ctrl-alt-right", MoveToNextSubwordEnd, Some("Editor")), - Binding::new("ctrl-alt-f", MoveToNextSubwordEnd, Some("Editor")), - Binding::new("cmd-left", MoveToBeginningOfLine, Some("Editor")), - Binding::new("ctrl-a", MoveToBeginningOfLine, Some("Editor")), - Binding::new("cmd-right", MoveToEndOfLine, Some("Editor")), - Binding::new("ctrl-e", MoveToEndOfLine, Some("Editor")), - Binding::new("cmd-up", MoveToBeginning, Some("Editor")), - Binding::new("cmd-down", MoveToEnd, Some("Editor")), - Binding::new("shift-up", SelectUp, Some("Editor")), - Binding::new("ctrl-shift-P", SelectUp, Some("Editor")), - Binding::new("shift-down", SelectDown, Some("Editor")), - Binding::new("ctrl-shift-N", SelectDown, Some("Editor")), - Binding::new("shift-left", SelectLeft, Some("Editor")), - Binding::new("ctrl-shift-B", SelectLeft, Some("Editor")), - Binding::new("shift-right", SelectRight, Some("Editor")), - Binding::new("ctrl-shift-F", SelectRight, Some("Editor")), - Binding::new("alt-shift-left", SelectToPreviousWordStart, Some("Editor")), - Binding::new("alt-shift-B", SelectToPreviousWordStart, Some("Editor")), - Binding::new( - "ctrl-alt-shift-left", - SelectToPreviousSubwordStart, - Some("Editor"), - ), - Binding::new( - "ctrl-alt-shift-B", - SelectToPreviousSubwordStart, - Some("Editor"), - ), - Binding::new("alt-shift-right", SelectToNextWordEnd, Some("Editor")), - Binding::new("alt-shift-F", SelectToNextWordEnd, Some("Editor")), - Binding::new( - "cmd-shift-left", - SelectToBeginningOfLine { - stop_at_soft_wraps: true, - }, - Some("Editor"), - ), - Binding::new( - "ctrl-alt-shift-right", - SelectToNextSubwordEnd, - Some("Editor"), - ), - Binding::new("ctrl-alt-shift-F", SelectToNextSubwordEnd, Some("Editor")), - Binding::new( - "ctrl-shift-A", - SelectToBeginningOfLine { - stop_at_soft_wraps: true, - }, - Some("Editor"), - ), - Binding::new( - "cmd-shift-right", - SelectToEndOfLine { - stop_at_soft_wraps: true, - }, - Some("Editor"), - ), - Binding::new( - "ctrl-shift-E", - SelectToEndOfLine { - stop_at_soft_wraps: true, - }, - Some("Editor"), - ), - Binding::new("cmd-shift-up", SelectToBeginning, Some("Editor")), - Binding::new("cmd-shift-down", SelectToEnd, Some("Editor")), - Binding::new("cmd-a", SelectAll, Some("Editor")), - Binding::new("cmd-l", SelectLine, Some("Editor")), - Binding::new("cmd-shift-L", SplitSelectionIntoLines, Some("Editor")), - Binding::new("cmd-alt-up", AddSelectionAbove, Some("Editor")), - Binding::new("cmd-ctrl-p", AddSelectionAbove, Some("Editor")), - Binding::new("cmd-alt-down", AddSelectionBelow, Some("Editor")), - Binding::new("cmd-ctrl-n", AddSelectionBelow, Some("Editor")), - Binding::new( - "cmd-d", - SelectNext { - replace_newest: false, - }, - Some("Editor"), - ), - Binding::new( - "cmd-k cmd-d", - SelectNext { - replace_newest: true, - }, - Some("Editor"), - ), - Binding::new("cmd-/", ToggleComments, Some("Editor")), - Binding::new("alt-up", SelectLargerSyntaxNode, Some("Editor")), - Binding::new("ctrl-w", SelectLargerSyntaxNode, Some("Editor")), - Binding::new("alt-down", SelectSmallerSyntaxNode, Some("Editor")), - Binding::new("ctrl-shift-W", SelectSmallerSyntaxNode, Some("Editor")), - Binding::new("cmd-u", UndoSelection, Some("Editor")), - Binding::new("cmd-shift-U", RedoSelection, Some("Editor")), - Binding::new("f8", GoToNextDiagnostic, Some("Editor")), - Binding::new("shift-f8", GoToPrevDiagnostic, Some("Editor")), - Binding::new("f2", Rename, Some("Editor")), - Binding::new("f12", GoToDefinition, Some("Editor")), - Binding::new("alt-shift-f12", FindAllReferences, Some("Editor")), - Binding::new("ctrl-m", MoveToEnclosingBracket, Some("Editor")), - Binding::new("pageup", PageUp, Some("Editor")), - Binding::new("pagedown", PageDown, Some("Editor")), - Binding::new("alt-cmd-[", Fold, Some("Editor")), - Binding::new("alt-cmd-]", UnfoldLines, Some("Editor")), - Binding::new("alt-cmd-f", FoldSelectedRanges, Some("Editor")), - Binding::new("ctrl-space", ShowCompletions, Some("Editor")), - Binding::new("cmd-.", ToggleCodeActions(false), Some("Editor")), - Binding::new("alt-enter", OpenExcerpts, Some("Editor")), - Binding::new("cmd-f10", RestartLanguageServer, Some("Editor")), - ]); - cx.add_action(Editor::open_new); cx.add_action(|this: &mut Editor, action: &Scroll, cx| this.set_scroll_position(action.0, cx)); cx.add_action(Editor::select); @@ -396,6 +224,7 @@ pub fn init(cx: &mut MutableAppContext) { cx.add_action(Editor::backspace); cx.add_action(Editor::delete); cx.add_action(Editor::tab); + cx.add_action(Editor::tab_prev); cx.add_action(Editor::indent); cx.add_action(Editor::outdent); cx.add_action(Editor::delete_line); @@ -849,7 +678,9 @@ impl CompletionsMenu { ) .with_cursor_style(CursorStyle::PointingHand) .on_mouse_down(move |cx| { - cx.dispatch_action(ConfirmCompletion(Some(item_ix))); + cx.dispatch_action(ConfirmCompletion { + item_ix: Some(item_ix), + }); }) .boxed(), ); @@ -975,7 +806,9 @@ impl CodeActionsMenu { }) .with_cursor_style(CursorStyle::PointingHand) .on_mouse_down(move |cx| { - cx.dispatch_action(ConfirmCodeAction(Some(item_ix))); + cx.dispatch_action(ConfirmCodeAction { + item_ix: Some(item_ix), + }); }) .boxed(), ); @@ -2473,7 +2306,7 @@ impl Editor { pub fn confirm_completion( &mut self, - ConfirmCompletion(completion_ix): &ConfirmCompletion, + action: &ConfirmCompletion, cx: &mut ViewContext, ) -> Option>> { use language::ToOffset as _; @@ -2486,7 +2319,7 @@ impl Editor { let mat = completions_menu .matches - .get(completion_ix.unwrap_or(completions_menu.selected_item))?; + .get(action.item_ix.unwrap_or(completions_menu.selected_item))?; let buffer_handle = completions_menu.buffer; let completion = completions_menu.completions.get(mat.candidate_id)?; @@ -2576,11 +2409,7 @@ impl Editor { })) } - pub fn toggle_code_actions( - &mut self, - &ToggleCodeActions(deployed_from_indicator): &ToggleCodeActions, - cx: &mut ViewContext, - ) { + pub fn toggle_code_actions(&mut self, action: &ToggleCodeActions, cx: &mut ViewContext) { if matches!( self.context_menu.as_ref(), Some(ContextMenu::CodeActions(_)) @@ -2590,6 +2419,7 @@ impl Editor { return; } + let deployed_from_indicator = action.deployed_from_indicator; let mut task = self.code_actions_task.take(); cx.spawn_weak(|this, mut cx| async move { while let Some(prev_task) = task { @@ -2624,7 +2454,7 @@ impl Editor { pub fn confirm_code_action( workspace: &mut Workspace, - ConfirmCodeAction(action_ix): &ConfirmCodeAction, + action: &ConfirmCodeAction, cx: &mut ViewContext, ) -> Option>> { let editor = workspace.active_item(cx)?.act_as::(cx)?; @@ -2635,7 +2465,7 @@ impl Editor { } else { return None; }; - let action_ix = action_ix.unwrap_or(actions_menu.selected_item); + let action_ix = action.item_ix.unwrap_or(actions_menu.selected_item); let action = actions_menu.actions.get(action_ix)?.clone(); let title = action.lsp_action.title.clone(); let buffer = actions_menu.buffer; @@ -2862,7 +2692,9 @@ impl Editor { .with_cursor_style(CursorStyle::PointingHand) .with_padding(Padding::uniform(3.)) .on_mouse_down(|cx| { - cx.dispatch_action(ToggleCodeActions(true)); + cx.dispatch_action(ToggleCodeActions { + deployed_from_indicator: true, + }); }) .boxed(), ) @@ -4558,7 +4390,7 @@ impl Editor { self.go_to_diagnostic(Direction::Next, cx) } - fn go_to_prev_diagnostic(&mut self, _: &GoToNextDiagnostic, cx: &mut ViewContext) { + fn go_to_prev_diagnostic(&mut self, _: &GoToPrevDiagnostic, cx: &mut ViewContext) { self.go_to_diagnostic(Direction::Prev, cx) } @@ -9394,7 +9226,7 @@ mod tests { let apply_additional_edits = editor.update(cx, |editor, cx| { editor.move_down(&MoveDown, cx); let apply_additional_edits = editor - .confirm_completion(&ConfirmCompletion(None), cx) + .confirm_completion(&ConfirmCompletion::default(), cx) .unwrap(); assert_eq!( editor.text(cx), @@ -9477,7 +9309,7 @@ mod tests { let apply_additional_edits = editor.update(cx, |editor, cx| { let apply_additional_edits = editor - .confirm_completion(&ConfirmCompletion(None), cx) + .confirm_completion(&ConfirmCompletion::default(), cx) .unwrap(); assert_eq!( editor.text(cx), diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index f7417f6663..962343a28a 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -10,7 +10,7 @@ use crate::{ AssetCache, AssetSource, ClipboardItem, FontCache, PathPromptOptions, TextLayoutCache, }; pub use action::*; -use anyhow::{anyhow, Result}; +use anyhow::{anyhow, Context, Result}; use collections::btree_map; use keymap::MatchResult; use lazy_static::lazy_static; @@ -870,6 +870,7 @@ impl MutableAppContext { .get(name) .ok_or_else(|| anyhow!("unknown action {}", name))?; callback(argument.unwrap_or("{}")) + .with_context(|| format!("invalid data for action {}", name)) } pub fn add_action(&mut self, handler: F) diff --git a/crates/gpui/src/keymap.rs b/crates/gpui/src/keymap.rs index a94abb8252..1b9e920ff2 100644 --- a/crates/gpui/src/keymap.rs +++ b/crates/gpui/src/keymap.rs @@ -1,5 +1,5 @@ use crate::Action; -use anyhow::anyhow; +use anyhow::{anyhow, Result}; use std::{ any::Any, collections::{HashMap, HashSet}, @@ -168,20 +168,26 @@ impl Keymap { impl Binding { pub fn new(keystrokes: &str, action: A, context: Option<&str>) -> Self { + Self::load(keystrokes, Box::new(action), context).unwrap() + } + + pub fn load(keystrokes: &str, action: Box, context: Option<&str>) -> Result { let context = if let Some(context) = context { - Some(ContextPredicate::parse(context).unwrap()) + Some(ContextPredicate::parse(context)?) } else { None }; - Self { - keystrokes: keystrokes - .split_whitespace() - .map(|key| Keystroke::parse(key).unwrap()) - .collect(), - action: Box::new(action), + let keystrokes = keystrokes + .split_whitespace() + .map(|key| Keystroke::parse(key)) + .collect::>()?; + + Ok(Self { + keystrokes, + action, context, - } + }) } } diff --git a/crates/server/src/rpc.rs b/crates/server/src/rpc.rs index 5ebe36e824..fa7afa5b2f 100644 --- a/crates/server/src/rpc.rs +++ b/crates/server/src/rpc.rs @@ -2419,7 +2419,7 @@ mod tests { .condition(&cx_b, |editor, _| editor.context_menu_visible()) .await; editor_b.update(cx_b, |editor, cx| { - editor.confirm_completion(&ConfirmCompletion(Some(0)), cx); + editor.confirm_completion(&ConfirmCompletion { item_ix: Some(0) }, cx); assert_eq!(editor.text(cx), "fn main() { a.first_method() }"); }); @@ -3608,7 +3608,12 @@ mod tests { // Toggle code actions and wait for them to display. editor_b.update(cx_b, |editor, cx| { - editor.toggle_code_actions(&ToggleCodeActions(false), cx); + editor.toggle_code_actions( + &ToggleCodeActions { + deployed_from_indicator: false, + }, + cx, + ); }); editor_b .condition(&cx_b, |editor, _| editor.context_menu_visible()) @@ -3619,7 +3624,7 @@ mod tests { // Confirming the code action will trigger a resolve request. let confirm_action = workspace_b .update(cx_b, |workspace, cx| { - Editor::confirm_code_action(workspace, &ConfirmCodeAction(Some(0)), cx) + Editor::confirm_code_action(workspace, &ConfirmCodeAction { item_ix: Some(0) }, cx) }) .unwrap(); fake_language_server.handle_request::( diff --git a/crates/workspace/src/menu.rs b/crates/workspace/src/menu.rs index e2412db741..33de4a677a 100644 --- a/crates/workspace/src/menu.rs +++ b/crates/workspace/src/menu.rs @@ -1,18 +1,4 @@ -use gpui::{actions, keymap::Binding, MutableAppContext}; - -actions!( +gpui::actions!( menu, - [Confirm, SelectPrev, SelectNext, SelectFirst, SelectLast,] + [Confirm, SelectPrev, SelectNext, SelectFirst, SelectLast] ); - -pub fn init(cx: &mut MutableAppContext) { - cx.add_bindings([ - Binding::new("up", SelectPrev, Some("menu")), - Binding::new("ctrl-p", SelectPrev, Some("menu")), - Binding::new("down", SelectNext, Some("menu")), - Binding::new("ctrl-n", SelectNext, Some("menu")), - Binding::new("cmd-up", SelectFirst, Some("menu")), - Binding::new("cmd-down", SelectLast, Some("menu")), - Binding::new("enter", Confirm, Some("menu")), - ]); -} diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index a60e2ff9db..a992897c11 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -8,7 +8,6 @@ use gpui::{ elements::*, geometry::{rect::RectF, vector::vec2f}, impl_actions, impl_internal_actions, - keymap::Binding, platform::{CursorStyle, NavigationDirection}, AppContext, Entity, MutableAppContext, PromptLevel, Quad, RenderContext, Task, View, ViewContext, ViewHandle, WeakViewHandle, @@ -41,14 +40,20 @@ pub struct CloseItem { #[derive(Clone, Deserialize)] pub struct ActivateItem(pub usize); -#[derive(Clone)] -pub struct GoBack(pub Option>); +#[derive(Clone, Deserialize)] +pub struct GoBack { + #[serde(skip_deserializing)] + pub pane: Option>, +} -#[derive(Clone)] -pub struct GoForward(pub Option>); +#[derive(Clone, Deserialize)] +pub struct GoForward { + #[serde(skip_deserializing)] + pub pane: Option>, +} -impl_actions!(pane, [Split]); -impl_internal_actions!(pane, [CloseItem, ActivateItem, GoBack, GoForward]); +impl_actions!(pane, [Split, GoBack, GoForward]); +impl_internal_actions!(pane, [CloseItem, ActivateItem]); const MAX_NAVIGATION_HISTORY_LEN: usize = 1024; @@ -75,7 +80,7 @@ pub fn init(cx: &mut MutableAppContext) { Pane::go_back( workspace, action - .0 + .pane .as_ref() .and_then(|weak_handle| weak_handle.upgrade(cx)), cx, @@ -86,26 +91,13 @@ pub fn init(cx: &mut MutableAppContext) { Pane::go_forward( workspace, action - .0 + .pane .as_ref() .and_then(|weak_handle| weak_handle.upgrade(cx)), cx, ) .detach(); }); - - cx.add_bindings(vec![ - Binding::new("shift-cmd-{", ActivatePrevItem, Some("Pane")), - Binding::new("shift-cmd-}", ActivateNextItem, Some("Pane")), - Binding::new("cmd-w", CloseActiveItem, Some("Pane")), - Binding::new("alt-cmd-w", CloseInactiveItems, Some("Pane")), - Binding::new("cmd-k up", Split(SplitDirection::Up), Some("Pane")), - Binding::new("cmd-k down", Split(SplitDirection::Down), Some("Pane")), - Binding::new("cmd-k left", Split(SplitDirection::Left), Some("Pane")), - Binding::new("cmd-k right", Split(SplitDirection::Right), Some("Pane")), - Binding::new("ctrl--", GoBack(None), Some("Pane")), - Binding::new("shift-ctrl-_", GoForward(None), Some("Pane")), - ]); } pub enum Event { @@ -815,8 +807,8 @@ impl View for Pane { .on_navigate_mouse_down(move |direction, cx| { let this = this.clone(); match direction { - NavigationDirection::Back => cx.dispatch_action(GoBack(Some(this))), - NavigationDirection::Forward => cx.dispatch_action(GoForward(Some(this))), + NavigationDirection::Back => cx.dispatch_action(GoBack { pane: Some(this) }), + NavigationDirection::Forward => cx.dispatch_action(GoForward { pane: Some(this) }), } true diff --git a/crates/workspace/src/pane_group.rs b/crates/workspace/src/pane_group.rs index d5661ba2c9..a17805822f 100644 --- a/crates/workspace/src/pane_group.rs +++ b/crates/workspace/src/pane_group.rs @@ -256,7 +256,6 @@ impl PaneAxis { } #[derive(Clone, Copy, Debug, Deserialize)] -#[serde(rename_all = "snake_case")] pub enum SplitDirection { Up, Down, diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 475913d9db..d63626e1d3 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -19,7 +19,6 @@ use gpui::{ geometry::{rect::RectF, vector::vec2f, PathBuilder}, impl_internal_actions, json::{self, to_string_pretty, ToJson}, - keymap::Binding, platform::{CursorStyle, WindowOptions}, AnyModelHandle, AnyViewHandle, AppContext, AsyncAppContext, Border, ClipboardItem, Entity, ImageData, ModelHandle, MutableAppContext, PathPromptOptions, PromptLevel, RenderContext, Task, @@ -32,7 +31,7 @@ pub use pane_group::*; use postage::prelude::Stream; use project::{fs, Fs, Project, ProjectEntryId, ProjectPath, Worktree}; use settings::Settings; -use sidebar::{Side, Sidebar, SidebarItemId, ToggleSidebarItem, ToggleSidebarItemFocus}; +use sidebar::{Side, Sidebar, ToggleSidebarItem, ToggleSidebarItemFocus}; use status_bar::StatusBar; pub use status_bar::StatusItemView; use std::{ @@ -108,7 +107,6 @@ impl_internal_actions!( pub fn init(client: &Arc, cx: &mut MutableAppContext) { pane::init(cx); - menu::init(cx); cx.add_global_action(open); cx.add_global_action(move |action: &OpenPaths, cx: &mut MutableAppContext| { @@ -144,29 +142,6 @@ pub fn init(client: &Arc, cx: &mut MutableAppContext) { cx.add_action(|workspace: &mut Workspace, _: &ActivateNextPane, cx| { workspace.activate_next_pane(cx) }); - cx.add_bindings(vec![ - Binding::new("ctrl-alt-cmd-f", FollowNextCollaborator, None), - Binding::new("cmd-s", Save, None), - Binding::new("cmd-alt-i", DebugElements, None), - Binding::new("cmd-k cmd-left", ActivatePreviousPane, None), - Binding::new("cmd-k cmd-right", ActivateNextPane, None), - Binding::new( - "cmd-shift-!", - ToggleSidebarItem(SidebarItemId { - side: Side::Left, - item_index: 0, - }), - None, - ), - Binding::new( - "cmd-1", - ToggleSidebarItemFocus(SidebarItemId { - side: Side::Left, - item_index: 0, - }), - None, - ), - ]); client.add_view_request_handler(Workspace::handle_follow); client.add_view_message_handler(Workspace::handle_unfollow); diff --git a/crates/zed/assets/keymaps/default.json b/crates/zed/assets/keymaps/default.json new file mode 100644 index 0000000000..1339a5e54f --- /dev/null +++ b/crates/zed/assets/keymaps/default.json @@ -0,0 +1,199 @@ +{ + "": { + "ctrl-alt-cmd-f": "workspace::FollowNextCollaborator", + "cmd-s": "workspace::Save", + "cmd-alt-i": "workspace::DebugElements", + "cmd-k cmd-left": "workspace::ActivatePreviousPane", + "cmd-k cmd-right": "workspace::ActivateNextPane", + "cmd-=": "zed::IncreaseBufferFontSize", + "cmd--": "zed::DecreaseBufferFontSize", + "cmd-,": "zed::OpenSettings" + }, + "menu": { + "up": "menu::SelectPrev", + "ctrl-p": "menu::SelectPrev", + "down": "menu::SelectNext", + "ctrl-n": "menu::SelectNext", + "cmd-up": "menu::SelectFirst", + "cmd-down": "menu::SelectLast", + "enter": "menu::Confirm" + }, + "Pane": { + "shift-cmd-{": "pane::ActivatePrevItem", + "shift-cmd-}": "pane::ActivateNextItem", + "cmd-w": "pane::CloseActiveItem", + "alt-cmd-w": "pane::CloseInactiveItems", + "ctrl--": "pane::GoBack", + "shift-ctrl-_": "pane::GoForward", + "cmd-k up": [ + "pane::Split", + "Up" + ], + "cmd-k down": [ + "pane::Split", + "Down" + ], + "cmd-k left": [ + "pane::Split", + "Left" + ], + "cmd-k right": [ + "pane::Split", + "Right" + ] + }, + "Editor": { + "escape": "editor::Cancel", + "backspace": "editor::Backspace", + "ctrl-h": "editor::Backspace", + "delete": "editor::Delete", + "ctrl-d": "editor::Delete", + "tab": "editor::Tab", + "shift-tab": "editor::TabPrev", + "cmd-[": "editor::Outdent", + "cmd-]": "editor::Indent", + "ctrl-shift-K": "editor::DeleteLine", + "alt-backspace": "editor::DeleteToPreviousWordStart", + "alt-h": "editor::DeleteToPreviousWordStart", + "ctrl-alt-backspace": "editor::DeleteToPreviousSubwordStart", + "ctrl-alt-h": "editor::DeleteToPreviousSubwordStart", + "alt-delete": "editor::DeleteToNextWordEnd", + "alt-d": "editor::DeleteToNextWordEnd", + "ctrl-alt-delete": "editor::DeleteToNextSubwordEnd", + "ctrl-alt-d": "editor::DeleteToNextSubwordEnd", + "cmd-backspace": "editor::DeleteToBeginningOfLine", + "cmd-delete": "editor::DeleteToEndOfLine", + "ctrl-k": "editor::CutToEndOfLine", + "cmd-shift-D": "editor::DuplicateLine", + "ctrl-cmd-up": "editor::MoveLineUp", + "ctrl-cmd-down": "editor::MoveLineDown", + "cmd-x": "editor::Cut", + "cmd-c": "editor::Copy", + "cmd-v": "editor::Paste", + "cmd-z": "editor::Undo", + "cmd-shift-Z": "editor::Redo", + "up": "editor::MoveUp", + "down": "editor::MoveDown", + "left": "editor::MoveLeft", + "right": "editor::MoveRight", + "ctrl-p": "editor::MoveUp", + "ctrl-n": "editor::MoveDown", + "ctrl-b": "editor::MoveLeft", + "ctrl-f": "editor::MoveRight", + "alt-left": "editor::MoveToPreviousWordStart", + "alt-b": "editor::MoveToPreviousWordStart", + "ctrl-alt-left": "editor::MoveToPreviousSubwordStart", + "ctrl-alt-b": "editor::MoveToPreviousSubwordStart", + "alt-right": "editor::MoveToNextWordEnd", + "alt-f": "editor::MoveToNextWordEnd", + "ctrl-alt-right": "editor::MoveToNextSubwordEnd", + "ctrl-alt-f": "editor::MoveToNextSubwordEnd", + "cmd-left": "editor::MoveToBeginningOfLine", + "ctrl-a": "editor::MoveToBeginningOfLine", + "cmd-right": "editor::MoveToEndOfLine", + "ctrl-e": "editor::MoveToEndOfLine", + "cmd-up": "editor::MoveToBeginning", + "cmd-down": "editor::MoveToEnd", + "shift-up": "editor::SelectUp", + "ctrl-shift-P": "editor::SelectUp", + "shift-down": "editor::SelectDown", + "ctrl-shift-N": "editor::SelectDown", + "shift-left": "editor::SelectLeft", + "ctrl-shift-B": "editor::SelectLeft", + "shift-right": "editor::SelectRight", + "ctrl-shift-F": "editor::SelectRight", + "alt-shift-left": "editor::SelectToPreviousWordStart", + "alt-shift-B": "editor::SelectToPreviousWordStart", + "ctrl-alt-shift-left": "editor::SelectToPreviousSubwordStart", + "ctrl-alt-shift-B": "editor::SelectToPreviousSubwordStart", + "alt-shift-right": "editor::SelectToNextWordEnd", + "alt-shift-F": "editor::SelectToNextWordEnd", + "ctrl-alt-shift-right": "editor::SelectToNextSubwordEnd", + "cmd-shift-up": "editor::SelectToBeginning", + "cmd-shift-down": "editor::SelectToEnd", + "cmd-a": "editor::SelectAll", + "cmd-l": "editor::SelectLine", + "cmd-shift-L": "editor::SplitSelectionIntoLines", + "cmd-alt-up": "editor::AddSelectionAbove", + "cmd-ctrl-p": "editor::AddSelectionAbove", + "cmd-alt-down": "editor::AddSelectionBelow", + "cmd-ctrl-n": "editor::AddSelectionBelow", + "ctrl-alt-shift-F": "editor::SelectToNextSubwordEnd", + "cmd-shift-left": [ + "editor::SelectToBeginningOfLine", + { + "stop_at_soft_wraps": true + } + ], + "ctrl-shift-A": [ + "editor::SelectToBeginningOfLine", + { + "stop_at_soft_wraps": true + } + ], + "cmd-shift-right": [ + "editor::SelectToEndOfLine", + { + "stop_at_soft_wraps": true + } + ], + "ctrl-shift-E": [ + "editor::SelectToEndOfLine", + { + "stop_at_soft_wraps": true + } + ], + "cmd-d": [ + "editor::SelectNext", + { + "replace_newest": false + } + ], + "cmd-k cmd-d": [ + "editor::SelectNext", + { + "replace_newest": true + } + ], + "cmd-/": "editor::ToggleComments", + "alt-up": "editor::SelectLargerSyntaxNode", + "ctrl-w": "editor::SelectLargerSyntaxNode", + "alt-down": "editor::SelectSmallerSyntaxNode", + "ctrl-shift-W": "editor::SelectSmallerSyntaxNode", + "cmd-u": "editor::UndoSelection", + "cmd-shift-U": "editor::RedoSelection", + "f8": "editor::GoToNextDiagnostic", + "shift-f8": "editor::GoToPrevDiagnostic", + "f2": "editor::Rename", + "f12": "editor::GoToDefinition", + "alt-shift-f12": "editor::FindAllReferences", + "ctrl-m": "editor::MoveToEnclosingBracket", + "pageup": "editor::PageUp", + "pagedown": "editor::PageDown", + "alt-cmd-[": "editor::Fold", + "alt-cmd-]": "editor::UnfoldLines", + "alt-cmd-f": "editor::FoldSelectedRanges", + "ctrl-space": "editor::ShowCompletions", + "cmd-.": "editor::ToggleCodeActions", + "alt-enter": "editor::OpenExcerpts", + "cmd-f10": "editor::RestartLanguageServer" + }, + "Editor && renaming": { + "enter": "editor::ConfirmRename" + }, + "Editor && showing_completions": { + "enter": "editor::ConfirmCompletion" + }, + "Editor && showing_code_actions": { + "enter": "editor::ConfirmCodeAction" + }, + "Editor && mode == full": { + "enter": "editor::Newline" + }, + "Editor && mode == auto_height": { + "alt-enter": [ + "editor::Input", + "\n" + ] + } +} \ No newline at end of file diff --git a/crates/zed/src/keymap_file.rs b/crates/zed/src/keymap_file.rs new file mode 100644 index 0000000000..2eaf1b7ecb --- /dev/null +++ b/crates/zed/src/keymap_file.rs @@ -0,0 +1,38 @@ +use anyhow::Result; +use collections::BTreeMap; +use gpui::{keymap::Binding, MutableAppContext}; +use serde::Deserialize; +use serde_json::value::RawValue; + +#[derive(Deserialize)] +struct ActionWithData<'a>(#[serde(borrow)] &'a str, #[serde(borrow)] &'a RawValue); +type ActionSetsByContext<'a> = BTreeMap<&'a str, ActionsByKeystroke<'a>>; +type ActionsByKeystroke<'a> = BTreeMap<&'a str, &'a RawValue>; + +pub fn load_keymap(cx: &mut MutableAppContext, content: &str) -> Result<()> { + let actions: ActionSetsByContext = serde_json::from_str(content)?; + for (context, actions) in actions { + let context = if context.is_empty() { + None + } else { + Some(context) + }; + cx.add_bindings( + actions + .into_iter() + .map(|(keystroke, action)| { + let action = action.get(); + let action = if action.starts_with('[') { + let ActionWithData(name, data) = serde_json::from_str(action)?; + cx.deserialize_action(name, Some(data.get())) + } else { + let name = serde_json::from_str(action)?; + cx.deserialize_action(name, None) + }?; + Binding::load(keystroke, action, context) + }) + .collect::>>()?, + ) + } + Ok(()) +} diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index abdf68e6ab..bfb1b34256 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -145,8 +145,8 @@ fn main() { build_workspace: &build_workspace, }); journal::init(app_state.clone(), cx); - zed::init(&app_state, cx); theme_selector::init(cx); + zed::init(&app_state, cx); cx.set_menus(menus::menus(&app_state.clone())); diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 6465c9b253..bae7b517e9 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -1,10 +1,12 @@ pub mod assets; +mod keymap_file; pub mod languages; pub mod menus; pub mod settings_file; #[cfg(any(test, feature = "test-support"))] pub mod test; +use assets::Assets; use breadcrumbs::Breadcrumbs; use chat_panel::ChatPanel; pub use client; @@ -14,7 +16,6 @@ pub use editor; use gpui::{ actions, geometry::vector::vec2f, - keymap::Binding, platform::{WindowBounds, WindowOptions}, ModelHandle, ViewContext, }; @@ -104,11 +105,11 @@ pub fn init(app_state: &Arc, cx: &mut gpui::MutableAppContext) { workspace::lsp_status::init(cx); - cx.add_bindings(vec![ - Binding::new("cmd-=", IncreaseBufferFontSize, None), - Binding::new("cmd--", DecreaseBufferFontSize, None), - Binding::new("cmd-,", OpenSettings, None), - ]) + keymap_file::load_keymap( + cx, + std::str::from_utf8(Assets::get("keymaps/default.json").unwrap().data.as_ref()).unwrap(), + ) + .unwrap(); } pub fn build_workspace( @@ -208,9 +209,8 @@ fn quit(_: &Quit, cx: &mut gpui::MutableAppContext) { #[cfg(test)] mod tests { - use crate::assets::Assets; - use super::*; + use crate::assets::Assets; use editor::{DisplayPoint, Editor}; use gpui::{AssetSource, MutableAppContext, TestAppContext, ViewHandle}; use project::{Fs, ProjectPath}; From 1e2eeaa22a8ed338d7540633c1756403a27df583 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Sun, 10 Apr 2022 11:30:08 -0700 Subject: [PATCH 04/22] Load project and buffer search key bindings from JSON file --- crates/search/src/buffer_search.rs | 24 +++---------------- crates/search/src/project_search.rs | 15 +++--------- crates/zed/assets/keymaps/default.json | 33 ++++++++++++++++++++++++-- 3 files changed, 37 insertions(+), 35 deletions(-) diff --git a/crates/search/src/buffer_search.rs b/crates/search/src/buffer_search.rs index 71e9a90970..b808b85160 100644 --- a/crates/search/src/buffer_search.rs +++ b/crates/search/src/buffer_search.rs @@ -5,9 +5,9 @@ use crate::{ use collections::HashMap; use editor::{display_map::ToDisplayPoint, Anchor, Autoscroll, Bias, Editor}; use gpui::{ - actions, elements::*, impl_actions, impl_internal_actions, keymap::Binding, - platform::CursorStyle, AppContext, Entity, MutableAppContext, RenderContext, Subscription, - Task, View, ViewContext, ViewHandle, WeakViewHandle, + actions, elements::*, impl_actions, impl_internal_actions, platform::CursorStyle, AppContext, + Entity, MutableAppContext, RenderContext, Subscription, Task, View, ViewContext, ViewHandle, + WeakViewHandle, }; use language::OffsetRangeExt; use project::search::SearchQuery; @@ -33,24 +33,6 @@ pub enum Event { } pub fn init(cx: &mut MutableAppContext) { - cx.add_bindings([ - Binding::new( - "cmd-f", - Deploy { focus: true }, - Some("Editor && mode == full"), - ), - Binding::new( - "cmd-e", - Deploy { focus: false }, - Some("Editor && mode == full"), - ), - Binding::new("escape", Dismiss, Some("BufferSearchBar")), - Binding::new("cmd-f", FocusEditor, Some("BufferSearchBar")), - Binding::new("enter", SelectNextMatch, Some("BufferSearchBar")), - Binding::new("shift-enter", SelectPrevMatch, Some("BufferSearchBar")), - Binding::new("cmd-g", SelectNextMatch, Some("Pane")), - Binding::new("cmd-shift-G", SelectPrevMatch, Some("Pane")), - ]); cx.add_action(BufferSearchBar::deploy); cx.add_action(BufferSearchBar::dismiss); cx.add_action(BufferSearchBar::focus_editor); diff --git a/crates/search/src/project_search.rs b/crates/search/src/project_search.rs index 39ff1a09ea..5e4096e483 100644 --- a/crates/search/src/project_search.rs +++ b/crates/search/src/project_search.rs @@ -5,9 +5,9 @@ use crate::{ use collections::HashMap; use editor::{Anchor, Autoscroll, Editor, MultiBuffer, SelectAll}; use gpui::{ - actions, elements::*, keymap::Binding, platform::CursorStyle, AppContext, ElementBox, Entity, - ModelContext, ModelHandle, MutableAppContext, RenderContext, Subscription, Task, View, - ViewContext, ViewHandle, WeakModelHandle, WeakViewHandle, + actions, elements::*, platform::CursorStyle, AppContext, ElementBox, Entity, ModelContext, + ModelHandle, MutableAppContext, RenderContext, Subscription, Task, View, ViewContext, + ViewHandle, WeakModelHandle, WeakViewHandle, }; use project::{search::SearchQuery, Project}; use settings::Settings; @@ -28,15 +28,6 @@ struct ActiveSearches(HashMap, WeakViewHandle Date: Sun, 10 Apr 2022 11:39:43 -0700 Subject: [PATCH 05/22] Load modal key bindings from JSON file --- crates/file_finder/src/file_finder.rs | 13 ++-------- crates/go_to_line/src/go_to_line.rs | 9 ++----- crates/outline/src/outline.rs | 12 ++------- crates/project_symbols/src/project_symbols.rs | 11 ++------ crates/theme_selector/src/theme_selector.rs | 13 ++-------- crates/zed/assets/keymaps/default.json | 26 +++++++++++++++++-- 6 files changed, 34 insertions(+), 50 deletions(-) diff --git a/crates/file_finder/src/file_finder.rs b/crates/file_finder/src/file_finder.rs index 659dde7c5b..f3f2c31d2c 100644 --- a/crates/file_finder/src/file_finder.rs +++ b/crates/file_finder/src/file_finder.rs @@ -1,12 +1,8 @@ use editor::Editor; use fuzzy::PathMatch; use gpui::{ - actions, - elements::*, - impl_internal_actions, - keymap::{self, Binding}, - AppContext, Axis, Entity, ModelHandle, MutableAppContext, RenderContext, Task, View, - ViewContext, ViewHandle, WeakViewHandle, + actions, elements::*, impl_internal_actions, keymap, AppContext, Axis, Entity, ModelHandle, + MutableAppContext, RenderContext, Task, View, ViewContext, ViewHandle, WeakViewHandle, }; use project::{Project, ProjectPath, WorktreeId}; use settings::Settings; @@ -50,11 +46,6 @@ pub fn init(cx: &mut MutableAppContext) { cx.add_action(FileFinder::select); cx.add_action(FileFinder::select_prev); cx.add_action(FileFinder::select_next); - - cx.add_bindings(vec![ - Binding::new("cmd-p", Toggle, None), - Binding::new("escape", Toggle, Some("FileFinder")), - ]); } pub enum Event { diff --git a/crates/go_to_line/src/go_to_line.rs b/crates/go_to_line/src/go_to_line.rs index 9995736550..16b633ad72 100644 --- a/crates/go_to_line/src/go_to_line.rs +++ b/crates/go_to_line/src/go_to_line.rs @@ -1,7 +1,7 @@ use editor::{display_map::ToDisplayPoint, Autoscroll, DisplayPoint, Editor}; use gpui::{ - actions, elements::*, geometry::vector::Vector2F, keymap::Binding, Axis, Entity, - MutableAppContext, RenderContext, View, ViewContext, ViewHandle, + actions, elements::*, geometry::vector::Vector2F, Axis, Entity, MutableAppContext, + RenderContext, View, ViewContext, ViewHandle, }; use settings::Settings; use text::{Bias, Point}; @@ -10,11 +10,6 @@ use workspace::Workspace; actions!(go_to_line, [Toggle, Confirm]); pub fn init(cx: &mut MutableAppContext) { - cx.add_bindings([ - Binding::new("ctrl-g", Toggle, Some("Editor")), - Binding::new("escape", Toggle, Some("GoToLine")), - Binding::new("enter", Confirm, Some("GoToLine")), - ]); cx.add_action(GoToLine::toggle); cx.add_action(GoToLine::confirm); } diff --git a/crates/outline/src/outline.rs b/crates/outline/src/outline.rs index 5386657ef2..08bc18a016 100644 --- a/crates/outline/src/outline.rs +++ b/crates/outline/src/outline.rs @@ -4,12 +4,8 @@ use editor::{ }; use fuzzy::StringMatch; use gpui::{ - actions, - elements::*, - geometry::vector::Vector2F, - keymap::{self, Binding}, - AppContext, Axis, Entity, MutableAppContext, RenderContext, View, ViewContext, ViewHandle, - WeakViewHandle, + actions, elements::*, geometry::vector::Vector2F, keymap, AppContext, Axis, Entity, + MutableAppContext, RenderContext, View, ViewContext, ViewHandle, WeakViewHandle, }; use language::Outline; use ordered_float::OrderedFloat; @@ -23,10 +19,6 @@ use workspace::{ actions!(outline, [Toggle]); pub fn init(cx: &mut MutableAppContext) { - cx.add_bindings([ - Binding::new("cmd-shift-O", Toggle, Some("Editor")), - Binding::new("escape", Toggle, Some("OutlineView")), - ]); cx.add_action(OutlineView::toggle); cx.add_action(OutlineView::confirm); cx.add_action(OutlineView::select_prev); diff --git a/crates/project_symbols/src/project_symbols.rs b/crates/project_symbols/src/project_symbols.rs index 689f579b81..c14f7bea33 100644 --- a/crates/project_symbols/src/project_symbols.rs +++ b/crates/project_symbols/src/project_symbols.rs @@ -3,11 +3,8 @@ use editor::{ }; use fuzzy::{StringMatch, StringMatchCandidate}; use gpui::{ - actions, - elements::*, - keymap::{self, Binding}, - AppContext, Axis, Entity, ModelHandle, MutableAppContext, RenderContext, Task, View, - ViewContext, ViewHandle, WeakViewHandle, + actions, elements::*, keymap, AppContext, Axis, Entity, ModelHandle, MutableAppContext, + RenderContext, Task, View, ViewContext, ViewHandle, WeakViewHandle, }; use ordered_float::OrderedFloat; use project::{Project, Symbol}; @@ -25,10 +22,6 @@ use workspace::{ actions!(project_symbols, [Toggle]); pub fn init(cx: &mut MutableAppContext) { - cx.add_bindings([ - Binding::new("cmd-t", Toggle, None), - Binding::new("escape", Toggle, Some("ProjectSymbolsView")), - ]); cx.add_action(ProjectSymbolsView::toggle); cx.add_action(ProjectSymbolsView::confirm); cx.add_action(ProjectSymbolsView::select_prev); diff --git a/crates/theme_selector/src/theme_selector.rs b/crates/theme_selector/src/theme_selector.rs index 733df65b82..37099eb510 100644 --- a/crates/theme_selector/src/theme_selector.rs +++ b/crates/theme_selector/src/theme_selector.rs @@ -1,11 +1,8 @@ use editor::Editor; use fuzzy::{match_strings, StringMatch, StringMatchCandidate}; use gpui::{ - actions, - elements::*, - keymap::{self, Binding}, - AppContext, Axis, Element, ElementBox, Entity, MutableAppContext, RenderContext, View, - ViewContext, ViewHandle, + actions, elements::*, keymap, AppContext, Axis, Element, ElementBox, Entity, MutableAppContext, + RenderContext, View, ViewContext, ViewHandle, }; use settings::Settings; use std::{cmp, sync::Arc}; @@ -33,12 +30,6 @@ pub fn init(cx: &mut MutableAppContext) { cx.add_action(ThemeSelector::select_next); cx.add_action(ThemeSelector::toggle); cx.add_action(ThemeSelector::reload); - - cx.add_bindings(vec![ - Binding::new("cmd-k cmd-t", Toggle, None), - Binding::new("cmd-k t", Reload, None), - Binding::new("escape", Toggle, Some("ThemeSelector")), - ]); } pub enum Event { diff --git a/crates/zed/assets/keymaps/default.json b/crates/zed/assets/keymaps/default.json index c121edad76..addd5ffb1e 100644 --- a/crates/zed/assets/keymaps/default.json +++ b/crates/zed/assets/keymaps/default.json @@ -47,7 +47,11 @@ "cmd-shift-G": "search::SelectPrevMatch" }, "Workspace": { - "cmd-shift-F": "project_search::Deploy" + "cmd-shift-F": "project_search::Deploy", + "cmd-k cmd-t": "theme_selector::Toggle", + "cmd-k t": "theme_selector::Reload", + "cmd-t": "project_symbols::Toggle", + "cmd-p": "file_finder::Toggle" }, "ProjectSearchBar": { "enter": "project_search::Search", @@ -217,12 +221,30 @@ { "focus": false } - ] + ], + "cmd-shift-O": "outline::Toggle", + "ctrl-g": "go_to_line::Toggle" }, "Editor && mode == auto_height": { "alt-enter": [ "editor::Input", "\n" ] + }, + "OutlineView": { + "escape": "outline::Toggle" + }, + "ProjectSymbolsView": { + "escape": "project_symbols::Toggle" + }, + "ThemeSelector": { + "escape": "theme_selector::Toggle" + }, + "GoToLine": { + "escape": "go_to_line::Toggle", + "enter": "go_to_line::Confirm" + }, + "FileFinder": { + "escape": "file_finder::Toggle" } } \ No newline at end of file From 9a4b8e3d8cbb6e207a2a1e057d34c40050545960 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Sun, 10 Apr 2022 14:29:45 -0700 Subject: [PATCH 06/22] Load all keybindings from JSON file --- crates/chat_panel/src/chat_panel.rs | 3 - crates/diagnostics/src/diagnostics.rs | 6 +- crates/journal/src/journal.rs | 3 +- crates/project_panel/src/project_panel.rs | 7 +-- crates/vim/src/insert.rs | 8 +-- crates/vim/src/normal.rs | 23 +------- crates/vim/src/normal/g_prefix.rs | 8 +-- crates/zed/assets/keymaps/default.json | 67 ++++++++++++++++++++++- crates/zed/src/keymap_file.rs | 9 ++- 9 files changed, 81 insertions(+), 53 deletions(-) diff --git a/crates/chat_panel/src/chat_panel.rs b/crates/chat_panel/src/chat_panel.rs index 3e432f98c1..187c0139db 100644 --- a/crates/chat_panel/src/chat_panel.rs +++ b/crates/chat_panel/src/chat_panel.rs @@ -6,7 +6,6 @@ use editor::Editor; use gpui::{ actions, elements::*, - keymap::Binding, platform::CursorStyle, views::{ItemType, Select, SelectStyle}, AppContext, Entity, ModelHandle, MutableAppContext, RenderContext, Subscription, Task, View, @@ -38,8 +37,6 @@ actions!(chat_panel, [Send, LoadMoreMessages]); pub fn init(cx: &mut MutableAppContext) { cx.add_action(ChatPanel::send); cx.add_action(ChatPanel::load_more_messages); - - cx.add_bindings(vec![Binding::new("enter", Send, Some("ChatPanel"))]); } impl ChatPanel { diff --git a/crates/diagnostics/src/diagnostics.rs b/crates/diagnostics/src/diagnostics.rs index ba5a518673..ea8150da45 100644 --- a/crates/diagnostics/src/diagnostics.rs +++ b/crates/diagnostics/src/diagnostics.rs @@ -8,9 +8,8 @@ use editor::{ highlight_diagnostic_message, Editor, ExcerptId, MultiBuffer, ToOffset, }; use gpui::{ - actions, elements::*, fonts::TextStyle, keymap::Binding, AnyViewHandle, AppContext, Entity, - ModelHandle, MutableAppContext, RenderContext, Task, View, ViewContext, ViewHandle, - WeakViewHandle, + actions, elements::*, fonts::TextStyle, AnyViewHandle, AppContext, Entity, ModelHandle, + MutableAppContext, RenderContext, Task, View, ViewContext, ViewHandle, WeakViewHandle, }; use language::{ Bias, Buffer, Diagnostic, DiagnosticEntry, DiagnosticSeverity, Point, Selection, SelectionGoal, @@ -33,7 +32,6 @@ actions!(diagnostics, [Deploy]); const CONTEXT_LINE_COUNT: u32 = 1; pub fn init(cx: &mut MutableAppContext) { - cx.add_bindings([Binding::new("alt-shift-D", Deploy, Some("Workspace"))]); cx.add_action(ProjectDiagnosticsEditor::deploy); } diff --git a/crates/journal/src/journal.rs b/crates/journal/src/journal.rs index de9945d10e..910c2947b4 100644 --- a/crates/journal/src/journal.rs +++ b/crates/journal/src/journal.rs @@ -1,6 +1,6 @@ use chrono::{Datelike, Local, Timelike}; use editor::{Autoscroll, Editor}; -use gpui::{actions, keymap::Binding, MutableAppContext}; +use gpui::{actions, MutableAppContext}; use std::{fs::OpenOptions, sync::Arc}; use util::TryFutureExt as _; use workspace::AppState; @@ -8,7 +8,6 @@ use workspace::AppState; actions!(journal, [NewJournalEntry]); pub fn init(app_state: Arc, cx: &mut MutableAppContext) { - cx.add_bindings(vec![Binding::new("ctrl-alt-cmd-j", NewJournalEntry, None)]); cx.add_global_action(move |_: &NewJournalEntry, cx| new_journal_entry(app_state.clone(), cx)); } diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index a14e03d27d..11e9f2db9e 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -4,8 +4,7 @@ use gpui::{ Align, ConstrainedBox, Empty, Flex, Label, MouseEventHandler, ParentElement, ScrollTarget, Svg, UniformList, UniformListState, }, - impl_internal_actions, - keymap::{self, Binding}, + impl_internal_actions, keymap, platform::CursorStyle, AppContext, Element, ElementBox, Entity, ModelHandle, MutableAppContext, View, ViewContext, ViewHandle, WeakViewHandle, @@ -63,10 +62,6 @@ pub fn init(cx: &mut MutableAppContext) { cx.add_action(ProjectPanel::select_prev); cx.add_action(ProjectPanel::select_next); cx.add_action(ProjectPanel::open_entry); - cx.add_bindings([ - Binding::new("right", ExpandSelectedEntry, Some("ProjectPanel")), - Binding::new("left", CollapseSelectedEntry, Some("ProjectPanel")), - ]); } pub enum Event { diff --git a/crates/vim/src/insert.rs b/crates/vim/src/insert.rs index 749ae7c5d3..597832f95a 100644 --- a/crates/vim/src/insert.rs +++ b/crates/vim/src/insert.rs @@ -1,18 +1,12 @@ use crate::{mode::Mode, SwitchMode, VimState}; use editor::Bias; -use gpui::{actions, keymap::Binding, MutableAppContext, ViewContext}; +use gpui::{actions, MutableAppContext, ViewContext}; use language::SelectionGoal; use workspace::Workspace; actions!(vim, [NormalBefore]); pub fn init(cx: &mut MutableAppContext) { - let context = Some("Editor && vim_mode == insert"); - cx.add_bindings(vec![ - Binding::new("escape", NormalBefore, context), - Binding::new("ctrl-c", NormalBefore, context), - ]); - cx.add_action(normal_before); } diff --git a/crates/vim/src/normal.rs b/crates/vim/src/normal.rs index 0a49d2c8fd..b6752544ae 100644 --- a/crates/vim/src/normal.rs +++ b/crates/vim/src/normal.rs @@ -1,8 +1,8 @@ mod g_prefix; -use crate::{mode::NormalState, Mode, SwitchMode, VimState}; +use crate::VimState; use editor::{char_kind, movement, Bias}; -use gpui::{actions, impl_actions, keymap::Binding, MutableAppContext, ViewContext}; +use gpui::{actions, impl_actions, MutableAppContext, ViewContext}; use language::SelectionGoal; use serde::Deserialize; use workspace::Workspace; @@ -40,26 +40,7 @@ actions!( ); pub fn init(cx: &mut MutableAppContext) { - let context = Some("Editor && vim_mode == normal"); - cx.add_bindings(vec![ - Binding::new("i", SwitchMode(Mode::Insert), context), - Binding::new("g", SwitchMode(Mode::Normal(NormalState::GPrefix)), context), - Binding::new("h", MoveLeft, context), - Binding::new("j", MoveDown, context), - Binding::new("k", MoveUp, context), - Binding::new("l", MoveRight, context), - Binding::new("0", MoveToStartOfLine, context), - Binding::new("shift-$", MoveToEndOfLine, context), - Binding::new("shift-G", MoveToEnd, context), - Binding::new("w", MoveToNextWordStart(false), context), - Binding::new("shift-W", MoveToNextWordStart(true), context), - Binding::new("e", MoveToNextWordEnd(false), context), - Binding::new("shift-E", MoveToNextWordEnd(true), context), - Binding::new("b", MoveToPreviousWordStart(false), context), - Binding::new("shift-B", MoveToPreviousWordStart(true), context), - ]); g_prefix::init(cx); - cx.add_action(move_left); cx.add_action(move_down); cx.add_action(move_up); diff --git a/crates/vim/src/normal/g_prefix.rs b/crates/vim/src/normal/g_prefix.rs index 79c48a686e..5fecbc4c5b 100644 --- a/crates/vim/src/normal/g_prefix.rs +++ b/crates/vim/src/normal/g_prefix.rs @@ -1,16 +1,10 @@ use crate::{mode::Mode, SwitchMode, VimState}; -use gpui::{actions, keymap::Binding, MutableAppContext, ViewContext}; +use gpui::{actions, MutableAppContext, ViewContext}; use workspace::Workspace; actions!(vim, [MoveToStart]); pub fn init(cx: &mut MutableAppContext) { - let context = Some("Editor && vim_mode == normal && vim_submode == g"); - cx.add_bindings(vec![ - Binding::new("g", MoveToStart, context), - Binding::new("escape", SwitchMode(Mode::normal()), context), - ]); - cx.add_action(move_to_start); } diff --git a/crates/zed/assets/keymaps/default.json b/crates/zed/assets/keymaps/default.json index addd5ffb1e..98a9901bd3 100644 --- a/crates/zed/assets/keymaps/default.json +++ b/crates/zed/assets/keymaps/default.json @@ -51,7 +51,9 @@ "cmd-k cmd-t": "theme_selector::Toggle", "cmd-k t": "theme_selector::Reload", "cmd-t": "project_symbols::Toggle", - "cmd-p": "file_finder::Toggle" + "cmd-p": "file_finder::Toggle", + "alt-shift-D": "diagnostics::Deploy", + "ctrl-alt-cmd-j": "journal::NewJournalEntry" }, "ProjectSearchBar": { "enter": "project_search::Search", @@ -246,5 +248,68 @@ }, "FileFinder": { "escape": "file_finder::Toggle" + }, + "ChatPanel": { + "enter": "chat_panel::Send" + }, + "ProjectPanel": { + "left": "project_panel::CollapseSelectedEntry", + "right": "project_panel::ExpandSelectedEntry" + }, + "Editor && vim_mode == insert": { + "escape": "vim::NormalBefore", + "ctrl-c": "vim::NormalBefore" + }, + "Editor && vim_mode == normal && vim_submode == g": { + "g": "vim::MoveToStart", + "escape": [ + "vim::SwitchMode", + { + "Normal": "None" + } + ] + }, + "Editor && vim_mode == normal": { + "i": [ + "vim::SwitchMode", + "Insert" + ], + "g": [ + "vim::SwitchMode", + { + "Normal": "GPrefix" + } + ], + "h": "vim::MoveLeft", + "j": "vim::MoveDown", + "k": "vim::MoveUp", + "l": "vim::MoveRight", + "0": "vim::MoveToStartOfLine", + "shift-$": "vim::MoveToEndOfLine", + "shift-G": "vim::MoveToEnd", + "w": [ + "vim::MoveToNextWordStart", + false + ], + "shift-W": [ + "vim::MoveToNextWordStart", + true + ], + "e": [ + "vim::MoveToNextWordEnd", + false + ], + "shift-E": [ + "vim::MoveToNextWordEnd", + true + ], + "b": [ + "vim::MoveToPreviousWordStart", + false + ], + "shift-B": [ + "vim::MoveToPreviousWordStart", + true + ] } } \ No newline at end of file diff --git a/crates/zed/src/keymap_file.rs b/crates/zed/src/keymap_file.rs index 2eaf1b7ecb..7d9423719e 100644 --- a/crates/zed/src/keymap_file.rs +++ b/crates/zed/src/keymap_file.rs @@ -1,4 +1,4 @@ -use anyhow::Result; +use anyhow::{Context, Result}; use collections::BTreeMap; use gpui::{keymap::Binding, MutableAppContext}; use serde::Deserialize; @@ -28,7 +28,12 @@ pub fn load_keymap(cx: &mut MutableAppContext, content: &str) -> Result<()> { } else { let name = serde_json::from_str(action)?; cx.deserialize_action(name, None) - }?; + } + .with_context(|| { + format!( + "invalid binding value for keystroke {keystroke}, context {context:?}" + ) + })?; Binding::load(keystroke, action, context) }) .collect::>>()?, From 3c116e32cbe1013e917414ad2c297d7bea93abb5 Mon Sep 17 00:00:00 2001 From: Keith Simmons Date: Mon, 11 Apr 2022 10:13:07 -0700 Subject: [PATCH 07/22] Reraise editor events in Project Search and activate workspace item from them --- crates/search/src/project_search.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/crates/search/src/project_search.rs b/crates/search/src/project_search.rs index 9009dfee79..d89982a92c 100644 --- a/crates/search/src/project_search.rs +++ b/crates/search/src/project_search.rs @@ -139,6 +139,7 @@ impl ProjectSearch { pub enum ViewEvent { UpdateTab, + EditorEvent(editor::Event), } impl Entity for ProjectSearchView { @@ -307,6 +308,14 @@ impl Item for ProjectSearchView { .update(cx, |editor, cx| editor.navigate(data, cx)) } + fn should_activate_item_on_event(event: &Self::Event) -> bool { + if let ViewEvent::EditorEvent(editor_event) = event { + Editor::should_activate_item_on_event(editor_event) + } else { + false + } + } + fn should_update_tab_on_event(event: &ViewEvent) -> bool { matches!(event, ViewEvent::UpdateTab) } @@ -341,6 +350,11 @@ impl ProjectSearchView { editor.set_text(query_text, cx); editor }); + // Subcribe to query_editor in order to reraise editor events for workspace item activation purposes + cx.subscribe(&query_editor, |_, _, event, cx| { + cx.emit(ViewEvent::EditorEvent(event.clone())) + }) + .detach(); let results_editor = cx.add_view(|cx| { let mut editor = Editor::for_multibuffer(excerpts, Some(project), cx); @@ -353,6 +367,8 @@ impl ProjectSearchView { if matches!(event, editor::Event::SelectionsChanged { .. }) { this.update_match_index(cx); } + // Reraise editor events for workspace item activation purposes + cx.emit(ViewEvent::EditorEvent(event.clone())); }) .detach(); From 7abd3a98a85cf5a5990c4e2ae027cf19b488aed6 Mon Sep 17 00:00:00 2001 From: Keith Simmons Date: Wed, 6 Apr 2022 21:28:46 -0700 Subject: [PATCH 08/22] Make atlas allocation fallable and skip rendering icons and paths when it fails --- crates/gpui/src/platform/mac/atlas.rs | 24 ++++++-------- crates/gpui/src/platform/mac/image_cache.rs | 5 ++- crates/gpui/src/platform/mac/renderer.rs | 12 ++++++- crates/gpui/src/platform/mac/sprite_cache.rs | 33 +++++++++++--------- 4 files changed, 42 insertions(+), 32 deletions(-) diff --git a/crates/gpui/src/platform/mac/atlas.rs b/crates/gpui/src/platform/mac/atlas.rs index 33f6fc19db..569a964670 100644 --- a/crates/gpui/src/platform/mac/atlas.rs +++ b/crates/gpui/src/platform/mac/atlas.rs @@ -2,7 +2,6 @@ use crate::geometry::{ rect::RectI, vector::{vec2i, Vector2I}, }; -use anyhow::anyhow; use etagere::BucketedAtlasAllocator; use foreign_types::ForeignType; use metal::{Device, TextureDescriptor}; @@ -41,36 +40,31 @@ impl AtlasAllocator { ) } - pub fn allocate(&mut self, requested_size: Vector2I) -> (AllocId, Vector2I) { + pub fn allocate(&mut self, requested_size: Vector2I) -> Option<(AllocId, Vector2I)> { let (alloc_id, origin) = self .atlases .last_mut() .unwrap() .allocate(requested_size) - .unwrap_or_else(|| { + .or_else(|| { let mut atlas = self.new_atlas(requested_size); - let (id, origin) = atlas - .allocate(requested_size) - .ok_or_else(|| { - anyhow!("could not allocate requested size {:?}", requested_size) - }) - .unwrap(); + let (id, origin) = atlas.allocate(requested_size)?; self.atlases.push(atlas); - (id, origin) - }); + Some((id, origin)) + })?; let id = AllocId { atlas_id: self.atlases.len() - 1, alloc_id, }; - (id, origin) + Some((id, origin)) } - pub fn upload(&mut self, size: Vector2I, bytes: &[u8]) -> (AllocId, RectI) { - let (alloc_id, origin) = self.allocate(size); + pub fn upload(&mut self, size: Vector2I, bytes: &[u8]) -> Option<(AllocId, RectI)> { + let (alloc_id, origin) = self.allocate(size)?; let bounds = RectI::new(origin, size); self.atlases[alloc_id.atlas_id].upload(bounds, bytes); - (alloc_id, bounds) + Some((alloc_id, bounds)) } pub fn deallocate(&mut self, id: AllocId) { diff --git a/crates/gpui/src/platform/mac/image_cache.rs b/crates/gpui/src/platform/mac/image_cache.rs index dac2e1a38b..14b7b23986 100644 --- a/crates/gpui/src/platform/mac/image_cache.rs +++ b/crates/gpui/src/platform/mac/image_cache.rs @@ -1,3 +1,4 @@ +use anyhow::anyhow; use metal::{MTLPixelFormat, TextureDescriptor, TextureRef}; use super::atlas::{AllocId, AtlasAllocator}; @@ -31,7 +32,9 @@ impl ImageCache { .prev_frame .remove(&image.id) .or_else(|| self.curr_frame.get(&image.id).copied()) - .unwrap_or_else(|| self.atlases.upload(image.size(), image.as_bytes())); + .or_else(|| self.atlases.upload(image.size(), image.as_bytes())) + .ok_or_else(|| anyhow!("Could not upload image of size {:?}", image.size())) + .unwrap(); self.curr_frame.insert(image.id, (alloc_id, atlas_bounds)); (alloc_id, atlas_bounds) } diff --git a/crates/gpui/src/platform/mac/renderer.rs b/crates/gpui/src/platform/mac/renderer.rs index 873586b61e..0ecee57a09 100644 --- a/crates/gpui/src/platform/mac/renderer.rs +++ b/crates/gpui/src/platform/mac/renderer.rs @@ -172,7 +172,13 @@ impl Renderer { for path in layer.paths() { let origin = path.bounds.origin() * scene.scale_factor(); let size = (path.bounds.size() * scene.scale_factor()).ceil(); - let (alloc_id, atlas_origin) = self.path_atlases.allocate(size.to_i32()); + + let path_allocation = self.path_atlases.allocate(size.to_i32()); + if path_allocation.is_none() { + // Path size was likely zero. + continue; + } + let (alloc_id, atlas_origin) = path_allocation.unwrap(); let atlas_origin = atlas_origin.to_f32(); sprites.push(PathSprite { layer_id, @@ -569,6 +575,10 @@ impl Renderer { let sprite = self.sprite_cache .render_icon(source_size, icon.path.clone(), icon.svg.clone()); + if sprite.is_none() { + continue; + } + let sprite = sprite.unwrap(); sprites_by_atlas .entry(sprite.atlas_id) diff --git a/crates/gpui/src/platform/mac/sprite_cache.rs b/crates/gpui/src/platform/mac/sprite_cache.rs index 17fec02066..2d2a604f68 100644 --- a/crates/gpui/src/platform/mac/sprite_cache.rs +++ b/crates/gpui/src/platform/mac/sprite_cache.rs @@ -4,6 +4,7 @@ use crate::{ geometry::vector::{vec2f, Vector2F, Vector2I}, platform, }; +use collections::hash_map::Entry; use metal::{MTLPixelFormat, TextureDescriptor}; use ordered_float::OrderedFloat; use std::{borrow::Cow, collections::HashMap, sync::Arc}; @@ -114,7 +115,9 @@ impl SpriteCache { scale_factor, )?; - let (alloc_id, atlas_bounds) = atlases.upload(glyph_bounds.size(), &mask); + let (alloc_id, atlas_bounds) = atlases + .upload(glyph_bounds.size(), &mask) + .expect("Could not upload glyph"); Some(GlyphSprite { atlas_id: alloc_id.atlas_id, atlas_origin: atlas_bounds.origin(), @@ -130,15 +133,15 @@ impl SpriteCache { size: Vector2I, path: Cow<'static, str>, svg: usvg::Tree, - ) -> IconSprite { + ) -> Option { let atlases = &mut self.atlases; - self.icons - .entry(IconDescriptor { - path, - width: size.x(), - height: size.y(), - }) - .or_insert_with(|| { + match self.icons.entry(IconDescriptor { + path, + width: size.x(), + height: size.y(), + }) { + Entry::Occupied(entry) => Some(entry.get().clone()), + Entry::Vacant(entry) => { let mut pixmap = tiny_skia::Pixmap::new(size.x() as u32, size.y() as u32).unwrap(); resvg::render(&svg, usvg::FitTo::Width(size.x() as u32), pixmap.as_mut()); let mask = pixmap @@ -146,15 +149,15 @@ impl SpriteCache { .iter() .map(|a| a.alpha()) .collect::>(); - - let (alloc_id, atlas_bounds) = atlases.upload(size, &mask); - IconSprite { + let (alloc_id, atlas_bounds) = atlases.upload(size, &mask)?; + let icon_sprite = IconSprite { atlas_id: alloc_id.atlas_id, atlas_origin: atlas_bounds.origin(), size, - } - }) - .clone() + }; + Some(entry.insert(icon_sprite).clone()) + } + } } pub fn atlas_texture(&self, atlas_id: usize) -> Option<&metal::TextureRef> { From 0ca4c9946a0b01d261a725d2f81858a801cfb23d Mon Sep 17 00:00:00 2001 From: Keith Simmons Date: Mon, 11 Apr 2022 10:31:38 -0700 Subject: [PATCH 09/22] Add logging when atlas allocator fails to allocate --- crates/gpui/src/platform/mac/atlas.rs | 14 ++++++++++++-- crates/gpui/src/platform/mac/image_cache.rs | 2 +- crates/gpui/src/platform/mac/renderer.rs | 2 ++ crates/gpui/src/platform/mac/sprite_cache.rs | 2 +- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/crates/gpui/src/platform/mac/atlas.rs b/crates/gpui/src/platform/mac/atlas.rs index 569a964670..a7a4de1000 100644 --- a/crates/gpui/src/platform/mac/atlas.rs +++ b/crates/gpui/src/platform/mac/atlas.rs @@ -4,6 +4,7 @@ use crate::geometry::{ }; use etagere::BucketedAtlasAllocator; use foreign_types::ForeignType; +use log::warn; use metal::{Device, TextureDescriptor}; use objc::{msg_send, sel, sel_impl}; @@ -41,7 +42,7 @@ impl AtlasAllocator { } pub fn allocate(&mut self, requested_size: Vector2I) -> Option<(AllocId, Vector2I)> { - let (alloc_id, origin) = self + let allocation = self .atlases .last_mut() .unwrap() @@ -51,7 +52,16 @@ impl AtlasAllocator { let (id, origin) = atlas.allocate(requested_size)?; self.atlases.push(atlas); Some((id, origin)) - })?; + }); + + if allocation.is_none() { + warn!( + "allocation of size {:?} could not be created", + requested_size, + ); + } + + let (alloc_id, origin) = allocation?; let id = AllocId { atlas_id: self.atlases.len() - 1, diff --git a/crates/gpui/src/platform/mac/image_cache.rs b/crates/gpui/src/platform/mac/image_cache.rs index 14b7b23986..37129d4fea 100644 --- a/crates/gpui/src/platform/mac/image_cache.rs +++ b/crates/gpui/src/platform/mac/image_cache.rs @@ -33,7 +33,7 @@ impl ImageCache { .remove(&image.id) .or_else(|| self.curr_frame.get(&image.id).copied()) .or_else(|| self.atlases.upload(image.size(), image.as_bytes())) - .ok_or_else(|| anyhow!("Could not upload image of size {:?}", image.size())) + .ok_or_else(|| anyhow!("could not upload image of size {:?}", image.size())) .unwrap(); self.curr_frame.insert(image.id, (alloc_id, atlas_bounds)); (alloc_id, atlas_bounds) diff --git a/crates/gpui/src/platform/mac/renderer.rs b/crates/gpui/src/platform/mac/renderer.rs index 0ecee57a09..b06dabc738 100644 --- a/crates/gpui/src/platform/mac/renderer.rs +++ b/crates/gpui/src/platform/mac/renderer.rs @@ -9,6 +9,7 @@ use crate::{ scene::{Glyph, Icon, Image, Layer, Quad, Scene, Shadow, Underline}, }; use cocoa::foundation::NSUInteger; +use log::warn; use metal::{MTLPixelFormat, MTLResourceOptions, NSRange}; use shaders::ToFloat2 as _; use std::{collections::HashMap, ffi::c_void, iter::Peekable, mem, sync::Arc, vec}; @@ -176,6 +177,7 @@ impl Renderer { let path_allocation = self.path_atlases.allocate(size.to_i32()); if path_allocation.is_none() { // Path size was likely zero. + warn!("could not allocate path texture of size {:?}", size); continue; } let (alloc_id, atlas_origin) = path_allocation.unwrap(); diff --git a/crates/gpui/src/platform/mac/sprite_cache.rs b/crates/gpui/src/platform/mac/sprite_cache.rs index 2d2a604f68..a9e6acb53f 100644 --- a/crates/gpui/src/platform/mac/sprite_cache.rs +++ b/crates/gpui/src/platform/mac/sprite_cache.rs @@ -117,7 +117,7 @@ impl SpriteCache { let (alloc_id, atlas_bounds) = atlases .upload(glyph_bounds.size(), &mask) - .expect("Could not upload glyph"); + .expect("could not upload glyph"); Some(GlyphSprite { atlas_id: alloc_id.atlas_id, atlas_origin: atlas_bounds.origin(), From 4b295f566a71c88d9c342b513a5520903e333762 Mon Sep 17 00:00:00 2001 From: Keith Simmons Date: Mon, 11 Apr 2022 15:11:23 -0700 Subject: [PATCH 10/22] Handle editor cancel in pane in order to dismiss find toolbar --- crates/editor/src/editor.rs | 46 ++++++++++++++++-------------- crates/search/src/buffer_search.rs | 11 +++++++ 2 files changed, 36 insertions(+), 21 deletions(-) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index e10fe9c17c..fdb555583c 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -1851,33 +1851,37 @@ impl Editor { return; } - if self.mode != EditorMode::Full { - cx.propagate_action(); - return; - } - - if self.active_diagnostics.is_some() { - self.dismiss_diagnostics(cx); - } else if let Some(pending) = self.pending_selection.clone() { - let mut selections = self.selections.clone(); - if selections.is_empty() { - selections = Arc::from([pending.selection]); + if self.mode == EditorMode::Full { + if self.active_diagnostics.is_some() { + self.dismiss_diagnostics(cx); + return; } - self.set_selections(selections, None, true, cx); - self.request_autoscroll(Autoscroll::Fit, cx); - } else { - let mut oldest_selection = self.oldest_selection::(&cx); - if self.selection_count() == 1 { - if oldest_selection.is_empty() { - cx.propagate_action(); - return; - } + if let Some(pending) = self.pending_selection.clone() { + let mut selections = self.selections.clone(); + if selections.is_empty() { + selections = Arc::from([pending.selection]); + } + self.set_selections(selections, None, true, cx); + self.request_autoscroll(Autoscroll::Fit, cx); + return; + } + + let mut oldest_selection = self.oldest_selection::(&cx); + if self.selection_count() > 1 { + self.update_selections(vec![oldest_selection], Some(Autoscroll::Fit), cx); + return; + } + + if !oldest_selection.is_empty() { oldest_selection.start = oldest_selection.head().clone(); oldest_selection.end = oldest_selection.head().clone(); + self.update_selections(vec![oldest_selection], Some(Autoscroll::Fit), cx); + return; } - self.update_selections(vec![oldest_selection], Some(Autoscroll::Fit), cx); } + + cx.propagate_action(); } #[cfg(any(test, feature = "test-support"))] diff --git a/crates/search/src/buffer_search.rs b/crates/search/src/buffer_search.rs index ffaf8e368d..67ad695d0d 100644 --- a/crates/search/src/buffer_search.rs +++ b/crates/search/src/buffer_search.rs @@ -50,6 +50,7 @@ pub fn init(cx: &mut MutableAppContext) { cx.add_action(BufferSearchBar::toggle_search_option); cx.add_action(BufferSearchBar::select_match); cx.add_action(BufferSearchBar::select_match_on_pane); + cx.add_action(BufferSearchBar::handle_editor_cancel); } pub struct BufferSearchBar { @@ -339,6 +340,16 @@ impl BufferSearchBar { cx.propagate_action(); } + fn handle_editor_cancel(pane: &mut Pane, _: &editor::Cancel, cx: &mut ViewContext) { + if let Some(search_bar) = pane.toolbar().read(cx).item_of_type::() { + if !search_bar.read(cx).dismissed { + search_bar.update(cx, |search_bar, cx| search_bar.dismiss(&Dismiss, cx)); + return; + } + } + cx.propagate_action(); + } + fn focus_editor(&mut self, _: &FocusEditor, cx: &mut ViewContext) { if let Some(active_editor) = self.active_editor.as_ref() { cx.focus(active_editor); From e0096ec1eb8c51459394312f35997d2c288aef03 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 11 Apr 2022 15:22:18 -0700 Subject: [PATCH 11/22] Move keymap_file module into settings crate Co-authored-by: Keith Simmons settings}/src/keymap_file.rs | 0 crates/settings/src/settings.rs | 2 ++ crates/zed/src/zed.rs | 3 +-- 5 files changed, 5 insertions(+), 2 deletions(-) rename crates/{zed => settings}/src/keymap_file.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index d32a21d201..4cd3be4969 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4425,6 +4425,7 @@ name = "settings" version = "0.1.0" dependencies = [ "anyhow", + "collections", "gpui", "schemars", "serde", diff --git a/crates/settings/Cargo.toml b/crates/settings/Cargo.toml index baaf787bee..11487af0af 100644 --- a/crates/settings/Cargo.toml +++ b/crates/settings/Cargo.toml @@ -11,6 +11,7 @@ doctest = false test-support = [] [dependencies] +collections = { path = "../collections" } gpui = { path = "../gpui" } theme = { path = "../theme" } util = { path = "../util" } diff --git a/crates/zed/src/keymap_file.rs b/crates/settings/src/keymap_file.rs similarity index 100% rename from crates/zed/src/keymap_file.rs rename to crates/settings/src/keymap_file.rs diff --git a/crates/settings/src/settings.rs b/crates/settings/src/settings.rs index c897586017..aa38ac8840 100644 --- a/crates/settings/src/settings.rs +++ b/crates/settings/src/settings.rs @@ -1,3 +1,5 @@ +pub mod keymap_file; + use anyhow::Result; use gpui::font_cache::{FamilyId, FontCache}; use schemars::{schema_for, JsonSchema}; diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index bae7b517e9..5d5c065b5e 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -1,5 +1,4 @@ pub mod assets; -mod keymap_file; pub mod languages; pub mod menus; pub mod settings_file; @@ -105,7 +104,7 @@ pub fn init(app_state: &Arc, cx: &mut gpui::MutableAppContext) { workspace::lsp_status::init(cx); - keymap_file::load_keymap( + settings::keymap_file::load_keymap( cx, std::str::from_utf8(Assets::get("keymaps/default.json").unwrap().data.as_ref()).unwrap(), ) From c065f283aa4214c4a59766832f864a0d931a78a8 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 11 Apr 2022 15:54:52 -0700 Subject: [PATCH 12/22] Move assets to their own crate, load keymaps in vim tests Also, move assets folder to the top-level. Co-authored-by: Keith Simmons --- Cargo.lock | 12 ++++ .../fonts/zed-mono/zed-mono-extended.ttf | Bin .../fonts/zed-mono/zed-mono-extendedbold.ttf | Bin .../zed-mono/zed-mono-extendedbolditalic.ttf | Bin .../zed-mono/zed-mono-extendeditalic.ttf | Bin .../fonts/zed-sans/zed-sans-extended.ttf | Bin .../fonts/zed-sans/zed-sans-extendedbold.ttf | Bin .../zed-sans/zed-sans-extendedbolditalic.ttf | Bin .../zed-sans/zed-sans-extendeditalic.ttf | Bin .../assets => assets}/icons/broadcast-24.svg | 0 .../assets => assets}/icons/comment-16.svg | 0 .../icons/diagnostic-error-10.svg | 0 .../icons/diagnostic-summary-error.svg | 0 .../icons/diagnostic-summary-warning.svg | 0 .../icons/diagnostic-warning-10.svg | 0 .../icons/disclosure-closed.svg | 0 .../icons/disclosure-open.svg | 0 .../zed/assets => assets}/icons/file-16.svg | 0 .../icons/folder-tree-16.svg | 0 .../zed/assets => assets}/icons/magnifier.svg | 0 .../assets => assets}/icons/offline-14.svg | 0 .../assets => assets}/icons/signed-out-12.svg | 0 .../zed/assets => assets}/icons/user-16.svg | 0 {crates/zed/assets => assets}/icons/x.svg | 0 {crates/zed/assets => assets}/icons/zap.svg | 0 .../assets => assets}/keymaps/default.json | 56 ----------------- assets/keymaps/vim.json | 58 ++++++++++++++++++ .../zed/assets => assets}/themes/dark.json | 0 .../zed/assets => assets}/themes/light.json | 0 crates/assets/Cargo.toml | 14 +++++ crates/{zed => assets}/src/assets.rs | 2 +- crates/settings/Cargo.toml | 1 + crates/settings/src/keymap_file.rs | 11 ++++ crates/vim/Cargo.toml | 1 + crates/vim/src/vim_test_context.rs | 3 + crates/workspace/Cargo.toml | 2 +- crates/zed/Cargo.toml | 1 + crates/zed/src/main.rs | 2 +- crates/zed/src/test.rs | 3 +- crates/zed/src/zed.rs | 10 +-- styles/src/buildThemes.ts | 2 +- 41 files changed, 109 insertions(+), 69 deletions(-) rename {crates/zed/assets => assets}/fonts/zed-mono/zed-mono-extended.ttf (100%) rename {crates/zed/assets => assets}/fonts/zed-mono/zed-mono-extendedbold.ttf (100%) rename {crates/zed/assets => assets}/fonts/zed-mono/zed-mono-extendedbolditalic.ttf (100%) rename {crates/zed/assets => assets}/fonts/zed-mono/zed-mono-extendeditalic.ttf (100%) rename {crates/zed/assets => assets}/fonts/zed-sans/zed-sans-extended.ttf (100%) rename {crates/zed/assets => assets}/fonts/zed-sans/zed-sans-extendedbold.ttf (100%) rename {crates/zed/assets => assets}/fonts/zed-sans/zed-sans-extendedbolditalic.ttf (100%) rename {crates/zed/assets => assets}/fonts/zed-sans/zed-sans-extendeditalic.ttf (100%) rename {crates/zed/assets => assets}/icons/broadcast-24.svg (100%) rename {crates/zed/assets => assets}/icons/comment-16.svg (100%) rename {crates/zed/assets => assets}/icons/diagnostic-error-10.svg (100%) rename {crates/zed/assets => assets}/icons/diagnostic-summary-error.svg (100%) rename {crates/zed/assets => assets}/icons/diagnostic-summary-warning.svg (100%) rename {crates/zed/assets => assets}/icons/diagnostic-warning-10.svg (100%) rename {crates/zed/assets => assets}/icons/disclosure-closed.svg (100%) rename {crates/zed/assets => assets}/icons/disclosure-open.svg (100%) rename {crates/zed/assets => assets}/icons/file-16.svg (100%) rename {crates/zed/assets => assets}/icons/folder-tree-16.svg (100%) rename {crates/zed/assets => assets}/icons/magnifier.svg (100%) rename {crates/zed/assets => assets}/icons/offline-14.svg (100%) rename {crates/zed/assets => assets}/icons/signed-out-12.svg (100%) rename {crates/zed/assets => assets}/icons/user-16.svg (100%) rename {crates/zed/assets => assets}/icons/x.svg (100%) rename {crates/zed/assets => assets}/icons/zap.svg (100%) rename {crates/zed/assets => assets}/keymaps/default.json (87%) create mode 100644 assets/keymaps/vim.json rename {crates/zed/assets => assets}/themes/dark.json (100%) rename {crates/zed/assets => assets}/themes/light.json (100%) create mode 100644 crates/assets/Cargo.toml rename crates/{zed => assets}/src/assets.rs (95%) diff --git a/Cargo.lock b/Cargo.lock index 4cd3be4969..8917fcac2f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -168,6 +168,15 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbf56136a5198c7b01a49e3afcbef6cf84597273d298f54432926024107b0109" +[[package]] +name = "assets" +version = "0.1.0" +dependencies = [ + "anyhow", + "gpui", + "rust-embed", +] + [[package]] name = "async-attributes" version = "1.1.2" @@ -4425,6 +4434,7 @@ name = "settings" version = "0.1.0" dependencies = [ "anyhow", + "assets", "collections", "gpui", "schemars", @@ -5743,6 +5753,7 @@ checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" name = "vim" version = "0.1.0" dependencies = [ + "assets", "collections", "editor", "gpui", @@ -6018,6 +6029,7 @@ name = "zed" version = "0.25.0" dependencies = [ "anyhow", + "assets", "async-compression", "async-recursion", "async-trait", diff --git a/crates/zed/assets/fonts/zed-mono/zed-mono-extended.ttf b/assets/fonts/zed-mono/zed-mono-extended.ttf similarity index 100% rename from crates/zed/assets/fonts/zed-mono/zed-mono-extended.ttf rename to assets/fonts/zed-mono/zed-mono-extended.ttf diff --git a/crates/zed/assets/fonts/zed-mono/zed-mono-extendedbold.ttf b/assets/fonts/zed-mono/zed-mono-extendedbold.ttf similarity index 100% rename from crates/zed/assets/fonts/zed-mono/zed-mono-extendedbold.ttf rename to assets/fonts/zed-mono/zed-mono-extendedbold.ttf diff --git a/crates/zed/assets/fonts/zed-mono/zed-mono-extendedbolditalic.ttf b/assets/fonts/zed-mono/zed-mono-extendedbolditalic.ttf similarity index 100% rename from crates/zed/assets/fonts/zed-mono/zed-mono-extendedbolditalic.ttf rename to assets/fonts/zed-mono/zed-mono-extendedbolditalic.ttf diff --git a/crates/zed/assets/fonts/zed-mono/zed-mono-extendeditalic.ttf b/assets/fonts/zed-mono/zed-mono-extendeditalic.ttf similarity index 100% rename from crates/zed/assets/fonts/zed-mono/zed-mono-extendeditalic.ttf rename to assets/fonts/zed-mono/zed-mono-extendeditalic.ttf diff --git a/crates/zed/assets/fonts/zed-sans/zed-sans-extended.ttf b/assets/fonts/zed-sans/zed-sans-extended.ttf similarity index 100% rename from crates/zed/assets/fonts/zed-sans/zed-sans-extended.ttf rename to assets/fonts/zed-sans/zed-sans-extended.ttf diff --git a/crates/zed/assets/fonts/zed-sans/zed-sans-extendedbold.ttf b/assets/fonts/zed-sans/zed-sans-extendedbold.ttf similarity index 100% rename from crates/zed/assets/fonts/zed-sans/zed-sans-extendedbold.ttf rename to assets/fonts/zed-sans/zed-sans-extendedbold.ttf diff --git a/crates/zed/assets/fonts/zed-sans/zed-sans-extendedbolditalic.ttf b/assets/fonts/zed-sans/zed-sans-extendedbolditalic.ttf similarity index 100% rename from crates/zed/assets/fonts/zed-sans/zed-sans-extendedbolditalic.ttf rename to assets/fonts/zed-sans/zed-sans-extendedbolditalic.ttf diff --git a/crates/zed/assets/fonts/zed-sans/zed-sans-extendeditalic.ttf b/assets/fonts/zed-sans/zed-sans-extendeditalic.ttf similarity index 100% rename from crates/zed/assets/fonts/zed-sans/zed-sans-extendeditalic.ttf rename to assets/fonts/zed-sans/zed-sans-extendeditalic.ttf diff --git a/crates/zed/assets/icons/broadcast-24.svg b/assets/icons/broadcast-24.svg similarity index 100% rename from crates/zed/assets/icons/broadcast-24.svg rename to assets/icons/broadcast-24.svg diff --git a/crates/zed/assets/icons/comment-16.svg b/assets/icons/comment-16.svg similarity index 100% rename from crates/zed/assets/icons/comment-16.svg rename to assets/icons/comment-16.svg diff --git a/crates/zed/assets/icons/diagnostic-error-10.svg b/assets/icons/diagnostic-error-10.svg similarity index 100% rename from crates/zed/assets/icons/diagnostic-error-10.svg rename to assets/icons/diagnostic-error-10.svg diff --git a/crates/zed/assets/icons/diagnostic-summary-error.svg b/assets/icons/diagnostic-summary-error.svg similarity index 100% rename from crates/zed/assets/icons/diagnostic-summary-error.svg rename to assets/icons/diagnostic-summary-error.svg diff --git a/crates/zed/assets/icons/diagnostic-summary-warning.svg b/assets/icons/diagnostic-summary-warning.svg similarity index 100% rename from crates/zed/assets/icons/diagnostic-summary-warning.svg rename to assets/icons/diagnostic-summary-warning.svg diff --git a/crates/zed/assets/icons/diagnostic-warning-10.svg b/assets/icons/diagnostic-warning-10.svg similarity index 100% rename from crates/zed/assets/icons/diagnostic-warning-10.svg rename to assets/icons/diagnostic-warning-10.svg diff --git a/crates/zed/assets/icons/disclosure-closed.svg b/assets/icons/disclosure-closed.svg similarity index 100% rename from crates/zed/assets/icons/disclosure-closed.svg rename to assets/icons/disclosure-closed.svg diff --git a/crates/zed/assets/icons/disclosure-open.svg b/assets/icons/disclosure-open.svg similarity index 100% rename from crates/zed/assets/icons/disclosure-open.svg rename to assets/icons/disclosure-open.svg diff --git a/crates/zed/assets/icons/file-16.svg b/assets/icons/file-16.svg similarity index 100% rename from crates/zed/assets/icons/file-16.svg rename to assets/icons/file-16.svg diff --git a/crates/zed/assets/icons/folder-tree-16.svg b/assets/icons/folder-tree-16.svg similarity index 100% rename from crates/zed/assets/icons/folder-tree-16.svg rename to assets/icons/folder-tree-16.svg diff --git a/crates/zed/assets/icons/magnifier.svg b/assets/icons/magnifier.svg similarity index 100% rename from crates/zed/assets/icons/magnifier.svg rename to assets/icons/magnifier.svg diff --git a/crates/zed/assets/icons/offline-14.svg b/assets/icons/offline-14.svg similarity index 100% rename from crates/zed/assets/icons/offline-14.svg rename to assets/icons/offline-14.svg diff --git a/crates/zed/assets/icons/signed-out-12.svg b/assets/icons/signed-out-12.svg similarity index 100% rename from crates/zed/assets/icons/signed-out-12.svg rename to assets/icons/signed-out-12.svg diff --git a/crates/zed/assets/icons/user-16.svg b/assets/icons/user-16.svg similarity index 100% rename from crates/zed/assets/icons/user-16.svg rename to assets/icons/user-16.svg diff --git a/crates/zed/assets/icons/x.svg b/assets/icons/x.svg similarity index 100% rename from crates/zed/assets/icons/x.svg rename to assets/icons/x.svg diff --git a/crates/zed/assets/icons/zap.svg b/assets/icons/zap.svg similarity index 100% rename from crates/zed/assets/icons/zap.svg rename to assets/icons/zap.svg diff --git a/crates/zed/assets/keymaps/default.json b/assets/keymaps/default.json similarity index 87% rename from crates/zed/assets/keymaps/default.json rename to assets/keymaps/default.json index 98a9901bd3..6b5511dbce 100644 --- a/crates/zed/assets/keymaps/default.json +++ b/assets/keymaps/default.json @@ -255,61 +255,5 @@ "ProjectPanel": { "left": "project_panel::CollapseSelectedEntry", "right": "project_panel::ExpandSelectedEntry" - }, - "Editor && vim_mode == insert": { - "escape": "vim::NormalBefore", - "ctrl-c": "vim::NormalBefore" - }, - "Editor && vim_mode == normal && vim_submode == g": { - "g": "vim::MoveToStart", - "escape": [ - "vim::SwitchMode", - { - "Normal": "None" - } - ] - }, - "Editor && vim_mode == normal": { - "i": [ - "vim::SwitchMode", - "Insert" - ], - "g": [ - "vim::SwitchMode", - { - "Normal": "GPrefix" - } - ], - "h": "vim::MoveLeft", - "j": "vim::MoveDown", - "k": "vim::MoveUp", - "l": "vim::MoveRight", - "0": "vim::MoveToStartOfLine", - "shift-$": "vim::MoveToEndOfLine", - "shift-G": "vim::MoveToEnd", - "w": [ - "vim::MoveToNextWordStart", - false - ], - "shift-W": [ - "vim::MoveToNextWordStart", - true - ], - "e": [ - "vim::MoveToNextWordEnd", - false - ], - "shift-E": [ - "vim::MoveToNextWordEnd", - true - ], - "b": [ - "vim::MoveToPreviousWordStart", - false - ], - "shift-B": [ - "vim::MoveToPreviousWordStart", - true - ] } } \ No newline at end of file diff --git a/assets/keymaps/vim.json b/assets/keymaps/vim.json new file mode 100644 index 0000000000..f8273286df --- /dev/null +++ b/assets/keymaps/vim.json @@ -0,0 +1,58 @@ +{ + "Editor && vim_mode == insert": { + "escape": "vim::NormalBefore", + "ctrl-c": "vim::NormalBefore" + }, + "Editor && vim_mode == normal && vim_submode == g": { + "g": "vim::MoveToStart", + "escape": [ + "vim::SwitchMode", + { + "Normal": "None" + } + ] + }, + "Editor && vim_mode == normal": { + "i": [ + "vim::SwitchMode", + "Insert" + ], + "g": [ + "vim::SwitchMode", + { + "Normal": "GPrefix" + } + ], + "h": "vim::MoveLeft", + "j": "vim::MoveDown", + "k": "vim::MoveUp", + "l": "vim::MoveRight", + "0": "vim::MoveToStartOfLine", + "shift-$": "vim::MoveToEndOfLine", + "shift-G": "vim::MoveToEnd", + "w": [ + "vim::MoveToNextWordStart", + false + ], + "shift-W": [ + "vim::MoveToNextWordStart", + true + ], + "e": [ + "vim::MoveToNextWordEnd", + false + ], + "shift-E": [ + "vim::MoveToNextWordEnd", + true + ], + "b": [ + "vim::MoveToPreviousWordStart", + false + ], + "shift-B": [ + "vim::MoveToPreviousWordStart", + true + ] + } +} \ No newline at end of file diff --git a/crates/zed/assets/themes/dark.json b/assets/themes/dark.json similarity index 100% rename from crates/zed/assets/themes/dark.json rename to assets/themes/dark.json diff --git a/crates/zed/assets/themes/light.json b/assets/themes/light.json similarity index 100% rename from crates/zed/assets/themes/light.json rename to assets/themes/light.json diff --git a/crates/assets/Cargo.toml b/crates/assets/Cargo.toml new file mode 100644 index 0000000000..71db57f320 --- /dev/null +++ b/crates/assets/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "assets" +version = "0.1.0" +edition = "2021" + +[lib] +path = "src/assets.rs" +doctest = false + +[dependencies] +gpui = { path = "../gpui" } +anyhow = "1.0.38" +rust-embed = { version = "6.3", features = ["include-exclude"] } + diff --git a/crates/zed/src/assets.rs b/crates/assets/src/assets.rs similarity index 95% rename from crates/zed/src/assets.rs rename to crates/assets/src/assets.rs index c0f3a1fbfc..7d5748e43b 100644 --- a/crates/zed/src/assets.rs +++ b/crates/assets/src/assets.rs @@ -3,7 +3,7 @@ use gpui::AssetSource; use rust_embed::RustEmbed; #[derive(RustEmbed)] -#[folder = "assets"] +#[folder = "../../assets"] #[exclude = "*.DS_Store"] pub struct Assets; diff --git a/crates/settings/Cargo.toml b/crates/settings/Cargo.toml index 11487af0af..cc37b1bcfd 100644 --- a/crates/settings/Cargo.toml +++ b/crates/settings/Cargo.toml @@ -11,6 +11,7 @@ doctest = false test-support = [] [dependencies] +assets = { path = "../assets" } collections = { path = "../collections" } gpui = { path = "../gpui" } theme = { path = "../theme" } diff --git a/crates/settings/src/keymap_file.rs b/crates/settings/src/keymap_file.rs index 7d9423719e..621310c220 100644 --- a/crates/settings/src/keymap_file.rs +++ b/crates/settings/src/keymap_file.rs @@ -1,4 +1,5 @@ use anyhow::{Context, Result}; +use assets::Assets; use collections::BTreeMap; use gpui::{keymap::Binding, MutableAppContext}; use serde::Deserialize; @@ -9,6 +10,16 @@ struct ActionWithData<'a>(#[serde(borrow)] &'a str, #[serde(borrow)] &'a RawValu type ActionSetsByContext<'a> = BTreeMap<&'a str, ActionsByKeystroke<'a>>; type ActionsByKeystroke<'a> = BTreeMap<&'a str, &'a RawValue>; +pub fn load_built_in_keymaps(cx: &mut MutableAppContext) { + for path in ["keymaps/default.json", "keymaps/vim.json"] { + load_keymap( + cx, + std::str::from_utf8(Assets::get(path).unwrap().data.as_ref()).unwrap(), + ) + .unwrap(); + } +} + pub fn load_keymap(cx: &mut MutableAppContext, content: &str) -> Result<()> { let actions: ActionSetsByContext = serde_json::from_str(content)?; for (context, actions) in actions { diff --git a/crates/vim/Cargo.toml b/crates/vim/Cargo.toml index f1413d7c51..aeda009ba4 100644 --- a/crates/vim/Cargo.toml +++ b/crates/vim/Cargo.toml @@ -8,6 +8,7 @@ path = "src/vim.rs" doctest = false [dependencies] +assets = { path = "../assets" } collections = { path = "../collections" } editor = { path = "../editor" } gpui = { path = "../gpui" } diff --git a/crates/vim/src/vim_test_context.rs b/crates/vim/src/vim_test_context.rs index 91acc8de6c..5818bdad65 100644 --- a/crates/vim/src/vim_test_context.rs +++ b/crates/vim/src/vim_test_context.rs @@ -23,7 +23,10 @@ impl<'a> VimTestContext<'a> { cx.update(|cx| { editor::init(cx); crate::init(cx); + + settings::keymap_file::load_built_in_keymaps(cx); }); + let params = cx.update(WorkspaceParams::test); cx.update(|cx| { diff --git a/crates/workspace/Cargo.toml b/crates/workspace/Cargo.toml index 75d1b1b8f2..d9deef146b 100644 --- a/crates/workspace/Cargo.toml +++ b/crates/workspace/Cargo.toml @@ -8,7 +8,7 @@ path = "src/workspace.rs" doctest = false [features] -test-support = ["client/test-support", "project/test-support"] +test-support = ["client/test-support", "project/test-support", "settings/test-support"] [dependencies] client = { path = "../client" } diff --git a/crates/zed/Cargo.toml b/crates/zed/Cargo.toml index f87046b05e..b0fbe48fe5 100644 --- a/crates/zed/Cargo.toml +++ b/crates/zed/Cargo.toml @@ -29,6 +29,7 @@ test-support = [ ] [dependencies] +assets = { path = "../assets" } breadcrumbs = { path = "../breadcrumbs" } chat_panel = { path = "../chat_panel" } collections = { path = "../collections" } diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index bfb1b34256..112de01898 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -15,9 +15,9 @@ use std::{env, fs, path::PathBuf, sync::Arc}; use theme::{ThemeRegistry, DEFAULT_THEME_NAME}; use util::ResultExt; use workspace::{self, AppState, OpenNew, OpenPaths}; +use assets::Assets; use zed::{ self, - assets::Assets, build_window_options, build_workspace, fs::RealFs, languages, menus, diff --git a/crates/zed/src/test.rs b/crates/zed/src/test.rs index 363c852c35..0b81c4361b 100644 --- a/crates/zed/src/test.rs +++ b/crates/zed/src/test.rs @@ -1,4 +1,5 @@ -use crate::{assets::Assets, build_window_options, build_workspace, AppState}; +use crate::{build_window_options, build_workspace, AppState}; +use assets::Assets; use client::{test::FakeHttpClient, ChannelList, Client, UserStore}; use gpui::MutableAppContext; use language::LanguageRegistry; diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 5d5c065b5e..6ab9619016 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -1,11 +1,9 @@ -pub mod assets; pub mod languages; pub mod menus; pub mod settings_file; #[cfg(any(test, feature = "test-support"))] pub mod test; -use assets::Assets; use breadcrumbs::Breadcrumbs; use chat_panel::ChatPanel; pub use client; @@ -104,11 +102,7 @@ pub fn init(app_state: &Arc, cx: &mut gpui::MutableAppContext) { workspace::lsp_status::init(cx); - settings::keymap_file::load_keymap( - cx, - std::str::from_utf8(Assets::get("keymaps/default.json").unwrap().data.as_ref()).unwrap(), - ) - .unwrap(); + settings::keymap_file::load_built_in_keymaps(cx); } pub fn build_workspace( @@ -209,7 +203,7 @@ fn quit(_: &Quit, cx: &mut gpui::MutableAppContext) { #[cfg(test)] mod tests { use super::*; - use crate::assets::Assets; + use assets::Assets; use editor::{DisplayPoint, Editor}; use gpui::{AssetSource, MutableAppContext, TestAppContext, ViewHandle}; use project::{Fs, ProjectPath}; diff --git a/styles/src/buildThemes.ts b/styles/src/buildThemes.ts index ccbaf82c7f..ce8812ebda 100644 --- a/styles/src/buildThemes.ts +++ b/styles/src/buildThemes.ts @@ -10,7 +10,7 @@ for (let theme of themes) { let styleTree = snakeCase(app(theme)); let styleTreeJSON = JSON.stringify(styleTree, null, 2); let outPath = path.resolve( - `${__dirname}/../../crates/zed/assets/themes/${theme.name}.json` + `${__dirname}/../assets/themes/${theme.name}.json` ); fs.writeFileSync(outPath, styleTreeJSON); console.log(`- ${outPath} created`); From be11f63f1e23c408adc4aad2e625ab1c8ba7d49b Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 11 Apr 2022 16:50:44 -0700 Subject: [PATCH 13/22] Watch ~/.zed/bindings.json file for custom key bindings Co-authored-by: Keith Simmons --- crates/gpui/src/app.rs | 4 ++ crates/gpui/src/keymap.rs | 9 ++++ crates/settings/src/keymap_file.rs | 83 ++++++++++++++++-------------- crates/settings/src/settings.rs | 4 +- crates/vim/src/vim_test_context.rs | 2 +- crates/zed/src/main.rs | 32 ++++++++---- crates/zed/src/settings_file.rs | 33 ++++++++---- crates/zed/src/zed.rs | 3 +- 8 files changed, 110 insertions(+), 60 deletions(-) diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index 962343a28a..f0d33252e4 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -1358,6 +1358,10 @@ impl MutableAppContext { self.keystroke_matcher.add_bindings(bindings); } + pub fn clear_bindings(&mut self) { + self.keystroke_matcher.clear_bindings(); + } + pub fn dispatch_keystroke( &mut self, window_id: usize, diff --git a/crates/gpui/src/keymap.rs b/crates/gpui/src/keymap.rs index 1b9e920ff2..723403f160 100644 --- a/crates/gpui/src/keymap.rs +++ b/crates/gpui/src/keymap.rs @@ -106,6 +106,11 @@ impl Matcher { self.keymap.add_bindings(bindings); } + pub fn clear_bindings(&mut self) { + self.pending.clear(); + self.keymap.clear(); + } + pub fn clear_pending(&mut self) { self.pending.clear(); } @@ -164,6 +169,10 @@ impl Keymap { fn add_bindings>(&mut self, bindings: T) { self.0.extend(bindings.into_iter()); } + + fn clear(&mut self) { + self.0.clear(); + } } impl Binding { diff --git a/crates/settings/src/keymap_file.rs b/crates/settings/src/keymap_file.rs index 621310c220..9ecebfd5d2 100644 --- a/crates/settings/src/keymap_file.rs +++ b/crates/settings/src/keymap_file.rs @@ -5,50 +5,57 @@ use gpui::{keymap::Binding, MutableAppContext}; use serde::Deserialize; use serde_json::value::RawValue; +#[derive(Deserialize, Default, Clone)] +#[serde(transparent)] +pub struct KeyMapFile(BTreeMap); + +type ActionsByKeystroke = BTreeMap>; + #[derive(Deserialize)] struct ActionWithData<'a>(#[serde(borrow)] &'a str, #[serde(borrow)] &'a RawValue); -type ActionSetsByContext<'a> = BTreeMap<&'a str, ActionsByKeystroke<'a>>; -type ActionsByKeystroke<'a> = BTreeMap<&'a str, &'a RawValue>; -pub fn load_built_in_keymaps(cx: &mut MutableAppContext) { - for path in ["keymaps/default.json", "keymaps/vim.json"] { - load_keymap( - cx, - std::str::from_utf8(Assets::get(path).unwrap().data.as_ref()).unwrap(), - ) - .unwrap(); +impl KeyMapFile { + pub fn load_defaults(cx: &mut MutableAppContext) { + for path in ["keymaps/default.json", "keymaps/vim.json"] { + Self::load(path, cx).unwrap(); + } } -} -pub fn load_keymap(cx: &mut MutableAppContext, content: &str) -> Result<()> { - let actions: ActionSetsByContext = serde_json::from_str(content)?; - for (context, actions) in actions { - let context = if context.is_empty() { - None - } else { - Some(context) - }; - cx.add_bindings( - actions - .into_iter() - .map(|(keystroke, action)| { - let action = action.get(); - let action = if action.starts_with('[') { - let ActionWithData(name, data) = serde_json::from_str(action)?; - cx.deserialize_action(name, Some(data.get())) - } else { - let name = serde_json::from_str(action)?; - cx.deserialize_action(name, None) - } - .with_context(|| { - format!( + pub fn load(asset_path: &str, cx: &mut MutableAppContext) -> Result<()> { + let content = Assets::get(asset_path).unwrap().data; + let content_str = std::str::from_utf8(content.as_ref()).unwrap(); + Ok(serde_json::from_str::(content_str)?.add(cx)?) + } + + pub fn add(self, cx: &mut MutableAppContext) -> Result<()> { + for (context, actions) in self.0 { + let context = if context.is_empty() { + None + } else { + Some(context) + }; + cx.add_bindings( + actions + .into_iter() + .map(|(keystroke, action)| { + let action = action.get(); + let action = if action.starts_with('[') { + let ActionWithData(name, data) = serde_json::from_str(action)?; + cx.deserialize_action(name, Some(data.get())) + } else { + let name = serde_json::from_str(action)?; + cx.deserialize_action(name, None) + } + .with_context(|| { + format!( "invalid binding value for keystroke {keystroke}, context {context:?}" ) - })?; - Binding::load(keystroke, action, context) - }) - .collect::>>()?, - ) + })?; + Binding::load(&keystroke, action, context.as_deref()) + }) + .collect::>>()?, + ) + } + Ok(()) } - Ok(()) } diff --git a/crates/settings/src/settings.rs b/crates/settings/src/settings.rs index d9a86037a2..eb4120bb52 100644 --- a/crates/settings/src/settings.rs +++ b/crates/settings/src/settings.rs @@ -1,4 +1,4 @@ -pub mod keymap_file; +mod keymap_file; use anyhow::Result; use gpui::font_cache::{FamilyId, FontCache}; @@ -15,6 +15,8 @@ use std::{collections::HashMap, sync::Arc}; use theme::{Theme, ThemeRegistry}; use util::ResultExt as _; +pub use keymap_file::KeyMapFile; + #[derive(Clone)] pub struct Settings { pub buffer_font_family: FamilyId, diff --git a/crates/vim/src/vim_test_context.rs b/crates/vim/src/vim_test_context.rs index 5818bdad65..2e9b0f60aa 100644 --- a/crates/vim/src/vim_test_context.rs +++ b/crates/vim/src/vim_test_context.rs @@ -24,7 +24,7 @@ impl<'a> VimTestContext<'a> { editor::init(cx); crate::init(cx); - settings::keymap_file::load_built_in_keymaps(cx); + settings::KeyMapFile::load("keymaps/vim.json", cx).unwrap(); }); let params = cx.update(WorkspaceParams::test); diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index 112de01898..d7b43bd721 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -2,6 +2,7 @@ #![allow(non_snake_case)] use anyhow::{anyhow, Context, Result}; +use assets::Assets; use client::{self, http, ChannelList, UserStore}; use fs::OpenOptions; use futures::{channel::oneshot, StreamExt}; @@ -9,19 +10,17 @@ use gpui::{App, AssetSource, Task}; use log::LevelFilter; use parking_lot::Mutex; use project::Fs; -use settings::{self, Settings}; +use settings::{self, KeyMapFile, Settings, SettingsFileContent}; use smol::process::Command; use std::{env, fs, path::PathBuf, sync::Arc}; use theme::{ThemeRegistry, DEFAULT_THEME_NAME}; use util::ResultExt; use workspace::{self, AppState, OpenNew, OpenPaths}; -use assets::Assets; use zed::{ - self, - build_window_options, build_workspace, + self, build_window_options, build_workspace, fs::RealFs, languages, menus, - settings_file::{settings_from_files, SettingsFile}, + settings_file::{settings_from_files, watch_keymap_file, WatchedJsonFile}, }; fn main() { @@ -63,7 +62,8 @@ fn main() { ..Default::default() }, ); - let settings_file = load_settings_file(&app, fs.clone()); + + let config_files = load_config_files(&app, fs.clone()); let login_shell_env_loaded = if stdout_is_a_pty() { Task::ready(()) @@ -112,13 +112,16 @@ fn main() { }) .detach_and_log_err(cx); - let settings_file = cx.background().block(settings_file).unwrap(); + let (settings_file, bindings_file) = cx.background().block(config_files).unwrap(); let mut settings_rx = settings_from_files( default_settings, vec![settings_file], themes.clone(), cx.font_cache().clone(), ); + + cx.spawn(|cx| watch_keymap_file(bindings_file, cx)).detach(); + let settings = cx.background().block(settings_rx.next()).unwrap(); cx.spawn(|mut cx| async move { while let Some(settings) = settings_rx.next().await { @@ -254,14 +257,23 @@ fn load_embedded_fonts(app: &App) { .unwrap(); } -fn load_settings_file(app: &App, fs: Arc) -> oneshot::Receiver { +fn load_config_files( + app: &App, + fs: Arc, +) -> oneshot::Receiver<( + WatchedJsonFile, + WatchedJsonFile, +)> { let executor = app.background(); let (tx, rx) = oneshot::channel(); executor .clone() .spawn(async move { - let file = SettingsFile::new(fs, &executor, zed::SETTINGS_PATH.clone()).await; - tx.send(file).ok() + let settings_file = + WatchedJsonFile::new(fs.clone(), &executor, zed::SETTINGS_PATH.clone()).await; + let bindings_file = + WatchedJsonFile::new(fs, &executor, zed::BINDINGS_PATH.clone()).await; + tx.send((settings_file, bindings_file)).ok() }) .detach(); rx diff --git a/crates/zed/src/settings_file.rs b/crates/zed/src/settings_file.rs index 46a3d41eb1..024a49447f 100644 --- a/crates/zed/src/settings_file.rs +++ b/crates/zed/src/settings_file.rs @@ -1,17 +1,22 @@ use futures::{stream, StreamExt}; -use gpui::{executor, FontCache}; +use gpui::{executor, AsyncAppContext, FontCache}; use postage::sink::Sink as _; use postage::{prelude::Stream, watch}; use project::Fs; +use serde::Deserialize; +use settings::KeyMapFile; use settings::{Settings, SettingsFileContent}; use std::{path::Path, sync::Arc, time::Duration}; use theme::ThemeRegistry; use util::ResultExt; #[derive(Clone)] -pub struct SettingsFile(watch::Receiver); +pub struct WatchedJsonFile(watch::Receiver); -impl SettingsFile { +impl WatchedJsonFile +where + T: 'static + for<'de> Deserialize<'de> + Clone + Default + Send + Sync, +{ pub async fn new( fs: Arc, executor: &executor::Background, @@ -35,21 +40,21 @@ impl SettingsFile { Self(rx) } - async fn load(fs: Arc, path: &Path) -> Option { + async fn load(fs: Arc, path: &Path) -> Option { if fs.is_file(&path).await { fs.load(&path) .await .log_err() .and_then(|data| serde_json::from_str(&data).log_err()) } else { - Some(SettingsFileContent::default()) + Some(T::default()) } } } pub fn settings_from_files( defaults: Settings, - sources: Vec, + sources: Vec>, theme_registry: Arc, font_cache: Arc, ) -> impl futures::stream::Stream { @@ -72,6 +77,16 @@ pub fn settings_from_files( }) } +pub async fn watch_keymap_file(mut file: WatchedJsonFile, mut cx: AsyncAppContext) { + while let Some(content) = file.0.recv().await { + cx.update(|cx| { + cx.clear_bindings(); + settings::KeyMapFile::load_defaults(cx); + content.add(cx).log_err(); + }); + } +} + #[cfg(test)] mod tests { use super::*; @@ -102,9 +117,9 @@ mod tests { .await .unwrap(); - let source1 = SettingsFile::new(fs.clone(), &executor, "/settings1.json".as_ref()).await; - let source2 = SettingsFile::new(fs.clone(), &executor, "/settings2.json".as_ref()).await; - let source3 = SettingsFile::new(fs.clone(), &executor, "/settings3.json".as_ref()).await; + let source1 = WatchedJsonFile::new(fs.clone(), &executor, "/settings1.json".as_ref()).await; + let source2 = WatchedJsonFile::new(fs.clone(), &executor, "/settings2.json".as_ref()).await; + let source3 = WatchedJsonFile::new(fs.clone(), &executor, "/settings3.json".as_ref()).await; let mut settings_rx = settings_from_files( cx.read(Settings::test), diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 5632c61038..6deecc9b0c 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -45,6 +45,7 @@ lazy_static! { .expect("failed to determine home directory") .join(".zed"); pub static ref SETTINGS_PATH: PathBuf = ROOT_PATH.join("settings.json"); + pub static ref BINDINGS_PATH: PathBuf = ROOT_PATH.join("bindings.json"); } pub fn init(app_state: &Arc, cx: &mut gpui::MutableAppContext) { @@ -102,7 +103,7 @@ pub fn init(app_state: &Arc, cx: &mut gpui::MutableAppContext) { workspace::lsp_status::init(cx); - settings::keymap_file::load_built_in_keymaps(cx); + settings::KeyMapFile::load_defaults(cx); } pub fn build_workspace( From ee3eb9658f9e2fa249304136fdbd8b876fa6aa61 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 11 Apr 2022 17:02:16 -0700 Subject: [PATCH 14/22] Use the word 'keymap' more consistently Co-authored-by: Keith Simmons --- crates/settings/src/keymap_file.rs | 4 ++-- crates/settings/src/settings.rs | 2 +- crates/vim/src/vim_test_context.rs | 2 +- crates/zed/src/main.rs | 13 ++++++------- crates/zed/src/settings_file.rs | 7 +++---- crates/zed/src/zed.rs | 4 ++-- 6 files changed, 15 insertions(+), 17 deletions(-) diff --git a/crates/settings/src/keymap_file.rs b/crates/settings/src/keymap_file.rs index 9ecebfd5d2..97ea45138a 100644 --- a/crates/settings/src/keymap_file.rs +++ b/crates/settings/src/keymap_file.rs @@ -7,14 +7,14 @@ use serde_json::value::RawValue; #[derive(Deserialize, Default, Clone)] #[serde(transparent)] -pub struct KeyMapFile(BTreeMap); +pub struct KeymapFile(BTreeMap); type ActionsByKeystroke = BTreeMap>; #[derive(Deserialize)] struct ActionWithData<'a>(#[serde(borrow)] &'a str, #[serde(borrow)] &'a RawValue); -impl KeyMapFile { +impl KeymapFile { pub fn load_defaults(cx: &mut MutableAppContext) { for path in ["keymaps/default.json", "keymaps/vim.json"] { Self::load(path, cx).unwrap(); diff --git a/crates/settings/src/settings.rs b/crates/settings/src/settings.rs index eb4120bb52..ccd39baf46 100644 --- a/crates/settings/src/settings.rs +++ b/crates/settings/src/settings.rs @@ -15,7 +15,7 @@ use std::{collections::HashMap, sync::Arc}; use theme::{Theme, ThemeRegistry}; use util::ResultExt as _; -pub use keymap_file::KeyMapFile; +pub use keymap_file::KeymapFile; #[derive(Clone)] pub struct Settings { diff --git a/crates/vim/src/vim_test_context.rs b/crates/vim/src/vim_test_context.rs index 2e9b0f60aa..2e87115af2 100644 --- a/crates/vim/src/vim_test_context.rs +++ b/crates/vim/src/vim_test_context.rs @@ -24,7 +24,7 @@ impl<'a> VimTestContext<'a> { editor::init(cx); crate::init(cx); - settings::KeyMapFile::load("keymaps/vim.json", cx).unwrap(); + settings::KeymapFile::load("keymaps/vim.json", cx).unwrap(); }); let params = cx.update(WorkspaceParams::test); diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index d7b43bd721..1d1f08f639 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -10,7 +10,7 @@ use gpui::{App, AssetSource, Task}; use log::LevelFilter; use parking_lot::Mutex; use project::Fs; -use settings::{self, KeyMapFile, Settings, SettingsFileContent}; +use settings::{self, KeymapFile, Settings, SettingsFileContent}; use smol::process::Command; use std::{env, fs, path::PathBuf, sync::Arc}; use theme::{ThemeRegistry, DEFAULT_THEME_NAME}; @@ -112,7 +112,7 @@ fn main() { }) .detach_and_log_err(cx); - let (settings_file, bindings_file) = cx.background().block(config_files).unwrap(); + let (settings_file, keymap_file) = cx.background().block(config_files).unwrap(); let mut settings_rx = settings_from_files( default_settings, vec![settings_file], @@ -120,7 +120,7 @@ fn main() { cx.font_cache().clone(), ); - cx.spawn(|cx| watch_keymap_file(bindings_file, cx)).detach(); + cx.spawn(|cx| watch_keymap_file(keymap_file, cx)).detach(); let settings = cx.background().block(settings_rx.next()).unwrap(); cx.spawn(|mut cx| async move { @@ -262,7 +262,7 @@ fn load_config_files( fs: Arc, ) -> oneshot::Receiver<( WatchedJsonFile, - WatchedJsonFile, + WatchedJsonFile, )> { let executor = app.background(); let (tx, rx) = oneshot::channel(); @@ -271,9 +271,8 @@ fn load_config_files( .spawn(async move { let settings_file = WatchedJsonFile::new(fs.clone(), &executor, zed::SETTINGS_PATH.clone()).await; - let bindings_file = - WatchedJsonFile::new(fs, &executor, zed::BINDINGS_PATH.clone()).await; - tx.send((settings_file, bindings_file)).ok() + let keymap_file = WatchedJsonFile::new(fs, &executor, zed::KEYMAP_PATH.clone()).await; + tx.send((settings_file, keymap_file)).ok() }) .detach(); rx diff --git a/crates/zed/src/settings_file.rs b/crates/zed/src/settings_file.rs index 024a49447f..d805e7490d 100644 --- a/crates/zed/src/settings_file.rs +++ b/crates/zed/src/settings_file.rs @@ -4,8 +4,7 @@ use postage::sink::Sink as _; use postage::{prelude::Stream, watch}; use project::Fs; use serde::Deserialize; -use settings::KeyMapFile; -use settings::{Settings, SettingsFileContent}; +use settings::{KeymapFile, Settings, SettingsFileContent}; use std::{path::Path, sync::Arc, time::Duration}; use theme::ThemeRegistry; use util::ResultExt; @@ -77,11 +76,11 @@ pub fn settings_from_files( }) } -pub async fn watch_keymap_file(mut file: WatchedJsonFile, mut cx: AsyncAppContext) { +pub async fn watch_keymap_file(mut file: WatchedJsonFile, mut cx: AsyncAppContext) { while let Some(content) = file.0.recv().await { cx.update(|cx| { cx.clear_bindings(); - settings::KeyMapFile::load_defaults(cx); + settings::KeymapFile::load_defaults(cx); content.add(cx).log_err(); }); } diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 6deecc9b0c..7b1ff803f5 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -45,7 +45,7 @@ lazy_static! { .expect("failed to determine home directory") .join(".zed"); pub static ref SETTINGS_PATH: PathBuf = ROOT_PATH.join("settings.json"); - pub static ref BINDINGS_PATH: PathBuf = ROOT_PATH.join("bindings.json"); + pub static ref KEYMAP_PATH: PathBuf = ROOT_PATH.join("keymap.json"); } pub fn init(app_state: &Arc, cx: &mut gpui::MutableAppContext) { @@ -103,7 +103,7 @@ pub fn init(app_state: &Arc, cx: &mut gpui::MutableAppContext) { workspace::lsp_status::init(cx); - settings::KeyMapFile::load_defaults(cx); + settings::KeymapFile::load_defaults(cx); } pub fn build_workspace( From 28da5b4afcb5e85c4bf20ebcee91a1dffbef607b Mon Sep 17 00:00:00 2001 From: Keith Simmons Date: Mon, 11 Apr 2022 17:05:24 -0700 Subject: [PATCH 15/22] Don't focus active editor when deploying project search and focus query editor on project search focus --- crates/search/src/project_search.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/crates/search/src/project_search.rs b/crates/search/src/project_search.rs index f96e3c84d1..03fb99a972 100644 --- a/crates/search/src/project_search.rs +++ b/crates/search/src/project_search.rs @@ -177,11 +177,7 @@ impl View for ProjectSearchView { .insert(self.model.read(cx).project.downgrade(), handle) }); - if self.model.read(cx).match_ranges.is_empty() { - cx.focus(&self.query_editor); - } else { - self.focus_results_editor(cx); - } + self.focus_query_editor(cx); } } @@ -390,6 +386,7 @@ impl ProjectSearchView { if let Some(existing) = existing { workspace.activate_item(&existing, cx); + existing.update(cx, |existing, cx| existing.focus_query_editor(cx)); } else { let model = cx.add_model(|cx| ProjectSearch::new(workspace.project().clone(), cx)); workspace.add_item( From 3b852ee2bd9e2796ca07d518dafae040534bb953 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 11 Apr 2022 18:15:41 -0600 Subject: [PATCH 16/22] Update Kubernetes manifest to refer to "collab" instead of "zed" --- crates/collab/k8s/manifest.template.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/collab/k8s/manifest.template.yml b/crates/collab/k8s/manifest.template.yml index cb6b710757..7f604fbf60 100644 --- a/crates/collab/k8s/manifest.template.yml +++ b/crates/collab/k8s/manifest.template.yml @@ -8,14 +8,14 @@ kind: Service apiVersion: v1 metadata: namespace: ${ZED_KUBE_NAMESPACE} - name: zed + name: collab annotations: service.beta.kubernetes.io/do-loadbalancer-tls-ports: "443" service.beta.kubernetes.io/do-loadbalancer-certificate-id: "2634d353-1ab4-437f-add2-4ffd8f315233" spec: type: LoadBalancer selector: - app: zed + app: collab ports: - name: web protocol: TCP @@ -26,19 +26,19 @@ apiVersion: apps/v1 kind: Deployment metadata: namespace: ${ZED_KUBE_NAMESPACE} - name: zed + name: collab spec: replicas: 1 selector: matchLabels: - app: zed + app: collab template: metadata: labels: - app: zed + app: collab spec: containers: - - name: zed + - name: collab image: "${ZED_IMAGE_ID}" ports: - containerPort: 8080 From add0dad6d73ae69e113389576ded8b9cbd73272e Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 11 Apr 2022 17:17:03 -0700 Subject: [PATCH 17/22] Use '*' to represent the default context in keymap files Co-authored-by: Keith Simmons --- assets/keymaps/default.json | 2 +- crates/settings/src/keymap_file.rs | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/assets/keymaps/default.json b/assets/keymaps/default.json index 6b5511dbce..dbfbcc03ab 100644 --- a/assets/keymaps/default.json +++ b/assets/keymaps/default.json @@ -1,5 +1,5 @@ { - "": { + "*": { "ctrl-alt-cmd-f": "workspace::FollowNextCollaborator", "cmd-s": "workspace::Save", "cmd-alt-i": "workspace::DebugElements", diff --git a/crates/settings/src/keymap_file.rs b/crates/settings/src/keymap_file.rs index 97ea45138a..d82c7ef8f6 100644 --- a/crates/settings/src/keymap_file.rs +++ b/crates/settings/src/keymap_file.rs @@ -29,16 +29,17 @@ impl KeymapFile { pub fn add(self, cx: &mut MutableAppContext) -> Result<()> { for (context, actions) in self.0 { - let context = if context.is_empty() { - None - } else { - Some(context) - }; + let context = if context == "*" { None } else { Some(context) }; cx.add_bindings( actions .into_iter() .map(|(keystroke, action)| { let action = action.get(); + + // This is a workaround for a limitation in serde: serde-rs/json#497 + // We want to deserialize the action data as a `RawValue` so that we can + // deserialize the action itself dynamically directly from the JSON + // string. But `RawValue` currently does not work inside of an untagged enum. let action = if action.starts_with('[') { let ActionWithData(name, data) = serde_json::from_str(action)?; cx.deserialize_action(name, Some(data.get())) From 72ea71ca52751afba6063512a6c296a3412ed8f5 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 11 Apr 2022 18:18:12 -0600 Subject: [PATCH 18/22] Update paths to renamed collab crate --- script/build-css | 2 +- script/deploy | 4 ++-- script/seed-db | 2 +- script/sqlx | 2 +- script/tailwind.config.js | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/script/build-css b/script/build-css index 5dc9b33ec8..08b205495d 100755 --- a/script/build-css +++ b/script/build-css @@ -7,4 +7,4 @@ cd ./script if [[ $1 == --release ]]; then export NODE_ENV=production # Purge unused styles in --release mode fi -npx tailwindcss build ../crates/server/styles.css --output ../crates/server/static/styles.css +npx tailwindcss build ../crates/collab/styles.css --output ../crates/collab/static/styles.css diff --git a/script/deploy b/script/deploy index 4ba674766b..ce50737170 100755 --- a/script/deploy +++ b/script/deploy @@ -16,7 +16,7 @@ if [[ $# < 1 ]]; then fi export ZED_KUBE_NAMESPACE=$1 -ENV_FILE="crates/server/k8s/environments/${ZED_KUBE_NAMESPACE}.sh" +ENV_FILE="crates/collab/k8s/environments/${ZED_KUBE_NAMESPACE}.sh" if [[ ! -f $ENV_FILE ]]; then echo "Invalid environment name '${ZED_KUBE_NAMESPACE}'" exit 1 @@ -34,4 +34,4 @@ export $(cat $ENV_FILE) docker build . --tag "$ZED_IMAGE_ID" docker push "$ZED_IMAGE_ID" -envsubst < crates/server/k8s/manifest.template.yml | kubectl apply -f - +envsubst < crates/collab/k8s/manifest.template.yml | kubectl apply -f - diff --git a/script/seed-db b/script/seed-db index 9da6ba2933..c69af799dd 100755 --- a/script/seed-db +++ b/script/seed-db @@ -1,7 +1,7 @@ #!/bin/bash set -e -cd crates/server +cd crates/collab # Export contents of .env.toml eval "$(cargo run --bin dotenv)" diff --git a/script/sqlx b/script/sqlx index 3d3ea00cc4..2241f4fa9a 100755 --- a/script/sqlx +++ b/script/sqlx @@ -5,7 +5,7 @@ set -e # Install sqlx-cli if needed [[ "$(sqlx --version)" == "sqlx-cli 0.5.7" ]] || cargo install sqlx-cli --version 0.5.7 -cd crates/server +cd crates/collab # Export contents of .env.toml eval "$(cargo run --bin dotenv)" diff --git a/script/tailwind.config.js b/script/tailwind.config.js index f237516eff..3c1670b0a4 100644 --- a/script/tailwind.config.js +++ b/script/tailwind.config.js @@ -40,7 +40,7 @@ module.exports = { }, darkMode: false, purge: [ - "../crates/server/templates/**/*.hbs", - "../crates/server/templates/*.hbs" + "../crates/collab/templates/**/*.hbs", + "../crates/collab/templates/*.hbs" ] } \ No newline at end of file From 5a5506ae1d68ad8d47d623289b86c29f525685a0 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 11 Apr 2022 18:33:55 -0600 Subject: [PATCH 19/22] Update certificate --- crates/collab/k8s/manifest.template.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/collab/k8s/manifest.template.yml b/crates/collab/k8s/manifest.template.yml index 7f604fbf60..f243a0adac 100644 --- a/crates/collab/k8s/manifest.template.yml +++ b/crates/collab/k8s/manifest.template.yml @@ -11,7 +11,7 @@ metadata: name: collab annotations: service.beta.kubernetes.io/do-loadbalancer-tls-ports: "443" - service.beta.kubernetes.io/do-loadbalancer-certificate-id: "2634d353-1ab4-437f-add2-4ffd8f315233" + service.beta.kubernetes.io/do-loadbalancer-certificate-id: "40879815-9a6b-4bbb-8207-8f2c7c0218f9" spec: type: LoadBalancer selector: From 1d8afdff801cf40887574a00a4c5d0fe30a5763b Mon Sep 17 00:00:00 2001 From: Keith Simmons Date: Mon, 11 Apr 2022 12:59:31 -0700 Subject: [PATCH 20/22] Set tsx default indent to 2 and remove js from extension list in tsx config.toml --- crates/zed/src/main.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index 8633005899..f05660e0f2 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -62,6 +62,13 @@ fn main() { tab_size: Some(2), ..Default::default() }, + ) + .with_overrides( + "TSX", + settings::LanguageOverride { + tab_size: Some(2), + ..Default::default() + }, ); let settings_file = load_settings_file(&app, fs.clone()); From 949fbe7cd302423ada34658a9d516bdb7a69146e Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 11 Apr 2022 19:51:46 -0700 Subject: [PATCH 21/22] Allow dumping the project diagnostic view's state as JSON Also, improve DebugElements action so that it shows the JSON in an editor. Co-authored-by: Nathan Sobo --- assets/keymaps/default.json | 2 +- crates/diagnostics/src/diagnostics.rs | 31 +++++++++++++++++++++++++-- crates/diagnostics/src/items.rs | 7 +++++- crates/editor/src/editor.rs | 2 +- crates/gpui/src/app.rs | 20 +++++++++++++++++ crates/gpui/src/presenter.rs | 20 ++++++++++------- crates/project/src/project.rs | 24 +++++++++++++++------ crates/workspace/src/workspace.rs | 26 ++++------------------ crates/zed/src/zed.rs | 26 ++++++++++++++++++++++ 9 files changed, 116 insertions(+), 42 deletions(-) diff --git a/assets/keymaps/default.json b/assets/keymaps/default.json index dbfbcc03ab..b517f9aebb 100644 --- a/assets/keymaps/default.json +++ b/assets/keymaps/default.json @@ -2,7 +2,7 @@ "*": { "ctrl-alt-cmd-f": "workspace::FollowNextCollaborator", "cmd-s": "workspace::Save", - "cmd-alt-i": "workspace::DebugElements", + "cmd-alt-i": "zed::DebugElements", "cmd-k cmd-left": "workspace::ActivatePreviousPane", "cmd-k cmd-right": "workspace::ActivateNextPane", "cmd-=": "zed::IncreaseBufferFontSize", diff --git a/crates/diagnostics/src/diagnostics.rs b/crates/diagnostics/src/diagnostics.rs index ea8150da45..c15c20c775 100644 --- a/crates/diagnostics/src/diagnostics.rs +++ b/crates/diagnostics/src/diagnostics.rs @@ -8,13 +8,15 @@ use editor::{ highlight_diagnostic_message, Editor, ExcerptId, MultiBuffer, ToOffset, }; use gpui::{ - actions, elements::*, fonts::TextStyle, AnyViewHandle, AppContext, Entity, ModelHandle, - MutableAppContext, RenderContext, Task, View, ViewContext, ViewHandle, WeakViewHandle, + actions, elements::*, fonts::TextStyle, serde_json, AnyViewHandle, AppContext, Entity, + ModelHandle, MutableAppContext, RenderContext, Task, View, ViewContext, ViewHandle, + WeakViewHandle, }; use language::{ Bias, Buffer, Diagnostic, DiagnosticEntry, DiagnosticSeverity, Point, Selection, SelectionGoal, }; use project::{DiagnosticSummary, Project, ProjectPath}; +use serde_json::json; use settings::Settings; use std::{ any::{Any, TypeId}, @@ -90,6 +92,31 @@ impl View for ProjectDiagnosticsEditor { cx.focus(&self.editor); } } + + fn debug_json(&self, cx: &AppContext) -> serde_json::Value { + let project = self.project.read(cx); + json!({ + "project": json!({ + "language_servers": project.language_server_statuses().collect::>(), + "summary": project.diagnostic_summary(cx), + }), + "summary": self.summary, + "paths_to_update": self.paths_to_update.iter().map(|path| + path.path.to_string_lossy() + ).collect::>(), + "paths_states": self.path_states.iter().map(|state| + json!({ + "path": state.path.path.to_string_lossy(), + "groups": state.diagnostic_groups.iter().map(|group| + json!({ + "block_count": group.blocks.len(), + "excerpt_count": group.excerpts.len(), + }) + ).collect::>(), + }) + ).collect::>(), + }) + } } impl ProjectDiagnosticsEditor { diff --git a/crates/diagnostics/src/items.rs b/crates/diagnostics/src/items.rs index 0f00b6dd7e..2f9a228256 100644 --- a/crates/diagnostics/src/items.rs +++ b/crates/diagnostics/src/items.rs @@ -1,6 +1,7 @@ use crate::render_summary; use gpui::{ - elements::*, platform::CursorStyle, Entity, ModelHandle, RenderContext, View, ViewContext, + elements::*, platform::CursorStyle, serde_json, Entity, ModelHandle, RenderContext, View, + ViewContext, }; use project::Project; use settings::Settings; @@ -67,6 +68,10 @@ impl View for DiagnosticSummary { .on_click(|cx| cx.dispatch_action(crate::Deploy)) .boxed() } + + fn debug_json(&self, _: &gpui::AppContext) -> serde_json::Value { + serde_json::json!({ "summary": self.summary }) + } } impl StatusItemView for DiagnosticSummary { diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 28d794729f..bc398754a7 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -1008,7 +1008,7 @@ impl Editor { if project.read(cx).is_remote() { cx.propagate_action(); } else if let Some(buffer) = project - .update(cx, |project, cx| project.create_buffer(cx)) + .update(cx, |project, cx| project.create_buffer("", None, cx)) .log_err() { workspace.add_item( diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index f0d33252e4..eb97b85c67 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -62,6 +62,9 @@ pub trait View: Entity + Sized { cx.set.insert(Self::ui_name().into()); cx } + fn debug_json(&self, _: &AppContext) -> serde_json::Value { + serde_json::Value::Null + } } pub trait ReadModel { @@ -2277,6 +2280,12 @@ pub struct AppContext { } impl AppContext { + pub(crate) fn root_view(&self, window_id: usize) -> Option { + self.windows + .get(&window_id) + .map(|window| window.root_view.clone()) + } + pub fn root_view_id(&self, window_id: usize) -> Option { self.windows .get(&window_id) @@ -2590,6 +2599,7 @@ pub trait AnyView { fn on_focus(&mut self, cx: &mut MutableAppContext, window_id: usize, view_id: usize); fn on_blur(&mut self, cx: &mut MutableAppContext, window_id: usize, view_id: usize); fn keymap_context(&self, cx: &AppContext) -> keymap::Context; + fn debug_json(&self, cx: &AppContext) -> serde_json::Value; } impl AnyView for T @@ -2653,6 +2663,10 @@ where fn keymap_context(&self, cx: &AppContext) -> keymap::Context { View::keymap_context(self, cx) } + + fn debug_json(&self, cx: &AppContext) -> serde_json::Value { + View::debug_json(self, cx) + } } pub struct ModelContext<'a, T: ?Sized> { @@ -3927,6 +3941,12 @@ impl AnyViewHandle { pub fn view_type(&self) -> TypeId { self.view_type } + + pub fn debug_json(&self, cx: &AppContext) -> serde_json::Value { + cx.views + .get(&(self.window_id, self.view_id)) + .map_or_else(|| serde_json::Value::Null, |view| view.debug_json(cx)) + } } impl Clone for AnyViewHandle { diff --git a/crates/gpui/src/presenter.rs b/crates/gpui/src/presenter.rs index ee840bd1e7..4585e321c4 100644 --- a/crates/gpui/src/presenter.rs +++ b/crates/gpui/src/presenter.rs @@ -209,15 +209,18 @@ impl Presenter { } pub fn debug_elements(&self, cx: &AppContext) -> Option { - cx.root_view_id(self.window_id) - .and_then(|root_view_id| self.rendered_views.get(&root_view_id)) - .map(|root_element| { - root_element.debug(&DebugContext { - rendered_views: &self.rendered_views, - font_cache: &self.font_cache, - app: cx, + let view = cx.root_view(self.window_id)?; + Some(json!({ + "root_view": view.debug_json(cx), + "root_element": self.rendered_views.get(&view.id()) + .map(|root_element| { + root_element.debug(&DebugContext { + rendered_views: &self.rendered_views, + font_cache: &self.font_cache, + app: cx, + }) }) - }) + })) } } @@ -554,6 +557,7 @@ impl Element for ChildView { "type": "ChildView", "view_id": self.view.id(), "bounds": bounds.to_json(), + "view": self.view.debug_json(cx.app), "child": if let Some(view) = cx.rendered_views.get(&self.view.id()) { view.debug(cx) } else { diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 409e49e9fb..1bc2d84109 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -28,6 +28,7 @@ use parking_lot::Mutex; use postage::watch; use rand::prelude::*; use search::SearchQuery; +use serde::Serialize; use settings::Settings; use sha2::{Digest, Sha256}; use similar::{ChangeTag, TextDiff}; @@ -132,16 +133,18 @@ pub enum Event { CollaboratorLeft(PeerId), } +#[derive(Serialize)] pub struct LanguageServerStatus { pub name: String, pub pending_work: BTreeMap, - pending_diagnostic_updates: isize, + pub pending_diagnostic_updates: isize, } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Serialize)] pub struct LanguageServerProgress { pub message: Option, pub percentage: Option, + #[serde(skip_serializing)] pub last_update_at: Instant, } @@ -151,7 +154,7 @@ pub struct ProjectPath { pub path: Arc, } -#[derive(Clone, Debug, Default, PartialEq)] +#[derive(Clone, Debug, Default, PartialEq, Serialize)] pub struct DiagnosticSummary { pub error_count: usize, pub warning_count: usize, @@ -467,7 +470,6 @@ impl Project { .and_then(|buffer| buffer.upgrade(cx)) } - #[cfg(any(test, feature = "test-support"))] pub fn languages(&self) -> &Arc { &self.languages } @@ -813,13 +815,19 @@ impl Project { !self.is_local() } - pub fn create_buffer(&mut self, cx: &mut ModelContext) -> Result> { + pub fn create_buffer( + &mut self, + text: &str, + language: Option>, + cx: &mut ModelContext, + ) -> Result> { if self.is_remote() { return Err(anyhow!("creating buffers as a guest is not supported yet")); } let buffer = cx.add_model(|cx| { - Buffer::new(self.replica_id(), "", cx).with_language(language::PLAIN_TEXT.clone(), cx) + Buffer::new(self.replica_id(), text, cx) + .with_language(language.unwrap_or(language::PLAIN_TEXT.clone()), cx) }); self.register_buffer(&buffer, cx)?; Ok(buffer) @@ -6581,7 +6589,9 @@ mod tests { .unwrap(); let worktree_id = worktree.read_with(cx, |worktree, _| worktree.id()); - let buffer = project.update(cx, |project, cx| project.create_buffer(cx).unwrap()); + let buffer = project.update(cx, |project, cx| { + project.create_buffer("", None, cx).unwrap() + }); buffer.update(cx, |buffer, cx| { buffer.edit([0..0], "abc", cx); assert!(buffer.is_dirty()); diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index d63626e1d3..c73a6bab5b 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -18,11 +18,11 @@ use gpui::{ elements::*, geometry::{rect::RectF, vector::vec2f, PathBuilder}, impl_internal_actions, - json::{self, to_string_pretty, ToJson}, + json::{self, ToJson}, platform::{CursorStyle, WindowOptions}, - AnyModelHandle, AnyViewHandle, AppContext, AsyncAppContext, Border, ClipboardItem, Entity, - ImageData, ModelHandle, MutableAppContext, PathPromptOptions, PromptLevel, RenderContext, Task, - View, ViewContext, ViewHandle, WeakViewHandle, + AnyModelHandle, AnyViewHandle, AppContext, AsyncAppContext, Border, Entity, ImageData, + ModelHandle, MutableAppContext, PathPromptOptions, PromptLevel, RenderContext, Task, View, + ViewContext, ViewHandle, WeakViewHandle, }; use language::LanguageRegistry; use log::error; @@ -75,7 +75,6 @@ actions!( ToggleShare, Unfollow, Save, - DebugElements, ActivatePreviousPane, ActivateNextPane, FollowNextCollaborator, @@ -133,7 +132,6 @@ pub fn init(client: &Arc, cx: &mut MutableAppContext) { workspace.save_active_item(cx).detach_and_log_err(cx); }, ); - cx.add_action(Workspace::debug_elements); cx.add_action(Workspace::toggle_sidebar_item); cx.add_action(Workspace::toggle_sidebar_item_focus); cx.add_action(|workspace: &mut Workspace, _: &ActivatePreviousPane, cx| { @@ -1053,22 +1051,6 @@ impl Workspace { cx.notify(); } - pub fn debug_elements(&mut self, _: &DebugElements, cx: &mut ViewContext) { - match to_string_pretty(&cx.debug_elements()) { - Ok(json) => { - let kib = json.len() as f32 / 1024.; - cx.as_mut().write_to_clipboard(ClipboardItem::new(json)); - log::info!( - "copied {:.1} KiB of element debug JSON to the clipboard", - kib - ); - } - Err(error) => { - log::error!("error debugging elements: {}", error); - } - }; - } - fn add_pane(&mut self, cx: &mut ViewContext) -> ViewHandle { let pane = cx.add_view(|cx| Pane::new(cx)); let pane_id = pane.id(); diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 7b1ff803f5..e9ed886557 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -10,6 +10,7 @@ pub use client; pub use contacts_panel; use contacts_panel::ContactsPanel; pub use editor; +use editor::Editor; use gpui::{ actions, geometry::vector::vec2f, @@ -22,8 +23,10 @@ use project::Project; pub use project::{self, fs}; use project_panel::ProjectPanel; use search::{BufferSearchBar, ProjectSearchBar}; +use serde_json::to_string_pretty; use settings::Settings; use std::{path::PathBuf, sync::Arc}; +use util::ResultExt; pub use workspace; use workspace::{AppState, Workspace, WorkspaceParams}; @@ -32,6 +35,7 @@ actions!( [ About, Quit, + DebugElements, OpenSettings, IncreaseBufferFontSize, DecreaseBufferFontSize @@ -100,6 +104,28 @@ pub fn init(app_state: &Arc, cx: &mut gpui::MutableAppContext) { .detach_and_log_err(cx); } }); + cx.add_action( + |workspace: &mut Workspace, _: &DebugElements, cx: &mut ViewContext| { + let content = to_string_pretty(&cx.debug_elements()).unwrap(); + let project = workspace.project().clone(); + let json_language = project.read(cx).languages().get_language("JSON").unwrap(); + if project.read(cx).is_remote() { + cx.propagate_action(); + } else if let Some(buffer) = project + .update(cx, |project, cx| { + project.create_buffer(&content, Some(json_language), cx) + }) + .log_err() + { + workspace.add_item( + Box::new( + cx.add_view(|cx| Editor::for_buffer(buffer, Some(project.clone()), cx)), + ), + cx, + ); + } + }, + ); workspace::lsp_status::init(cx); From ae9f71cc07f186b47d2afee0ea6cc046db71b740 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 11 Apr 2022 21:09:01 -0700 Subject: [PATCH 22/22] Avoid bailing out of Project::symbols when one LSP request fails --- crates/project/src/project.rs | 135 ++++++++++++++++------------------ 1 file changed, 65 insertions(+), 70 deletions(-) diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 409e49e9fb..f3479c4757 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -2270,86 +2270,81 @@ impl Project { pub fn symbols(&self, query: &str, cx: &mut ModelContext) -> Task>> { if self.is_local() { - let mut language_servers = HashMap::default(); + let mut requests = Vec::new(); for ((worktree_id, _), (lsp_adapter, language_server)) in self.language_servers.iter() { + let worktree_id = *worktree_id; if let Some(worktree) = self - .worktree_for_id(*worktree_id, cx) + .worktree_for_id(worktree_id, cx) .and_then(|worktree| worktree.read(cx).as_local()) { - language_servers - .entry(Arc::as_ptr(language_server)) - .or_insert(( - lsp_adapter.clone(), - language_server.clone(), - *worktree_id, - worktree.abs_path().clone(), - )); + let lsp_adapter = lsp_adapter.clone(); + let worktree_abs_path = worktree.abs_path().clone(); + requests.push( + language_server + .request::(lsp::WorkspaceSymbolParams { + query: query.to_string(), + ..Default::default() + }) + .log_err() + .map(move |response| { + ( + lsp_adapter, + worktree_id, + worktree_abs_path, + response.unwrap_or_default(), + ) + }), + ); } } - let mut requests = Vec::new(); - for (_, language_server, _, _) in language_servers.values() { - requests.push(language_server.request::( - lsp::WorkspaceSymbolParams { - query: query.to_string(), - ..Default::default() - }, - )); - } - cx.spawn_weak(|this, cx| async move { - let responses = futures::future::try_join_all(requests).await?; + let responses = futures::future::join_all(requests).await; + let this = if let Some(this) = this.upgrade(&cx) { + this + } else { + return Ok(Default::default()); + }; + this.read_with(&cx, |this, cx| { + let mut symbols = Vec::new(); + for (adapter, source_worktree_id, worktree_abs_path, response) in responses { + symbols.extend(response.into_iter().flatten().filter_map(|lsp_symbol| { + let abs_path = lsp_symbol.location.uri.to_file_path().ok()?; + let mut worktree_id = source_worktree_id; + let path; + if let Some((worktree, rel_path)) = + this.find_local_worktree(&abs_path, cx) + { + worktree_id = worktree.read(cx).id(); + path = rel_path; + } else { + path = relativize_path(&worktree_abs_path, &abs_path); + } - let mut symbols = Vec::new(); - if let Some(this) = this.upgrade(&cx) { - this.read_with(&cx, |this, cx| { - for ((adapter, _, source_worktree_id, worktree_abs_path), lsp_symbols) in - language_servers.into_values().zip(responses) - { - symbols.extend(lsp_symbols.into_iter().flatten().filter_map( - |lsp_symbol| { - let abs_path = lsp_symbol.location.uri.to_file_path().ok()?; - let mut worktree_id = source_worktree_id; - let path; - if let Some((worktree, rel_path)) = - this.find_local_worktree(&abs_path, cx) - { - worktree_id = worktree.read(cx).id(); - path = rel_path; - } else { - path = relativize_path(&worktree_abs_path, &abs_path); - } + let label = this + .languages + .select_language(&path) + .and_then(|language| { + language.label_for_symbol(&lsp_symbol.name, lsp_symbol.kind) + }) + .unwrap_or_else(|| CodeLabel::plain(lsp_symbol.name.clone(), None)); + let signature = this.symbol_signature(worktree_id, &path); - let label = this - .languages - .select_language(&path) - .and_then(|language| { - language - .label_for_symbol(&lsp_symbol.name, lsp_symbol.kind) - }) - .unwrap_or_else(|| { - CodeLabel::plain(lsp_symbol.name.clone(), None) - }); - let signature = this.symbol_signature(worktree_id, &path); - - Some(Symbol { - source_worktree_id, - worktree_id, - language_server_name: adapter.name(), - name: lsp_symbol.name, - kind: lsp_symbol.kind, - label, - path, - range: range_from_lsp(lsp_symbol.location.range), - signature, - }) - }, - )); - } - }) - } - - Ok(symbols) + Some(Symbol { + source_worktree_id, + worktree_id, + language_server_name: adapter.name(), + name: lsp_symbol.name, + kind: lsp_symbol.kind, + label, + path, + range: range_from_lsp(lsp_symbol.location.range), + signature, + }) + })); + } + Ok(symbols) + }) }) } else if let Some(project_id) = self.remote_id() { let request = self.client.request(proto::GetProjectSymbols {