In 0.6.0, EditBuffer.setText("a\fb") throws NativeError. The editor places
its cursor by display cell, and a control character took no cells, so the
cursor could not move past it or delete it. In 0.5.14, which accepted
controls, the cursor in "a\fb" could not reach column 0, Backspace stopped at
"a\f", and rendering "A\x07B\x1bC\fD" wrote raw BEL and ESC bytes to the
terminal. Rejecting the text stopped that, but every application then had to
remove these characters before it could edit a string.
In 0.6.1, editors keep control characters and show them the way Vim and
Neovim do. The text "a\fb\0c\x1bd\x85e\x7ff" shows as a^Lb^@c^[d<85>e^?f. A
C0 control or DEL is caret notation in two cells, and a C1 control is
lowercase hex in four cells. The notation changes only how the text looks. The
cursor stops before each control, one Backspace deletes it, and getText(),
undo, and selection copy return the original characters. Tab, carriage
return, and line feed work as before. Read-only text, such as
TextRenderable, still gives controls no cells.
This has one cost. An editor offset is no longer the same as a JavaScript
string width. Bun.stringWidth("\f") is 0, but ^L takes two cells. Code
that calculates editor offsets from string widths, such as code that places an
extmark after a match, must ask the buffer instead. measureText() measures
text the way the buffer lays it out, and getTextRange() converts an offset
back to a string index:
buffer.setText("\f@file")
const text = buffer.getText()
const offset = buffer.measureText(text.slice(0, text.indexOf("@"))) // 2: ^L takes two cells
buffer.getTextRange(0, offset).length // 1: the index of "@"Added
- core:
EditBuffer.measureText(text)returns the display offset at the
end oftextas the buffer would lay it out. It counts each line break as
one. See Editing buffers and views.
(#1636) - native:
ot_edit_buffer_measure_text()gives the same measurement
through the C interface. See
Editing buffers and views.
(#1636)
Changed
- core:
EditBuffer.setText(),insertText(), andreplaceText(),
TextareainitialValue,Input.value, and placeholders accept control
characters and do not throwNativeError. An editor shows C0 controls and
DEL as^@to^_and^?in two cells, and C1 controls as<80>to
<9f>in four cells. See Editing buffers and views.
(#1636) - core: Paste in
TextareaandInputkeeps control characters. It
removes terminal escape sequences, including a lone ESC and an incomplete
sequence, the same way on Bun and Node. Core no longer depends on
strip-ansi. See Editing buffers and views.
(#1636)
Fixed
- core: Extmarks and the
Inputcursor use native display offsets. As a
result, they keep the correct position in text that contains control
characters. See Editing buffers and views.
(#1636)
API changes and documentation: https://opentui.com/docs/releases/0.6.1
What's Changed
- editor: show control characters as notation by @simonklee in #1636
Full Changelog: v0.6.0...v0.6.1