Files
bare-operating-system/packages/bare-os-coreutils/test/edit-key-parse.test.mjs
T
Raven Scott ef0301f435 fix(edit,nano): bracketed paste + bounded prompts so Save-as cannot flood
Enable xterm bracketed paste (?2004h/?2004l), parse ESC[200~…201~ as a single
paste event, insert paste in the buffer with one undo step, and replace
prompt input with first-line sanitized text capped by BARE_EDIT_MAX_PROMPT.
Cap typed prompt length for terminals without bracketed paste. Extend tests and
rebuild kernel /bin edit and nano bundles.
2026-04-21 18:45:55 -04:00

109 lines
3.6 KiB
JavaScript

/**
* Loads lib/edit-key-parse.js in an isolated function scope (same source as /bin/edit preamble).
*/
import assert from 'node:assert/strict'
import { readFileSync } from 'node:fs'
import { dirname, join } from 'node:path'
import { fileURLToPath } from 'node:url'
const __dirname = dirname(fileURLToPath(import.meta.url))
const parseSrc = readFileSync(join(__dirname, '../lib/edit-key-parse.js'), 'utf8')
const hook = {}
new Function(
'exports',
`${parseSrc}\nexports.bareEditTryConsumeKey = bareEditTryConsumeKey;\nexports.bareEditTryConsumeBracketedPaste = bareEditTryConsumeBracketedPaste;\nexports.bareEditFinalizeBracketedPasteOnEof = bareEditFinalizeBracketedPasteOnEof;`
)(hook)
const {
bareEditTryConsumeKey,
bareEditTryConsumeBracketedPaste,
bareEditFinalizeBracketedPasteOnEof
} = hook
function consumeAll(bytes) {
const q = [...bytes]
const out = []
while (q.length) {
const ev = bareEditTryConsumeKey(q)
assert.ok(ev, 'expected complete key, queue=' + JSON.stringify(q))
out.push(ev)
}
return out
}
assert.equal(bareEditTryConsumeKey([97])?.type, 'key')
assert.equal(bareEditTryConsumeKey([97])?.ch, 'a')
const upCsi = consumeAll([27, 91, 65])
assert.deepEqual(upCsi, [{ type: 'nav', key: 'up' }])
const upCsiNum = consumeAll([27, 91, 49, 59, 53, 65])
assert.deepEqual(upCsiNum, [{ type: 'nav', key: 'up' }])
const leftCsi = consumeAll([27, 91, 68])
assert.deepEqual(leftCsi, [{ type: 'nav', key: 'left' }])
const stabCsi = consumeAll([27, 91, 90])
assert.deepEqual(stabCsi, [{ type: 'nav', key: 'stab' }])
const stabCsiMod = consumeAll([27, 91, 49, 59, 50, 90])
assert.deepEqual(stabCsiMod, [{ type: 'nav', key: 'stab' }])
const tabKey = consumeAll([9])
assert.deepEqual(tabKey, [{ type: 'key', ch: '\t' }])
const ss3Up = consumeAll([27, 79, 65])
assert.deepEqual(ss3Up, [{ type: 'nav', key: 'up' }])
const ss3Left = consumeAll([27, 79, 68])
assert.deepEqual(ss3Left, [{ type: 'nav', key: 'left' }])
const del = consumeAll([27, 91, 51, 126])
assert.deepEqual(del, [{ type: 'ctrl', code: 'delete' }])
/* ESC must not be consumed as generic ctrl before CSI: order test */
const q = [27, 91, 66]
const ev1 = bareEditTryConsumeKey(q)
assert.deepEqual(ev1, { type: 'nav', key: 'down' })
assert.equal(q.length, 0)
/* Incomplete CSI waits for more bytes */
const q2 = [27, 91]
assert.equal(bareEditTryConsumeKey(q2), null)
assert.deepEqual(q2, [27, 91])
q2.push(67)
const ev2 = bareEditTryConsumeKey(q2)
assert.deepEqual(ev2, { type: 'nav', key: 'right' })
/** ESC [ 200 ~ */
const BP_START = [27, 91, 50, 48, 48, 126]
/** ESC [ 201 ~ */
const BP_END = [27, 91, 50, 48, 49, 126]
/* Incomplete bracketed paste waits without consuming */
const partial = [...BP_START.slice(0, 4)]
assert.equal(bareEditTryConsumeBracketedPaste(partial), null)
assert.deepEqual(partial, BP_START.slice(0, 4))
/* Complete bracketed paste returns inner UTF-8 text */
const hello = [104, 101, 108, 108, 111]
const qPaste = [...BP_START, ...hello, ...BP_END, 97]
assert.equal(bareEditTryConsumeBracketedPaste(qPaste), 'hello')
assert.deepEqual(qPaste, [97])
const evLetter = bareEditTryConsumeKey(qPaste)
assert.deepEqual(evLetter, { type: 'key', ch: 'a' })
/* Inner € (UTF-8) decodes correctly */
const euro = [0xe2, 0x82, 0xac]
const qEuro = [...BP_START, ...euro, ...BP_END]
assert.equal(bareEditTryConsumeBracketedPaste(qEuro), '\u20ac')
assert.equal(qEuro.length, 0)
/* EOF finalize: START without END yields inner text */
const qEof = [...BP_START, ...hello]
assert.equal(bareEditFinalizeBracketedPasteOnEof(qEof), 'hello')
assert.equal(qEof.length, 0)
console.log('edit-key-parse tests ok')