Implement comprehensive test suite for linenoise:
VT100 Terminal Emulator:
- Column-based UTF-8 representation with display width tracking
- Each screen cell stores complete UTF-8 characters (up to 32 bytes)
- Proper handling of wide characters (emoji, CJK) as 2-column cells
- ZWJ tracking for grapheme cluster storage
- Escape sequence parsing for cursor movement and screen clearing
Test Harness:
- Fork/pipe architecture for testing via LINENOISE_ASSUME_TTY
- Visual rendering to real terminal for debugging failed tests
- Assertion helpers for screen content and cursor position
Test Coverage (72 tests):
- Basic typing and cursor movement
- UTF-8 input and navigation (é, 中, 🎉)
- Emoji cursor movement and deletion
- Grapheme clusters (heart+VS, thumbs up+skin tone, rainbow flag)
- Horizontal scrolling with long lines
- Horizontal scrolling with UTF-8 content
- Multiline mode basics
- Multiline history navigation (regression test)
- Word/line deletion (Ctrl-W, Ctrl-U)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement comprehensive UTF-8 handling for linenoise:
Core UTF-8 support:
- Proper multi-byte character navigation (left/right arrows)
- Correct backspace deletion for multi-byte characters
- Display width calculation for cursor positioning
- Wide character support (CJK, emoji) as 2-column display
Grapheme cluster support for complex emoji:
- Variation selectors (U+FE0E, U+FE0F) for emoji style
- Skin tone modifiers (U+1F3FB-U+1F3FF)
- Zero Width Joiner (U+200D) sequences like rainbow flag
- Regional indicators for flag emoji
- Combining diacritical marks
Navigation and deletion now treat entire grapheme clusters as single
units. For example, 🏳️🌈 (14 bytes, 4 codepoints) is handled as one
character for cursor movement and backspace.
Multiline mode fixes:
- Fix history navigation regression where going from multi-row to
single-row entries left dirty rows on screen
- Save actual cursor row position (oldrpos) instead of recalculating
Updates to linenoise.c:
- Add helper functions for UTF-8 decoding and grapheme detection
- Rewrite utf8PrevCharLen/utf8NextCharLen for grapheme clusters
- Add utf8CharWidth with proper zero-width character handling
- Add utf8StrWidth with ZWJ sequence support
- Fix refreshMultiLine cursor row tracking
Updates to linenoise.h:
- Add oldrpos field to linenoiseState for multiline cursor tracking
Updates to README:
- Document UTF-8 support for multi-byte characters and emoji
- Update line count from ~850 to ~1100
- Add "Running the tests" section
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
For some reason, the old code was always cleaning the maximum number of
rows used so far while editing in multi line mode. Actually we need to
clean just the number of rows used by the last line. The old behavior
created problems in multiplexing mode, where the line is refreshed at a
different row, if the user used linenoiseHide() / show() in order to
print something. With the new behavior, all looks fine, so far.
Linenoise is used in multiple projects for enough time, let's tag this
commit with a version number as requested into issue #88, so that we
have an initial reference.
Given the nature of the library, the version was also added in the
linenoise C and header file as well so that it is easy to realize for
people having a copy embedded somewhere if they are using the latest
version.
This makes sure that if we are editing in multi-line mode a line that
actually spawns across multiple lines, the next output performed by the
application using linenoise will not overwrite the edited line.
OSX default Terminal app does not handle 999D well, the cursor will wrap
back to the previous row in the last colum, instead of ignoring the
sequence if the cursor is already at the left edge.
In order to avoid reintroducing the nG sequence that is not compatible
with base VT100 emulation and ANSI.SYS, we use CR that should be
hopefully widely supported.
This fixes a bug introduced with ANSI.SYS compatibility.
When we want to move at a specific column, we need to emit the sequence
to move the cursor to the right (after we moved 999 positions to the left)
only if we want to actually move right at least 1 position, since a
count of zero will still move the cursor one position to the right.
Github user @welash proposed a change in issue #73 in order to improve
the linenoise compatibility with older terminal emulators only able to
deal with a subset of ANSI sequences, notably ANSI.SYS and VT100
terminals strictly able to handle the original set of VT100 escape
sequences.
In order to improve the compatibility, the CHA sequence was removed and
translated to move 999 positions to the left, then move on the right
for the desired number of positions. The CHA sequence was apparently
added only with VT220, that's why it is not available everywhere.
This commit features almost exactly the change proposed in issue #73
with a small fix for a bug in multi-line editing mode introduced by the
patch.