Fix #3407: add text.unix_word_rubout

This commit is contained in:
Oliver Blanthorn 2026-07-25 08:04:31 +02:00
parent 91f1ff22b1
commit 8ed0f11d59
No known key found for this signature in database
GPG key ID: 2BB8C36BB504BFF3
2 changed files with 47 additions and 1 deletions

View file

@ -335,6 +335,25 @@ export const backward_kill_word = wrap_input(
}), }),
) )
/** Deletes back to the previous sequence of letters, or deletes the selection. */
export const unix_word_rubout = wrap_input(
needs_text((text, selectionStart, selectionEnd) => {
if (selectionEnd === 0) return [null, selectionStart, null]
let deletionStart =
selectionStart === selectionEnd
? text
.substring(0, selectionStart)
.search(/[a-zA-Z]+[^a-zA-Z]*$/)
: selectionStart
if (deletionStart === -1) deletionStart = 0
return [
text.substring(0, deletionStart) + text.substring(selectionEnd),
deletionStart,
null,
]
}),
)
/** /**
* Behaves like readline's [beginning_of_line](http://web.mit.edu/gnu/doc/html/rlman_1.html#SEC12). Moves the caret to the right of the first newline character found at the left of the caret. If no newline can be found, move the caret to the beginning of the text. * Behaves like readline's [beginning_of_line](http://web.mit.edu/gnu/doc/html/rlman_1.html#SEC12). Moves the caret to the right of the first newline character found at the left of the caret. If no newline can be found, move the caret to the beginning of the text.
**/ **/

View file

@ -1,4 +1,8 @@
import { beginning_of_line } from "@src/lib/editor" import {
backward_kill_word,
beginning_of_line,
unix_word_rubout,
} from "@src/lib/editor"
test("beginning_of_line does not expose an intermediate selection", () => { test("beginning_of_line does not expose an intermediate selection", () => {
const input = document.createElement("input") const input = document.createElement("input")
@ -23,3 +27,26 @@ test("beginning_of_line does not expose an intermediate selection", () => {
expect(observedSelections).not.toContainEqual([0, 5]) expect(observedSelections).not.toContainEqual([0, 5])
expect([input.selectionStart, input.selectionEnd]).toEqual([0, 0]) expect([input.selectionStart, input.selectionEnd]).toEqual([0, 0])
}) })
test("unix_word_rubout uses letter boundaries", () => {
const rubout = (value: string, start = value.length, end = start) => {
const input = document.createElement("input")
input.value = value
input.setSelectionRange(start, end)
unix_word_rubout(input)
return [input.value, input.selectionStart, input.selectionEnd]
}
expect(rubout("some-text-here")).toEqual(["some-text-", 10, 10])
expect(rubout("some-text-here ")).toEqual(["some-text-", 10, 10])
expect(rubout("---")).toEqual(["", 0, 0])
expect(rubout(" ")).toEqual(["", 0, 0])
expect(rubout("some-text-here", 5, 9)).toEqual(["some--here", 5, 5])
expect(rubout("some-text-here", 0)).toEqual(["some-text-here", 0, 0])
const input = document.createElement("input")
input.value = "some-text-here"
input.setSelectionRange(input.value.length, input.value.length)
backward_kill_word(input)
expect(input.value).toBe("")
})