Fixed incorrect cursor position if prompt contains ANSI sequences
- And added delete key handling
This commit is contained in:
parent
1101c53bf6
commit
ca08c9e3e5
1 changed files with 59 additions and 2 deletions
61
main.c
61
main.c
|
|
@ -161,6 +161,47 @@ size_t utf8_display_width(const char *buf, size_t len)
|
||||||
return width;
|
return width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t visible_width(const char *s)
|
||||||
|
{
|
||||||
|
size_t i = 0;
|
||||||
|
size_t width = 0;
|
||||||
|
|
||||||
|
while (s[i]) {
|
||||||
|
|
||||||
|
// ANSI escape sequence
|
||||||
|
if (s[i] == '\x1b' && s[i+1] == '[') {
|
||||||
|
i += 2;
|
||||||
|
|
||||||
|
while (s[i] && !((s[i] >= '@' && s[i] <= '~')))
|
||||||
|
i++;
|
||||||
|
|
||||||
|
if (s[i]) i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char c = s[i];
|
||||||
|
|
||||||
|
if ((c & 0x80) == 0) {
|
||||||
|
i += 1;
|
||||||
|
width += 1;
|
||||||
|
}
|
||||||
|
else if ((c & 0xE0) == 0xC0) {
|
||||||
|
i += 2;
|
||||||
|
width += 1;
|
||||||
|
}
|
||||||
|
else if ((c & 0xF0) == 0xE0) {
|
||||||
|
i += 3;
|
||||||
|
width += 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
i += 4;
|
||||||
|
width += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
char* __readline_interactive(char* prompt)
|
char* __readline_interactive(char* prompt)
|
||||||
{
|
{
|
||||||
enable_raw_mode();
|
enable_raw_mode();
|
||||||
|
|
@ -179,7 +220,7 @@ char* __readline_interactive(char* prompt)
|
||||||
write(STDOUT_FILENO, buf, len);
|
write(STDOUT_FILENO, buf, len);
|
||||||
|
|
||||||
swrite(STDOUT_FILENO, "\x1b[K");
|
swrite(STDOUT_FILENO, "\x1b[K");
|
||||||
size_t prompt_width = utf8_display_width(prompt, strlen(prompt));
|
size_t prompt_width = visible_width(prompt);
|
||||||
size_t cell_cursor = utf8_display_width(buf, cursor);
|
size_t cell_cursor = utf8_display_width(buf, cursor);
|
||||||
char seq[64];
|
char seq[64];
|
||||||
snprintf(seq, sizeof(seq), "\r\x1b[%zuC", prompt_width + cell_cursor);
|
snprintf(seq, sizeof(seq), "\r\x1b[%zuC", prompt_width + cell_cursor);
|
||||||
|
|
@ -193,7 +234,7 @@ char* __readline_interactive(char* prompt)
|
||||||
if (clen <= 0) continue;
|
if (clen <= 0) continue;
|
||||||
|
|
||||||
if (utf8[0] == '\x1b') {
|
if (utf8[0] == '\x1b') {
|
||||||
char seq[2];
|
char seq[3];
|
||||||
if (read(STDIN_FILENO, &seq[0], 1) != 1) continue;
|
if (read(STDIN_FILENO, &seq[0], 1) != 1) continue;
|
||||||
if (read(STDIN_FILENO, &seq[1], 1) != 1) continue;
|
if (read(STDIN_FILENO, &seq[1], 1) != 1) continue;
|
||||||
|
|
||||||
|
|
@ -208,6 +249,22 @@ char* __readline_interactive(char* prompt)
|
||||||
case 'D': // Arrow left
|
case 'D': // Arrow left
|
||||||
cursor = prev_char_start(buffer, cursor);
|
cursor = prev_char_start(buffer, cursor);
|
||||||
break;
|
break;
|
||||||
|
case '3':
|
||||||
|
if (read(STDIN_FILENO, &seq[2], 1) != 1) continue;
|
||||||
|
switch (seq[2])
|
||||||
|
{
|
||||||
|
case '~': // Delete
|
||||||
|
if (cursor < len) {
|
||||||
|
|
||||||
|
size_t next = next_char_start(buffer, len, cursor);
|
||||||
|
size_t diff = next - cursor;
|
||||||
|
|
||||||
|
memmove(buffer + cursor, buffer + next, len - next);
|
||||||
|
len -= diff;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (utf8[0] == '\r') { // enter
|
} else if (utf8[0] == '\r') { // enter
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue