Skip to content

Commit 8253be7

Browse files
oz-agentwarp-agent
andcommitted
Pick the fallback search word deterministically
Splitting the stripped line on whitespace left inline syntax attached to the words, so a link's label never produced a usable term, and the tie-break between equally long words fell out of `max_by_key` returning the last maximum. Split on non-alphanumerics and keep the earliest of the longest words. Co-Authored-By: Warp Agent <agent@warp.dev>
1 parent 9ff2ad8 commit 8253be7

2 files changed

Lines changed: 25 additions & 6 deletions

File tree

app/src/notebooks/file/mod.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1354,10 +1354,19 @@ fn rendered_search_terms_for_source_line(markdown: &str, line_num: usize) -> Vec
13541354
};
13551355

13561356
let stripped = strip_markdown_syntax(line);
1357+
// Split on non-alphanumerics rather than whitespace so a word survives the
1358+
// inline syntax `strip_markdown_syntax` leaves behind, such as a link's
1359+
// `[label](target)`. Ties keep the earliest word, so the chosen term does
1360+
// not hinge on which extreme the iterator happens to return.
13571361
let longest_word = stripped
1358-
.split_whitespace()
1359-
.map(|word| word.trim_matches(|c: char| !c.is_alphanumeric()))
1360-
.max_by_key(|word| word.chars().count())
1362+
.split(|c: char| !c.is_alphanumeric())
1363+
.reduce(|longest, word| {
1364+
if word.chars().count() > longest.chars().count() {
1365+
word
1366+
} else {
1367+
longest
1368+
}
1369+
})
13611370
.unwrap_or_default();
13621371

13631372
[line.trim(), stripped.as_str(), longest_word]

app/src/notebooks/file/mod_tests.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -451,15 +451,15 @@ fn test_rendered_search_terms_for_source_line() {
451451
let markdown = "# Heading one\n\n- a **bold** item\n\n```rust\nlet total = compute();\n```\n\n> quoted line here\n";
452452

453453
// Headings, list bullets and emphasis are stripped so the term matches the
454-
// rendered text; the longest word is kept as a last resort. Equally long
455-
// words are just as usable as each other, so the last one wins.
454+
// rendered text; the longest word is kept as a last resort, and equally
455+
// long words resolve to the earliest one.
456456
assert_eq!(
457457
rendered_search_terms_for_source_line(markdown, 1),
458458
["# Heading one", "Heading one", "Heading"]
459459
);
460460
assert_eq!(
461461
rendered_search_terms_for_source_line(markdown, 3),
462-
["- a **bold** item", "a bold item", "item"]
462+
["- a **bold** item", "a bold item", "bold"]
463463
);
464464
assert_eq!(
465465
rendered_search_terms_for_source_line(markdown, 9),
@@ -472,6 +472,16 @@ fn test_rendered_search_terms_for_source_line() {
472472
["let total = compute();", "compute"]
473473
);
474474

475+
// A link's visible label survives, even though the surrounding syntax does
476+
// not, because words are split on non-alphanumerics.
477+
assert_eq!(
478+
rendered_search_terms_for_source_line("See [the configuration guide](./config.md).", 1),
479+
[
480+
"See [the configuration guide](./config.md).",
481+
"configuration"
482+
]
483+
);
484+
475485
// Nothing visible to search for.
476486
assert!(rendered_search_terms_for_source_line(markdown, 2).is_empty());
477487
assert!(rendered_search_terms_for_source_line(markdown, 999).is_empty());

0 commit comments

Comments
 (0)