Add cmd+shift+click action for triggering go to type definition
This commit is contained in:
@@ -6,7 +6,9 @@ use super::{
|
||||
use crate::{
|
||||
display_map::{BlockStyle, DisplaySnapshot, TransformBlock},
|
||||
hover_popover::HoverAt,
|
||||
link_go_to_definition::{CmdChanged, GoToFetchedDefinition, UpdateGoToDefinitionLink},
|
||||
link_go_to_definition::{
|
||||
CmdShiftChanged, GoToFetchedDefinition, GoToFetchedTypeDefinition, UpdateGoToDefinitionLink,
|
||||
},
|
||||
mouse_context_menu::DeployMouseContextMenu,
|
||||
EditorStyle,
|
||||
};
|
||||
@@ -122,7 +124,12 @@ impl EditorElement {
|
||||
if cmd && paint.text_bounds.contains_point(position) {
|
||||
let (point, overshoot) = paint.point_for_position(&self.snapshot(cx), layout, position);
|
||||
if overshoot.is_zero() {
|
||||
cx.dispatch_action(GoToFetchedDefinition { point });
|
||||
if shift {
|
||||
cx.dispatch_action(GoToFetchedTypeDefinition { point });
|
||||
} else {
|
||||
cx.dispatch_action(GoToFetchedDefinition { point });
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -238,8 +245,12 @@ impl EditorElement {
|
||||
|
||||
fn mouse_moved(
|
||||
&self,
|
||||
position: Vector2F,
|
||||
cmd: bool,
|
||||
MouseMovedEvent {
|
||||
cmd,
|
||||
shift,
|
||||
position,
|
||||
..
|
||||
}: MouseMovedEvent,
|
||||
layout: &LayoutState,
|
||||
paint: &PaintState,
|
||||
cx: &mut EventContext,
|
||||
@@ -260,6 +271,7 @@ impl EditorElement {
|
||||
cx.dispatch_action(UpdateGoToDefinitionLink {
|
||||
point,
|
||||
cmd_held: cmd,
|
||||
shift_held: shift,
|
||||
});
|
||||
|
||||
if paint
|
||||
@@ -283,8 +295,11 @@ impl EditorElement {
|
||||
true
|
||||
}
|
||||
|
||||
fn modifiers_changed(&self, cmd: bool, cx: &mut EventContext) -> bool {
|
||||
cx.dispatch_action(CmdChanged { cmd_down: cmd });
|
||||
fn modifiers_changed(&self, event: ModifiersChangedEvent, cx: &mut EventContext) -> bool {
|
||||
cx.dispatch_action(CmdShiftChanged {
|
||||
cmd_down: event.cmd,
|
||||
shift_down: event.shift,
|
||||
});
|
||||
false
|
||||
}
|
||||
|
||||
@@ -1534,32 +1549,34 @@ impl Element for EditorElement {
|
||||
paint,
|
||||
cx,
|
||||
),
|
||||
|
||||
Event::MouseDown(MouseButtonEvent {
|
||||
button: MouseButton::Right,
|
||||
position,
|
||||
..
|
||||
}) => self.mouse_right_down(*position, layout, paint, cx),
|
||||
|
||||
Event::MouseUp(MouseButtonEvent {
|
||||
button: MouseButton::Left,
|
||||
position,
|
||||
..
|
||||
}) => self.mouse_up(*position, cx),
|
||||
|
||||
Event::MouseMoved(MouseMovedEvent {
|
||||
pressed_button: Some(MouseButton::Left),
|
||||
position,
|
||||
..
|
||||
}) => self.mouse_dragged(*position, layout, paint, cx),
|
||||
|
||||
Event::ScrollWheel(ScrollWheelEvent {
|
||||
position,
|
||||
delta,
|
||||
precise,
|
||||
}) => self.scroll(*position, *delta, *precise, layout, paint, cx),
|
||||
Event::ModifiersChanged(ModifiersChangedEvent { cmd, .. }) => {
|
||||
self.modifiers_changed(*cmd, cx)
|
||||
}
|
||||
Event::MouseMoved(MouseMovedEvent { position, cmd, .. }) => {
|
||||
self.mouse_moved(*position, *cmd, layout, paint, cx)
|
||||
}
|
||||
|
||||
&Event::ModifiersChanged(event) => self.modifiers_changed(event, cx),
|
||||
|
||||
&Event::MouseMoved(event) => self.mouse_moved(event, layout, paint, cx),
|
||||
|
||||
_ => false,
|
||||
}
|
||||
|
||||
@@ -8,18 +8,21 @@ use util::TryFutureExt;
|
||||
use workspace::Workspace;
|
||||
|
||||
use crate::{
|
||||
Anchor, DisplayPoint, Editor, EditorSnapshot, Event, GoToDefinition, Select, SelectPhase,
|
||||
Anchor, DisplayPoint, Editor, EditorSnapshot, Event, GoToDefinition, GoToTypeDefinition,
|
||||
Select, SelectPhase,
|
||||
};
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub struct UpdateGoToDefinitionLink {
|
||||
pub point: Option<DisplayPoint>,
|
||||
pub cmd_held: bool,
|
||||
pub shift_held: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub struct CmdChanged {
|
||||
pub struct CmdShiftChanged {
|
||||
pub cmd_down: bool,
|
||||
pub shift_down: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
@@ -27,28 +30,44 @@ pub struct GoToFetchedDefinition {
|
||||
pub point: DisplayPoint,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub struct GoToFetchedTypeDefinition {
|
||||
pub point: DisplayPoint,
|
||||
}
|
||||
|
||||
impl_internal_actions!(
|
||||
editor,
|
||||
[UpdateGoToDefinitionLink, CmdChanged, GoToFetchedDefinition]
|
||||
[
|
||||
UpdateGoToDefinitionLink,
|
||||
CmdShiftChanged,
|
||||
GoToFetchedDefinition,
|
||||
GoToFetchedTypeDefinition
|
||||
]
|
||||
);
|
||||
|
||||
pub fn init(cx: &mut MutableAppContext) {
|
||||
cx.add_action(update_go_to_definition_link);
|
||||
cx.add_action(cmd_changed);
|
||||
cx.add_action(cmd_shift_changed);
|
||||
cx.add_action(go_to_fetched_definition);
|
||||
cx.add_action(go_to_fetched_type_definition);
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct LinkGoToDefinitionState {
|
||||
pub last_mouse_location: Option<Anchor>,
|
||||
pub symbol_range: Option<Range<Anchor>>,
|
||||
pub kind: Option<LinkDefinitionKind>,
|
||||
pub definitions: Vec<LocationLink>,
|
||||
pub task: Option<Task<Option<()>>>,
|
||||
}
|
||||
|
||||
pub fn update_go_to_definition_link(
|
||||
editor: &mut Editor,
|
||||
&UpdateGoToDefinitionLink { point, cmd_held }: &UpdateGoToDefinitionLink,
|
||||
&UpdateGoToDefinitionLink {
|
||||
point,
|
||||
cmd_held,
|
||||
shift_held,
|
||||
}: &UpdateGoToDefinitionLink,
|
||||
cx: &mut ViewContext<Editor>,
|
||||
) {
|
||||
// Store new mouse point as an anchor
|
||||
@@ -72,7 +91,13 @@ pub fn update_go_to_definition_link(
|
||||
editor.link_go_to_definition_state.last_mouse_location = point.clone();
|
||||
if cmd_held {
|
||||
if let Some(point) = point {
|
||||
show_link_definition(editor, point, snapshot, cx);
|
||||
let kind = if shift_held {
|
||||
LinkDefinitionKind::Type
|
||||
} else {
|
||||
LinkDefinitionKind::Symbol
|
||||
};
|
||||
|
||||
show_link_definition(kind, editor, point, snapshot, cx);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -80,9 +105,12 @@ pub fn update_go_to_definition_link(
|
||||
hide_link_definition(editor, cx);
|
||||
}
|
||||
|
||||
pub fn cmd_changed(
|
||||
pub fn cmd_shift_changed(
|
||||
editor: &mut Editor,
|
||||
&CmdChanged { cmd_down }: &CmdChanged,
|
||||
&CmdShiftChanged {
|
||||
cmd_down,
|
||||
shift_down,
|
||||
}: &CmdShiftChanged,
|
||||
cx: &mut ViewContext<Editor>,
|
||||
) {
|
||||
if let Some(point) = editor
|
||||
@@ -92,19 +120,37 @@ pub fn cmd_changed(
|
||||
{
|
||||
if cmd_down {
|
||||
let snapshot = editor.snapshot(cx);
|
||||
show_link_definition(editor, point.clone(), snapshot, cx);
|
||||
let kind = if shift_down {
|
||||
LinkDefinitionKind::Type
|
||||
} else {
|
||||
LinkDefinitionKind::Symbol
|
||||
};
|
||||
|
||||
show_link_definition(kind, editor, point.clone(), snapshot, cx);
|
||||
} else {
|
||||
hide_link_definition(editor, cx)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum LinkDefinitionKind {
|
||||
Symbol,
|
||||
Type,
|
||||
}
|
||||
|
||||
pub fn show_link_definition(
|
||||
definition_kind: LinkDefinitionKind,
|
||||
editor: &mut Editor,
|
||||
trigger_point: Anchor,
|
||||
snapshot: EditorSnapshot,
|
||||
cx: &mut ViewContext<Editor>,
|
||||
) {
|
||||
let same_kind = editor.link_go_to_definition_state.kind == Some(definition_kind);
|
||||
if !same_kind {
|
||||
hide_link_definition(editor, cx);
|
||||
}
|
||||
|
||||
if editor.pending_rename.is_some() {
|
||||
return;
|
||||
}
|
||||
@@ -135,17 +181,22 @@ pub fn show_link_definition(
|
||||
return;
|
||||
};
|
||||
|
||||
// Don't request again if the location is within the symbol region of a previous request
|
||||
// Don't request again if the location is within the symbol region of a previous request with the same kind
|
||||
if let Some(symbol_range) = &editor.link_go_to_definition_state.symbol_range {
|
||||
if symbol_range
|
||||
let point_after_start = symbol_range
|
||||
.start
|
||||
.cmp(&trigger_point, &snapshot.buffer_snapshot)
|
||||
.is_le()
|
||||
&& symbol_range
|
||||
.end
|
||||
.cmp(&trigger_point, &snapshot.buffer_snapshot)
|
||||
.is_ge()
|
||||
{
|
||||
.is_le();
|
||||
|
||||
let point_before_end = symbol_range
|
||||
.end
|
||||
.cmp(&trigger_point, &snapshot.buffer_snapshot)
|
||||
.is_ge();
|
||||
|
||||
let point_within_range = point_after_start && point_before_end;
|
||||
let same_kind = editor.link_go_to_definition_state.kind == Some(definition_kind);
|
||||
|
||||
if point_within_range && same_kind {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -154,8 +205,14 @@ pub fn show_link_definition(
|
||||
async move {
|
||||
// query the LSP for definition info
|
||||
let definition_request = cx.update(|cx| {
|
||||
project.update(cx, |project, cx| {
|
||||
project.definition(&buffer, buffer_position.clone(), cx)
|
||||
project.update(cx, |project, cx| match definition_kind {
|
||||
LinkDefinitionKind::Symbol => {
|
||||
project.definition(&buffer, buffer_position.clone(), cx)
|
||||
}
|
||||
|
||||
LinkDefinitionKind::Type => {
|
||||
project.type_definition(&buffer, buffer_position.clone(), cx)
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
@@ -181,6 +238,7 @@ pub fn show_link_definition(
|
||||
this.update(&mut cx, |this, cx| {
|
||||
// Clear any existing highlights
|
||||
this.clear_text_highlights::<LinkGoToDefinitionState>(cx);
|
||||
this.link_go_to_definition_state.kind = Some(definition_kind);
|
||||
this.link_go_to_definition_state.symbol_range = result
|
||||
.as_ref()
|
||||
.and_then(|(symbol_range, _)| symbol_range.clone());
|
||||
@@ -258,7 +316,24 @@ pub fn hide_link_definition(editor: &mut Editor, cx: &mut ViewContext<Editor>) {
|
||||
|
||||
pub fn go_to_fetched_definition(
|
||||
workspace: &mut Workspace,
|
||||
GoToFetchedDefinition { point }: &GoToFetchedDefinition,
|
||||
&GoToFetchedDefinition { point }: &GoToFetchedDefinition,
|
||||
cx: &mut ViewContext<Workspace>,
|
||||
) {
|
||||
go_to_fetched_definition_of_kind(LinkDefinitionKind::Symbol, workspace, point, cx);
|
||||
}
|
||||
|
||||
pub fn go_to_fetched_type_definition(
|
||||
workspace: &mut Workspace,
|
||||
&GoToFetchedTypeDefinition { point }: &GoToFetchedTypeDefinition,
|
||||
cx: &mut ViewContext<Workspace>,
|
||||
) {
|
||||
go_to_fetched_definition_of_kind(LinkDefinitionKind::Type, workspace, point, cx);
|
||||
}
|
||||
|
||||
fn go_to_fetched_definition_of_kind(
|
||||
kind: LinkDefinitionKind,
|
||||
workspace: &mut Workspace,
|
||||
point: DisplayPoint,
|
||||
cx: &mut ViewContext<Workspace>,
|
||||
) {
|
||||
let active_item = workspace.active_item(cx);
|
||||
@@ -271,13 +346,14 @@ pub fn go_to_fetched_definition(
|
||||
return;
|
||||
};
|
||||
|
||||
let definitions = editor_handle.update(cx, |editor, cx| {
|
||||
let (cached_definitions, cached_definitions_kind) = editor_handle.update(cx, |editor, cx| {
|
||||
let definitions = editor.link_go_to_definition_state.definitions.clone();
|
||||
hide_link_definition(editor, cx);
|
||||
definitions
|
||||
(definitions, editor.link_go_to_definition_state.kind)
|
||||
});
|
||||
|
||||
if !definitions.is_empty() {
|
||||
let is_correct_kind = cached_definitions_kind == Some(kind);
|
||||
if !cached_definitions.is_empty() && is_correct_kind {
|
||||
editor_handle.update(cx, |editor, cx| {
|
||||
if !editor.focused {
|
||||
cx.focus_self();
|
||||
@@ -285,7 +361,7 @@ pub fn go_to_fetched_definition(
|
||||
}
|
||||
});
|
||||
|
||||
Editor::navigate_to_definitions(workspace, editor_handle, definitions, cx);
|
||||
Editor::navigate_to_definitions(workspace, editor_handle, cached_definitions, cx);
|
||||
} else {
|
||||
editor_handle.update(cx, |editor, cx| {
|
||||
editor.select(
|
||||
@@ -298,7 +374,13 @@ pub fn go_to_fetched_definition(
|
||||
);
|
||||
});
|
||||
|
||||
Editor::go_to_definition(workspace, &GoToDefinition, cx);
|
||||
match kind {
|
||||
LinkDefinitionKind::Symbol => Editor::go_to_definition(workspace, &GoToDefinition, cx),
|
||||
|
||||
LinkDefinitionKind::Type => {
|
||||
Editor::go_to_type_definition(workspace, &GoToTypeDefinition, cx)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -367,6 +449,7 @@ mod tests {
|
||||
&UpdateGoToDefinitionLink {
|
||||
point: Some(hover_point),
|
||||
cmd_held: true,
|
||||
shift_held: false,
|
||||
},
|
||||
cx,
|
||||
);
|
||||
@@ -382,7 +465,14 @@ mod tests {
|
||||
|
||||
// Unpress cmd causes highlight to go away
|
||||
cx.update_editor(|editor, cx| {
|
||||
cmd_changed(editor, &CmdChanged { cmd_down: false }, cx);
|
||||
cmd_shift_changed(
|
||||
editor,
|
||||
&CmdShiftChanged {
|
||||
cmd_down: false,
|
||||
shift_down: false,
|
||||
},
|
||||
cx,
|
||||
);
|
||||
});
|
||||
// Assert no link highlights
|
||||
cx.assert_editor_text_highlights::<LinkGoToDefinitionState>(indoc! {"
|
||||
@@ -412,6 +502,7 @@ mod tests {
|
||||
&UpdateGoToDefinitionLink {
|
||||
point: Some(hover_point),
|
||||
cmd_held: true,
|
||||
shift_held: false,
|
||||
},
|
||||
cx,
|
||||
);
|
||||
@@ -445,6 +536,7 @@ mod tests {
|
||||
&UpdateGoToDefinitionLink {
|
||||
point: Some(hover_point),
|
||||
cmd_held: true,
|
||||
shift_held: false,
|
||||
},
|
||||
cx,
|
||||
);
|
||||
@@ -473,6 +565,7 @@ mod tests {
|
||||
&UpdateGoToDefinitionLink {
|
||||
point: Some(hover_point),
|
||||
cmd_held: false,
|
||||
shift_held: false,
|
||||
},
|
||||
cx,
|
||||
);
|
||||
@@ -512,7 +605,14 @@ mod tests {
|
||||
])))
|
||||
});
|
||||
cx.update_editor(|editor, cx| {
|
||||
cmd_changed(editor, &CmdChanged { cmd_down: true }, cx);
|
||||
cmd_shift_changed(
|
||||
editor,
|
||||
&CmdShiftChanged {
|
||||
cmd_down: true,
|
||||
shift_down: false,
|
||||
},
|
||||
cx,
|
||||
);
|
||||
});
|
||||
requests.next().await;
|
||||
cx.foreground().run_until_parked();
|
||||
@@ -537,6 +637,7 @@ mod tests {
|
||||
&UpdateGoToDefinitionLink {
|
||||
point: Some(hover_point),
|
||||
cmd_held: true,
|
||||
shift_held: false,
|
||||
},
|
||||
cx,
|
||||
);
|
||||
|
||||
@@ -11,7 +11,7 @@ pub struct KeyUpEvent {
|
||||
pub keystroke: Keystroke,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct ModifiersChangedEvent {
|
||||
pub ctrl: bool,
|
||||
pub alt: bool,
|
||||
@@ -19,7 +19,7 @@ pub struct ModifiersChangedEvent {
|
||||
pub cmd: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
pub struct ScrollWheelEvent {
|
||||
pub position: Vector2F,
|
||||
pub delta: Vector2F,
|
||||
|
||||
Reference in New Issue
Block a user