diff --git a/FIX.md b/FIX.md index 8b39bc9..5afb1c2 100644 --- a/FIX.md +++ b/FIX.md @@ -4,8 +4,7 @@ - [ ] !x no args - [x] Conditional jump/ invalid read with cd (PWD env var set) - [x] Alias loop -- [ ] All AFL crashes -- [ ] Fix CTRL+E and -> +- [x] Fix CTRL+E and -> - [x] Multi line editing - [ ] Foreach in if - [x] Output flushing when open an other shell with 42sh diff --git a/TODO.md b/TODO.md index bf9d396..65e8a01 100644 --- a/TODO.md +++ b/TODO.md @@ -1,7 +1,7 @@ # TODO - [x] Add job control in main branch -- [ ] Add auto complete -- [ ] Finish line editing +- [x] Add auto complete - [ ] Syntax highlighting -- [ ] CTRL+R +- [x] CTRL+R - [x] Git integration +- [x] Finish line editing diff --git a/src/repl/auto_completion.c b/src/repl/auto_completion.c new file mode 100644 index 0000000..6969db8 --- /dev/null +++ b/src/repl/auto_completion.c @@ -0,0 +1,61 @@ +/* +** EPITECH PROJECT, 2025 +** __ +** File description: +** _ +*/ + +#include +#include +#include +#include +#include + +#include "readline.h" + +static +buff_t get_current_word(readline_helper_t *rh, buff_t *buff) +{ + buff_t word = {buff->str, .sz = rh->cursor}; + + for (size_t i = rh->cursor; i; i--) { + if (isblank(buff->str[i])) { + word.str = &buff->str[i + 1]; + word.sz = rh->cursor - (i + 1); + break; + } + } + return word; +} + +bool handle_key_tab(readline_helper_t *rh, exec_ctx_t *ec, buff_t *buff) +{ + buff_t word; + glob_t globs; + char *pattern; + + if (!rh->cursor || !buff->sz) + return false; + printf("TAB\n"); + word = get_current_word(rh, buff); + printf("Current word [%.*s]\n", (int)word.sz, word.str); + pattern = malloc(sizeof *pattern * (word.sz + 2)); + if (pattern == nullptr) + return true; + strncpy(pattern, word.str, word.sz); + strcpy(pattern + word.sz, "*\0"); + printf("Gen pattern [%s]\n", pattern); + if (glob(pattern, GLOB_ERR, nullptr, &globs) != 0) + return false; + for (size_t i = 0; i < globs.gl_pathc; i++) { + printf("Path v [%s] [%zu]\n", globs.gl_pathv[i], i); + } + if (!ensure_buff_av_capacity(buff, strlen(globs.gl_pathv[0]))) + return true; + strcpy(word.str, globs.gl_pathv[0]); + buff->sz += strlen(globs.gl_pathv[0]) - word.sz; + rh->cursor = buff->sz; + refresh_line(rh); + free(pattern); + return false; +} diff --git a/src/repl/key_handler.h b/src/repl/key_handler.h index 51bcf6f..f56b1cc 100644 --- a/src/repl/key_handler.h +++ b/src/repl/key_handler.h @@ -31,6 +31,7 @@ bool handle_key_ctrl_y(readline_helper_t *rh, exec_ctx_t *, buff_t *buff); bool handle_key_ctrl_r(readline_helper_t *rh, exec_ctx_t *ec, buff_t *buff); bool handle_backspace(readline_helper_t *rh, exec_ctx_t *ec, buff_t *buff); bool handle_delete(readline_helper_t *rh, exec_ctx_t *, buff_t *buff); +bool handle_key_tab(readline_helper_t *rh, exec_ctx_t *ec, buff_t *buff); // Arrows bool handle_key_arrow_up(readline_helper_t *rh, exec_ctx_t *ec, buff_t *buff); diff --git a/src/repl/repl.c b/src/repl/repl.c index 9bf569f..8440d8a 100644 --- a/src/repl/repl.c +++ b/src/repl/repl.c @@ -34,6 +34,7 @@ const key_handler_t KEY_HANDLERS[] = { {ESC "[B", handle_key_arrow_down}, {ESC "[C", handle_key_arrow_right}, {ESC "[D", handle_key_arrow_left}, + {"\t", handle_key_tab}, {"\x7f", handle_backspace}, {"\x1b[3~", handle_delete}, }; @@ -62,6 +63,10 @@ void print_git_prompt(git_status_t *gs) { if (!gs->ahead && !gs->behind) printf(BLUE " [" RED "%s" BLUE "] " RESET "-", gs->branch); + if (gs->ahead) + printf(BLUE " [" RED "%s" GREEN " +" BLUE "] " RESET "-", gs->branch); + else if (gs->behind) + printf(BLUE " [" RED "%s" RED " -" BLUE "] " RESET "-", gs->branch); } static @@ -105,26 +110,14 @@ void print_shell_prompt(exec_ctx_t *ec) } } -void init_shell_repl(exec_ctx_t *ec) +bool is_sequence(char *read_buff) { - struct termios new_settings = ec->saved_term_settings; - - ec->is_running = true; - if (ec->isatty) { - setvbuf(stdout, nullptr, _IONBF, 0); - WRITE_CONST(STDOUT_FILENO, BLINKING_VERTICAL_CURSOR); - new_settings.c_iflag &= ~IXON; - new_settings.c_lflag &= ~(ECHO | ICANON | ISIG); - new_settings.c_cc[VMIN] = 1; - new_settings.c_cc[VTIME] = 0; - tcsetattr(ec->read_fd, TCSANOW, &new_settings); + for (size_t i = 0; i < sizeof KEY_HANDLERS / sizeof *KEY_HANDLERS; i++) { + if (strncmp(read_buff, KEY_HANDLERS[i].name, + strlen(KEY_HANDLERS[i].name)) == 0) + return true; } -} - -void restore_term_flags(exec_ctx_t *exec_ctx) -{ - if (exec_ctx->isatty) - tcsetattr(exec_ctx->read_fd, TCSANOW, &exec_ctx->saved_term_settings); + return false; } ssize_t handle_keys( @@ -133,6 +126,8 @@ ssize_t handle_keys( char const *read_buff, size_t len) { + if (!rh->ec->isatty) + return 0; for (size_t i = 0; i < sizeof KEY_HANDLERS / sizeof *KEY_HANDLERS; i++) { if (strncmp(read_buff, KEY_HANDLERS[i].name, strlen(KEY_HANDLERS[i].name)) != 0) @@ -143,5 +138,5 @@ ssize_t handle_keys( } for (size_t i = 0; i < len; i++) U_DEBUG("<- [%d]\n", read_buff[i]); - return 1; + return 0; } diff --git a/src/repl/term.c b/src/repl/term.c new file mode 100644 index 0000000..4066086 --- /dev/null +++ b/src/repl/term.c @@ -0,0 +1,36 @@ +/* +** EPITECH PROJECT, 2025 +** __ +** File description: +** _ +*/ + + +#include +#include + +#include "builtins_handler.h" +#include "u_str.h" +#include "vt100_esc_codes.h" + +void init_shell_repl(exec_ctx_t *ec) +{ + struct termios new_settings = ec->saved_term_settings; + + ec->is_running = true; + if (ec->isatty) { + setvbuf(stdout, nullptr, _IONBF, 0); + WRITE_CONST(STDOUT_FILENO, BLINKING_VERTICAL_CURSOR); + new_settings.c_iflag &= ~IXON; + new_settings.c_lflag &= ~(ECHO | ICANON | ISIG); + new_settings.c_cc[VMIN] = 1; + new_settings.c_cc[VTIME] = 0; + tcsetattr(ec->read_fd, TCSANOW, &new_settings); + } +} + +void restore_term_flags(exec_ctx_t *exec_ctx) +{ + if (exec_ctx->isatty) + tcsetattr(exec_ctx->read_fd, TCSANOW, &exec_ctx->saved_term_settings); +}