Only highlight individual comment words for comments that are similar

pull/25/head
Wilfred Hughes 2021-07-24 17:01:30 +07:00
parent 3a26616fac
commit 928584676a
6 changed files with 70 additions and 5 deletions

@ -8,6 +8,9 @@ Fixed handling of `@`, `<` and `>` in elisp.
Fixed an issue where comment replacements were not detected.
Changed words in comments are now only highlighted when comments are
relatively similar (according to their Levenshtein distance).
### Command Line Interface
Removed unused `--inline` argument.

9
Cargo.lock generated

@ -46,7 +46,7 @@ dependencies = [
"ansi_term",
"atty",
"bitflags",
"strsim",
"strsim 0.8.0",
"textwrap",
"unicode-width",
"vec_map",
@ -97,6 +97,7 @@ dependencies = [
"regex",
"rust-embed",
"rustc-hash",
"strsim 0.10.0",
"term_size",
"toml",
"typed-arena",
@ -267,6 +268,12 @@ version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "syn"
version = "1.0.62"

@ -19,6 +19,7 @@ typed-arena = "2.0.1"
toml = "0.5.8"
rust-embed = "5.9.0"
rustc-hash = "1.1.0"
strsim = "0.10.0"
[dev-dependencies]
pretty_assertions = "0.6.1"

@ -0,0 +1,8 @@
;; Unchanged comment.
(f1)
;; Changing a comment word.
(f2)
;; Completely novel text.
(f3)

@ -0,0 +1,8 @@
;; Unchanged comment.
(f1)
;; Changing a single word.
(f2)
;; Changing virtually everything written in the comment.
(f3)

@ -5,6 +5,7 @@ use std::hash::{Hash, Hasher};
use crate::lines::LineNumber;
use crate::syntax::{ChangeKind, Syntax};
use rustc_hash::FxHashMap;
use strsim::normalized_levenshtein;
use Edge::*;
#[derive(Debug, Clone)]
@ -75,8 +76,6 @@ impl<'a> Eq for OrdVertex<'a> {}
enum Edge {
UnchangedNode(u64),
UnchangedDelimiter(u64),
// TODO: consider a replaced Atom edge if the levenshtein distance
// is reasonably close?
ReplacedComment,
NovelAtomLHS { contiguous: bool },
NovelAtomRHS { contiguous: bool },
@ -250,16 +249,23 @@ fn neighbours<'a>(v: &Vertex<'a>) -> Vec<(Edge, Vertex<'a>)> {
if let (
Syntax::Atom {
content: lhs_content,
is_comment: lhs_is_comment,
..
},
Syntax::Atom {
content: rhs_content,
is_comment: rhs_is_comment,
..
},
) = (lhs_syntax, rhs_syntax)
{
if *lhs_is_comment && *rhs_is_comment {
// Both sides are comments and their content is reasonably
// similar.
if *lhs_is_comment
&& *rhs_is_comment
&& normalized_levenshtein(lhs_content, rhs_content) > 0.4
{
res.push((
ReplacedComment,
Vertex {
@ -826,7 +832,7 @@ mod tests {
);
}
#[test]
fn replace_comment() {
fn replace_similar_comment() {
let arena = Arena::new();
let lhs: Vec<&Syntax> = vec![Syntax::new_comment(
@ -854,4 +860,36 @@ mod tests {
let actions = route.iter().map(|(action, _)| *action).collect_vec();
assert_eq!(actions, vec![ReplacedComment]);
}
#[test]
fn replace_very_different_comment() {
let arena = Arena::new();
let lhs: Vec<&Syntax> = vec![Syntax::new_comment(
&arena,
pos_helper(1),
"the quick brown fox",
)];
init_info(&lhs);
let rhs: Vec<&Syntax> = vec![Syntax::new_comment(&arena, pos_helper(1), "foo bar")];
init_info(&rhs);
let start = Vertex {
lhs_syntax: lhs.get(0).map(|n| *n),
lhs_prev_novel: None,
rhs_syntax: rhs.get(0).map(|n| *n),
rhs_prev_novel: None,
};
let route = shortest_path(start);
let actions = route.iter().map(|(action, _)| *action).collect_vec();
assert_eq!(
actions,
vec![
NovelAtomLHS { contiguous: false },
NovelAtomRHS { contiguous: false }
]
);
}
}