mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-28 15:44:20 +03:00
Merge branch 'main' of github.com:zed-industries/zed
This commit is contained in:
commit
0b1dab7fa7
3
Cargo.lock
generated
3
Cargo.lock
generated
@ -5356,6 +5356,7 @@ dependencies = [
|
||||
"alacritty_terminal",
|
||||
"anyhow",
|
||||
"client",
|
||||
"context_menu",
|
||||
"dirs 4.0.0",
|
||||
"editor",
|
||||
"futures",
|
||||
@ -6995,7 +6996,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "zed"
|
||||
version = "0.49.1"
|
||||
version = "0.50.0"
|
||||
dependencies = [
|
||||
"activity_indicator",
|
||||
"anyhow",
|
||||
|
@ -31,7 +31,7 @@
|
||||
"cmd-n": "workspace::NewFile",
|
||||
"cmd-shift-n": "workspace::NewWindow",
|
||||
"cmd-o": "workspace::Open",
|
||||
"ctrl-`": "terminal::Deploy"
|
||||
"ctrl-`": "workspace::NewTerminal"
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -300,7 +300,7 @@
|
||||
8
|
||||
],
|
||||
"cmd-b": "workspace::ToggleLeftSidebar",
|
||||
"cmd-shift-f": "project_search::Deploy",
|
||||
"cmd-shift-f": "workspace::NewSearch",
|
||||
"cmd-k cmd-t": "theme_selector::Toggle",
|
||||
"cmd-k cmd-s": "zed::OpenKeymap",
|
||||
"cmd-t": "project_symbols::Toggle",
|
||||
|
@ -144,5 +144,6 @@
|
||||
"TSX": {
|
||||
"tab_size": 2
|
||||
}
|
||||
}
|
||||
},
|
||||
"lsp": {}
|
||||
}
|
||||
|
@ -2057,7 +2057,8 @@ async fn test_definition(cx_a: &mut TestAppContext, cx_b: &mut TestAppContext) {
|
||||
"a.rs": "const ONE: usize = b::TWO + b::THREE;",
|
||||
},
|
||||
"dir-2": {
|
||||
"b.rs": "const TWO: usize = 2;\nconst THREE: usize = 3;",
|
||||
"b.rs": "const TWO: c::T2 = 2;\nconst THREE: usize = 3;",
|
||||
"c.rs": "type T2 = usize;",
|
||||
}
|
||||
}),
|
||||
)
|
||||
@ -2093,7 +2094,7 @@ async fn test_definition(cx_a: &mut TestAppContext, cx_b: &mut TestAppContext) {
|
||||
let target_buffer = definitions_1[0].target.buffer.read(cx);
|
||||
assert_eq!(
|
||||
target_buffer.text(),
|
||||
"const TWO: usize = 2;\nconst THREE: usize = 3;"
|
||||
"const TWO: c::T2 = 2;\nconst THREE: usize = 3;"
|
||||
);
|
||||
assert_eq!(
|
||||
definitions_1[0].target.range.to_point(target_buffer),
|
||||
@ -2122,7 +2123,7 @@ async fn test_definition(cx_a: &mut TestAppContext, cx_b: &mut TestAppContext) {
|
||||
let target_buffer = definitions_2[0].target.buffer.read(cx);
|
||||
assert_eq!(
|
||||
target_buffer.text(),
|
||||
"const TWO: usize = 2;\nconst THREE: usize = 3;"
|
||||
"const TWO: c::T2 = 2;\nconst THREE: usize = 3;"
|
||||
);
|
||||
assert_eq!(
|
||||
definitions_2[0].target.range.to_point(target_buffer),
|
||||
@ -2133,6 +2134,35 @@ async fn test_definition(cx_a: &mut TestAppContext, cx_b: &mut TestAppContext) {
|
||||
definitions_1[0].target.buffer,
|
||||
definitions_2[0].target.buffer
|
||||
);
|
||||
|
||||
fake_language_server.handle_request::<lsp::request::GotoTypeDefinition, _, _>(
|
||||
|req, _| async move {
|
||||
assert_eq!(
|
||||
req.text_document_position_params.position,
|
||||
lsp::Position::new(0, 7)
|
||||
);
|
||||
Ok(Some(lsp::GotoDefinitionResponse::Scalar(
|
||||
lsp::Location::new(
|
||||
lsp::Url::from_file_path("/root/dir-2/c.rs").unwrap(),
|
||||
lsp::Range::new(lsp::Position::new(0, 5), lsp::Position::new(0, 7)),
|
||||
),
|
||||
)))
|
||||
},
|
||||
);
|
||||
|
||||
let type_definitions = project_b
|
||||
.update(cx_b, |p, cx| p.type_definition(&buffer_b, 7, cx))
|
||||
.await
|
||||
.unwrap();
|
||||
cx_b.read(|cx| {
|
||||
assert_eq!(type_definitions.len(), 1);
|
||||
let target_buffer = type_definitions[0].target.buffer.read(cx);
|
||||
assert_eq!(target_buffer.text(), "type T2 = usize;");
|
||||
assert_eq!(
|
||||
type_definitions[0].target.range.to_point(target_buffer),
|
||||
Point::new(0, 5)..Point::new(0, 7)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
#[gpui::test(iterations = 10)]
|
||||
|
@ -165,6 +165,7 @@ impl Server {
|
||||
.add_message_handler(Server::update_diagnostic_summary)
|
||||
.add_request_handler(Server::forward_project_request::<proto::GetHover>)
|
||||
.add_request_handler(Server::forward_project_request::<proto::GetDefinition>)
|
||||
.add_request_handler(Server::forward_project_request::<proto::GetTypeDefinition>)
|
||||
.add_request_handler(Server::forward_project_request::<proto::GetReferences>)
|
||||
.add_request_handler(Server::forward_project_request::<proto::SearchProject>)
|
||||
.add_request_handler(Server::forward_project_request::<proto::GetDocumentHighlights>)
|
||||
|
@ -22,6 +22,7 @@ pub fn init(cx: &mut MutableAppContext) {
|
||||
cx.add_action(ContextMenu::cancel);
|
||||
}
|
||||
|
||||
//
|
||||
pub enum ContextMenuItem {
|
||||
Item {
|
||||
label: String,
|
||||
@ -258,6 +259,7 @@ impl ContextMenu {
|
||||
let style = style
|
||||
.item
|
||||
.style_for(Default::default(), Some(ix) == self.selected_index);
|
||||
|
||||
Label::new(label.to_string(), style.label.clone())
|
||||
.contained()
|
||||
.with_style(style.container)
|
||||
@ -319,9 +321,12 @@ impl ContextMenu {
|
||||
MouseEventHandler::new::<MenuItem, _, _>(ix, cx, |state, _| {
|
||||
let style =
|
||||
style.item.style_for(state, Some(ix) == self.selected_index);
|
||||
|
||||
Flex::row()
|
||||
.with_child(
|
||||
Label::new(label.to_string(), style.label.clone()).boxed(),
|
||||
Label::new(label.to_string(), style.label.clone())
|
||||
.contained()
|
||||
.boxed(),
|
||||
)
|
||||
.with_child({
|
||||
KeystrokeLabel::new(
|
||||
|
@ -389,6 +389,7 @@ impl Project {
|
||||
client.add_model_request_handler(Self::handle_get_completions);
|
||||
client.add_model_request_handler(Self::handle_lsp_command::<GetHover>);
|
||||
client.add_model_request_handler(Self::handle_lsp_command::<GetDefinition>);
|
||||
client.add_model_request_handler(Self::handle_lsp_command::<GetTypeDefinition>);
|
||||
client.add_model_request_handler(Self::handle_lsp_command::<GetDocumentHighlights>);
|
||||
client.add_model_request_handler(Self::handle_lsp_command::<GetReferences>);
|
||||
client.add_model_request_handler(Self::handle_lsp_command::<PrepareRename>);
|
||||
@ -2071,6 +2072,24 @@ impl Project {
|
||||
None
|
||||
}
|
||||
|
||||
fn merge_json_value_into(source: serde_json::Value, target: &mut serde_json::Value) {
|
||||
use serde_json::Value;
|
||||
|
||||
match (source, target) {
|
||||
(Value::Object(source), Value::Object(target)) => {
|
||||
for (key, value) in source {
|
||||
if let Some(target) = target.get_mut(&key) {
|
||||
Self::merge_json_value_into(value, target);
|
||||
} else {
|
||||
target.insert(key.clone(), value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(source, target) => *target = source,
|
||||
}
|
||||
}
|
||||
|
||||
fn start_language_server(
|
||||
&mut self,
|
||||
worktree_id: WorktreeId,
|
||||
@ -2092,6 +2111,20 @@ impl Project {
|
||||
};
|
||||
let key = (worktree_id, adapter.name.clone());
|
||||
|
||||
let mut initialization_options = adapter.initialization_options.clone();
|
||||
|
||||
let lsp = &cx.global::<Settings>().lsp.get(&adapter.name.0);
|
||||
let override_options = lsp.map(|s| s.initialization_options.clone()).flatten();
|
||||
match (&mut initialization_options, override_options) {
|
||||
(Some(initialization_options), Some(override_options)) => {
|
||||
Self::merge_json_value_into(override_options, initialization_options);
|
||||
}
|
||||
|
||||
(None, override_options) => initialization_options = override_options,
|
||||
|
||||
_ => {}
|
||||
}
|
||||
|
||||
self.language_server_ids
|
||||
.entry(key.clone())
|
||||
.or_insert_with(|| {
|
||||
@ -2108,7 +2141,7 @@ impl Project {
|
||||
LanguageServerState::Starting(cx.spawn_weak(|this, mut cx| async move {
|
||||
let language_server = language_server?.await.log_err()?;
|
||||
let language_server = language_server
|
||||
.initialize(adapter.initialization_options.clone())
|
||||
.initialize(initialization_options)
|
||||
.await
|
||||
.log_err()?;
|
||||
let this = this.upgrade(&cx)?;
|
||||
|
@ -24,7 +24,7 @@ use workspace::{
|
||||
Item, ItemHandle, ItemNavHistory, Pane, ToolbarItemLocation, ToolbarItemView, Workspace,
|
||||
};
|
||||
|
||||
actions!(project_search, [Deploy, SearchInNew, ToggleFocus]);
|
||||
actions!(project_search, [SearchInNew, ToggleFocus]);
|
||||
|
||||
#[derive(Default)]
|
||||
struct ActiveSearches(HashMap<WeakModelHandle<Project>, WeakViewHandle<ProjectSearchView>>);
|
||||
@ -431,7 +431,11 @@ impl ProjectSearchView {
|
||||
|
||||
// Re-activate the most recently activated search or the most recent if it has been closed.
|
||||
// If no search exists in the workspace, create a new one.
|
||||
fn deploy(workspace: &mut Workspace, _: &Deploy, cx: &mut ViewContext<Workspace>) {
|
||||
fn deploy(
|
||||
workspace: &mut Workspace,
|
||||
_: &workspace::NewSearch,
|
||||
cx: &mut ViewContext<Workspace>,
|
||||
) {
|
||||
// Clean up entries for dropped projects
|
||||
cx.update_global(|state: &mut ActiveSearches, cx| {
|
||||
state.0.retain(|project, _| project.is_upgradable(cx))
|
||||
|
@ -34,6 +34,7 @@ pub struct Settings {
|
||||
pub terminal_overrides: TerminalSettings,
|
||||
pub language_defaults: HashMap<Arc<str>, EditorSettings>,
|
||||
pub language_overrides: HashMap<Arc<str>, EditorSettings>,
|
||||
pub lsp: HashMap<Arc<str>, LspSettings>,
|
||||
pub theme: Arc<Theme>,
|
||||
}
|
||||
|
||||
@ -131,9 +132,17 @@ pub struct SettingsFileContent {
|
||||
#[serde(alias = "language_overrides")]
|
||||
pub languages: HashMap<Arc<str>, EditorSettings>,
|
||||
#[serde(default)]
|
||||
pub lsp: HashMap<Arc<str>, LspSettings>,
|
||||
#[serde(default)]
|
||||
pub theme: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Eq, JsonSchema)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub struct LspSettings {
|
||||
pub initialization_options: Option<Value>,
|
||||
}
|
||||
|
||||
impl Settings {
|
||||
pub fn defaults(
|
||||
assets: impl AssetSource,
|
||||
@ -174,6 +183,7 @@ impl Settings {
|
||||
terminal_overrides: Default::default(),
|
||||
language_defaults: defaults.languages,
|
||||
language_overrides: Default::default(),
|
||||
lsp: defaults.lsp.clone(),
|
||||
theme: themes.get(&defaults.theme.unwrap()).unwrap(),
|
||||
}
|
||||
}
|
||||
@ -218,6 +228,7 @@ impl Settings {
|
||||
self.terminal_defaults.font_size = data.terminal.font_size;
|
||||
self.terminal_overrides = data.terminal;
|
||||
self.language_overrides = data.languages;
|
||||
self.lsp = data.lsp;
|
||||
}
|
||||
|
||||
pub fn with_language_defaults(
|
||||
@ -288,6 +299,7 @@ impl Settings {
|
||||
terminal_overrides: Default::default(),
|
||||
language_defaults: Default::default(),
|
||||
language_overrides: Default::default(),
|
||||
lsp: Default::default(),
|
||||
projects_online_by_default: true,
|
||||
theme: gpui::fonts::with_font_cache(cx.font_cache().clone(), || Default::default()),
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ theme = { path = "../theme" }
|
||||
settings = { path = "../settings" }
|
||||
workspace = { path = "../workspace" }
|
||||
project = { path = "../project" }
|
||||
context_menu = { path = "../context_menu" }
|
||||
smallvec = { version = "1.6", features = ["union"] }
|
||||
smol = "1.2.5"
|
||||
mio-extras = "2.0.6"
|
||||
|
@ -33,7 +33,9 @@ use std::{
|
||||
use std::{fmt::Debug, ops::Sub};
|
||||
|
||||
use crate::{
|
||||
connected_view::ConnectedView, mappings::colors::convert_color, Terminal, TerminalSize,
|
||||
connected_view::{ConnectedView, DeployContextMenu},
|
||||
mappings::colors::convert_color,
|
||||
Terminal, TerminalSize,
|
||||
};
|
||||
|
||||
///Scrolling is unbearably sluggish by default. Alacritty supports a configurable
|
||||
@ -463,6 +465,12 @@ impl TerminalEl {
|
||||
}
|
||||
},
|
||||
)
|
||||
.on_click(
|
||||
MouseButton::Right,
|
||||
move |MouseButtonEvent { position, .. }, cx| {
|
||||
cx.dispatch_action(DeployContextMenu { position });
|
||||
},
|
||||
)
|
||||
.on_drag(
|
||||
MouseButton::Left,
|
||||
move |_, MouseMovedEvent { position, .. }, cx| {
|
||||
|
@ -1,8 +1,14 @@
|
||||
use alacritty_terminal::term::TermMode;
|
||||
use context_menu::{ContextMenu, ContextMenuItem};
|
||||
use gpui::{
|
||||
actions, keymap::Keystroke, AppContext, Element, ElementBox, ModelHandle, MutableAppContext,
|
||||
View, ViewContext,
|
||||
actions,
|
||||
elements::{ChildView, ParentElement, Stack},
|
||||
geometry::vector::Vector2F,
|
||||
impl_internal_actions,
|
||||
keymap::Keystroke,
|
||||
AppContext, Element, ElementBox, ModelHandle, MutableAppContext, View, ViewContext, ViewHandle,
|
||||
};
|
||||
use workspace::pane;
|
||||
|
||||
use crate::{connected_el::TerminalEl, Event, Terminal};
|
||||
|
||||
@ -10,10 +16,16 @@ use crate::{connected_el::TerminalEl, Event, Terminal};
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct ScrollTerminal(pub i32);
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub struct DeployContextMenu {
|
||||
pub position: Vector2F,
|
||||
}
|
||||
|
||||
actions!(
|
||||
terminal,
|
||||
[Up, Down, CtrlC, Escape, Enter, Clear, Copy, Paste,]
|
||||
);
|
||||
impl_internal_actions!(project_panel, [DeployContextMenu]);
|
||||
|
||||
pub fn init(cx: &mut MutableAppContext) {
|
||||
//Global binding overrrides
|
||||
@ -23,6 +35,7 @@ pub fn init(cx: &mut MutableAppContext) {
|
||||
cx.add_action(ConnectedView::escape);
|
||||
cx.add_action(ConnectedView::enter);
|
||||
//Useful terminal views
|
||||
cx.add_action(ConnectedView::deploy_context_menu);
|
||||
cx.add_action(ConnectedView::copy);
|
||||
cx.add_action(ConnectedView::paste);
|
||||
cx.add_action(ConnectedView::clear);
|
||||
@ -36,6 +49,7 @@ pub struct ConnectedView {
|
||||
has_bell: bool,
|
||||
// Only for styling purposes. Doesn't effect behavior
|
||||
modal: bool,
|
||||
context_menu: ViewHandle<ContextMenu>,
|
||||
}
|
||||
|
||||
impl ConnectedView {
|
||||
@ -67,6 +81,7 @@ impl ConnectedView {
|
||||
has_new_content: true,
|
||||
has_bell: false,
|
||||
modal,
|
||||
context_menu: cx.add_view(|cx| ContextMenu::new(cx)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -87,6 +102,18 @@ impl ConnectedView {
|
||||
cx.emit(Event::Wakeup);
|
||||
}
|
||||
|
||||
pub fn deploy_context_menu(&mut self, action: &DeployContextMenu, cx: &mut ViewContext<Self>) {
|
||||
let menu_entries = vec![
|
||||
ContextMenuItem::item("Clear Buffer", Clear),
|
||||
ContextMenuItem::item("Close Terminal", pane::CloseActiveItem),
|
||||
];
|
||||
|
||||
self.context_menu
|
||||
.update(cx, |menu, cx| menu.show(action.position, menu_entries, cx));
|
||||
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
fn clear(&mut self, _: &Clear, cx: &mut ViewContext<Self>) {
|
||||
self.terminal.update(cx, |term, _| term.clear());
|
||||
cx.notify();
|
||||
@ -152,8 +179,14 @@ impl View for ConnectedView {
|
||||
|
||||
fn render(&mut self, cx: &mut gpui::RenderContext<'_, Self>) -> ElementBox {
|
||||
let terminal_handle = self.terminal.clone().downgrade();
|
||||
TerminalEl::new(cx.handle(), terminal_handle, self.modal)
|
||||
.contained()
|
||||
|
||||
Stack::new()
|
||||
.with_child(
|
||||
TerminalEl::new(cx.handle(), terminal_handle, self.modal)
|
||||
.contained()
|
||||
.boxed(),
|
||||
)
|
||||
.with_child(ChildView::new(&self.context_menu).boxed())
|
||||
.boxed()
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,6 @@ use futures::{
|
||||
use modal::deploy_modal;
|
||||
use settings::{Settings, Shell};
|
||||
use std::{collections::HashMap, fmt::Display, path::PathBuf, sync::Arc, time::Duration};
|
||||
use terminal_view::TerminalView;
|
||||
use thiserror::Error;
|
||||
|
||||
use gpui::{
|
||||
@ -43,9 +42,9 @@ use crate::mappings::{
|
||||
|
||||
///Initialize and register all of our action handlers
|
||||
pub fn init(cx: &mut MutableAppContext) {
|
||||
cx.add_action(TerminalView::deploy);
|
||||
cx.add_action(deploy_modal);
|
||||
|
||||
terminal_view::init(cx);
|
||||
connected_view::init(cx);
|
||||
}
|
||||
|
||||
|
@ -1,21 +1,26 @@
|
||||
use crate::connected_view::ConnectedView;
|
||||
use crate::{Event, Terminal, TerminalBuilder, TerminalError};
|
||||
|
||||
use dirs::home_dir;
|
||||
use gpui::{
|
||||
actions, elements::*, AnyViewHandle, AppContext, Entity, ModelHandle, View, ViewContext,
|
||||
ViewHandle,
|
||||
actions, elements::*, AnyViewHandle, AppContext, Entity, ModelHandle, MutableAppContext, View,
|
||||
ViewContext, ViewHandle,
|
||||
};
|
||||
use workspace::{Item, Workspace};
|
||||
|
||||
use crate::TerminalSize;
|
||||
use project::{LocalWorktree, Project, ProjectPath};
|
||||
use settings::{Settings, WorkingDirectory};
|
||||
use smallvec::SmallVec;
|
||||
use std::path::{Path, PathBuf};
|
||||
use workspace::{Item, Workspace};
|
||||
|
||||
use crate::connected_el::TerminalEl;
|
||||
|
||||
actions!(terminal, [Deploy, DeployModal]);
|
||||
actions!(terminal, [DeployModal]);
|
||||
|
||||
pub fn init(cx: &mut MutableAppContext) {
|
||||
cx.add_action(TerminalView::deploy);
|
||||
}
|
||||
|
||||
//Make terminal view an enum, that can give you views for the error and non-error states
|
||||
//Take away all the result unwrapping in the current TerminalView by making it 'infallible'
|
||||
@ -59,7 +64,11 @@ impl Entity for ErrorView {
|
||||
|
||||
impl TerminalView {
|
||||
///Create a new Terminal in the current working directory or the user's home directory
|
||||
pub fn deploy(workspace: &mut Workspace, _: &Deploy, cx: &mut ViewContext<Workspace>) {
|
||||
pub fn deploy(
|
||||
workspace: &mut Workspace,
|
||||
_: &workspace::NewTerminal,
|
||||
cx: &mut ViewContext<Workspace>,
|
||||
) {
|
||||
let strategy = cx
|
||||
.global::<Settings>()
|
||||
.terminal_overrides
|
||||
@ -134,7 +143,6 @@ impl View for TerminalView {
|
||||
TerminalContent::Connected(connected) => ChildView::new(connected),
|
||||
TerminalContent::Error(error) => ChildView::new(error),
|
||||
};
|
||||
|
||||
if self.modal {
|
||||
let settings = cx.global::<Settings>();
|
||||
let container_style = settings.theme.terminal.modal_container;
|
||||
|
@ -267,6 +267,8 @@ pub struct ContextMenuItem {
|
||||
pub container: ContainerStyle,
|
||||
pub label: TextStyle,
|
||||
pub keystroke: ContainedText,
|
||||
pub icon_width: f32,
|
||||
pub icon_spacing: f32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Default)]
|
||||
|
@ -1,5 +1,5 @@
|
||||
use super::{ItemHandle, SplitDirection};
|
||||
use crate::{toolbar::Toolbar, Item, WeakItemHandle, Workspace};
|
||||
use crate::{toolbar::Toolbar, Item, NewFile, NewSearch, NewTerminal, WeakItemHandle, Workspace};
|
||||
use anyhow::Result;
|
||||
use collections::{HashMap, HashSet, VecDeque};
|
||||
use context_menu::{ContextMenu, ContextMenuItem};
|
||||
@ -65,8 +65,13 @@ pub struct DeploySplitMenu {
|
||||
position: Vector2F,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub struct DeployNewMenu {
|
||||
position: Vector2F,
|
||||
}
|
||||
|
||||
impl_actions!(pane, [GoBack, GoForward, ActivateItem]);
|
||||
impl_internal_actions!(pane, [CloseItem, DeploySplitMenu]);
|
||||
impl_internal_actions!(pane, [CloseItem, DeploySplitMenu, DeployNewMenu]);
|
||||
|
||||
const MAX_NAVIGATION_HISTORY_LEN: usize = 1024;
|
||||
|
||||
@ -98,6 +103,7 @@ pub fn init(cx: &mut MutableAppContext) {
|
||||
cx.add_action(|pane: &mut Pane, _: &SplitRight, cx| pane.split(SplitDirection::Right, cx));
|
||||
cx.add_action(|pane: &mut Pane, _: &SplitDown, cx| pane.split(SplitDirection::Down, cx));
|
||||
cx.add_action(Pane::deploy_split_menu);
|
||||
cx.add_action(Pane::deploy_new_menu);
|
||||
cx.add_action(|workspace: &mut Workspace, _: &ReopenClosedItem, cx| {
|
||||
Pane::reopen_closed_item(workspace, cx).detach();
|
||||
});
|
||||
@ -141,7 +147,7 @@ pub struct Pane {
|
||||
autoscroll: bool,
|
||||
nav_history: Rc<RefCell<NavHistory>>,
|
||||
toolbar: ViewHandle<Toolbar>,
|
||||
split_menu: ViewHandle<ContextMenu>,
|
||||
context_menu: ViewHandle<ContextMenu>,
|
||||
}
|
||||
|
||||
pub struct ItemNavHistory {
|
||||
@ -182,7 +188,7 @@ pub struct NavigationEntry {
|
||||
impl Pane {
|
||||
pub fn new(cx: &mut ViewContext<Self>) -> Self {
|
||||
let handle = cx.weak_handle();
|
||||
let split_menu = cx.add_view(|cx| ContextMenu::new(cx));
|
||||
let context_menu = cx.add_view(|cx| ContextMenu::new(cx));
|
||||
Self {
|
||||
items: Vec::new(),
|
||||
is_active: true,
|
||||
@ -197,7 +203,7 @@ impl Pane {
|
||||
pane: handle.clone(),
|
||||
})),
|
||||
toolbar: cx.add_view(|_| Toolbar::new(handle)),
|
||||
split_menu,
|
||||
context_menu,
|
||||
}
|
||||
}
|
||||
|
||||
@ -831,7 +837,7 @@ impl Pane {
|
||||
}
|
||||
|
||||
fn deploy_split_menu(&mut self, action: &DeploySplitMenu, cx: &mut ViewContext<Self>) {
|
||||
self.split_menu.update(cx, |menu, cx| {
|
||||
self.context_menu.update(cx, |menu, cx| {
|
||||
menu.show(
|
||||
action.position,
|
||||
vec![
|
||||
@ -845,6 +851,20 @@ impl Pane {
|
||||
});
|
||||
}
|
||||
|
||||
fn deploy_new_menu(&mut self, action: &DeployNewMenu, cx: &mut ViewContext<Self>) {
|
||||
self.context_menu.update(cx, |menu, cx| {
|
||||
menu.show(
|
||||
action.position,
|
||||
vec![
|
||||
ContextMenuItem::item("New File", NewFile),
|
||||
ContextMenuItem::item("New Terminal", NewTerminal),
|
||||
ContextMenuItem::item("New Search", NewSearch),
|
||||
],
|
||||
cx,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
pub fn toolbar(&self) -> &ViewHandle<Toolbar> {
|
||||
&self.toolbar
|
||||
}
|
||||
@ -1083,10 +1103,40 @@ impl View for Pane {
|
||||
.with_child(self.render_tabs(cx).flex(1., true).named("tabs"));
|
||||
|
||||
if self.is_active {
|
||||
tab_row.add_child(
|
||||
tab_row.add_children([
|
||||
MouseEventHandler::new::<SplitIcon, _, _>(
|
||||
0,
|
||||
cx,
|
||||
|mouse_state, cx| {
|
||||
let theme =
|
||||
&cx.global::<Settings>().theme.workspace.tab_bar;
|
||||
let style =
|
||||
theme.pane_button.style_for(mouse_state, false);
|
||||
Svg::new("icons/plus_12.svg")
|
||||
.with_color(style.color)
|
||||
.constrained()
|
||||
.with_width(style.icon_width)
|
||||
.aligned()
|
||||
.contained()
|
||||
.with_style(style.container)
|
||||
.constrained()
|
||||
.with_width(style.button_width)
|
||||
.with_height(style.button_width)
|
||||
.aligned()
|
||||
.boxed()
|
||||
},
|
||||
)
|
||||
.with_cursor_style(CursorStyle::PointingHand)
|
||||
.on_down(
|
||||
MouseButton::Left,
|
||||
|MouseButtonEvent { position, .. }, cx| {
|
||||
cx.dispatch_action(DeployNewMenu { position });
|
||||
},
|
||||
)
|
||||
.boxed(),
|
||||
MouseEventHandler::new::<SplitIcon, _, _>(
|
||||
1,
|
||||
cx,
|
||||
|mouse_state, cx| {
|
||||
let theme =
|
||||
&cx.global::<Settings>().theme.workspace.tab_bar;
|
||||
@ -1114,7 +1164,7 @@ impl View for Pane {
|
||||
},
|
||||
)
|
||||
.boxed(),
|
||||
)
|
||||
])
|
||||
}
|
||||
|
||||
tab_row
|
||||
@ -1155,7 +1205,7 @@ impl View for Pane {
|
||||
})
|
||||
.boxed(),
|
||||
)
|
||||
.with_child(ChildView::new(&self.split_menu).boxed())
|
||||
.with_child(ChildView::new(&self.context_menu).boxed())
|
||||
.named("pane")
|
||||
}
|
||||
|
||||
|
@ -96,6 +96,8 @@ actions!(
|
||||
FollowNextCollaborator,
|
||||
ToggleLeftSidebar,
|
||||
ToggleRightSidebar,
|
||||
NewTerminal,
|
||||
NewSearch
|
||||
]
|
||||
);
|
||||
|
||||
|
@ -3,7 +3,7 @@ authors = ["Nathan Sobo <nathansobo@gmail.com>"]
|
||||
description = "The fast, collaborative code editor."
|
||||
edition = "2021"
|
||||
name = "zed"
|
||||
version = "0.49.1"
|
||||
version = "0.50.0"
|
||||
|
||||
[lib]
|
||||
name = "zed"
|
||||
|
@ -136,7 +136,7 @@ pub fn menus() -> Vec<Menu<'static>> {
|
||||
},
|
||||
MenuItem::Action {
|
||||
name: "Find In Project",
|
||||
action: Box::new(search::project_search::Deploy),
|
||||
action: Box::new(workspace::NewSearch),
|
||||
},
|
||||
MenuItem::Separator,
|
||||
MenuItem::Action {
|
||||
|
@ -16,6 +16,8 @@ export default function contextMenu(theme: Theme) {
|
||||
border: border(theme, "primary"),
|
||||
keystrokeMargin: 30,
|
||||
item: {
|
||||
iconSpacing: 8,
|
||||
iconWidth: 14,
|
||||
padding: { left: 4, right: 4, top: 2, bottom: 2 },
|
||||
cornerRadius: 6,
|
||||
label: text(theme, "sans", "primary", { size: "sm" }),
|
||||
|
Loading…
Reference in New Issue
Block a user