Shell: add bareboness utf8 support

This should work as long as TTY provides only valid utf8.
If the utf is invalid, assertion fails and the shell dies.
This commit is contained in:
Bananymous 2023-06-05 18:53:52 +03:00
parent 90e48970e6
commit 2f2c298c68
1 changed files with 49 additions and 18 deletions

View File

@ -106,7 +106,7 @@ int main(int argc, char** argv)
size_t index = 0; size_t index = 0;
size_t col = 0; size_t col = 0;
bool got_csi = false; int waiting_utf8 = 0;
BAN::String prompt("\e[32muser@host\e[m:\e[34m/\e[m$ "sv); BAN::String prompt("\e[32muser@host\e[m:\e[34m/\e[m$ "sv);
fprintf(stdout, "%s", prompt.data()); fprintf(stdout, "%s", prompt.data());
@ -114,30 +114,62 @@ int main(int argc, char** argv)
while (true) while (true)
{ {
char c; uint8_t ch;
fread(&c, 1, sizeof(char), stdin); fread(&ch, 1, sizeof(char), stdin);
switch (c) if (waiting_utf8 > 0)
{
waiting_utf8--;
ASSERT((ch & 0xC0) == 0x80);
fputc(ch, stdout);
MUST(buffers[index].insert(ch, col++));
if (waiting_utf8 == 0)
{
fprintf(stdout, "\e[s%s\e[u", buffers[index].data() + col);
fflush(stdout);
}
continue;
}
else if (ch & 0x80)
{
if ((ch & 0xE0) == 0xC0)
waiting_utf8 = 1;
else if ((ch & 0xF0) == 0xE0)
waiting_utf8 = 2;
else if ((ch & 0xF8) == 0xF0)
waiting_utf8 = 3;
else
ASSERT_NOT_REACHED();
fputc(ch, stdout);
MUST(buffers[index].insert(ch, col++));
continue;
}
switch (ch)
{ {
case '\e': case '\e':
fread(&c, 1, sizeof(char), stdin); fread(&ch, 1, sizeof(char), stdin);
if (c != '[') if (ch != '[')
break; break;
fread(&c, 1, sizeof(char), stdin); fread(&ch, 1, sizeof(char), stdin);
switch (c) switch (ch)
{ {
case 'A': if (index > 0) { index--; col = buffers[index].size(); fprintf(stdout, "\e[%dG%s\e[K", prompt_length(prompt) + 1, buffers[index].data()); fflush(stdout); } break; case 'A': if (index > 0) { index--; col = buffers[index].size(); fprintf(stdout, "\e[%dG%s\e[K", prompt_length(prompt) + 1, buffers[index].data()); fflush(stdout); } break;
case 'B': if (index < buffers.size() - 1) { index++; col = buffers[index].size(); fprintf(stdout, "\e[%dG%s\e[K", prompt_length(prompt) + 1, buffers[index].data()); fflush(stdout); } break; case 'B': if (index < buffers.size() - 1) { index++; col = buffers[index].size(); fprintf(stdout, "\e[%dG%s\e[K", prompt_length(prompt) + 1, buffers[index].data()); fflush(stdout); } break;
case 'C': if (col < buffers[index].size() - 1) { col++; fprintf(stdout, "\e[C"); fflush(stdout); } break; case 'C': if (col < buffers[index].size()) { col++; while ((buffers[index][col - 1] & 0xC0) == 0x80) col++; fprintf(stdout, "\e[C"); fflush(stdout); } break;
case 'D': if (col > 0) { col--; fprintf(stdout, "\e[D"); fflush(stdout); } break; case 'D': if (col > 0) { while ((buffers[index][col - 1] & 0xC0) == 0x80) col--; col--; fprintf(stdout, "\e[D"); fflush(stdout); } break;
} }
break; break;
case '\b': case '\b':
if (col > 0) if (col > 0)
{ {
col--; while ((buffers[index][col - 1] & 0xC0) == 0x80)
buffers[index].remove(col); buffers[index].remove(--col);
fprintf(stdout, "\b\e[s%s\e[K\e[u", buffers[index].data() + col); buffers[index].remove(--col);
fprintf(stdout, "\b\e[s%s \e[u", buffers[index].data() + col);
fflush(stdout); fflush(stdout);
} }
break; break;
@ -156,10 +188,9 @@ int main(int argc, char** argv)
col = 0; col = 0;
break; break;
default: default:
MUST(buffers[index].push_back(c)); MUST(buffers[index].insert(ch, col++));
fprintf(stdout, "%s \b", buffers[index].data() + col); fprintf(stdout, "%c\e[s%s\e[u", ch, buffers[index].data() + col);
fflush(stdout); fflush(stdout);
col++;
break; break;
} }
} }