Take in as much of a Regular's outer punctuation as a reason spells
A mention extended over a stored name's optional outer punctuation only when the reason spelled all of it, so "Like your Beef Chili!" left the mention of "Beef Chili!!" at "Beef Chili" while "Chili!" extended through its "!", and neither covered the other. Extend through the longest portion of the punctuation the reason spells after which the border still holds, at either end of the name. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -319,10 +319,11 @@ func drop(q SideQuest, regulars regularNames, known *harness.Deduper, kept []Sid
|
||||
// Chili-inspired" and "Beef Chili's" mention "Beef Chili" while "Beef
|
||||
// Chilis" does not, nor does "Cafe" with a combining accent after it
|
||||
// mention "Cafe". Punctuation at either end of the name, with any spacing
|
||||
// beside it, is optional, and a mention takes it in only where text spells
|
||||
// it, spaced in any way, and the border still holds after it: "Easy Beef
|
||||
// Chili!" is mentioned by "Easy Beef Chili." too, by "Easy Beef Chili !"
|
||||
// with its "!", and by "Easy Beef Chili!x" without its "!". A
|
||||
// beside it, is optional, and a mention takes in as much of it as text
|
||||
// spells, spaced in any way, with the border still holding after it: "Easy
|
||||
// Beef Chili!" is mentioned by "Easy Beef Chili." too, by "Easy Beef Chili
|
||||
// !" with its "!", and by "Easy Beef Chili!x" without its "!", and "Beef
|
||||
// Chili!!" by "Beef Chili!" with one "!". A
|
||||
// combining mark is part of its letter, never punctuation. A mention names
|
||||
// its Regular unless a mention of a different Regular covers the same text
|
||||
// or more, so "Your Easy Beef Chili." names "Easy Beef Chili" and not "Beef
|
||||
@@ -357,12 +358,8 @@ func (r regularNames) named(text string) []string {
|
||||
if !bordered(start, end) {
|
||||
continue
|
||||
}
|
||||
if s := spelledBefore(text, start, lead); s >= 0 && bordered(s, end) {
|
||||
start = s
|
||||
}
|
||||
if e := spelledAfter(text, end, trail); e >= 0 && bordered(start, e) {
|
||||
end = e
|
||||
}
|
||||
start = spelledBefore(text, start, lead, func(s int) bool { return bordered(s, end) })
|
||||
end = spelledAfter(text, end, trail, func(e int) bool { return bordered(start, e) })
|
||||
mentions = append(mentions, mention{name, start, end})
|
||||
}
|
||||
}
|
||||
@@ -378,31 +375,41 @@ func (r regularNames) named(text string) []string {
|
||||
return names
|
||||
}
|
||||
|
||||
// spelledAfter returns where outer ends when text spells it from at,
|
||||
// ignoring spacing, or -1 when text does not.
|
||||
func spelledAfter(text string, at int, outer string) int {
|
||||
// spelledAfter returns where the longest start of outer that text spells
|
||||
// from at ends, ignoring spacing, among those after which bordered holds,
|
||||
// or at when there are none.
|
||||
func spelledAfter(text string, at int, outer string, bordered func(int) bool) int {
|
||||
end := at
|
||||
for _, c := range strings.Join(strings.Fields(outer), "") {
|
||||
at = len(text) - len(strings.TrimLeftFunc(text[at:], unicode.IsSpace))
|
||||
if !strings.HasPrefix(text[at:], string(c)) {
|
||||
return -1
|
||||
break
|
||||
}
|
||||
at += utf8.RuneLen(c)
|
||||
if bordered(at) {
|
||||
end = at
|
||||
}
|
||||
}
|
||||
return at
|
||||
return end
|
||||
}
|
||||
|
||||
// spelledBefore returns where outer starts when text spells it up to at,
|
||||
// ignoring spacing, or -1 when text does not.
|
||||
func spelledBefore(text string, at int, outer string) int {
|
||||
// spelledBefore returns where the longest end of outer that text spells up
|
||||
// to at starts, ignoring spacing, among those before which bordered holds,
|
||||
// or at when there are none.
|
||||
func spelledBefore(text string, at int, outer string, bordered func(int) bool) int {
|
||||
start := at
|
||||
punct := []rune(strings.Join(strings.Fields(outer), ""))
|
||||
for i := len(punct) - 1; i >= 0; i-- {
|
||||
at = len(strings.TrimRightFunc(text[:at], unicode.IsSpace))
|
||||
if !strings.HasSuffix(text[:at], string(punct[i])) {
|
||||
return -1
|
||||
break
|
||||
}
|
||||
at -= utf8.RuneLen(punct[i])
|
||||
if bordered(at) {
|
||||
start = at
|
||||
}
|
||||
}
|
||||
return at
|
||||
return start
|
||||
}
|
||||
|
||||
// isWord reports whether c is a letter, a mark on one or a digit.
|
||||
|
||||
@@ -258,6 +258,11 @@ func TestSuggestSideQuestsReasonMentionRule(t *testing.T) {
|
||||
"spacing after punctuation": {[]string{"¡Beef Chili"}, "Your ¡ Beef Chili is our inspiration.", "¡Beef Chili", ""},
|
||||
"stored spacing left off": {[]string{"Beef Chili !", "Chili!"}, "Like your Beef Chili!", "Beef Chili !", ""},
|
||||
"inside unspaced punctuation": {[]string{"Beef Chili !", "Chili!"}, "Like your Beef Chili!", "Chili!", none},
|
||||
"stored punctuation partly": {[]string{"Beef Chili!!", "Chili!"}, "Like your Beef Chili!", "Beef Chili!!", ""},
|
||||
"inside partial punctuation": {[]string{"Beef Chili!!", "Chili!"}, "Like your Beef Chili!", "Chili!", none},
|
||||
"partly then a letter": {[]string{"Beef Chili!!", "Chili!"}, "Your Beef Chili!!X is our inspiration.", "Chili!", none},
|
||||
"leading punctuation partly": {[]string{"¡¡Beef Chili", "¡Beef"}, "Like your ¡Beef Chili.", "¡¡Beef Chili", ""},
|
||||
"inside partial leading": {[]string{"¡¡Beef Chili", "¡Beef"}, "Like your ¡Beef Chili.", "¡Beef", none},
|
||||
"stored symbol left off": {[]string{"Green Chili 🌶"}, "Like your Green Chili, gone green.", "Green Chili 🌶", none},
|
||||
"stored accent left off": {[]string{"Chicken Cafe\u0301"}, "Like your Chicken Cafe, gone green.", "Chicken Cafe\u0301", none},
|
||||
"accent written after name": {[]string{"Chicken Cafe"}, "Like your Chicken Cafe\u0301, gone green.", "Chicken Cafe", none},
|
||||
|
||||
Reference in New Issue
Block a user