WIP
This commit is contained in:
parent
2664dad2bc
commit
dfbfa86548
3 changed files with 84 additions and 11 deletions
|
@ -10,7 +10,10 @@ use buffer::Rope;
|
||||||
use fold_map::{FoldMap, ToFoldPoint as _};
|
use fold_map::{FoldMap, ToFoldPoint as _};
|
||||||
use gpui::{fonts::FontId, AppContext, Entity, ModelContext, ModelHandle};
|
use gpui::{fonts::FontId, AppContext, Entity, ModelContext, ModelHandle};
|
||||||
use language::{Anchor, Buffer, Point, ToOffset, ToPoint};
|
use language::{Anchor, Buffer, Point, ToOffset, ToPoint};
|
||||||
use std::{collections::HashSet, ops::Range};
|
use std::{
|
||||||
|
collections::{HashMap, HashSet},
|
||||||
|
ops::Range,
|
||||||
|
};
|
||||||
use sum_tree::Bias;
|
use sum_tree::Bias;
|
||||||
use tab_map::TabMap;
|
use tab_map::TabMap;
|
||||||
use theme::{BlockStyle, SyntaxTheme};
|
use theme::{BlockStyle, SyntaxTheme};
|
||||||
|
@ -128,6 +131,13 @@ impl DisplayMap {
|
||||||
block_map.insert(blocks, cx)
|
block_map.insert(blocks, cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn restyle_blocks<F>(&mut self, styles: HashMap<BlockId, Option<F>>)
|
||||||
|
where
|
||||||
|
F: 'static + Fn(&AppContext) -> BlockStyle,
|
||||||
|
{
|
||||||
|
self.block_map.restyle(styles);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn remove_blocks(&mut self, ids: HashSet<BlockId>, cx: &mut ModelContext<Self>) {
|
pub fn remove_blocks(&mut self, ids: HashSet<BlockId>, cx: &mut ModelContext<Self>) {
|
||||||
let (snapshot, edits) = self.fold_map.read(cx);
|
let (snapshot, edits) = self.fold_map.read(cx);
|
||||||
let (snapshot, edits) = self.tab_map.sync(snapshot, edits);
|
let (snapshot, edits) = self.tab_map.sync(snapshot, edits);
|
||||||
|
|
|
@ -8,7 +8,7 @@ use language::{Buffer, Chunk};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use std::{
|
use std::{
|
||||||
cmp::{self, Ordering},
|
cmp::{self, Ordering},
|
||||||
collections::HashSet,
|
collections::{HashMap, HashSet},
|
||||||
fmt::Debug,
|
fmt::Debug,
|
||||||
iter,
|
iter,
|
||||||
ops::{Deref, Range},
|
ops::{Deref, Range},
|
||||||
|
@ -53,7 +53,7 @@ pub struct Block {
|
||||||
position: Anchor,
|
position: Anchor,
|
||||||
text: Rope,
|
text: Rope,
|
||||||
build_runs: Option<Arc<dyn Fn(&AppContext) -> Vec<(usize, HighlightStyle)>>>,
|
build_runs: Option<Arc<dyn Fn(&AppContext) -> Vec<(usize, HighlightStyle)>>>,
|
||||||
build_style: Option<Arc<dyn Fn(&AppContext) -> BlockStyle>>,
|
build_style: Mutex<Option<Arc<dyn Fn(&AppContext) -> BlockStyle>>>,
|
||||||
disposition: BlockDisposition,
|
disposition: BlockDisposition,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -332,6 +332,19 @@ impl BlockMap {
|
||||||
drop(cursor);
|
drop(cursor);
|
||||||
*transforms = new_transforms;
|
*transforms = new_transforms;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn restyle<F>(&mut self, mut styles: HashMap<BlockId, Option<F>>)
|
||||||
|
where
|
||||||
|
F: 'static + Fn(&AppContext) -> BlockStyle,
|
||||||
|
{
|
||||||
|
for block in &self.blocks {
|
||||||
|
if let Some(build_style) = styles.remove(&block.id) {
|
||||||
|
*block.build_style.lock() = build_style.map(|build_style| {
|
||||||
|
Arc::new(build_style) as Arc<dyn Fn(&AppContext) -> BlockStyle>
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_isomorphic(tree: &mut SumTree<Transform>, rows: u32) {
|
fn push_isomorphic(tree: &mut SumTree<Transform>, rows: u32) {
|
||||||
|
@ -421,7 +434,7 @@ impl<'a> BlockMapWriter<'a> {
|
||||||
position,
|
position,
|
||||||
text: block.text.into(),
|
text: block.text.into(),
|
||||||
build_runs: block.build_runs,
|
build_runs: block.build_runs,
|
||||||
build_style: block.build_style,
|
build_style: Mutex::new(block.build_style),
|
||||||
disposition: block.disposition,
|
disposition: block.disposition,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
@ -896,7 +909,7 @@ impl<'a> Iterator for BufferRows<'a> {
|
||||||
if let Some(block) = &transform.block {
|
if let Some(block) = &transform.block {
|
||||||
let style = self
|
let style = self
|
||||||
.cx
|
.cx
|
||||||
.and_then(|cx| block.build_style.as_ref().map(|f| f(cx)));
|
.and_then(|cx| block.build_style.lock().as_ref().map(|f| f(cx)));
|
||||||
Some(DisplayRow::Block(block.id, style))
|
Some(DisplayRow::Block(block.id, style))
|
||||||
} else {
|
} else {
|
||||||
Some(self.input_buffer_rows.next().unwrap())
|
Some(self.input_buffer_rows.next().unwrap())
|
||||||
|
@ -1017,7 +1030,7 @@ mod tests {
|
||||||
id: BlockId(0),
|
id: BlockId(0),
|
||||||
position: Anchor::min(),
|
position: Anchor::min(),
|
||||||
text: "one!\ntwo three\nfour".into(),
|
text: "one!\ntwo three\nfour".into(),
|
||||||
build_style: None,
|
build_style: Mutex::new(None),
|
||||||
build_runs: Some(Arc::new(move |_| {
|
build_runs: Some(Arc::new(move |_| {
|
||||||
vec![(3, red.into()), (6, Default::default()), (5, blue.into())]
|
vec![(3, red.into()), (6, Default::default()), (5, blue.into())]
|
||||||
})),
|
})),
|
||||||
|
|
|
@ -24,7 +24,7 @@ use smol::Timer;
|
||||||
use std::{
|
use std::{
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
cmp::{self, Ordering},
|
cmp::{self, Ordering},
|
||||||
collections::HashSet,
|
collections::{HashMap, HashSet},
|
||||||
iter, mem,
|
iter, mem,
|
||||||
ops::{Range, RangeInclusive},
|
ops::{Range, RangeInclusive},
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
|
@ -341,8 +341,10 @@ struct BracketPairState {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct ActiveDiagnosticGroup {
|
struct ActiveDiagnosticGroup {
|
||||||
primary_range: Range<Anchor>,
|
primary_range: Range<Anchor>,
|
||||||
|
primary_message: String,
|
||||||
|
blocks: HashMap<BlockId, Diagnostic>,
|
||||||
group_range: Range<Anchor>,
|
group_range: Range<Anchor>,
|
||||||
block_ids: HashSet<BlockId>,
|
is_valid: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
|
@ -2268,13 +2270,17 @@ impl Editor {
|
||||||
..buffer.anchor_before(group_end);
|
..buffer.anchor_before(group_end);
|
||||||
let primary_range = buffer.anchor_after(primary_range.start)
|
let primary_range = buffer.anchor_after(primary_range.start)
|
||||||
..buffer.anchor_before(primary_range.end);
|
..buffer.anchor_before(primary_range.end);
|
||||||
|
let mut primary_message = None;
|
||||||
|
|
||||||
let block_ids = display_map
|
let blocks = display_map
|
||||||
.insert_blocks(
|
.insert_blocks(
|
||||||
diagnostic_group.iter().map(|(range, diagnostic)| {
|
diagnostic_group.iter().map(|(range, diagnostic)| {
|
||||||
let build_settings = self.build_settings.clone();
|
let build_settings = self.build_settings.clone();
|
||||||
let message_len = diagnostic.message.len();
|
let message_len = diagnostic.message.len();
|
||||||
let severity = diagnostic.severity;
|
let severity = diagnostic.severity;
|
||||||
|
if diagnostic.is_primary {
|
||||||
|
primary_message = Some(diagnostic.message.clone());
|
||||||
|
}
|
||||||
BlockProperties {
|
BlockProperties {
|
||||||
position: range.start,
|
position: range.start,
|
||||||
text: diagnostic.message.as_str(),
|
text: diagnostic.message.as_str(),
|
||||||
|
@ -2303,12 +2309,19 @@ impl Editor {
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
.zip(
|
||||||
|
diagnostic_group
|
||||||
|
.into_iter()
|
||||||
|
.map(|(_, diagnostic)| diagnostic),
|
||||||
|
)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
Some(ActiveDiagnosticGroup {
|
Some(ActiveDiagnosticGroup {
|
||||||
primary_range,
|
primary_range,
|
||||||
|
primary_message: primary_message.unwrap(),
|
||||||
group_range,
|
group_range,
|
||||||
block_ids,
|
blocks,
|
||||||
|
is_valid: true,
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -2333,10 +2346,46 @@ impl Editor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
|
||||||
|
if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
|
||||||
|
let buffer = self.buffer.read(cx);
|
||||||
|
let primary_range_start = active_diagnostics.primary_range.start.to_offset(buffer);
|
||||||
|
let matching_diagnostic = buffer
|
||||||
|
.diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone())
|
||||||
|
.find_map(|(range, diagnostic)| {
|
||||||
|
if diagnostic.is_primary
|
||||||
|
&& range.start == primary_range_start
|
||||||
|
&& diagnostic.message == active_diagnostics.primary_message
|
||||||
|
{
|
||||||
|
Some(diagnostic.group_id)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if let Some(matching_diagnostic) = matching_diagnostic {
|
||||||
|
} else if active_diagnostics.is_valid {
|
||||||
|
let mut new_styles = HashMap::new();
|
||||||
|
for (block_id, diagnostic) in &active_diagnostics.blocks {
|
||||||
|
let build_settings = self.build_settings.clone();
|
||||||
|
let severity = diagnostic.severity;
|
||||||
|
new_styles.insert(
|
||||||
|
*block_id,
|
||||||
|
Some(move |cx: &AppContext| {
|
||||||
|
let settings = build_settings.borrow()(cx);
|
||||||
|
diagnostic_style(severity, false, &settings.style).block
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
self.display_map
|
||||||
|
.update(cx, |display_map, _| display_map.restyle_blocks(new_styles));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
|
fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
|
||||||
if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
|
if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
|
||||||
self.display_map.update(cx, |display_map, cx| {
|
self.display_map.update(cx, |display_map, cx| {
|
||||||
display_map.remove_blocks(active_diagnostic_group.block_ids, cx);
|
display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
|
||||||
});
|
});
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
@ -2799,6 +2848,7 @@ impl Editor {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_buffer_changed(&mut self, _: ModelHandle<Buffer>, cx: &mut ViewContext<Self>) {
|
fn on_buffer_changed(&mut self, _: ModelHandle<Buffer>, cx: &mut ViewContext<Self>) {
|
||||||
|
self.refresh_active_diagnostics(cx);
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue