Fix #2100: w should not collapse selection in visual mode

This commit is contained in:
Oliver Blanthorn 2026-07-22 20:32:20 +02:00
parent 6b1376df37
commit 4df421beb4
No known key found for this signature in database
GPG key ID: 2BB8C36BB504BFF3
3 changed files with 47 additions and 1 deletions

View file

@ -441,7 +441,7 @@ export class default_config {
tri.visual.extendByCharacter(sel, "backward");
`,
e: 'js tri.dom.getSelection().modify("extend","forward","word")',
w: 'js let s=tri.dom.getSelection(); s.modify("extend","forward","word"); s.modify("extend","forward","word"); s.modify("extend","backward","word"); s.modify("extend","forward","character")',
w: "js tri.visual.extendByWord(tri.dom.getSelection())",
b: 'js let s=tri.dom.getSelection(); s.modify("extend","backward","character"); s.modify("extend","backward","word"); s.modify("extend","forward","character")',
j: 'js tri.dom.getSelection().modify("extend","forward","line")',
q: "composite js tri.dom.getSelection().toString() | text2qr --timeout 5",

26
src/lib/visual.test.ts Normal file
View file

@ -0,0 +1,26 @@
import { extendByWord } from "@src/lib/visual"
test("word movement restores the last selection at its boundary", () => {
const node = document.createTextNode("one two")
document.body.appendChild(node)
const selection = getSelection()
selection.setBaseAndExtent(node, 5, node, 1)
const focusOffsets = [3, 7, 4, 5]
let moves = 0
const modify = jest.fn(() => {
selection.setBaseAndExtent(node, 5, node, focusOffsets[moves++])
})
selection.modify = modify
extendByWord(selection)
expect(modify.mock.calls).toEqual([
["extend", "forward", "word"],
["extend", "forward", "word"],
["extend", "backward", "word"],
["extend", "forward", "character"],
])
expect(selection.isCollapsed).toBe(false)
expect(selection.anchorOffset).toBe(5)
expect(selection.focusOffset).toBe(4)
})

View file

@ -57,3 +57,23 @@ export function extendByCharacter(
reverseSelection(selection)
selection.modify("extend", direction, "character")
}
export function extendByWord(selection: Selection): void {
if (!selection.focusNode) return
selection.modify("extend", "forward", "word")
selection.modify("extend", "forward", "word")
selection.modify("extend", "backward", "word")
const oldFocusNode = selection.focusNode
const oldFocusOffset = selection.focusOffset
const oldAnchorNode = selection.anchorNode
const oldAnchorOffset = selection.anchorOffset
selection.modify("extend", "forward", "character")
if (!selection.isCollapsed) return
selection.setBaseAndExtent(
oldAnchorNode,
oldAnchorOffset,
oldFocusNode,
oldFocusOffset,
)
}