Do word diffing on text too

pull/573/head
Wilfred Hughes 2023-09-12 13:03:27 +07:00
parent 2b9aca85f3
commit 1e7866b64e
7 changed files with 41 additions and 13 deletions

@ -4,6 +4,12 @@
Added support for XML.
### Diffing
Text nodes now get word diffing, consistent with string literals and
comments. This is used in languages like HTML and XML that have
separate text nodes.
### Display
Improved syntax highlighting of constructors (i.e. type names when

@ -77,7 +77,7 @@ sample_files/helpful_before.el sample_files/helpful_after.el
91ce9866aeb9c8e2f59836819d1a4e06 -
sample_files/html_before.html sample_files/html_after.html
46fa37a2379d57bf9ac97984fa060dfd -
b5149551376defd7a0cda51aeaef420d -
sample_files/html_simple_before.html sample_files/html_simple_after.html
915a46736d489be724b18c87b4ebf6b2 -

@ -585,12 +585,12 @@ pub fn set_neighbours<'s, 'b>(
if let (
Syntax::Atom {
content: lhs_content,
kind: lhs_kind @ AtomKind::Comment | lhs_kind @ AtomKind::String,
kind: lhs_kind @ AtomKind::Comment | lhs_kind @ AtomKind::String(_),
..
},
Syntax::Atom {
content: rhs_content,
kind: rhs_kind @ AtomKind::Comment | rhs_kind @ AtomKind::String,
kind: rhs_kind @ AtomKind::Comment | rhs_kind @ AtomKind::String(_),
..
},
) = (lhs_syntax, rhs_syntax)

@ -10,7 +10,7 @@ use crate::{
side_by_side::lines_with_novel,
},
lines::MaxLine,
parse::syntax::{self, MatchedPos},
parse::syntax::{self, MatchedPos, StringKind},
summary::{DiffResult, FileContent, FileFormat},
};
@ -261,7 +261,8 @@ impl Highlight {
match highlight {
TokenKind::Delimiter => Highlight::Delimiter,
TokenKind::Atom(atom) => match atom {
AtomKind::String => Highlight::String,
AtomKind::String(StringKind::StringLiteral) => Highlight::String,
AtomKind::String(StringKind::Text) => Highlight::Normal,
AtomKind::Keyword => Highlight::Keyword,
AtomKind::Comment => Highlight::Comment,
AtomKind::Type => Highlight::Type,

@ -7,6 +7,7 @@ use line_numbers::SingleLineSpan;
use owo_colors::{OwoColorize, Style};
use unicode_width::{UnicodeWidthChar, UnicodeWidthStr};
use crate::parse::syntax::StringKind;
use crate::{
constants::Side,
hash::DftHashMap,
@ -325,13 +326,14 @@ pub fn color_positions(
if syntax_highlight {
if let TokenKind::Atom(atom_kind) = highlight {
match atom_kind {
AtomKind::String => {
AtomKind::String(StringKind::StringLiteral) => {
style = if background.is_dark() {
style.bright_magenta()
} else {
style.magenta()
};
}
AtomKind::String(StringKind::Text) => {}
AtomKind::Comment => {
style = style.italic();
style = if background.is_dark() {

@ -559,10 +559,20 @@ impl<'a> PartialEq for Syntax<'a> {
}
impl<'a> Eq for Syntax<'a> {}
/// Different types of strings. We want to diff these the same way,
/// but highlight them differently.
#[derive(PartialEq, Eq, Debug, Clone, Copy, Hash)]
pub enum StringKind {
/// A string literal, such as `"foo"`.
StringLiteral,
/// Plain text, such as the content of `<p>foo</p>`.
Text,
}
#[derive(PartialEq, Eq, Debug, Clone, Copy, Hash)]
pub enum AtomKind {
Normal,
String,
String(StringKind),
Type,
Comment,
Keyword,
@ -709,7 +719,7 @@ fn split_atom_words(
opposite_pos: &[SingleLineSpan],
kind: AtomKind,
) -> Vec<MatchedPos> {
debug_assert!(kind == AtomKind::Comment || kind == AtomKind::String);
debug_assert!(kind == AtomKind::Comment || matches!(kind, AtomKind::String(_)));
// TODO: merge adjacent single-line comments unless there are
// blank lines between them.
@ -837,10 +847,17 @@ impl MatchedPos {
content, position, ..
} => (content, position),
};
let kind = if let ReplacedComment(_, _) = ck {
AtomKind::Comment
let kind = if let ReplacedString(this, _) = ck {
match this {
Atom {
kind: AtomKind::String(StringKind::Text),
..
} => AtomKind::String(StringKind::Text),
_ => AtomKind::String(StringKind::StringLiteral),
}
} else {
AtomKind::String
AtomKind::Comment
};
split_atom_words(this_content, pos, opposite_content, opposite_pos, kind)

@ -6,8 +6,8 @@ use line_numbers::LinePositions;
use tree_sitter as ts;
use typed_arena::Arena;
use super::syntax;
use super::syntax::MatchedPos;
use super::syntax::{self, StringKind};
use crate::hash::DftHashMap;
use crate::options::DiffOptions;
use crate::parse::guess_language as guess;
@ -1701,9 +1701,11 @@ fn atom_from_cursor<'a>(
} else if highlights.keyword_ids.contains(&node.id()) {
AtomKind::Keyword
} else if highlights.string_ids.contains(&node.id()) {
AtomKind::String
AtomKind::String(StringKind::StringLiteral)
} else if highlights.type_ids.contains(&node.id()) {
AtomKind::Type
} else if node.kind() == "CharData" || node.kind() == "text" {
AtomKind::String(StringKind::Text)
} else {
AtomKind::Normal
};