Syntax highlighting working. Getting started on markdown support

This commit is contained in:
Keith Simmons 2022-05-31 22:49:47 -07:00
parent 863a3b1886
commit b014352740
7 changed files with 102 additions and 44 deletions

12
Cargo.lock generated
View file

@ -3419,6 +3419,7 @@ dependencies = [
"lsp",
"parking_lot",
"postage",
"pulldown-cmark",
"rand 0.8.3",
"regex",
"rocksdb",
@ -3555,6 +3556,17 @@ dependencies = [
"prost 0.9.0",
]
[[package]]
name = "pulldown-cmark"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34f197a544b0c9ab3ae46c359a7ec9cbbb5c7bf97054266fecb7ead794a181d6"
dependencies = [
"bitflags",
"memchr",
"unicase",
]
[[package]]
name = "quote"
version = "1.0.9"

View file

@ -39,7 +39,7 @@ pub use multi_buffer::{
Anchor, AnchorRangeExt, ExcerptId, MultiBuffer, MultiBufferSnapshot, ToOffset, ToPoint,
};
use ordered_float::OrderedFloat;
use project::{Project, ProjectTransaction};
use project::{HoverContents, Project, ProjectTransaction};
use selections_collection::{resolve_multiple, MutableSelectionsCollection, SelectionsCollection};
use serde::{Deserialize, Serialize};
use settings::Settings;
@ -891,20 +891,28 @@ impl CodeActionsMenu {
}
}
#[derive(Clone)]
struct HoverPopover {
pub point: DisplayPoint,
pub text: String,
pub runs: Vec<(Range<usize>, HighlightStyle)>,
pub contents: Vec<HoverContents>,
}
impl HoverPopover {
fn render(&self, style: EditorStyle) -> (DisplayPoint, ElementBox) {
let contents = self.contents.first().unwrap();
(
self.point,
Text::new(self.text.clone(), style.text.clone())
Text::new(contents.text.clone(), style.text.clone())
.with_soft_wrap(false)
.with_highlights(self.runs.clone())
.with_highlights(
contents
.runs
.iter()
.filter_map(|(range, id)| {
id.style(style.theme.syntax.as_ref())
.map(|style| (range.clone(), style))
})
.collect(),
)
.contained()
.with_style(style.hover_popover)
.boxed(),
@ -2458,7 +2466,6 @@ impl Editor {
}
fn hover(&mut self, action: &Hover, cx: &mut ViewContext<Self>) {
// dbg!("hover");
if let Some(point) = action.point {
self.show_hover(&ShowHover(point), cx);
} else {
@ -2520,7 +2527,7 @@ impl Editor {
let task = cx.spawn_weak(|this, mut cx| {
async move {
// TODO: what to show while LSP is loading?
let mut text = None;
let mut contents = None;
let hover = match hover.await {
Ok(hover) => hover,
@ -2528,37 +2535,27 @@ impl Editor {
};
if let Some(hover) = hover {
text = Some(match hover.contents {
lsp::HoverContents::Scalar(marked_string) => match marked_string {
lsp::MarkedString::String(string) => string,
lsp::MarkedString::LanguageString(string) => string.value,
},
lsp::HoverContents::Array(marked_strings) => {
// TODO: what to do?
todo!()
}
lsp::HoverContents::Markup(markup) => markup.value,
});
if hover.contents.is_empty() {
contents = None;
} else {
contents = Some(hover.contents);
if let Some(range) = hover.range {
let offset_range = range.to_offset(&buffer_snapshot);
if offset_range
.contains(&point.to_offset(&snapshot.display_snapshot, Bias::Left))
{
point = offset_range
.start
.to_display_point(&snapshot.display_snapshot);
} else {
text = None;
if let Some(range) = hover.range {
let offset_range = range.to_offset(&buffer_snapshot);
if offset_range
.contains(&point.to_offset(&snapshot.display_snapshot, Bias::Left))
{
point = offset_range
.start
.to_display_point(&snapshot.display_snapshot);
} else {
contents = None;
}
}
}
};
let hover_popover = text.map(|text| HoverPopover {
point,
text,
runs: Vec::new(),
});
let hover_popover = contents.map(|contents| HoverPopover { point, contents });
if let Some(this) = this.upgrade(&cx) {
this.update(&mut cx, |this, cx| {

View file

@ -236,7 +236,7 @@ impl LanguageRegistry {
self.languages
.read()
.iter()
.find(|language| language.name().as_ref() == name)
.find(|language| language.name().to_lowercase() == name.to_lowercase())
.cloned()
}

View file

@ -296,6 +296,10 @@ impl LanguageServer {
prepare_support: Some(true),
..Default::default()
}),
hover: Some(HoverClientCapabilities {
content_format: Some(vec![MarkupKind::Markdown]),
..Default::default()
}),
..Default::default()
}),
experimental: Some(json!({

View file

@ -38,6 +38,7 @@ libc = "0.2"
log = { version = "0.4.16", features = ["kv_unstable_serde"] }
parking_lot = "0.11.1"
postage = { version = "0.4.1", features = ["futures-traits"] }
pulldown-cmark = { version = "0.9.1", default-features = false }
rand = "0.8.3"
regex = "1.5"
serde = { version = "1.0", features = ["derive", "rc"] }

View file

@ -1,4 +1,4 @@
use crate::{DocumentHighlight, Hover, Location, Project, ProjectTransaction};
use crate::{DocumentHighlight, Hover, HoverContents, Location, Project, ProjectTransaction};
use anyhow::{anyhow, Result};
use async_trait::async_trait;
use client::{proto, PeerId};
@ -835,10 +835,48 @@ impl LspCommand for GetHover {
})
});
Hover {
contents: hover.contents,
range,
fn highlight(lsp_marked_string: lsp::MarkedString, project: &Project) -> HoverContents {
match lsp_marked_string {
lsp::MarkedString::LanguageString(lsp::LanguageString { language, value }) => {
if let Some(language) = project.languages().get_language(&language) {
let runs =
language.highlight_text(&value.as_str().into(), 0..value.len());
HoverContents { text: value, runs }
} else {
HoverContents {
text: value,
runs: Vec::new(),
}
}
}
lsp::MarkedString::String(text) => HoverContents {
text,
runs: Vec::new(),
},
}
}
let contents = cx.read(|cx| {
let project = project.read(cx);
match dbg!(hover.contents) {
lsp::HoverContents::Scalar(marked_string) => {
vec![highlight(marked_string, project)]
}
lsp::HoverContents::Array(marked_strings) => marked_strings
.into_iter()
.map(|marked_string| highlight(marked_string, project))
.collect(),
lsp::HoverContents::Markup(markup_content) => {
// TODO: handle markdown
vec![HoverContents {
text: markup_content.value,
runs: Vec::new(),
}]
}
}
});
Hover { contents, range }
}))
}
@ -855,7 +893,7 @@ impl LspCommand for GetHover {
async fn from_proto(
message: Self::ProtoRequest,
project: ModelHandle<Project>,
_: ModelHandle<Project>,
buffer: ModelHandle<Buffer>,
mut cx: AsyncAppContext,
) -> Result<Self> {

View file

@ -19,9 +19,9 @@ use language::{
point_to_lsp,
proto::{deserialize_anchor, deserialize_version, serialize_anchor, serialize_version},
range_from_lsp, range_to_lsp, Anchor, Bias, Buffer, CodeAction, CodeLabel, Completion,
Diagnostic, DiagnosticEntry, DiagnosticSet, Event as BufferEvent, File as _, Language,
LanguageRegistry, LanguageServerName, LocalFile, LspAdapter, OffsetRangeExt, Operation, Patch,
PointUtf16, TextBufferSnapshot, ToOffset, ToPointUtf16, Transaction,
Diagnostic, DiagnosticEntry, DiagnosticSet, Event as BufferEvent, File as _, HighlightId,
Language, LanguageRegistry, LanguageServerName, LocalFile, LspAdapter, OffsetRangeExt,
Operation, Patch, PointUtf16, TextBufferSnapshot, ToOffset, ToPointUtf16, Transaction,
};
use lsp::{DiagnosticSeverity, DiagnosticTag, DocumentHighlightKind, LanguageServer};
use lsp_command::*;
@ -216,9 +216,15 @@ pub struct Symbol {
pub signature: [u8; 32],
}
#[derive(Debug)]
pub struct HoverContents {
pub text: String,
pub runs: Vec<(Range<usize>, HighlightId)>,
}
#[derive(Debug)]
pub struct Hover {
pub contents: lsp::HoverContents,
pub contents: Vec<HoverContents>,
pub range: Option<Range<language::Anchor>>,
}