Setup special key handler

This commit is contained in:
savalet
2025-05-09 00:28:10 +02:00
parent eb0ac4d564
commit 3900418014
9 changed files with 155 additions and 45 deletions

View File

@@ -12,6 +12,7 @@ Checks: "-*,
-readability-braces-around-statements,
-readability-identifier-length,
-readability-implicit-bool-conversion,
-readability-named-parameter,
clang-analyzer-*,
modernize-*,
llvm-*,

View File

@@ -21,6 +21,7 @@ SRC += $(wildcard src/builtins/expr/*.c)
SRC += $(wildcard src/ast/*.c)
SRC += $(wildcard src/utils/*.c)
SRC += $(wildcard src/local/*.c)
SRC += $(wildcard src/repl/*.c)
LIB_SRC := $(wildcard ulib/*.c)
LIB_SRC += $(wildcard ulib/write/printf/*.c)

View File

@@ -61,7 +61,7 @@ bool append_null_terminator(buff_t *out)
}
static
bool populate_single_char(
bool copy_single_char(
exec_ctx_t *exec_ctx,
buff_t *out,
char *cpy,
@@ -69,7 +69,7 @@ bool populate_single_char(
{
if (in == '\r')
in = '\n';
if (in == '\0')
if (in == '\0' || in == '\f')
return false;
if (isspace(in) || isprint(in) || !exec_ctx->isatty) {
*cpy = in;
@@ -82,34 +82,34 @@ bool populate_single_char(
static
bool populate_copy_buff(
exec_ctx_t *exec_ctx, readline_helper_t *rh, ssize_t rd,
exec_ctx_t *ec, readline_helper_t *rh, ssize_t rd,
text_parse_info_t *tpi)
{
size_t w = 0;
ssize_t i = 0;
ssize_t skip;
for (bool done = false; !done && i < rd; i++) {
if (populate_single_char(exec_ctx, rh->out, &rh->cpy[w], rh->in[i])) {
done = rh->cpy[w] == '\n';
w++;
if (copy_single_char(ec, rh->out, &rh->cpy[tpi->written], rh->in[i])) {
done = rh->cpy[tpi->written] == '\n';
tpi->written++;
continue;
}
if (handle_keys(exec_ctx, rh->out, &rh->in[i])) {
skip = handle_keys(ec, rh->out, &rh->in[i], BULK_READ_BUFF_SZ - i);
if (skip < 0) {
tpi->used = i;
tpi->written = w;
return false;
}
i += skip - 1;
}
if (exec_ctx->isatty)
write(STDOUT_FILENO, rh->cpy, w);
if (ec->isatty)
write(STDOUT_FILENO, rh->cpy, tpi->written);
tpi->used = i;
tpi->written = w;
return true;
}
static
bool read_until_line_ending(
exec_ctx_t *exec_ctx, readline_helper_t *rh, ssize_t rd)
exec_ctx_t *ec, readline_helper_t *rh, ssize_t rd)
{
text_parse_info_t tpi;
@@ -117,13 +117,14 @@ bool read_until_line_ending(
memset(&tpi, '\0', sizeof tpi);
if (!ensure_buff_av_capacity(rh->out, BULK_READ_BUFF_SZ))
return false;
populate_copy_buff(exec_ctx, rh, rd, &tpi);
if (!populate_copy_buff(ec, rh, rd, &tpi))
return true;
U_DEBUG("copied %zu chars to cpy (%zu used)\n", tpi.written, tpi.used);
memmove(rh->in, &rh->in[tpi.used], BULK_READ_BUFF_SZ - tpi.used);
memset(&rh->in[BULK_READ_BUFF_SZ - tpi.used], '\0', tpi.used);
if (rh->cpy[tpi.written - 1] == '\n')
break;
rd = read(exec_ctx->read_fd, rh->in, BULK_READ_BUFF_SZ);
rd = read(ec->read_fd, rh->in, BULK_READ_BUFF_SZ);
if (rd <= 0)
return (rd == 0);
U_DEBUG("read %zu characters\n", rd);
@@ -131,7 +132,7 @@ bool read_until_line_ending(
return true;
}
bool readline(exec_ctx_t *exec_ctx, buff_t *out)
bool readline(exec_ctx_t *ec, buff_t *out)
{
static char read_buff[BULK_READ_BUFF_SZ] = {0};
readline_helper_t rh = { out, read_buff, { 0 } };
@@ -142,12 +143,12 @@ bool readline(exec_ctx_t *exec_ctx, buff_t *out)
is_empty &= read_buff[i] == '\0';
U_DEBUG("readline buff is empty? %d\n", is_empty);
if (is_empty) {
rd = read(exec_ctx->read_fd, read_buff, sizeof read_buff);
rd = read(ec->read_fd, read_buff, sizeof read_buff);
if (rd < 0)
return (rd == 0);
} else
rd = BULK_READ_BUFF_SZ;
if (!read_until_line_ending(exec_ctx, &rh, rd))
if (!read_until_line_ending(ec, &rh, rd))
return false;
return append_null_terminator(out);
}

View File

@@ -7,15 +7,16 @@
#ifndef READLINE
#define READLINE
#define BUFF_INIT_SZ 16
#include <stdbool.h>
#include "exec.h"
#include "builtins_handler.h"
#include "u_str.h"
#define BULK_READ_BUFF_SZ 32
bool readline(exec_ctx_t *exec_ctx, buff_t *out);
bool readline(exec_ctx_t *ec, buff_t *out);
typedef struct {
buff_t *out;

View File

@@ -7,11 +7,21 @@
#ifndef REPL_H
#define REPL_H
#include "exec.h"
#include <stdio.h>
#include "builtins_handler.h"
#include "u_str.h"
void init_shell_repl(exec_ctx_t *exec_ctx);
void restore_term_flags(exec_ctx_t *exec_ctx);
bool handle_keys(exec_ctx_t *exec_ctx, buff_t *buff, char const *read_buff);
ssize_t handle_keys(
exec_ctx_t *ec,
buff_t *buff,
char const *read_buff,
size_t len);
void print_shell_prompt(exec_ctx_t *exec_ctx);
#endif /* REPL_H */

32
src/repl/key_arrow.c Normal file
View File

@@ -0,0 +1,32 @@
/*
** EPITECH PROJECT, 2025
** __
** File description:
** _
*/
#include <unistd.h>
#include "key_handler.h"
#include "repl.h"
#include "vt100_esc_codes.h"
bool handle_key_arrow_up(exec_ctx_t *ec, buff_t *buff)
{
return true;
}
bool handle_key_arrow_left(exec_ctx_t *ec, buff_t *buff)
{
return true;
}
bool handle_key_arrow_right(exec_ctx_t *ec, buff_t *buff)
{
return true;
}
bool handle_key_arrow_down(exec_ctx_t *ec, buff_t *buff)
{
return true;
}

33
src/repl/key_control.c Normal file
View File

@@ -0,0 +1,33 @@
/*
** EPITECH PROJECT, 2025
** __
** File description:
** _
*/
#include <unistd.h>
#include "key_handler.h"
#include "repl.h"
#include "vt100_esc_codes.h"
bool handle_key_ctrl_c(exec_ctx_t *ec, buff_t *buff)
{
WRITE_CONST(ec->read_fd, "\n");
print_shell_prompt(ec);
return true;
}
bool handle_key_ctrl_d(exec_ctx_t *ec, buff_t *buff)
{
buff->sz = 0;
return false;
}
bool handle_key_ctrl_l(exec_ctx_t *ec, buff_t *buff)
{
WRITE_CONST(STDOUT_FILENO, ESC "[2J");
WRITE_CONST(STDOUT_FILENO, ESC "[H");
print_shell_prompt(ec);
return false;
}

28
src/repl/key_handler.h Normal file
View File

@@ -0,0 +1,28 @@
/*
** EPITECH PROJECT, 2025
** __
** File description:
** _
*/
#ifndef KEY_HANDLER_H
#define KEY_HANDLER_H
#include "builtins_handler.h"
#include "u_str.h"
typedef struct {
const char *name;
bool (*exec)(exec_ctx_t *ec, buff_t *buff);
} key_handler_t;
bool handle_key_ctrl_c(exec_ctx_t *ec, buff_t *buff);
bool handle_key_ctrl_d(exec_ctx_t *ec, buff_t *buff);
bool handle_key_ctrl_l(exec_ctx_t *ec, buff_t *buff);
bool handle_key_arrow_up(exec_ctx_t *ec, buff_t *buff);
bool handle_key_arrow_left(exec_ctx_t *ec, buff_t *buff);
bool handle_key_arrow_right(exec_ctx_t *ec, buff_t *buff);
bool handle_key_arrow_down(exec_ctx_t *ec, buff_t *buff);
#endif

View File

@@ -7,15 +7,26 @@
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include "common.h"
#include "repl.h"
#include "debug.h"
#include "repl.h"
#include "repl/key_handler.h"
#include "u_str.h"
#include "vt100_esc_codes.h"
const key_handler_t KEY_HANDLERS[] = {
{"\03", handle_key_ctrl_c}, // ^C
{"\04", handle_key_ctrl_d}, // ^D
{"\014", handle_key_ctrl_l}, // ^L
{"]A", handle_key_arrow_up},
{"]B", handle_key_arrow_down},
{"]D", handle_key_arrow_left},
{"]C", handle_key_arrow_right},
};
void print_shell_prompt(exec_ctx_t *exec_ctx)
{
@@ -58,29 +69,21 @@ void restore_term_flags(exec_ctx_t *exec_ctx)
tcsetattr(exec_ctx->read_fd, TCSANOW, &exec_ctx->saved_term_settings);
}
static
void ignore_sigint(exec_ctx_t *exec_ctx)
{
WRITE_CONST(exec_ctx->read_fd, "\n");
print_shell_prompt(exec_ctx);
}
bool handle_keys(exec_ctx_t *exec_ctx, buff_t *buff, char const *read_buff)
ssize_t handle_keys(
exec_ctx_t *ec,
buff_t *buff,
char const *read_buff,
size_t len)
{
U_DEBUG("Found special char, [%hhx]\n", *read_buff);
switch (*read_buff) {
case CTRL('d'):
buff->sz = 0;
return true;
case CTRL('c'):
ignore_sigint(exec_ctx);
return false;
case CTRL('l'):
WRITE_CONST(STDOUT_FILENO, ESC "[2J");
WRITE_CONST(STDOUT_FILENO, ESC "[H");
print_shell_prompt(exec_ctx);
return false;
default:
return false;
for (size_t i = 0; i < sizeof KEY_HANDLERS / sizeof *KEY_HANDLERS; i++) {
if (strncmp(read_buff, KEY_HANDLERS[i].name, len) == 0)
continue;
if (!KEY_HANDLERS[i].exec(ec, buff))
return strlen(KEY_HANDLERS[i].name);
return -1;
}
for (size_t i = 0; i < len; i++)
U_DEBUG("<- [%d]\n", read_buff[i]);
return 0;
}