From: Simon Tatham Date: Fri, 5 Jan 2024 22:26:37 +0000 (+0000) Subject: Editor: fix handling of abutting scan matches. X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?a=commitdiff_plain;h=9bdc99f8991d09b120c549c847a0a83d5b2267e3;p=mastodonochrome.git Editor: fix handling of abutting scan matches. My example test of '#hashtag@mention' _shouldn't_ have highlighted the mention, because the word character before the @ disqualifies it. But I was doing the matching on a slice of the string, instead of giving get_span the whole string and telling it where to start from. That in turn was because I hadn't bothered to give get_span that argument. But it's really easy to add! Now done. --- diff --git a/src/editor.rs b/src/editor.rs index aac14ba..d357d96 100644 --- a/src/editor.rs +++ b/src/editor.rs @@ -893,8 +893,8 @@ impl Composer { // something starting soonest (out of those that pick up // anything at all). let next_match = scanners.iter().filter_map(|(colour, scanner)| { - scanner.get_span(&core.text[pos..]) - .map(|(start, end)| (pos + start, pos + end, colour)) + scanner.get_span(&core.text, pos) + .map(|(start, end)| (start, end, colour)) }).min(); match next_match { @@ -1216,14 +1216,22 @@ fn test_regions() { ComposeBufferRegion { start: 90, end: 91, colour: ' ' }, }); - // Scan a shorter piece of text in which a hashtag and a mention - // directly abut. FIXME: actually, surely we _shouldn't_ match - // this? + // When a hashtag and a mention directly abut, it should + // disqualify the hashtag. let composer = Composer::test_new( standard_conf.clone(), "#hashtag@mention"); assert_eq!(composer.make_regions(&composer.core), vec! { ComposeBufferRegion { start: 0, end: 8, colour: '#' }, - ComposeBufferRegion { start: 8, end: 16, colour: '@' }, + ComposeBufferRegion { start: 8, end: 16, colour: ' ' }, + }); + + // But a space between them is enough to make them work. + let composer = Composer::test_new( + standard_conf.clone(), "#hashtag @mention"); + assert_eq!(composer.make_regions(&composer.core), vec! { + ComposeBufferRegion { start: 0, end: 8, colour: '#' }, + ComposeBufferRegion { start: 8, end: 9, colour: ' ' }, + ComposeBufferRegion { start: 9, end: 17, colour: '@' }, }); // The total cost of main_sample_text is 61 (counting the mention diff --git a/src/scan_re.rs b/src/scan_re.rs index 43c9a20..adc3844 100644 --- a/src/scan_re.rs +++ b/src/scan_re.rs @@ -8,8 +8,8 @@ pub struct Findable { } impl Findable { - pub fn get_span(&self, text: &str) -> Option<(usize, usize)> { - let mut start: usize = 0; + pub fn get_span(&self, text: &str, start: usize) -> Option<(usize, usize)> { + let mut start = start; loop { match self.text.find_at(&text, start) { None => break None, @@ -159,68 +159,68 @@ impl Scan { #[test] fn test_mention() { let scan = Scan::get(); - assert_eq!(scan.mention.get_span("hello @user"), + assert_eq!(scan.mention.get_span("hello @user", 0), Some((6, 11))); - assert_eq!(scan.mention.get_span("hello @user@domain.foo"), + assert_eq!(scan.mention.get_span("hello @user@domain.foo", 0), Some((6, 22))); - assert_eq!(scan.mention.get_span("hello a@user"), None); - assert_eq!(scan.mention.get_span("hello =@user"), None); - assert_eq!(scan.mention.get_span("hello /@user"), None); - assert_eq!(scan.mention.get_span("hello )@user"), + assert_eq!(scan.mention.get_span("hello a@user", 0), None); + assert_eq!(scan.mention.get_span("hello =@user", 0), None); + assert_eq!(scan.mention.get_span("hello /@user", 0), None); + assert_eq!(scan.mention.get_span("hello )@user", 0), Some((7, 12))); - assert_eq!(scan.mention.get_span("hello @user.name"), + assert_eq!(scan.mention.get_span("hello @user.name", 0), Some((6, 16))); - assert_eq!(scan.mention.get_span("hello @user.name."), + assert_eq!(scan.mention.get_span("hello @user.name.", 0), Some((6, 16))); - assert_eq!(scan.mention.get_span("hello @user-name"), + assert_eq!(scan.mention.get_span("hello @user-name", 0), Some((6, 16))); - assert_eq!(scan.mention.get_span("hello @user-name-"), + assert_eq!(scan.mention.get_span("hello @user-name-", 0), Some((6, 16))); } #[test] fn test_hashtag() { let scan = Scan::get(); - assert_eq!(scan.hashtag.get_span("some #text here"), + assert_eq!(scan.hashtag.get_span("some #text here", 0), Some((5, 10))); - assert_eq!(scan.hashtag.get_span("some # here"), None); - assert_eq!(scan.hashtag.get_span("some #__a__ here"), + assert_eq!(scan.hashtag.get_span("some # here", 0), None); + assert_eq!(scan.hashtag.get_span("some #__a__ here", 0), Some((5, 11))); - assert_eq!(scan.hashtag.get_span("some #_____ here"), + assert_eq!(scan.hashtag.get_span("some #_____ here", 0), Some((5, 11))); - assert_eq!(scan.hashtag.get_span("some #_0_0_ here"), + assert_eq!(scan.hashtag.get_span("some #_0_0_ here", 0), Some((5, 11))); - assert_eq!(scan.hashtag.get_span("some a#text here"), None); - assert_eq!(scan.hashtag.get_span("some )#text here"), None); - assert_eq!(scan.hashtag.get_span("some (#text here"), + assert_eq!(scan.hashtag.get_span("some a#text here", 0), None); + assert_eq!(scan.hashtag.get_span("some )#text here", 0), None); + assert_eq!(scan.hashtag.get_span("some (#text here", 0), Some((6,11))); } #[test] fn test_domain() { let scan = Scan::get(); - assert_eq!(scan.domain.get_span("foo.bar.baz"), + assert_eq!(scan.domain.get_span("foo.bar.baz", 0), Some((0, 11))); - assert_eq!(scan.domain.get_span("foo.bar.baz."), + assert_eq!(scan.domain.get_span("foo.bar.baz.", 0), Some((0, 11))); - assert_eq!(scan.domain.get_span("foo.b-r.baz"), + assert_eq!(scan.domain.get_span("foo.b-r.baz", 0), Some((0, 11))); - assert_eq!(scan.domain.get_span("foo.-br.baz"), + assert_eq!(scan.domain.get_span("foo.-br.baz", 0), Some((0, 3))); - assert_eq!(scan.domain.get_span("foo.br-.baz"), + assert_eq!(scan.domain.get_span("foo.br-.baz", 0), Some((0, 6))); // matches foo.br } #[test] fn test_url() { let scan = Scan::get(); - assert_eq!(scan.url.get_span("Look at https://example.com."), + assert_eq!(scan.url.get_span("Look at https://example.com.", 0), Some((8, 27))); - assert_eq!(scan.url.get_span("Or https://en.wikipedia.org/wiki/Panda_(disambiguation)."), + assert_eq!(scan.url.get_span("Or https://en.wikipedia.org/wiki/Panda_(disambiguation).", 0), Some((3, 55))); - assert_eq!(scan.url.get_span("Or https://example.com/music/Track_(Thing_(Edited))."), + assert_eq!(scan.url.get_span("Or https://example.com/music/Track_(Thing_(Edited)).", 0), Some((3, 51))); }