Convert query capture indices to style ids
* Introduce a Theme struct as a new part of the app's settings * Store on each Language a ThemeMap, which converts the capture ids from that language's highlight query into StyleIds, which identify styles in the current Theme. * Update `highlighted_chunks` methods to provide StyleIds instead of capture ids.
This commit is contained in:
@@ -16,6 +16,7 @@ use crate::{
|
||||
editor::Bias,
|
||||
language::{Language, Tree},
|
||||
operation_queue::{self, OperationQueue},
|
||||
settings::{StyleId, ThemeMap},
|
||||
sum_tree::{self, FilterCursor, SeekBias, SumTree},
|
||||
time::{self, ReplicaId},
|
||||
worktree::FileHandle,
|
||||
@@ -617,6 +618,7 @@ impl Buffer {
|
||||
handle.update(&mut ctx, |this, ctx| {
|
||||
this.tree = Some((new_tree, new_version));
|
||||
ctx.emit(Event::Reparsed);
|
||||
ctx.notify();
|
||||
});
|
||||
}
|
||||
handle.update(&mut ctx, |this, _| this.is_parsing = false);
|
||||
@@ -778,6 +780,7 @@ impl Buffer {
|
||||
highlights: Some(Highlights {
|
||||
captures: captures.peekable(),
|
||||
stack: Default::default(),
|
||||
theme_mapping: language.theme_mapping(),
|
||||
cursor,
|
||||
}),
|
||||
buffer: self,
|
||||
@@ -2200,8 +2203,9 @@ impl<'a> tree_sitter::TextProvider<'a> for TextProvider<'a> {
|
||||
|
||||
struct Highlights<'a> {
|
||||
captures: iter::Peekable<tree_sitter::QueryCaptures<'a, 'a, TextProvider<'a>>>,
|
||||
stack: Vec<(usize, usize)>,
|
||||
stack: Vec<(usize, StyleId)>,
|
||||
cursor: QueryCursor,
|
||||
theme_mapping: ThemeMap,
|
||||
}
|
||||
|
||||
pub struct HighlightedChunks<'a> {
|
||||
@@ -2240,7 +2244,7 @@ impl<'a> HighlightedChunks<'a> {
|
||||
}
|
||||
|
||||
impl<'a> Iterator for HighlightedChunks<'a> {
|
||||
type Item = (&'a str, Option<usize>);
|
||||
type Item = (&'a str, StyleId);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let mut next_capture_start = usize::MAX;
|
||||
@@ -2260,9 +2264,8 @@ impl<'a> Iterator for HighlightedChunks<'a> {
|
||||
next_capture_start = capture.node.start_byte();
|
||||
break;
|
||||
} else {
|
||||
highlights
|
||||
.stack
|
||||
.push((capture.node.end_byte(), capture.index as usize));
|
||||
let style_id = highlights.theme_mapping.get(capture.index);
|
||||
highlights.stack.push((capture.node.end_byte(), style_id));
|
||||
highlights.captures.next().unwrap();
|
||||
}
|
||||
}
|
||||
@@ -2271,12 +2274,12 @@ impl<'a> Iterator for HighlightedChunks<'a> {
|
||||
if let Some(chunk) = self.chunks.peek() {
|
||||
let chunk_start = self.range.start;
|
||||
let mut chunk_end = (self.chunks.offset() + chunk.len()).min(next_capture_start);
|
||||
let mut capture_ix = None;
|
||||
if let Some((parent_capture_end, parent_capture_ix)) =
|
||||
let mut capture_ix = StyleId::default();
|
||||
if let Some((parent_capture_end, parent_style_id)) =
|
||||
self.highlights.as_ref().and_then(|h| h.stack.last())
|
||||
{
|
||||
chunk_end = chunk_end.min(*parent_capture_end);
|
||||
capture_ix = Some(*parent_capture_ix);
|
||||
capture_ix = *parent_style_id;
|
||||
}
|
||||
|
||||
let slice =
|
||||
|
||||
@@ -2,7 +2,12 @@ use super::{
|
||||
buffer, movement, Anchor, Bias, Buffer, BufferElement, DisplayMap, DisplayPoint, Point,
|
||||
Selection, SelectionGoal, SelectionSetId, ToOffset, ToPoint,
|
||||
};
|
||||
use crate::{settings::Settings, util::post_inc, workspace, worktree::FileHandle};
|
||||
use crate::{
|
||||
settings::{Settings, StyleId},
|
||||
util::post_inc,
|
||||
workspace,
|
||||
worktree::FileHandle,
|
||||
};
|
||||
use anyhow::Result;
|
||||
use gpui::{
|
||||
color::ColorU, fonts::Properties as FontProperties, geometry::vector::Vector2F,
|
||||
@@ -2145,8 +2150,9 @@ impl BufferView {
|
||||
let mut row = rows.start;
|
||||
let snapshot = self.display_map.snapshot(ctx);
|
||||
let chunks = snapshot.highlighted_chunks_at(rows.start, ctx);
|
||||
let theme = settings.theme.clone();
|
||||
|
||||
'outer: for (chunk, capture_ix) in chunks.chain(Some(("\n", None))) {
|
||||
'outer: for (chunk, style_ix) in chunks.chain(Some(("\n", StyleId::default()))) {
|
||||
for (ix, line_chunk) in chunk.split('\n').enumerate() {
|
||||
if ix > 0 {
|
||||
layouts.push(layout_cache.layout_str(&line, font_size, &styles));
|
||||
@@ -2160,7 +2166,7 @@ impl BufferView {
|
||||
|
||||
if !line_chunk.is_empty() {
|
||||
line.push_str(line_chunk);
|
||||
styles.push((line_chunk.len(), font_id, ColorU::black()));
|
||||
styles.push((line_chunk.len(), font_id, theme.syntax_style(style_ix).0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ use super::{
|
||||
};
|
||||
use crate::{
|
||||
editor::buffer,
|
||||
settings::StyleId,
|
||||
sum_tree::{self, Cursor, FilterCursor, SeekBias, SumTree},
|
||||
time,
|
||||
};
|
||||
@@ -741,12 +742,12 @@ impl<'a> Iterator for Chunks<'a> {
|
||||
pub struct HighlightedChunks<'a> {
|
||||
transform_cursor: Cursor<'a, Transform, DisplayOffset, TransformSummary>,
|
||||
buffer_chunks: buffer::HighlightedChunks<'a>,
|
||||
buffer_chunk: Option<(usize, &'a str, Option<usize>)>,
|
||||
buffer_chunk: Option<(usize, &'a str, StyleId)>,
|
||||
buffer_offset: usize,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for HighlightedChunks<'a> {
|
||||
type Item = (&'a str, Option<usize>);
|
||||
type Item = (&'a str, StyleId);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let transform = if let Some(item) = self.transform_cursor.item() {
|
||||
@@ -768,7 +769,7 @@ impl<'a> Iterator for HighlightedChunks<'a> {
|
||||
self.transform_cursor.next();
|
||||
}
|
||||
|
||||
return Some((display_text, None));
|
||||
return Some((display_text, StyleId::default()));
|
||||
}
|
||||
|
||||
// Retrieve a chunk from the current location in the buffer.
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
mod fold_map;
|
||||
|
||||
use crate::settings::StyleId;
|
||||
|
||||
use super::{buffer, Anchor, Bias, Buffer, Edit, Point, ToOffset, ToPoint};
|
||||
pub use fold_map::BufferRows;
|
||||
use fold_map::{FoldMap, FoldMapSnapshot};
|
||||
@@ -163,7 +165,7 @@ impl DisplayMapSnapshot {
|
||||
column: 0,
|
||||
tab_size: self.tab_size,
|
||||
chunk: "",
|
||||
capture_ix: None,
|
||||
style_id: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -355,19 +357,19 @@ impl<'a> Iterator for Chunks<'a> {
|
||||
pub struct HighlightedChunks<'a> {
|
||||
fold_chunks: fold_map::HighlightedChunks<'a>,
|
||||
chunk: &'a str,
|
||||
capture_ix: Option<usize>,
|
||||
style_id: StyleId,
|
||||
column: usize,
|
||||
tab_size: usize,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for HighlightedChunks<'a> {
|
||||
type Item = (&'a str, Option<usize>);
|
||||
type Item = (&'a str, StyleId);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.chunk.is_empty() {
|
||||
if let Some((chunk, capture_ix)) = self.fold_chunks.next() {
|
||||
if let Some((chunk, style_id)) = self.fold_chunks.next() {
|
||||
self.chunk = chunk;
|
||||
self.capture_ix = capture_ix;
|
||||
self.style_id = style_id;
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
@@ -379,12 +381,12 @@ impl<'a> Iterator for HighlightedChunks<'a> {
|
||||
if ix > 0 {
|
||||
let (prefix, suffix) = self.chunk.split_at(ix);
|
||||
self.chunk = suffix;
|
||||
return Some((prefix, self.capture_ix));
|
||||
return Some((prefix, self.style_id));
|
||||
} else {
|
||||
self.chunk = &self.chunk[1..];
|
||||
let len = self.tab_size - self.column % self.tab_size;
|
||||
self.column += len;
|
||||
return Some((&SPACES[0..len], self.capture_ix));
|
||||
return Some((&SPACES[0..len], self.style_id));
|
||||
}
|
||||
}
|
||||
'\n' => self.column = 0,
|
||||
@@ -392,7 +394,9 @@ impl<'a> Iterator for HighlightedChunks<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
Some((mem::take(&mut self.chunk), self.capture_ix.take()))
|
||||
let style_id = self.style_id;
|
||||
self.style_id = StyleId::default();
|
||||
Some((mem::take(&mut self.chunk), style_id))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user