New uselect_rip.js, to be used as a "Select Item" loadable module for RIP-capable terminals.

Currently, uselect_rip seems to work fairly well. The only remaining issue is that after displaying the RIP lightbar menu, there is sometimes a stray "!" on the screen.

There was an issue where after uselect_rip.js exited, there was a noticeable delay between a user entering a command and processing that command, but I seem to have fixed that (with Claude's help and some manual tweaking & testing).

This is a screenshot, with the stray ! in the lower-left corner (otherwise, I think it looks as expected): uselect_rip_stray_exc

Claude says it thinks it has identified the bug:

I found the root cause. It's a bug in SyncTerm's parse_rip() triggered specifically by |# (RIPNoMore) being the last command on a RIP line. Here's the chain:

The bug is in ripper.c:16373-16378 — the |# handler in the PIPE state:

if (buf[pos] == '#') {
    handle_rip_line(buf, &blen, &pos, &rip_start, maxlen, RIP_STATE_CMD);
    rip.lchars = 0;
    rip_start = pos + 1;   // ← problem
    rip.state = RIP_STATE_BANG;
    break;
}

When |# is the last command on a RIP line, handle_rip_line() takes its first branch (ripper.c:15846-15852) which truncates blen to rip_start (position 1, just the \r) and sets *pos = *blen = 1. After handle_rip_line returns, the handler sets rip_start = pos + 1 = 2, which now exceeds blen (1).

The for loop exits (pos >= blen). At the end of parse_rip() (ripper.c:16484-16494):

if (rip_start <= maxlen) {       // 2 <= 4096: TRUE
    if (rip_start <= blen) {     // 2 <= 1: FALSE → skips buffer_rip
        buffer_rip(...);
    }
    return rip_start;            // returns 2
}

rip_start (2) is returned as the output length, but blen is only 1. The buffer still physically has the original ! at position 1 (logically truncated but never overwritten). The caller reads 2 bytes — \r and ! — and passes both to cterm. The ! is rendered to the text window.

Reliable fix from uselect_rip.js: Remove RIPNoMore() from the sendRIP call. In SyncTerm's do_rip_command() (ripper.c:10879-10898), |# just sets handled = true and does nothing — removing it has zero functional impact but eliminates the trigger for this bug.

Claude had also said:

Ensure |# is never the last command on the line — If another command follows (e.g., |g0000), the | after # transitions BANG → PIPE and processing continues normally through the regular \r\n termination path, bypassing the stale rip_start value.

I have verified that in uselect_rip.js, on line 74, if I comment out or remove the RIPNoMore() call, the stray "!" doesn't appear. I'm not sure if I should remove that though, since the documentation for RIP_NO_MORE says it allows the terminal to activate mouse regions and respond to mouse clicks. That would be useful, since the RIP lightbar menu used with this update responds to mouse clicks.

Edited by Eric Oulashin

Merge request reports

Loading