Detailed changes
@@ -8,7 +8,7 @@ pub use block_map::{BlockDisposition, BlockId, BlockProperties, BufferRows, Chun
use block_map::{BlockMap, BlockPoint};
use buffer::Rope;
use fold_map::{FoldMap, ToFoldPoint as _};
-use gpui::{fonts::FontId, Entity, ModelContext, ModelHandle};
+use gpui::{fonts::FontId, AppContext, Entity, ModelContext, ModelHandle};
use language::{Anchor, Buffer, Point, ToOffset, ToPoint};
use std::{collections::HashSet, ops::Range};
use sum_tree::Bias;
@@ -230,7 +230,7 @@ impl DisplayMapSnapshot {
pub fn text_chunks(&self, display_row: u32) -> impl Iterator<Item = &str> {
self.blocks_snapshot
- .chunks(display_row..self.max_point().row() + 1, None)
+ .chunks(display_row..self.max_point().row() + 1, None, None)
.map(|h| h.text)
}
@@ -238,8 +238,9 @@ impl DisplayMapSnapshot {
&'a self,
display_rows: Range<u32>,
theme: Option<&'a SyntaxTheme>,
+ cx: &'a AppContext,
) -> block_map::Chunks<'a> {
- self.blocks_snapshot.chunks(display_rows, theme)
+ self.blocks_snapshot.chunks(display_rows, theme, Some(cx))
}
pub fn chars_at<'a>(&'a self, point: DisplayPoint) -> impl Iterator<Item = char> + 'a {
@@ -1025,7 +1026,7 @@ mod tests {
) -> Vec<(String, Option<Color>)> {
let snapshot = map.update(cx, |map, cx| map.snapshot(cx));
let mut chunks: Vec<(String, Option<Color>)> = Vec::new();
- for chunk in snapshot.chunks(rows, Some(theme)) {
+ for chunk in snapshot.chunks(rows, Some(theme), cx) {
let color = chunk.highlight_style.map(|s| s.color);
if let Some((last_chunk, last_color)) = chunks.last_mut() {
if color == *last_color {
@@ -6,13 +6,14 @@ use parking_lot::Mutex;
use std::{
cmp::{self, Ordering},
collections::HashSet,
+ fmt::Debug,
iter,
ops::Range,
- slice,
sync::{
atomic::{AtomicUsize, Ordering::SeqCst},
Arc,
},
+ vec,
};
use sum_tree::SumTree;
use theme::SyntaxTheme;
@@ -44,12 +45,11 @@ struct BlockRow(u32);
#[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq)]
struct WrapRow(u32);
-#[derive(Debug)]
struct Block {
id: BlockId,
position: Anchor,
text: Rope,
- runs: Vec<(usize, HighlightStyle)>,
+ build_runs: Option<Arc<dyn Fn(&AppContext) -> Vec<(usize, HighlightStyle)>>>,
disposition: BlockDisposition,
}
@@ -61,7 +61,7 @@ where
{
pub position: P,
pub text: T,
- pub runs: Vec<(usize, HighlightStyle)>,
+ pub build_runs: Option<Arc<dyn Fn(&AppContext) -> Vec<(usize, HighlightStyle)>>>,
pub disposition: BlockDisposition,
}
@@ -92,11 +92,12 @@ pub struct Chunks<'a> {
block_chunks: Option<BlockChunks<'a>>,
output_row: u32,
max_output_row: u32,
+ cx: Option<&'a AppContext>,
}
struct BlockChunks<'a> {
chunks: rope::Chunks<'a>,
- runs: iter::Peekable<slice::Iter<'a, (usize, HighlightStyle)>>,
+ runs: iter::Peekable<vec::IntoIter<(usize, HighlightStyle)>>,
chunk: Option<&'a str>,
run_start: usize,
offset: usize,
@@ -403,7 +404,7 @@ impl<'a> BlockMapWriter<'a> {
id,
position,
text: block.text.into(),
- runs: block.runs,
+ build_runs: block.build_runs,
disposition: block.disposition,
}),
);
@@ -460,12 +461,17 @@ impl<'a> BlockMapWriter<'a> {
impl BlockSnapshot {
#[cfg(test)]
fn text(&mut self) -> String {
- self.chunks(0..self.transforms.summary().output_rows, None)
+ self.chunks(0..self.transforms.summary().output_rows, None, None)
.map(|chunk| chunk.text)
.collect()
}
- pub fn chunks<'a>(&'a self, rows: Range<u32>, theme: Option<&'a SyntaxTheme>) -> Chunks<'a> {
+ pub fn chunks<'a>(
+ &'a self,
+ rows: Range<u32>,
+ theme: Option<&'a SyntaxTheme>,
+ cx: Option<&'a AppContext>,
+ ) -> Chunks<'a> {
let max_output_row = cmp::min(rows.end, self.transforms.summary().output_rows);
let mut cursor = self.transforms.cursor::<(BlockRow, WrapRow)>();
let input_end = {
@@ -499,6 +505,7 @@ impl BlockSnapshot {
transforms: cursor,
output_row: rows.start,
max_output_row,
+ cx,
}
}
@@ -709,7 +716,11 @@ impl<'a> Iterator for Chunks<'a> {
let start_in_block = self.output_row - block_start;
let end_in_block = cmp::min(self.max_output_row, block_end) - block_start;
self.transforms.next(&());
- self.block_chunks = Some(BlockChunks::new(block, start_in_block..end_in_block));
+ self.block_chunks = Some(BlockChunks::new(
+ block,
+ start_in_block..end_in_block,
+ self.cx,
+ ));
return self.next();
}
@@ -748,11 +759,18 @@ impl<'a> Iterator for Chunks<'a> {
}
impl<'a> BlockChunks<'a> {
- fn new(block: &'a Block, rows: Range<u32>) -> Self {
+ fn new(block: &'a Block, rows: Range<u32>, cx: Option<&'a AppContext>) -> Self {
let offset_range = block.text.point_to_offset(Point::new(rows.start, 0))
..block.text.point_to_offset(Point::new(rows.end, 0));
- let mut runs = block.runs.iter().peekable();
+ let mut runs = block
+ .build_runs
+ .as_ref()
+ .zip(cx)
+ .map(|(build_runs, cx)| build_runs(cx))
+ .unwrap_or_default()
+ .into_iter()
+ .peekable();
let mut run_start = 0;
while let Some((run_len, _)) = runs.peek() {
let run_end = run_start + run_len;
@@ -874,6 +892,17 @@ impl BlockDisposition {
}
}
+impl Debug for Block {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ f.debug_struct("Block")
+ .field("id", &self.id)
+ .field("position", &self.position)
+ .field("text", &self.text)
+ .field("disposition", &self.disposition)
+ .finish()
+ }
+}
+
// Count the number of bytes prior to a target point. If the string doesn't contain the target
// point, return its total extent. Otherwise return the target point itself.
fn offset_for_row(s: &str, target: u32) -> (u32, usize) {
@@ -938,19 +967,19 @@ mod tests {
position: Point::new(1, 0),
text: "BLOCK 1",
disposition: BlockDisposition::Above,
- runs: vec![],
+ build_runs: None,
},
BlockProperties {
position: Point::new(1, 2),
text: "BLOCK 2",
disposition: BlockDisposition::Above,
- runs: vec![],
+ build_runs: None,
},
BlockProperties {
position: Point::new(3, 2),
text: "BLOCK 3",
disposition: BlockDisposition::Below,
- runs: vec![],
+ build_runs: None,
},
],
cx,
@@ -1078,13 +1107,13 @@ mod tests {
position: Point::new(1, 12),
text: "<BLOCK 1",
disposition: BlockDisposition::Above,
- runs: vec![],
+ build_runs: None,
},
BlockProperties {
position: Point::new(1, 1),
text: ">BLOCK 2",
disposition: BlockDisposition::Below,
- runs: vec![],
+ build_runs: None,
},
],
cx,
@@ -1177,7 +1206,7 @@ mod tests {
BlockProperties {
position,
text,
- runs: Vec::<(usize, HighlightStyle)>::new(),
+ build_runs: None,
disposition,
}
})
@@ -1252,7 +1281,7 @@ mod tests {
BlockProperties {
position: row,
text: block.text,
- runs: block.runs,
+ build_runs: block.build_runs.clone(),
disposition: block.disposition,
},
)
@@ -1313,7 +1342,7 @@ mod tests {
for start_row in 0..expected_row_count {
let expected_text = expected_lines[start_row..].join("\n");
let actual_text = blocks_snapshot
- .chunks(start_row as u32..expected_row_count as u32, None)
+ .chunks(start_row as u32..expected_row_count as u32, None, None)
.map(|chunk| chunk.text)
.collect::<String>();
assert_eq!(
@@ -17,7 +17,7 @@ use gpui::{
MutableAppContext, PaintContext, Quad, Scene, SizeConstraint, ViewContext, WeakViewHandle,
};
use json::json;
-use language::{Chunk, DiagnosticSeverity};
+use language::Chunk;
use smallvec::SmallVec;
use std::{
cmp::{self, Ordering},
@@ -493,7 +493,7 @@ impl EditorElement {
let mut styles = Vec::new();
let mut row = rows.start;
let mut line_exceeded_max_len = false;
- let chunks = snapshot.chunks(rows.clone(), Some(&style.syntax));
+ let chunks = snapshot.chunks(rows.clone(), Some(&style.syntax), cx);
let newline_chunk = Chunk {
text: "\n",
@@ -541,13 +541,7 @@ impl EditorElement {
}
let underline = if let Some(severity) = chunk.diagnostic {
- match severity {
- DiagnosticSeverity::ERROR => Some(style.error_underline),
- DiagnosticSeverity::WARNING => Some(style.warning_underline),
- DiagnosticSeverity::INFORMATION => Some(style.information_underline),
- DiagnosticSeverity::HINT => Some(style.hint_underline),
- _ => highlight_style.underline,
- }
+ Some(super::diagnostic_color(severity, style))
} else {
highlight_style.underline
};
@@ -12,6 +12,7 @@ use display_map::*;
pub use element::*;
use gpui::{
action,
+ color::Color,
geometry::vector::{vec2f, Vector2F},
keymap::Binding,
text_layout, AppContext, ClipboardItem, Element, ElementBox, Entity, ModelHandle,
@@ -2250,21 +2251,30 @@ impl Editor {
let buffer = self.buffer.read(cx);
let diagnostic_group = buffer
.diagnostic_group::<Point>(group_id)
- .map(|(range, diagnostic)| (range, diagnostic.message.clone()))
+ .map(|(range, diagnostic)| (range, diagnostic.clone()))
.collect::<Vec<_>>();
let primary_range = buffer.anchor_after(primary_range.start)
..buffer.anchor_before(primary_range.end);
let block_ids = display_map
.insert_blocks(
- diagnostic_group
- .iter()
- .map(|(range, message)| BlockProperties {
+ diagnostic_group.iter().map(|(range, diagnostic)| {
+ let build_settings = self.build_settings.clone();
+ let message_len = diagnostic.message.len();
+ let severity = diagnostic.severity;
+ BlockProperties {
position: range.start,
- text: message.as_str(),
- runs: vec![],
- disposition: BlockDisposition::Above,
- }),
+ text: diagnostic.message.as_str(),
+ build_runs: Some(Arc::new(move |cx| {
+ let settings = build_settings.borrow()(cx);
+ vec![(
+ message_len,
+ diagnostic_color(severity, &settings.style).into(),
+ )]
+ })),
+ disposition: BlockDisposition::Below,
+ }
+ }),
cx,
)
.into_iter()
@@ -2813,8 +2823,9 @@ impl Snapshot {
&'a self,
display_rows: Range<u32>,
theme: Option<&'a SyntaxTheme>,
+ cx: &'a AppContext,
) -> display_map::Chunks<'a> {
- self.display_snapshot.chunks(display_rows, theme)
+ self.display_snapshot.chunks(display_rows, theme, cx)
}
pub fn scroll_position(&self) -> Vector2F {
@@ -2882,10 +2893,10 @@ impl EditorSettings {
selection: Default::default(),
guest_selections: Default::default(),
syntax: Default::default(),
- error_underline: Default::default(),
- warning_underline: Default::default(),
- information_underline: Default::default(),
- hint_underline: Default::default(),
+ error_color: Default::default(),
+ warning_color: Default::default(),
+ information_color: Default::default(),
+ hint_color: Default::default(),
}
},
}
@@ -3009,6 +3020,16 @@ impl SelectionExt for Selection<Point> {
}
}
+pub fn diagnostic_color(severity: DiagnosticSeverity, style: &EditorStyle) -> Color {
+ match severity {
+ DiagnosticSeverity::ERROR => style.error_color,
+ DiagnosticSeverity::WARNING => style.warning_color,
+ DiagnosticSeverity::INFORMATION => style.information_color,
+ DiagnosticSeverity::HINT => style.hint_color,
+ _ => style.text.color,
+ }
+}
+
#[cfg(test)]
mod tests {
use super::*;
@@ -227,12 +227,12 @@ pub struct EditorStyle {
pub line_number_active: Color,
pub guest_selections: Vec<SelectionStyle>,
pub syntax: Arc<SyntaxTheme>,
- pub error_underline: Color,
- pub warning_underline: Color,
+ pub error_color: Color,
+ pub warning_color: Color,
#[serde(default)]
- pub information_underline: Color,
+ pub information_color: Color,
#[serde(default)]
- pub hint_underline: Color,
+ pub hint_color: Color,
}
#[derive(Clone, Copy, Default, Deserialize)]
@@ -273,10 +273,10 @@ impl InputEditorStyle {
line_number_active: Default::default(),
guest_selections: Default::default(),
syntax: Default::default(),
- error_underline: Default::default(),
- warning_underline: Default::default(),
- information_underline: Default::default(),
- hint_underline: Default::default(),
+ error_color: Default::default(),
+ warning_color: Default::default(),
+ information_color: Default::default(),
+ hint_color: Default::default(),
}
}
}
@@ -173,7 +173,7 @@ corner_radius = 6
[project_panel]
extends = "$panel"
-padding.top = 6 # ($workspace.tab.height - $project_panel.entry.height) / 2
+padding.top = 6 # ($workspace.tab.height - $project_panel.entry.height) / 2
[project_panel.entry]
text = "$text.1"
@@ -235,7 +235,7 @@ line_number = "$text.2.color"
line_number_active = "$text.0.color"
selection = "$selection.host"
guest_selections = "$selection.guests"
-error_underline = "$status.bad"
-warning_underline = "$status.warn"
-info_underline = "$status.info"
-hint_underline = "$status.info"
+error_color = "$status.bad"
+warning_color = "$status.warn"
+info_color = "$status.info"
+hint_color = "$status.info"