Merge branch 'main' into zed2-breadcrumbs

This commit is contained in:
Julia
2023-11-30 11:38:29 -05:00
197 changed files with 11947 additions and 8365 deletions
+202 -169
View File
@@ -40,11 +40,12 @@ use fuzzy::{StringMatch, StringMatchCandidate};
use git::diff_hunk_to_display;
use gpui::{
actions, div, point, prelude::*, px, relative, rems, size, uniform_list, Action, AnyElement,
AppContext, AsyncWindowContext, BackgroundExecutor, Bounds, ClipboardItem, Context, ElementId,
EventEmitter, FocusHandle, FocusableView, FontFeatures, FontStyle, FontWeight, HighlightStyle,
Hsla, InputHandler, InteractiveText, KeyContext, Model, MouseButton, ParentElement, Pixels,
Render, RenderOnce, SharedString, Styled, StyledText, Subscription, Task, TextRun, TextStyle,
UniformListScrollHandle, View, ViewContext, VisualContext, WeakView, WhiteSpace, WindowContext,
AppContext, AsyncWindowContext, BackgroundExecutor, Bounds, ClipboardItem, Context,
DispatchPhase, Div, ElementId, EventEmitter, FocusHandle, FocusableView, FontFeatures,
FontStyle, FontWeight, HighlightStyle, Hsla, InputHandler, InteractiveText, KeyContext, Model,
MouseButton, ParentElement, Pixels, Render, RenderOnce, SharedString, Styled, StyledText,
Subscription, Task, TextRun, TextStyle, UniformListScrollHandle, View, ViewContext,
VisualContext, WeakView, WhiteSpace, WindowContext,
};
use highlight_matching_bracket::refresh_matching_bracket_highlights;
use hover_popover::{hide_hover, HoverState};
@@ -72,7 +73,7 @@ use ordered_float::OrderedFloat;
use parking_lot::{Mutex, RwLock};
use project::{FormatTrigger, Location, Project, ProjectPath, ProjectTransaction};
use rand::prelude::*;
use rpc::proto::*;
use rpc::proto::{self, *};
use scroll::{
autoscroll::Autoscroll, OngoingScroll, ScrollAnchor, ScrollManager, ScrollbarAutoHide,
};
@@ -98,12 +99,13 @@ use text::{OffsetUtf16, Rope};
use theme::{
ActiveTheme, DiagnosticStyle, PlayerColor, SyntaxTheme, Theme, ThemeColors, ThemeSettings,
};
use ui::{h_stack, v_stack, HighlightedLabel, IconButton, Popover, StyledExt, Tooltip};
use ui::prelude::*;
use ui::{h_stack, v_stack, HighlightedLabel, IconButton, Popover, Tooltip};
use util::{post_inc, RangeExt, ResultExt, TryFutureExt};
use workspace::{
item::{ItemEvent, ItemHandle},
searchable::SearchEvent,
ItemNavHistory, SplitDirection, ViewId, Workspace,
ItemNavHistory, Pane, SplitDirection, ViewId, Workspace,
};
const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
@@ -152,7 +154,6 @@ pub fn render_parsed_markdown(
}),
);
// todo!("add the ability to change cursor style for link ranges")
let mut links = Vec::new();
let mut link_ranges = Vec::new();
for (range, region) in parsed.region_ranges.iter().zip(&parsed.regions) {
@@ -529,8 +530,6 @@ pub fn init(cx: &mut AppContext) {
// cx.register_action_type(Editor::context_menu_next);
// cx.register_action_type(Editor::context_menu_last);
hover_popover::init(cx);
workspace::register_project_item::<Editor>(cx);
workspace::register_followable_item::<Editor>(cx);
workspace::register_deserializable_item::<Editor>(cx);
@@ -663,6 +662,7 @@ pub struct Editor {
pixel_position_of_newest_cursor: Option<gpui::Point<Pixels>>,
gutter_width: Pixels,
style: Option<EditorStyle>,
editor_actions: Vec<Box<dyn Fn(&mut ViewContext<Self>)>>,
}
pub struct EditorSnapshot {
@@ -970,95 +970,94 @@ impl CompletionsMenu {
fn pre_resolve_completion_documentation(
&self,
_editor: &Editor,
_cx: &mut ViewContext<Editor>,
editor: &Editor,
cx: &mut ViewContext<Editor>,
) -> Option<Task<()>> {
// todo!("implementation below ");
None
let settings = EditorSettings::get_global(cx);
if !settings.show_completion_documentation {
return None;
}
let Some(project) = editor.project.clone() else {
return None;
};
let client = project.read(cx).client();
let language_registry = project.read(cx).languages().clone();
let is_remote = project.read(cx).is_remote();
let project_id = project.read(cx).remote_id();
let completions = self.completions.clone();
let completion_indices: Vec<_> = self.matches.iter().map(|m| m.candidate_id).collect();
Some(cx.spawn(move |this, mut cx| async move {
if is_remote {
let Some(project_id) = project_id else {
log::error!("Remote project without remote_id");
return;
};
for completion_index in completion_indices {
let completions_guard = completions.read();
let completion = &completions_guard[completion_index];
if completion.documentation.is_some() {
continue;
}
let server_id = completion.server_id;
let completion = completion.lsp_completion.clone();
drop(completions_guard);
Self::resolve_completion_documentation_remote(
project_id,
server_id,
completions.clone(),
completion_index,
completion,
client.clone(),
language_registry.clone(),
)
.await;
_ = this.update(&mut cx, |_, cx| cx.notify());
}
} else {
for completion_index in completion_indices {
let completions_guard = completions.read();
let completion = &completions_guard[completion_index];
if completion.documentation.is_some() {
continue;
}
let server_id = completion.server_id;
let completion = completion.lsp_completion.clone();
drop(completions_guard);
let server = project
.read_with(&mut cx, |project, _| {
project.language_server_for_id(server_id)
})
.ok()
.flatten();
let Some(server) = server else {
return;
};
Self::resolve_completion_documentation_local(
server,
completions.clone(),
completion_index,
completion,
language_registry.clone(),
)
.await;
_ = this.update(&mut cx, |_, cx| cx.notify());
}
}
}))
}
// {
// let settings = EditorSettings::get_global(cx);
// if !settings.show_completion_documentation {
// return None;
// }
// let Some(project) = editor.project.clone() else {
// return None;
// };
// let client = project.read(cx).client();
// let language_registry = project.read(cx).languages().clone();
// let is_remote = project.read(cx).is_remote();
// let project_id = project.read(cx).remote_id();
// let completions = self.completions.clone();
// let completion_indices: Vec<_> = self.matches.iter().map(|m| m.candidate_id).collect();
// Some(cx.spawn(move |this, mut cx| async move {
// if is_remote {
// let Some(project_id) = project_id else {
// log::error!("Remote project without remote_id");
// return;
// };
// for completion_index in completion_indices {
// let completions_guard = completions.read();
// let completion = &completions_guard[completion_index];
// if completion.documentation.is_some() {
// continue;
// }
// let server_id = completion.server_id;
// let completion = completion.lsp_completion.clone();
// drop(completions_guard);
// Self::resolve_completion_documentation_remote(
// project_id,
// server_id,
// completions.clone(),
// completion_index,
// completion,
// client.clone(),
// language_registry.clone(),
// )
// .await;
// _ = this.update(&mut cx, |_, cx| cx.notify());
// }
// } else {
// for completion_index in completion_indices {
// let completions_guard = completions.read();
// let completion = &completions_guard[completion_index];
// if completion.documentation.is_some() {
// continue;
// }
// let server_id = completion.server_id;
// let completion = completion.lsp_completion.clone();
// drop(completions_guard);
// let server = project.read_with(&mut cx, |project, _| {
// project.language_server_for_id(server_id)
// });
// let Some(server) = server else {
// return;
// };
// Self::resolve_completion_documentation_local(
// server,
// completions.clone(),
// completion_index,
// completion,
// language_registry.clone(),
// )
// .await;
// _ = this.update(&mut cx, |_, cx| cx.notify());
// }
// }
// }))
// }
fn attempt_resolve_selected_completion_documentation(
&mut self,
@@ -1079,10 +1078,9 @@ impl CompletionsMenu {
let completions = self.completions.clone();
let completions_guard = completions.read();
let completion = &completions_guard[completion_index];
// todo!()
// if completion.documentation.is_some() {
// return;
// }
if completion.documentation.is_some() {
return;
}
let server_id = completion.server_id;
let completion = completion.lsp_completion.clone();
@@ -1141,41 +1139,40 @@ impl CompletionsMenu {
client: Arc<Client>,
language_registry: Arc<LanguageRegistry>,
) {
// todo!()
// let request = proto::ResolveCompletionDocumentation {
// project_id,
// language_server_id: server_id.0 as u64,
// lsp_completion: serde_json::to_string(&completion).unwrap().into_bytes(),
// };
let request = proto::ResolveCompletionDocumentation {
project_id,
language_server_id: server_id.0 as u64,
lsp_completion: serde_json::to_string(&completion).unwrap().into_bytes(),
};
// let Some(response) = client
// .request(request)
// .await
// .context("completion documentation resolve proto request")
// .log_err()
// else {
// return;
// };
let Some(response) = client
.request(request)
.await
.context("completion documentation resolve proto request")
.log_err()
else {
return;
};
// if response.text.is_empty() {
// let mut completions = completions.write();
// let completion = &mut completions[completion_index];
// completion.documentation = Some(Documentation::Undocumented);
// }
if response.text.is_empty() {
let mut completions = completions.write();
let completion = &mut completions[completion_index];
completion.documentation = Some(Documentation::Undocumented);
}
// let documentation = if response.is_markdown {
// Documentation::MultiLineMarkdown(
// markdown::parse_markdown(&response.text, &language_registry, None).await,
// )
// } else if response.text.lines().count() <= 1 {
// Documentation::SingleLine(response.text)
// } else {
// Documentation::MultiLinePlainText(response.text)
// };
let documentation = if response.is_markdown {
Documentation::MultiLineMarkdown(
markdown::parse_markdown(&response.text, &language_registry, None).await,
)
} else if response.text.lines().count() <= 1 {
Documentation::SingleLine(response.text)
} else {
Documentation::MultiLinePlainText(response.text)
};
// let mut completions = completions.write();
// let completion = &mut completions[completion_index];
// completion.documentation = Some(documentation);
let mut completions = completions.write();
let completion = &mut completions[completion_index];
completion.documentation = Some(documentation);
}
async fn resolve_completion_documentation_local(
@@ -1185,38 +1182,37 @@ impl CompletionsMenu {
completion: lsp::CompletionItem,
language_registry: Arc<LanguageRegistry>,
) {
// todo!()
// let can_resolve = server
// .capabilities()
// .completion_provider
// .as_ref()
// .and_then(|options| options.resolve_provider)
// .unwrap_or(false);
// if !can_resolve {
// return;
// }
let can_resolve = server
.capabilities()
.completion_provider
.as_ref()
.and_then(|options| options.resolve_provider)
.unwrap_or(false);
if !can_resolve {
return;
}
// let request = server.request::<lsp::request::ResolveCompletionItem>(completion);
// let Some(completion_item) = request.await.log_err() else {
// return;
// };
let request = server.request::<lsp::request::ResolveCompletionItem>(completion);
let Some(completion_item) = request.await.log_err() else {
return;
};
// if let Some(lsp_documentation) = completion_item.documentation {
// let documentation = language::prepare_completion_documentation(
// &lsp_documentation,
// &language_registry,
// None, // TODO: Try to reasonably work out which language the completion is for
// )
// .await;
if let Some(lsp_documentation) = completion_item.documentation {
let documentation = language::prepare_completion_documentation(
&lsp_documentation,
&language_registry,
None, // TODO: Try to reasonably work out which language the completion is for
)
.await;
// let mut completions = completions.write();
// let completion = &mut completions[completion_index];
// completion.documentation = Some(documentation);
// } else {
// let mut completions = completions.write();
// let completion = &mut completions[completion_index];
// completion.documentation = Some(Documentation::Undocumented);
// }
let mut completions = completions.write();
let completion = &mut completions[completion_index];
completion.documentation = Some(documentation);
} else {
let mut completions = completions.write();
let completion = &mut completions[completion_index];
completion.documentation = Some(Documentation::Undocumented);
}
}
fn visible(&self) -> bool {
@@ -1272,6 +1268,13 @@ impl CompletionsMenu {
multiline_docs.map(|div| {
div.id("multiline_docs")
.max_h(max_height)
.flex_1()
.px_1p5()
.py_1()
.min_w(px(260.))
.max_w(px(640.))
.w(px(500.))
.text_ui()
.overflow_y_scroll()
// Prevent a mouse down on documentation from being propagated to the editor,
// because that would move the cursor.
@@ -1322,13 +1325,18 @@ impl CompletionsMenu {
div()
.id(mat.candidate_id)
.min_w(px(300.))
.max_w(px(700.))
.min_w(px(220.))
.max_w(px(540.))
.whitespace_nowrap()
.overflow_hidden()
.bg(gpui::green())
.hover(|style| style.bg(gpui::blue()))
.when(item_ix == selected_item, |div| div.bg(gpui::red()))
.text_ui()
.px_1()
.rounded(px(4.))
.bg(cx.theme().colors().ghost_element_background)
.hover(|style| style.bg(cx.theme().colors().ghost_element_hover))
.when(item_ix == selected_item, |div| {
div.bg(cx.theme().colors().ghost_element_selected)
})
.on_mouse_down(
MouseButton::Left,
cx.listener(move |editor, event, cx| {
@@ -1887,6 +1895,7 @@ impl Editor {
pixel_position_of_newest_cursor: None,
gutter_width: Default::default(),
style: None,
editor_actions: Default::default(),
_subscriptions: vec![
cx.observe(&buffer, Self::on_buffer_changed),
cx.subscribe(&buffer, Self::on_buffer_event),
@@ -2018,10 +2027,14 @@ impl Editor {
&self.buffer
}
fn workspace(&self) -> Option<View<Workspace>> {
pub fn workspace(&self) -> Option<View<Workspace>> {
self.workspace.as_ref()?.0.upgrade()
}
pub fn pane(&self, cx: &AppContext) -> Option<View<Pane>> {
self.workspace()?.read(cx).pane_for(&self.handle.upgrade()?)
}
pub fn title<'a>(&self, cx: &'a AppContext) -> Cow<'a, str> {
self.buffer().read(cx).title(cx)
}
@@ -4369,7 +4382,7 @@ impl Editor {
editor.fold_at(&FoldAt { buffer_row }, cx);
}
}))
.color(ui::Color::Muted)
.icon_color(ui::Color::Muted)
})
})
.flatten()
@@ -9178,6 +9191,26 @@ impl Editor {
cx.emit(EditorEvent::Blurred);
cx.notify();
}
pub fn register_action<A: Action>(
&mut self,
listener: impl Fn(&A, &mut WindowContext) + 'static,
) -> &mut Self {
let listener = Arc::new(listener);
self.editor_actions.push(Box::new(move |cx| {
let view = cx.view().clone();
let cx = cx.window_context();
let listener = listener.clone();
cx.on_action(TypeId::of::<A>(), move |action, phase, cx| {
let action = action.downcast_ref().unwrap();
if phase == DispatchPhase::Bubble {
listener(action, cx)
}
})
}));
self
}
}
pub trait CollaborationHub {