html: Open extra newline between opening and closing HTML tags (#25130)
Closes #12064 It feels a bit strange to use `brackets` for this but it seems to work without unintended consequences from my testing so far. Release Notes: - N/A --------- Co-authored-by: Marshall Bowers <git@maxdeviant.com>
This commit is contained in:
parent
528da6eb26
commit
1429363218
7 changed files with 199 additions and 62 deletions
|
@ -782,6 +782,13 @@ impl EditPreview {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct BracketMatch {
|
||||
pub open_range: Range<usize>,
|
||||
pub close_range: Range<usize>,
|
||||
pub newline_only: bool,
|
||||
}
|
||||
|
||||
impl Buffer {
|
||||
/// Create a new buffer with the given base text.
|
||||
pub fn local<T: Into<String>>(base_text: T, cx: &Context<Self>) -> Self {
|
||||
|
@ -3556,15 +3563,10 @@ impl BufferSnapshot {
|
|||
self.syntax.matches(range, self, query)
|
||||
}
|
||||
|
||||
/// Returns bracket range pairs overlapping or adjacent to `range`
|
||||
pub fn bracket_ranges<T: ToOffset>(
|
||||
pub fn all_bracket_ranges(
|
||||
&self,
|
||||
range: Range<T>,
|
||||
) -> impl Iterator<Item = (Range<usize>, Range<usize>)> + '_ {
|
||||
// Find bracket pairs that *inclusively* contain the given range.
|
||||
let range = range.start.to_offset(self).saturating_sub(1)
|
||||
..self.len().min(range.end.to_offset(self) + 1);
|
||||
|
||||
range: Range<usize>,
|
||||
) -> impl Iterator<Item = BracketMatch> + '_ {
|
||||
let mut matches = self.syntax.matches(range.clone(), &self.text, |grammar| {
|
||||
grammar.brackets_config.as_ref().map(|c| &c.query)
|
||||
});
|
||||
|
@ -3579,6 +3581,7 @@ impl BufferSnapshot {
|
|||
let mut open = None;
|
||||
let mut close = None;
|
||||
let config = &configs[mat.grammar_index];
|
||||
let pattern = &config.patterns[mat.pattern_index];
|
||||
for capture in mat.captures {
|
||||
if capture.index == config.open_capture_ix {
|
||||
open = Some(capture.node.byte_range());
|
||||
|
@ -3589,21 +3592,37 @@ impl BufferSnapshot {
|
|||
|
||||
matches.advance();
|
||||
|
||||
let Some((open, close)) = open.zip(close) else {
|
||||
let Some((open_range, close_range)) = open.zip(close) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let bracket_range = open.start..=close.end;
|
||||
let bracket_range = open_range.start..=close_range.end;
|
||||
if !bracket_range.overlaps(&range) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return Some((open, close));
|
||||
return Some(BracketMatch {
|
||||
open_range,
|
||||
close_range,
|
||||
newline_only: pattern.newline_only,
|
||||
});
|
||||
}
|
||||
None
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns bracket range pairs overlapping or adjacent to `range`
|
||||
pub fn bracket_ranges<T: ToOffset>(
|
||||
&self,
|
||||
range: Range<T>,
|
||||
) -> impl Iterator<Item = BracketMatch> + '_ {
|
||||
// Find bracket pairs that *inclusively* contain the given range.
|
||||
let range = range.start.to_offset(self).saturating_sub(1)
|
||||
..self.len().min(range.end.to_offset(self) + 1);
|
||||
self.all_bracket_ranges(range)
|
||||
.filter(|pair| !pair.newline_only)
|
||||
}
|
||||
|
||||
pub fn text_object_ranges<T: ToOffset>(
|
||||
&self,
|
||||
range: Range<T>,
|
||||
|
@ -3674,11 +3693,12 @@ impl BufferSnapshot {
|
|||
pub fn enclosing_bracket_ranges<T: ToOffset>(
|
||||
&self,
|
||||
range: Range<T>,
|
||||
) -> impl Iterator<Item = (Range<usize>, Range<usize>)> + '_ {
|
||||
) -> impl Iterator<Item = BracketMatch> + '_ {
|
||||
let range = range.start.to_offset(self)..range.end.to_offset(self);
|
||||
|
||||
self.bracket_ranges(range.clone())
|
||||
.filter(move |(open, close)| open.start <= range.start && close.end >= range.end)
|
||||
self.bracket_ranges(range.clone()).filter(move |pair| {
|
||||
pair.open_range.start <= range.start && pair.close_range.end >= range.end
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the smallest enclosing bracket ranges containing the given range or None if no brackets contain range
|
||||
|
@ -3694,14 +3714,14 @@ impl BufferSnapshot {
|
|||
// Get the ranges of the innermost pair of brackets.
|
||||
let mut result: Option<(Range<usize>, Range<usize>)> = None;
|
||||
|
||||
for (open, close) in self.enclosing_bracket_ranges(range.clone()) {
|
||||
for pair in self.enclosing_bracket_ranges(range.clone()) {
|
||||
if let Some(range_filter) = range_filter {
|
||||
if !range_filter(open.clone(), close.clone()) {
|
||||
if !range_filter(pair.open_range.clone(), pair.close_range.clone()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
let len = close.end - open.start;
|
||||
let len = pair.close_range.end - pair.open_range.start;
|
||||
|
||||
if let Some((existing_open, existing_close)) = &result {
|
||||
let existing_len = existing_close.end - existing_open.start;
|
||||
|
@ -3710,7 +3730,7 @@ impl BufferSnapshot {
|
|||
}
|
||||
}
|
||||
|
||||
result = Some((open, close));
|
||||
result = Some((pair.open_range, pair.close_range));
|
||||
}
|
||||
|
||||
result
|
||||
|
|
|
@ -3401,7 +3401,10 @@ fn assert_bracket_pairs(
|
|||
.collect::<Vec<_>>();
|
||||
|
||||
assert_set_eq!(
|
||||
buffer.bracket_ranges(selection_range).collect::<Vec<_>>(),
|
||||
buffer
|
||||
.bracket_ranges(selection_range)
|
||||
.map(|pair| (pair.open_range, pair.close_range))
|
||||
.collect::<Vec<_>>(),
|
||||
bracket_pairs
|
||||
);
|
||||
}
|
||||
|
|
|
@ -918,7 +918,7 @@ pub struct Grammar {
|
|||
pub ts_language: tree_sitter::Language,
|
||||
pub(crate) error_query: Option<Query>,
|
||||
pub(crate) highlights_query: Option<Query>,
|
||||
pub(crate) brackets_config: Option<BracketConfig>,
|
||||
pub(crate) brackets_config: Option<BracketsConfig>,
|
||||
pub(crate) redactions_config: Option<RedactionConfig>,
|
||||
pub(crate) runnable_config: Option<RunnableConfig>,
|
||||
pub(crate) indents_config: Option<IndentConfig>,
|
||||
|
@ -1039,10 +1039,16 @@ struct InjectionPatternConfig {
|
|||
combined: bool,
|
||||
}
|
||||
|
||||
struct BracketConfig {
|
||||
struct BracketsConfig {
|
||||
query: Query,
|
||||
open_capture_ix: u32,
|
||||
close_capture_ix: u32,
|
||||
patterns: Vec<BracketsPatternConfig>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
struct BracketsPatternConfig {
|
||||
newline_only: bool,
|
||||
}
|
||||
|
||||
impl Language {
|
||||
|
@ -1284,11 +1290,24 @@ impl Language {
|
|||
("close", &mut close_capture_ix),
|
||||
],
|
||||
);
|
||||
let patterns = (0..query.pattern_count())
|
||||
.map(|ix| {
|
||||
let mut config = BracketsPatternConfig::default();
|
||||
for setting in query.property_settings(ix) {
|
||||
match setting.key.as_ref() {
|
||||
"newline.only" => config.newline_only = true,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
config
|
||||
})
|
||||
.collect();
|
||||
if let Some((open_capture_ix, close_capture_ix)) = open_capture_ix.zip(close_capture_ix) {
|
||||
grammar.brackets_config = Some(BracketConfig {
|
||||
grammar.brackets_config = Some(BracketsConfig {
|
||||
query,
|
||||
open_capture_ix,
|
||||
close_capture_ix,
|
||||
patterns,
|
||||
});
|
||||
}
|
||||
Ok(self)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue