109 lines
3.6 KiB
JavaScript
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/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')
|