1
0
Fork 0
forked from fun/fun

Added backward and forward navigation in the REPL to navigate within a typed string.

This commit is contained in:
Johannes Findeisen 2025-09-27 11:14:37 +02:00
commit c8d3fbea51
2 changed files with 41 additions and 18 deletions

View file

@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.16)
project(fun VERSION 0.5.0 LANGUAGES C)
project(fun VERSION 0.5.1 LANGUAGES C)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)

View file

@ -299,15 +299,20 @@ static int read_line_edit(char *out, size_t out_cap, const char *prompt) {
}
size_t len = 0;
size_t pos = 0; /* cursor position in [0..len] */
int hist_pos = rl_count; /* rl_count means "editing current input", 0..rl_count-1 indexes history entries */
char saved_current[4096];
int has_saved = 0;
#define RL_REDRAW() do { \
#define RL_REDRAW_POS() do { \
fputc('\r', stdout); \
if (prompt) fputs(prompt, stdout); \
fwrite(out, 1, len, stdout); \
fputs("\x1b[K", stdout); \
if (pos < len) { \
size_t back = (size_t)(len - pos); \
if (back > 0) fprintf(stdout, "\x1b[%zuD", back); \
} \
fflush(stdout); \
} while(0)
@ -346,7 +351,8 @@ static int read_line_edit(char *out, size_t out_cap, const char *prompt) {
memcpy(out, h, hl);
out[hl] = '\0';
len = hl;
RL_REDRAW();
pos = len;
RL_REDRAW_POS();
} else {
fputc('\a', stdout); fflush(stdout);
}
@ -372,42 +378,59 @@ static int read_line_edit(char *out, size_t out_cap, const char *prompt) {
out[hl] = '\0';
len = hl;
}
RL_REDRAW();
pos = len;
RL_REDRAW_POS();
} else {
fputc('\a', stdout); fflush(stdout);
}
} else if (c2 == 'C') { /* Right */
if (pos < len) { pos++; fputs("\x1b[C", stdout); fflush(stdout); }
else { fputc('\a', stdout); fflush(stdout); }
} else if (c2 == 'D') { /* Left */
if (pos > 0) { pos--; fputs("\x1b[D", stdout); fflush(stdout); }
else { fputc('\a', stdout); fflush(stdout); }
} else {
/* ignore other CSI sequences */
}
}
} else if (ch == 127 || ch == 8) {
/* backspace */
if (len > 0) {
/* backspace: delete char left of cursor */
if (pos > 0) {
/* shift tail left */
memmove(out + pos - 1, out + pos, len - pos);
len--;
pos--;
out[len] = '\0';
/* efficient backspace */
fputs("\b \b", stdout);
fflush(stdout);
RL_REDRAW_POS();
} else {
fputc('\a', stdout);
fflush(stdout);
}
} else if (ch == '\t') {
/* only attempt completion for ':load ' */
out[len] = '\0';
size_t newlen = len;
if (complete_load_path(out, &newlen)) {
len = newlen;
/* only attempt completion for ':load ' when at end of line */
if (pos != len) {
fputc('\a', stdout);
fflush(stdout);
} else {
out[len] = '\0';
size_t newlen = len;
if (complete_load_path(out, &newlen)) {
len = newlen;
pos = len;
}
RL_REDRAW_POS();
}
RL_REDRAW();
} else if (ch >= 32 && ch <= 126) {
if (len + 1 < out_cap) {
out[len++] = (char)ch;
/* insert at cursor */
memmove(out + pos + 1, out + pos, len - pos);
out[pos] = (char)ch;
len++;
pos++;
out[len] = '\0';
fputc(ch, stdout);
fflush(stdout);
/* when typing after navigating history, we are editing current line; reset hist_pos to end */
hist_pos = rl_count;
RL_REDRAW_POS();
} else {
fputc('\a', stdout);
fflush(stdout);