Fast and reasonably complete (framebuffer) terminal emulator (Zig fork)

Terminate OSC sequences at ESC \ and BEL, skipping the text in between

It fixes the fish default prompt, which sends unsupported escape codes
even with TERM=linux

Changed files
+30 -14
src
+30 -14
src/flanterm.c
···
}
}
-
static void osc_parse(struct flanterm_context *ctx, uint8_t c) {
-
if (ctx->osc_escape && c == '\\') {
-
goto cleanup;
+
static bool osc_parse(struct flanterm_context *ctx, uint8_t c) {
+
// ESC \ terminates an OSC sequence cleanly
+
// but if ESC is followed by non-\, report failure from osc_parse and
+
// try parsing the character as another escape code
+
if (ctx->osc_escape) {
+
if (c == '\\') {
+
ctx->osc = false;
+
ctx->osc_escape = false;
+
ctx->escape = false;
+
return true;
+
} else {
+
ctx->osc_escape = false;
+
ctx->osc = false;
+
// escape stays true here
+
return false;
+
}
}
-
-
ctx->osc_escape = false;
-
switch (c) {
case 0x1b:
ctx->osc_escape = true;
-
return;
+
break;
+
// BEL is the other terminator
case '\a':
+
ctx->osc_escape = false;
+
ctx->osc = false;
+
ctx->escape = false;
+
break;
default:
break;
}
-
-
cleanup:
-
ctx->osc_escape = false;
-
ctx->osc = false;
-
ctx->escape = false;
+
return true;
}
static void control_sequence_parse(struct flanterm_context *ctx, uint8_t c) {
···
ctx->escape_offset++;
if (ctx->osc == true) {
-
osc_parse(ctx, c);
-
return;
+
// ESC \ is one of the two possible terminators of OSC sequences,
+
// so osc_parse consumes ESC.
+
// If it is then followed by \ it cleans correctly,
+
// otherwise it returns false, and it tries parsing it as another escape sequence
+
if (osc_parse(ctx, c)) {
+
return;
+
}
}
if (ctx->control_sequence == true) {