Added Ctrl+left/right arrow key navigation (0.5.2)
This commit is contained in:
parent
ad70918041
commit
d25c4b616d
2 changed files with 65 additions and 12 deletions
|
|
@ -1,5 +1,5 @@
|
||||||
cmake_minimum_required(VERSION 3.16)
|
cmake_minimum_required(VERSION 3.16)
|
||||||
project(fun VERSION 0.5.1 LANGUAGES C)
|
project(fun VERSION 0.5.2 LANGUAGES C)
|
||||||
|
|
||||||
set(CMAKE_C_STANDARD 11)
|
set(CMAKE_C_STANDARD 11)
|
||||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||||
|
|
|
||||||
75
src/fun.c
75
src/fun.c
|
|
@ -41,6 +41,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
/* REPL line editing and completion (POSIX) */
|
/* REPL line editing and completion (POSIX) */
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
|
@ -335,9 +336,48 @@ static int read_line_edit(char *out, size_t out_cap, const char *prompt) {
|
||||||
} else if (ch == 27) { /* ESC sequence */
|
} else if (ch == 27) { /* ESC sequence */
|
||||||
int c1 = getchar();
|
int c1 = getchar();
|
||||||
if (c1 == '[') {
|
if (c1 == '[') {
|
||||||
int c2 = getchar();
|
/* Parse CSI parameters (e.g., "1;5D") until a final byte A-Z or ~ */
|
||||||
if (c2 == 'A') { /* Up */
|
char params[16];
|
||||||
if (!has_saved) { /* save current line to restore on Down past newest */
|
int pi = 0;
|
||||||
|
int final = 0;
|
||||||
|
for (;;) {
|
||||||
|
int cx = getchar();
|
||||||
|
if (cx == EOF) break;
|
||||||
|
if ((cx >= 'A' && cx <= 'Z') || (cx >= 'a' && cx <= 'z') || cx == '~') {
|
||||||
|
final = cx;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (pi + 1 < (int)sizeof(params)) {
|
||||||
|
params[pi++] = (char)cx;
|
||||||
|
params[pi] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Detect Ctrl modifier: presence of ";5" or "5" as a parameter */
|
||||||
|
int ctrl = 0;
|
||||||
|
if (pi > 0) {
|
||||||
|
if (strstr(params, ";5") != NULL || strcmp(params, "5") == 0 || strstr(params, "1;5") != NULL) {
|
||||||
|
ctrl = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Helpers for word-jumps: words are runs of non-space chars */
|
||||||
|
auto void word_left(void) {
|
||||||
|
if (pos == 0) return;
|
||||||
|
/* skip spaces left */
|
||||||
|
while (pos > 0 && out[pos - 1] == ' ') pos--;
|
||||||
|
/* skip non-spaces left */
|
||||||
|
while (pos > 0 && out[pos - 1] != ' ') pos--;
|
||||||
|
};
|
||||||
|
auto void word_right(void) {
|
||||||
|
if (pos >= len) return;
|
||||||
|
/* skip non-spaces right */
|
||||||
|
while (pos < len && out[pos] != ' ') pos++;
|
||||||
|
/* skip spaces right */
|
||||||
|
while (pos < len && out[pos] == ' ') pos++;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (final == 'A') { /* Up */
|
||||||
|
if (!has_saved) {
|
||||||
size_t sl = len < sizeof(saved_current) - 1 ? len : sizeof(saved_current) - 1;
|
size_t sl = len < sizeof(saved_current) - 1 ? len : sizeof(saved_current) - 1;
|
||||||
memcpy(saved_current, out, sl);
|
memcpy(saved_current, out, sl);
|
||||||
saved_current[sl] = '\0';
|
saved_current[sl] = '\0';
|
||||||
|
|
@ -356,11 +396,10 @@ static int read_line_edit(char *out, size_t out_cap, const char *prompt) {
|
||||||
} else {
|
} else {
|
||||||
fputc('\a', stdout); fflush(stdout);
|
fputc('\a', stdout); fflush(stdout);
|
||||||
}
|
}
|
||||||
} else if (c2 == 'B') { /* Down */
|
} else if (final == 'B') { /* Down */
|
||||||
if (hist_pos < rl_count) {
|
if (hist_pos < rl_count) {
|
||||||
hist_pos++;
|
hist_pos++;
|
||||||
if (hist_pos == rl_count) {
|
if (hist_pos == rl_count) {
|
||||||
/* restore saved current */
|
|
||||||
if (has_saved) {
|
if (has_saved) {
|
||||||
size_t hl = strlen(saved_current);
|
size_t hl = strlen(saved_current);
|
||||||
if (hl >= out_cap) hl = out_cap - 1;
|
if (hl >= out_cap) hl = out_cap - 1;
|
||||||
|
|
@ -383,12 +422,26 @@ static int read_line_edit(char *out, size_t out_cap, const char *prompt) {
|
||||||
} else {
|
} else {
|
||||||
fputc('\a', stdout); fflush(stdout);
|
fputc('\a', stdout); fflush(stdout);
|
||||||
}
|
}
|
||||||
} else if (c2 == 'C') { /* Right */
|
} else if (final == 'C') { /* Right */
|
||||||
if (pos < len) { pos++; fputs("\x1b[C", stdout); fflush(stdout); }
|
if (ctrl) {
|
||||||
else { fputc('\a', stdout); fflush(stdout); }
|
size_t old = pos;
|
||||||
} else if (c2 == 'D') { /* Left */
|
word_right();
|
||||||
if (pos > 0) { pos--; fputs("\x1b[D", stdout); fflush(stdout); }
|
if (pos != old) RL_REDRAW_POS();
|
||||||
else { fputc('\a', stdout); fflush(stdout); }
|
else { fputc('\a', stdout); fflush(stdout); }
|
||||||
|
} else {
|
||||||
|
if (pos < len) { pos++; fputs("\x1b[C", stdout); fflush(stdout); }
|
||||||
|
else { fputc('\a', stdout); fflush(stdout); }
|
||||||
|
}
|
||||||
|
} else if (final == 'D') { /* Left */
|
||||||
|
if (ctrl) {
|
||||||
|
size_t old = pos;
|
||||||
|
word_left();
|
||||||
|
if (pos != old) RL_REDRAW_POS();
|
||||||
|
else { fputc('\a', stdout); fflush(stdout); }
|
||||||
|
} else {
|
||||||
|
if (pos > 0) { pos--; fputs("\x1b[D", stdout); fflush(stdout); }
|
||||||
|
else { fputc('\a', stdout); fflush(stdout); }
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* ignore other CSI sequences */
|
/* ignore other CSI sequences */
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue