Start work on syntax highlighting completions
This commit is contained in:
parent
45898daf83
commit
439d12cb85
7 changed files with 349 additions and 221 deletions
|
@ -7,7 +7,7 @@ pub use crate::{
|
|||
use crate::{
|
||||
diagnostic_set::{DiagnosticEntry, DiagnosticGroup},
|
||||
outline::OutlineItem,
|
||||
range_from_lsp, Outline, ToLspPosition,
|
||||
range_from_lsp, CompletionLabel, Outline, ToLspPosition,
|
||||
};
|
||||
use anyhow::{anyhow, Result};
|
||||
use clock::ReplicaId;
|
||||
|
@ -114,7 +114,7 @@ pub struct Diagnostic {
|
|||
pub struct Completion<T> {
|
||||
pub old_range: Range<T>,
|
||||
pub new_text: String,
|
||||
pub label: Option<String>,
|
||||
pub label: CompletionLabel,
|
||||
pub lsp_completion: lsp::CompletionItem,
|
||||
}
|
||||
|
||||
|
@ -1829,7 +1829,7 @@ impl Buffer {
|
|||
Some(Completion {
|
||||
old_range: this.anchor_before(old_range.start)..this.anchor_after(old_range.end),
|
||||
new_text,
|
||||
label: language.as_ref().and_then(|l| l.label_for_completion(&lsp_completion)),
|
||||
label: language.as_ref().and_then(|l| l.label_for_completion(&lsp_completion)).unwrap_or_else(|| CompletionLabel::plain(&lsp_completion)),
|
||||
lsp_completion,
|
||||
})
|
||||
} else {
|
||||
|
@ -2664,28 +2664,12 @@ impl Default for Diagnostic {
|
|||
}
|
||||
|
||||
impl<T> Completion<T> {
|
||||
pub fn label(&self) -> &str {
|
||||
self.label.as_deref().unwrap_or(&self.lsp_completion.label)
|
||||
}
|
||||
|
||||
pub fn filter_range(&self) -> Range<usize> {
|
||||
if let Some(filter_text) = self.lsp_completion.filter_text.as_deref() {
|
||||
if let Some(start) = self.label().find(filter_text) {
|
||||
start..start + filter_text.len()
|
||||
} else {
|
||||
0..self.label().len()
|
||||
}
|
||||
} else {
|
||||
0..self.label().len()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sort_key(&self) -> (usize, &str) {
|
||||
let kind_key = match self.lsp_completion.kind {
|
||||
Some(lsp::CompletionItemKind::VARIABLE) => 0,
|
||||
_ => 1,
|
||||
};
|
||||
(kind_key, &self.label()[self.filter_range()])
|
||||
(kind_key, &self.label.text[self.label.filter_range.clone()])
|
||||
}
|
||||
|
||||
pub fn is_snippet(&self) -> bool {
|
||||
|
|
|
@ -5,7 +5,7 @@ use theme::SyntaxTheme;
|
|||
#[derive(Clone, Debug)]
|
||||
pub struct HighlightMap(Arc<[HighlightId]>);
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub struct HighlightId(pub u32);
|
||||
|
||||
const DEFAULT_HIGHLIGHT_ID: HighlightId = HighlightId(u32::MAX);
|
||||
|
|
|
@ -49,11 +49,23 @@ pub trait ToLspPosition {
|
|||
|
||||
pub trait LspPostProcessor: 'static + Send + Sync {
|
||||
fn process_diagnostics(&self, diagnostics: &mut lsp::PublishDiagnosticsParams);
|
||||
fn label_for_completion(&self, _completion: &lsp::CompletionItem) -> Option<String> {
|
||||
fn label_for_completion(
|
||||
&self,
|
||||
_: &lsp::CompletionItem,
|
||||
_: &Language,
|
||||
) -> Option<CompletionLabel> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct CompletionLabel {
|
||||
pub text: String,
|
||||
pub runs: Vec<(Range<usize>, HighlightId)>,
|
||||
pub filter_range: Range<usize>,
|
||||
pub left_aligned_len: usize,
|
||||
}
|
||||
|
||||
#[derive(Default, Deserialize)]
|
||||
pub struct LanguageConfig {
|
||||
pub name: String,
|
||||
|
@ -253,24 +265,26 @@ impl Language {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn label_for_completion(&self, completion: &lsp::CompletionItem) -> Option<String> {
|
||||
pub fn label_for_completion(
|
||||
&self,
|
||||
completion: &lsp::CompletionItem,
|
||||
) -> Option<CompletionLabel> {
|
||||
self.lsp_post_processor
|
||||
.as_ref()
|
||||
.and_then(|p| p.label_for_completion(completion))
|
||||
.as_ref()?
|
||||
.label_for_completion(completion, self)
|
||||
}
|
||||
|
||||
pub fn highlight_text<'a>(&'a self, text: &'a Rope) -> Vec<(Range<usize>, HighlightId)> {
|
||||
pub fn highlight_text<'a>(
|
||||
&'a self,
|
||||
text: &'a Rope,
|
||||
range: Range<usize>,
|
||||
) -> Vec<(Range<usize>, HighlightId)> {
|
||||
let mut result = Vec::new();
|
||||
if let Some(grammar) = &self.grammar {
|
||||
let tree = grammar.parse_text(text, None);
|
||||
let mut offset = 0;
|
||||
for chunk in BufferChunks::new(
|
||||
text,
|
||||
0..text.len(),
|
||||
Some(&tree),
|
||||
self.grammar.as_ref(),
|
||||
vec![],
|
||||
) {
|
||||
for chunk in BufferChunks::new(text, range, Some(&tree), self.grammar.as_ref(), vec![])
|
||||
{
|
||||
let end_offset = offset + chunk.text.len();
|
||||
if let Some(highlight_id) = chunk.highlight_id {
|
||||
result.push((offset..end_offset, highlight_id));
|
||||
|
@ -291,6 +305,10 @@ impl Language {
|
|||
HighlightMap::new(grammar.highlights_query.capture_names(), theme);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn grammar(&self) -> Option<&Arc<Grammar>> {
|
||||
self.grammar.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl Grammar {
|
||||
|
@ -316,6 +334,28 @@ impl Grammar {
|
|||
pub fn highlight_map(&self) -> HighlightMap {
|
||||
self.highlight_map.lock().clone()
|
||||
}
|
||||
|
||||
pub fn highlight_id_for_name(&self, name: &str) -> Option<HighlightId> {
|
||||
let capture_id = self.highlights_query.capture_index_for_name(name)?;
|
||||
Some(self.highlight_map.lock().get(capture_id))
|
||||
}
|
||||
}
|
||||
|
||||
impl CompletionLabel {
|
||||
fn plain(completion: &lsp::CompletionItem) -> Self {
|
||||
let mut result = Self {
|
||||
text: completion.label.clone(),
|
||||
runs: Vec::new(),
|
||||
left_aligned_len: completion.label.len(),
|
||||
filter_range: 0..completion.label.len(),
|
||||
};
|
||||
if let Some(filter_text) = &completion.filter_text {
|
||||
if let Some(ix) = completion.label.find(filter_text) {
|
||||
result.filter_range = ix..ix + filter_text.len();
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
use crate::{diagnostic_set::DiagnosticEntry, Completion, Diagnostic, Language, Operation};
|
||||
use crate::{
|
||||
diagnostic_set::DiagnosticEntry, Completion, CompletionLabel, Diagnostic, Language, Operation,
|
||||
};
|
||||
use anyhow::{anyhow, Result};
|
||||
use clock::ReplicaId;
|
||||
use collections::HashSet;
|
||||
|
@ -403,7 +405,9 @@ pub fn deserialize_completion(
|
|||
Ok(Completion {
|
||||
old_range: old_start..old_end,
|
||||
new_text: completion.new_text,
|
||||
label: language.and_then(|l| l.label_for_completion(&lsp_completion)),
|
||||
label: language
|
||||
.and_then(|l| l.label_for_completion(&lsp_completion))
|
||||
.unwrap_or(CompletionLabel::plain(&lsp_completion)),
|
||||
lsp_completion,
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue