Release History
See also: CHANGELOG.md on GitHub for the full changelog.
v0.3.5 (2026-08-01)
No library code changes. src/xelp.c and
src/xelp.h are byte-identical to 0.3.4 apart from the version macro,
and compiled sizes are unchanged on every target. This release fixes and
verifies the publishing pipeline, which can only be exercised by tagging.
- Fixed ESP-IDF Component Registry publishing from CI.
compote component uploadran without--namespace, defaulting to theespressifnamespace instead ofdeftio. Locally the namespace came from a~/.espressifprofile that does not exist on a CI runner, so the job had failed on every release since 0.3.2 while hand-publishing covered for it. - Excluded
tmp/from the published component.compotereads onlyfiles.exclude, not.gitignore, so packing from a working tree with scratch files produced a 1.27 MB archive instead of 209 KB. - Release notes can no longer be silently empty. Extraction
now anchors on the
## [X.Y.Z]heading for the version being released and fails the release rather than publishing placeholder text. actions/checkoutv6 → v7,actions/setup-pythonv5 → v7, and dependabot now groups all action updates into one PR.
v0.3.4 (2026-08-01)
- Fixed: history recall broken on unsigned-
chartargets (#18).mHistBrowsewas a plainchar, whose signedness is implementation-defined. Wherecharis unsigned — most ARM and embedded MCU toolchains — the-1“not browsing” sentinel stored as255and the== -1test could never fire, so users had to press UP three or more times to recall a single stored command. Reported by @XiaoMu-712. - History ring indices are now
int(mHistWrite,mHistCount,mHistBrowse,mHistSavedLen). This fixes the issue at the type level and removes the undocumentedXELP_HIST_DEPTH <= 127andXELP_CMDBUFSZ <= 128ceilings the byte-wide fields carried. - Size note: FULL-profile builds grow on targets where
charis unsigned (ARM Thumb 3463 → 3587 bytes) because compilers had been dead-code-eliminating the unreachable first-UP branch — that code now exists and runs. Targets wherecharis signed (x86, m68k, MIPS) are flat or slightly smaller. KEY and CLI profiles are byte-identical to 0.3.3, since history is not compiled into them. make tests-unsigned-char: runs the full unit suite built with-funsigned-char, now part ofmake validate. x86 and Apple ARM64 defaultcharto signed, so the build matrix had never exercised the case this bug depended on.- Test suite expanded to 51 units, 707 test cases.
v0.3.3 (2026-05-12)
- Structured argc/argv parsing (
XELP_ENABLE_ARGV): newXelpBuf2Argvfunction tokenizes a command line into a null-terminatedargv[]array with quote stripping, escape processing, and configurable max arguments (XELP_ARGV_MAX, default 8). ~530–700 bytes ARM Thumb. XELP_PARSE_ARGV(ths, args, len)convenience macro: declaresargc/argvand callsXelpBuf2Argvin one line. Recommended for new command handlers.XelpArgvInt/XelpArgvStr: extract the Nth argument as an integer or string from an argv array.XELP_ARGVBUFSZ: decouples argv scratch buffer size fromXELP_CMDBUFSZ. Defaults toXELP_CMDBUFSZ(zero change for existing users); override for variable expansion.XELP_ESC_MAP: configurable escape expansion in double-quoted arguments (\n→ newline,\t→ tab). Set to""to disable.XELP_ENTER_CR/XELP_ENTER_LF: independently enable\rand\nas ENTER in interactive input.xelpcfg.hrefactored to#ifndefguard pattern withxelp_ovr.hoverride — selective override without supplying every define.const char **argvsignatures for const-correctness.- Fuzz harness for
XelpBuf2Argv. - ESP32 BLE CLI example (
examples/esp32-ble-cli/): dual-instance xelp on USB Serial + BLE (Nordic UART Service) with Web Bluetooth terminal, cross-instance messaging, and NeoPixel RGB control. - Updated READMEs for arduino, arduino-cpp, esp32-wifi, pico-cli, and pico-cli-arduino examples with arduino-cli commands.
- Fixed
\rstripping in Web Bluetooth terminals. - Fixed
dev/size_profiles.shreporting identical sizes for all profiles. - Test suite expanded to 50 units, 693 test cases.
v0.3.2 (2026-04-26)
- Command history (
XELP_ENABLE_HISTORY): UP/DOWN arrow recall of previously entered commands. Fixed-slot ring buffer, configurable depth (XELP_HIST_DEPTH, default 4). Consecutive duplicate suppression, in-progress line save/restore. ~420 bytes ARM Thumb. XelpArgInt/XelpArgStr: direct-access convenience functions for getting the Nth argument as an integer or string span in a single call.- Fixed
XELPKEY_BKSP(0x07 BEL): addedXELPKEY_BS(0x08) so both backspace codes are accepted. - Test suite expanded to 47 units, 598 test cases.
v0.3.1 (2026-04-26)
- Function rename: all public functions renamed from
XELPprefix toXelpprefix (e.g.XELPInit→XelpInit). Types, macros, and constants retainXELP. - Single-line editing (
XELP_ENABLE_LINE_EDIT): left/right cursor movement, Home/End, insert-at-cursor, Delete. Eliminates garbage[Acharacters from arrow keys. - Multi-byte key support:
XELPKEYCODEtype and named macros (XELP_KEYCODE_UP, etc.) for ANSI escape sequences in KEY mode dispatch. - Output control:
mOutEnablegates all output;mEchoCharcontrols echo (normal, off, or mask character). XelpArgssequential argument iterator:XelpArgsInit,XelpNextTok,XelpNextInt,XelpArgCount.XelpPutcfunction for single-character output.- Fuzz testing with libFuzzer; found and fixed SEGV in
XelpTokLineXB. - Multi-instance stress test (two interleaved instances).
- Cross-build Docker tooling:
extract_size.pyfor robust multi-format size extraction. 18 targets, KEY/CLI/FULL configurations. - Internal macros converted to static functions (~28 bytes saved).
- Test suite expanded to 39 units, 531 test cases.
- BREAKING: KEY command signature changed from
fn(XELP *ths, int key)tofn(XELP *ths, XELPKEYCODE key).
v0.3.0 (2026-04-19)
- BREAKING: CLI command signature changed from
fn(const char *args, int len)tofn(XELP *ths, const char *args, int len). - BREAKING: KEY command signature changed from
fn(int key)tofn(XELP *ths, int key). - BREAKING: XelpBuf macros normalized to SCREAMING_CASE
(
XELP_XB_INIT,XELP_XB_PUTC, etc.). - Cross-compilation targets: m68k, RISC-V rv32, Xtensa LX106 added.
- Multi-instance example rewritten to use
thspointer.
v0.2.3 (2026-04-17)
- Fixed 10 bugs across xelp.h, xelp.c, xelpcfg.h
- API naming consistency: all public functions use
XELPprefix - Status codes normalized to SCREAMING_CASE
XELP_VERSIONchanged to 32-bit0x00MMmmppformat- Replaced defunct Travis CI with GitHub Actions
- Default command handlers (
mpfDefKey,mpfDefCLI) - 100% line coverage of xelp.c (269 test cases)
- Docker cross-compilation tooling, release script, documentation
v0.2.1 (2024-06-05)
- Added
XelpParseNumfor safer string-to-integer conversion - Added Arduino example
- Added
XelpBufCmpbuffer comparison with multiple modes - Added
XelpFindToktoken search function - Expanded unit test coverage
v0.2.0 (2024-02-25) — first GitHub release
- Initial public release on GitHub
- Char-at-a-time CLI parser with KEY, CLI, and THRU modes
- Tokenizer with quoted strings, escape sequences, comments
- Command dispatch for both single-key and CLI modes
- Multi-instance support, no global state
- No dynamic memory allocation
- Platform abstraction layer (5 function pointers)
- Compile-time feature selection via
xelpcfg.h - Posix example with ncurses, unit tests with jumpbug framework
- Support for 8-bit through 64-bit architectures
Project history
xelp predates its GitHub presence by roughly two decades. The original code was written around 2005–2006 as a lightweight debug shell for bare-metal embedded projects. It lived in Subversion for many years, then migrated to Bitbucket (Mercurial, later Git) as those platforms became common in embedded shops.
In 2024 the repository moved to GitHub as a public open-source project. The v0.2.0 tag marks the first GitHub release, not the first version of the library itself.
| Era | Hosting | Notes |
|---|---|---|
| ~2005–2012 | Subversion (private) | Original development for 8051 and MSP430 targets |
| 2012–2023 | Bitbucket (private) | Migrated to Mercurial, later Git; added ARM, AVR support |
| 2024–present | GitHub (public) | Open-sourced under BSD 2-Clause; CI, cross-build tooling, docs |