Implement command history and input color updates

This commit is contained in:
Lluciocc 2026-04-17 11:40:11 +02:00 committed by GitHub
parent a09103e40d
commit c4562e8778
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -4,6 +4,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <syscall.h> #include <syscall.h>
#include "libc/libui.h" #include "libc/libui.h"
#include "libc/input.h"
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
@ -19,6 +20,8 @@
#define TAB_CLOSE_PAD 6 #define TAB_CLOSE_PAD 6
#define MAX_TABS 4 #define MAX_TABS 4
#define TTY_READ_CHUNK 512 #define TTY_READ_CHUNK 512
#define HISTORY_MAX 64
#define HISTORY_LINE_MAX 256
typedef struct { typedef struct {
char c; char c;
@ -38,12 +41,21 @@ typedef struct {
int cursor_col; int cursor_col;
uint32_t fg_color; uint32_t fg_color;
uint32_t bg_color; uint32_t bg_color;
uint32_t input_color;
int ansi_state; int ansi_state;
int ansi_params[8]; int ansi_params[8];
int ansi_param_count; int ansi_param_count;
int saved_row; int saved_row;
int saved_col; int saved_col;
char history[HISTORY_MAX][HISTORY_LINE_MAX];
int history_count;
int history_index;
char current_input[HISTORY_LINE_MAX];
int input_len;
} TerminalSession; } TerminalSession;
static ui_window_t g_win; static ui_window_t g_win;
@ -663,6 +675,16 @@ static void draw_session(TerminalSession *s) {
if (ch == 0) ch = ' '; if (ch == 0) ch = ' ';
color = line[col].color; color = line[col].color;
} }
if (s->scroll_offset == 0 && row == s->cursor_row) {
int cmd_len = 0;
while (cmd_len < s->input_len &&
s->current_input[cmd_len] != ' ') {
cmd_len++;
}
if (col < cmd_len) {
color = s->input_color;
}
}
char str[2] = { ch, 0 }; char str[2] = { ch, 0 };
int x = col * CHAR_W; int x = col * CHAR_W;
int y = base_y + row * g_line_h; int y = base_y + row * g_line_h;
@ -691,6 +713,10 @@ static void tab_init(TerminalSession *s, int tty_id, int bsh_pid) {
s->ansi_param_count = 0; s->ansi_param_count = 0;
s->saved_row = 0; s->saved_row = 0;
s->saved_col = 0; s->saved_col = 0;
s->history_count = 0;
s->history_index = 0;
s->input_len = 0;
s->current_input[0] = 0;
session_reset_colors(s); session_reset_colors(s);
scrollback_init(s); scrollback_init(s);
session_clear(s); session_clear(s);
@ -778,27 +804,77 @@ static int create_tab(void) {
return g_tab_count - 1; return g_tab_count - 1;
} }
// checks if a command exist in /bin
static bool command_exists(const char *cmd) {
char path[256];
// test /bin/cmd
path[0] = 0;
str_append(path, "/bin/", sizeof(path));
str_append(path, cmd, sizeof(path));
if (sys_exists(path)) return true;
// test /bin/cmd.elf
path[0] = 0;
str_append(path, "/bin/", sizeof(path));
str_append(path, cmd, sizeof(path));
str_append(path, ".elf", sizeof(path));
if (sys_exists(path)) return true;
return false;
}
static void update_input_color(TerminalSession *s) {
if (s->input_len == 0) {
s->input_color = 0xFFFFFFFF;
return;
}
char cmd[64];
int i = 0;
while (i < s->input_len &&
s->current_input[i] != ' ' &&
i < 63) {
cmd[i] = s->current_input[i];
i++;
}
cmd[i] = 0;
if (command_exists(cmd)) {
s->input_color = 0xFF55FF55; // green
} else {
s->input_color = 0xFFFF5555; // red
}
}
static void handle_key(gui_event_t *ev) { static void handle_key(gui_event_t *ev) {
TerminalSession *s = &g_tabs[g_active_tab]; TerminalSession *s = &g_tabs[g_active_tab];
char c = (char)ev->arg1; char c = (char)ev->arg1;
bool ctrl = ev->arg3 != 0; bool ctrl = ev->arg3 != 0;
// create new tab with ctrl + t
if (ctrl && c == 't') { if (ctrl && c == 't') {
int idx = create_tab(); int idx = create_tab();
if (idx >= 0) g_active_tab = idx; if (idx >= 0) g_active_tab = idx;
return; return;
} }
if (ctrl && c == 20) { // switch to tab right, with ctrl + arrow right
if (ctrl && c == KEY_RIGHT) {
if (g_tab_count > 0) g_active_tab = (g_active_tab + 1) % g_tab_count; if (g_tab_count > 0) g_active_tab = (g_active_tab + 1) % g_tab_count;
return; return;
} }
if (ctrl && c == 19) { // switch to tab left, with ctrl + arrow left
if (ctrl && c == KEY_LEFT) {
if (g_tab_count > 0) g_active_tab = (g_active_tab + g_tab_count - 1) % g_tab_count; if (g_tab_count > 0) g_active_tab = (g_active_tab + g_tab_count - 1) % g_tab_count;
return; return;
} }
// kill the processus with ctrl + c
if (ctrl && (c == 'c' || c == 'C')) { if (ctrl && (c == 'c' || c == 'C')) {
int fg = sys_tty_get_fg(s->tty_id); int fg = sys_tty_get_fg(s->tty_id);
if (fg > 0) { if (fg > 0) {
@ -811,6 +887,92 @@ static void handle_key(gui_event_t *ev) {
return; return;
} }
// enter = save command
if (c == KEY_ENTER) {
if (s->input_len > 0) {
strcpy(s->history[s->history_count % HISTORY_MAX], s->current_input);
s->history_count++;
}
s->input_color = 0xFFFFFFFF;
s->history_index = s->history_count;
s->input_len = 0;
s->current_input[0] = 0;
}
// Storing command logic
// Backspace
else if (c == KEY_BACKSPACE) {
if (s->input_len > 0) {
s->input_len--;
s->current_input[s->input_len] = 0;
}
update_input_color(s);
}
// Normal char
else if (c >= 32 && c < 127) {
if (s->input_len < HISTORY_LINE_MAX - 1) {
s->current_input[s->input_len++] = c;
s->current_input[s->input_len] = 0;
}
update_input_color(s);
}
// Restoring command logic
if (c == KEY_UP) {
if (s->history_count > 0 && s->history_index > 0) {
s->history_index--;
char *cmd = s->history[s->history_index % HISTORY_MAX];
// remove actual line
for (int i = 0; i < s->input_len; i++) {
char bs = 8;
sys_tty_write_in(s->tty_id, &bs, 1);
}
strcpy(s->current_input, cmd);
s->input_len = strlen(cmd);
update_input_color(s);
sys_tty_write_in(s->tty_id, cmd, s->input_len);
}
return;
}
if (c == KEY_DOWN) {
if (s->history_index < s->history_count - 1) {
s->history_index++;
char *cmd = s->history[s->history_index % HISTORY_MAX];
for (int i = 0; i < s->input_len; i++) {
char bs = 8;
sys_tty_write_in(s->tty_id, &bs, 1);
}
strcpy(s->current_input, cmd);
s->input_len = strlen(cmd);
update_input_color(s);
sys_tty_write_in(s->tty_id, cmd, s->input_len);
}
else {
// we want an empty line if we go back and nothing in history
for (int i = 0; i < s->input_len; i++) {
char bs = 8;
sys_tty_write_in(s->tty_id, &bs, 1);
}
s->history_index = s->history_count;
s->input_len = 0;
s->current_input[0] = 0;
s->input_color = 0xFFFFFFFF;
}
return;
}
sys_tty_write_in(s->tty_id, &c, 1); sys_tty_write_in(s->tty_id, &c, 1);
} }
@ -885,8 +1047,7 @@ int main(void) {
draw_tabs(); draw_tabs();
draw_session(&g_tabs[g_active_tab]); draw_session(&g_tabs[g_active_tab]);
} else { } else {
// Avoid a tight poll loop when idle; sleep yields to the scheduler. sys_yield();
sleep(1);
} }
} }