From 723dd13aba0603323daebfffac709a37d3e53b0a Mon Sep 17 00:00:00 2001 From: Anonymus Raccoon Date: Thu, 21 May 2020 18:23:50 +0200 Subject: [PATCH 1/8] Starting the autocompletion --- Makefile | 3 ++- include/key_functions.h | 2 ++ src/key_bindings/autocompletion.c | 16 ++++++++++++++++ src/key_bindings/default_bindings.c | 3 +++ 4 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 src/key_bindings/autocompletion.c diff --git a/Makefile b/Makefile index 8980c7b..5977f96 100644 --- a/Makefile +++ b/Makefile @@ -44,7 +44,8 @@ SRC = src/shell.c \ src/key_bindings/move_commands.c \ src/my_ncurses/my_ncurses.c \ src/my_ncurses/string_utils.c \ - src/my_ncurses/pause_utils.c + src/my_ncurses/pause_utils.c \ + src/key_bindings/autocompletion.c OBJ = $(SRC:%.c=%.o) OBJ += src/main.o diff --git a/include/key_functions.h b/include/key_functions.h index ff31335..467eb43 100644 --- a/include/key_functions.h +++ b/include/key_functions.h @@ -41,3 +41,5 @@ int end_of_line_command(int key, buffer_t *buffer, env_t *env); int up_history_command(int key, buffer_t *buffer, env_t *env); int down_history_command(int key, buffer_t *buffer, env_t *env); + +int complete_command(int key, buffer_t *buffer, env_t *env); \ No newline at end of file diff --git a/src/key_bindings/autocompletion.c b/src/key_bindings/autocompletion.c new file mode 100644 index 0000000..4f6619b --- /dev/null +++ b/src/key_bindings/autocompletion.c @@ -0,0 +1,16 @@ +/* +** EPITECH PROJECT, 2020 +** ash +** File description: +** autocompletion +*/ + +#include "shell.h" + +int complete_command(int key, buffer_t *buffer, env_t *env) +{ + if (!buffer->buffer || + (!strchr(buffer->buffer, ' ') && !strchr(buffer->buffer, '\t'))) + return (0); + return (0); +} \ No newline at end of file diff --git a/src/key_bindings/default_bindings.c b/src/key_bindings/default_bindings.c index 91595af..406c350 100644 --- a/src/key_bindings/default_bindings.c +++ b/src/key_bindings/default_bindings.c @@ -20,6 +20,8 @@ const key_function_t key_functions[] = { {"forward-char", &forward_char_command}, {"beginning-of-line", &beginning_of_line_command}, {"end-of-line", &end_of_line_command}, + {"up-history", &up_history_command}, + {"down-history", &down_history_command}, {NULL, NULL} }; @@ -35,5 +37,6 @@ const binding_t emacs_bindings[] = { {KEY_END, &end_of_line_command}, {KEY_UP, &up_history_command}, {KEY_DOWN, &down_history_command}, + {'\t', &complete_command}, {0, NULL} }; \ No newline at end of file From 324be40b7ea5896e28c1b77603094ca12d16b3c5 Mon Sep 17 00:00:00 2001 From: Anonymus Raccoon Date: Thu, 21 May 2020 23:44:44 +0200 Subject: [PATCH 2/8] Completing the command when only one file is available --- include/utility.h | 4 +- src/glob.c | 2 +- src/key_bindings/autocompletion.c | 72 ++++++++++++++++++++++++++++++- src/my_ncurses/my_ncurses.c | 1 + src/shell.c | 2 +- 5 files changed, 76 insertions(+), 5 deletions(-) diff --git a/include/utility.h b/include/utility.h index 94fe99d..d8b2976 100644 --- a/include/utility.h +++ b/include/utility.h @@ -23,4 +23,6 @@ char **split_commands(char *cmd); int *get_return_separator(char *cmd); int split_is_invalid(char **cmds, int *return_values, int i); int count_char(const char *str, char c); -int ncount_char(const char *str, int end, char c); \ No newline at end of file +int ncount_char(const char *str, int end, char c); + +#define MAX(x, y) ((x) < (y) ? (y) : (x)) \ No newline at end of file diff --git a/src/glob.c b/src/glob.c index 8a7e113..6113b24 100644 --- a/src/glob.c +++ b/src/glob.c @@ -26,7 +26,7 @@ char **glob_error(char **argv, int err) char **globbing(char **argv) { static glob_t results; - int flags = GLOB_DOOFFS | GLOB_NOMAGIC; + int flags = GLOB_DOOFFS | GLOB_NOMAGIC | GLOB_TILDE; int ret = 0; for (int i = 0; argv[i] && ret == 0; i++) { diff --git a/src/key_bindings/autocompletion.c b/src/key_bindings/autocompletion.c index 4f6619b..2a28c27 100644 --- a/src/key_bindings/autocompletion.c +++ b/src/key_bindings/autocompletion.c @@ -5,12 +5,80 @@ ** autocompletion */ +#define _GNU_SOURCE #include "shell.h" +#include "utility.h" +#include +#include +#include +#include + +char *get_start_of_current_arg(buffer_t *buffer) +{ + if (!buffer->buffer) + return (NULL); + return (memrchr(buffer->buffer, ' ', buffer->pos) + 1); +} + +void print_results(unsigned count, char **results) +{ + unsigned size = 0; + + putchar('\n'); + my_clrtobot(); + for (unsigned i = 0; i < count; i++) + size = MAX(size, strlen(results[i])); + size++; + for (unsigned i = 0; i < count; i++) + printf("%-*s", size, results[i]); +} + +void buffer_replace(buffer_t *buffer, char *to_replace, int start, int end) +{ + int len = strlen(to_replace); + int total = len + (buffer->buffer ? strlen(buffer->buffer) : 0); + + if (buffer->size < total) { + buffer->buffer = realloc(buffer->buffer, total + 50); + buffer->size = total + 50; + } + for (int i = strlen(buffer->buffer); i > end; i--) + buffer->buffer[i + len] = buffer->buffer[i]; + memcpy(buffer->buffer + start, to_replace, len); +} + +void complete_current(buffer_t *buffer, char *cmd) +{ + char *start = get_start_of_current_arg(buffer); + char *end; + + if (!start) + return; + end = strchr(start, ' '); + if (!end) + end = buffer->buffer + strlen(buffer->buffer); + buffer_replace(buffer, cmd, start - buffer->buffer, end - buffer->buffer); + buffer->pos = start - buffer->buffer + strlen(cmd); +} int complete_command(int key, buffer_t *buffer, env_t *env) { - if (!buffer->buffer || - (!strchr(buffer->buffer, ' ') && !strchr(buffer->buffer, '\t'))) + char *str; + char *p = get_start_of_current_arg(buffer); + glob_t result; + + if (!buffer->buffer || !p) return (0); + str = malloc(buffer->pos - (p - buffer->buffer) + 2); + strncpy(str, p, buffer->pos - (p - buffer->buffer) + 1); + strcat(str, "*"); + if (!glob(str, GLOB_MARK | GLOB_BRACE, NULL, &result)) { + if (result.gl_pathc == 1) + complete_current(buffer, result.gl_pathv[0]); + else + print_results(result.gl_pathc, result.gl_pathv); + } + globfree(&result); + free(str); return (0); } \ No newline at end of file diff --git a/src/my_ncurses/my_ncurses.c b/src/my_ncurses/my_ncurses.c index bc13b0c..9a9ede8 100644 --- a/src/my_ncurses/my_ncurses.c +++ b/src/my_ncurses/my_ncurses.c @@ -19,6 +19,7 @@ void on_resize(int sig, siginfo_t *info, void *context) { my_getmaxyx(&stdwin->h, &stdwin->w); my_getcuryx(&stdwin->y, &stdwin->x); + my_clrtobot(); } my_window *my_initwin(void) diff --git a/src/shell.c b/src/shell.c index bb722c6..debeff6 100644 --- a/src/shell.c +++ b/src/shell.c @@ -57,7 +57,7 @@ void shell_refresh(buffer_t *buffer, env_t *env) if (buffer->buffer) my_mvaddstr(env->window, y, buffer->startx, buffer->buffer); - my_clrtobot(); + my_clrtoeol(); my_move(env->window, newy, buf_getx(buffer, env)); my_refresh(); oldbuffer_pos = buffer->pos; From 3e619f78bd4c62e05782d9dc08e520c9e6ed0dcd Mon Sep 17 00:00:00 2001 From: Anonymus Raccoon Date: Fri, 22 May 2020 02:21:48 +0200 Subject: [PATCH 3/8] Handling middle autocompletion --- src/key_bindings/autocompletion.c | 10 +++++++--- src/shell.c | 1 + 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/key_bindings/autocompletion.c b/src/key_bindings/autocompletion.c index 2a28c27..31e7b31 100644 --- a/src/key_bindings/autocompletion.c +++ b/src/key_bindings/autocompletion.c @@ -42,9 +42,12 @@ void buffer_replace(buffer_t *buffer, char *to_replace, int start, int end) buffer->buffer = realloc(buffer->buffer, total + 50); buffer->size = total + 50; } - for (int i = strlen(buffer->buffer); i > end; i--) - buffer->buffer[i + len] = buffer->buffer[i]; + if (!buffer->buffer) + return; + for (int i = strlen(buffer->buffer); i >= end; i--) + buffer->buffer[i + len - 1] = buffer->buffer[i]; memcpy(buffer->buffer + start, to_replace, len); + buffer->buffer[total - (end - start)] = '\0'; } void complete_current(buffer_t *buffer, char *cmd) @@ -70,7 +73,8 @@ int complete_command(int key, buffer_t *buffer, env_t *env) if (!buffer->buffer || !p) return (0); str = malloc(buffer->pos - (p - buffer->buffer) + 2); - strncpy(str, p, buffer->pos - (p - buffer->buffer) + 1); + strncpy(str, p, buffer->pos - (p - buffer->buffer)); + str[buffer->pos - (p - buffer->buffer)] = '\0'; strcat(str, "*"); if (!glob(str, GLOB_MARK | GLOB_BRACE, NULL, &result)) { if (result.gl_pathc == 1) diff --git a/src/shell.c b/src/shell.c index debeff6..8f77e8f 100644 --- a/src/shell.c +++ b/src/shell.c @@ -23,6 +23,7 @@ int process_key(int key, buffer_t *buffer, env_t *env) { if (key <= 0) return (0); + my_clrtobot(); for (int i = 0; env->bindings[i].func; i++) if (key == env->bindings[i].key) return (env->bindings[i].func(key, buffer, env)); From f86e694bc6a59b7c6179a266cd1d38e4197d599e Mon Sep 17 00:00:00 2001 From: Anonymus Raccoon Date: Fri, 22 May 2020 21:06:21 +0200 Subject: [PATCH 4/8] =?UTF-8?q?Handling=20line=20overflow=20for=20autocomp?= =?UTF-8?q?letions=C3=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/key_bindings/autocompletion.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/key_bindings/autocompletion.c b/src/key_bindings/autocompletion.c index 31e7b31..572ace8 100644 --- a/src/key_bindings/autocompletion.c +++ b/src/key_bindings/autocompletion.c @@ -20,17 +20,22 @@ char *get_start_of_current_arg(buffer_t *buffer) return (memrchr(buffer->buffer, ' ', buffer->pos) + 1); } -void print_results(unsigned count, char **results) +void print_results(my_window *window, unsigned count, char **results) { unsigned size = 0; + int per_line; putchar('\n'); my_clrtobot(); for (unsigned i = 0; i < count; i++) size = MAX(size, strlen(results[i])); size++; - for (unsigned i = 0; i < count; i++) - printf("%-*s", size, results[i]); + per_line = window->w / size; + for (unsigned i = 0; i < count; i += per_line) { + for (int j = 0; j < per_line && i + j < count; j++) + printf("%-*s", size, results[i + j]); + printf("\n"); + } } void buffer_replace(buffer_t *buffer, char *to_replace, int start, int end) @@ -80,7 +85,7 @@ int complete_command(int key, buffer_t *buffer, env_t *env) if (result.gl_pathc == 1) complete_current(buffer, result.gl_pathv[0]); else - print_results(result.gl_pathc, result.gl_pathv); + print_results(env->window, result.gl_pathc, result.gl_pathv); } globfree(&result); free(str); From ea3e6b30a497080eb3e846a344c748807f6815db Mon Sep 17 00:00:00 2001 From: Anonymus Raccoon Date: Fri, 22 May 2020 21:26:32 +0200 Subject: [PATCH 5/8] Removing prefixs on subdirectory autocompletion listing --- src/key_bindings/autocompletion.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/key_bindings/autocompletion.c b/src/key_bindings/autocompletion.c index 572ace8..fec28f4 100644 --- a/src/key_bindings/autocompletion.c +++ b/src/key_bindings/autocompletion.c @@ -24,17 +24,21 @@ void print_results(my_window *window, unsigned count, char **results) { unsigned size = 0; int per_line; + int prefix_length = 0; + char *p = memrchr(results[0], '/', strlen(results[0]) - 1); + if (p) + prefix_length = p - results[0] + 1; putchar('\n'); my_clrtobot(); for (unsigned i = 0; i < count; i++) - size = MAX(size, strlen(results[i])); + size = MAX(size, strlen(results[i]) - prefix_length); size++; per_line = window->w / size; for (unsigned i = 0; i < count; i += per_line) { for (int j = 0; j < per_line && i + j < count; j++) - printf("%-*s", size, results[i + j]); - printf("\n"); + printf("%-*s", size, results[i + j] + prefix_length); + putchar('\n'); } } From 5578eff174488cb8e160ac9428a731c1d14923b5 Mon Sep 17 00:00:00 2001 From: Anonymus Raccoon Date: Fri, 22 May 2020 23:18:42 +0200 Subject: [PATCH 6/8] Handling scroll on autocompletion --- src/key_bindings/autocompletion.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/key_bindings/autocompletion.c b/src/key_bindings/autocompletion.c index fec28f4..bcba818 100644 --- a/src/key_bindings/autocompletion.c +++ b/src/key_bindings/autocompletion.c @@ -40,6 +40,7 @@ void print_results(my_window *window, unsigned count, char **results) printf("%-*s", size, results[i + j] + prefix_length); putchar('\n'); } + window->y -= MAX(0, (window->y + 2 + ((int)count / per_line) + 1 - window->h)); } void buffer_replace(buffer_t *buffer, char *to_replace, int start, int end) From a9f67600767afd76daeccdd31f34d74cc33bc4c4 Mon Sep 17 00:00:00 2001 From: Anonymus Raccoon Date: Fri, 22 May 2020 23:20:15 +0200 Subject: [PATCH 7/8] Cleaning up --- src/key_bindings/autocompletion.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/key_bindings/autocompletion.c b/src/key_bindings/autocompletion.c index bcba818..53d9e01 100644 --- a/src/key_bindings/autocompletion.c +++ b/src/key_bindings/autocompletion.c @@ -40,7 +40,7 @@ void print_results(my_window *window, unsigned count, char **results) printf("%-*s", size, results[i + j] + prefix_length); putchar('\n'); } - window->y -= MAX(0, (window->y + 2 + ((int)count / per_line) + 1 - window->h)); + window->y -= MAX(0, (window->y + ((int)count / per_line) + 3 - window->h)); } void buffer_replace(buffer_t *buffer, char *to_replace, int start, int end) @@ -49,7 +49,7 @@ void buffer_replace(buffer_t *buffer, char *to_replace, int start, int end) int total = len + (buffer->buffer ? strlen(buffer->buffer) : 0); if (buffer->size < total) { - buffer->buffer = realloc(buffer->buffer, total + 50); + buffer->buffer = realloc(buffer->buffer, total + 50); buffer->size = total + 50; } if (!buffer->buffer) From 656054ec9ea91c281b5decbc3b9c8b817e3d099a Mon Sep 17 00:00:00 2001 From: Anonymus Raccoon Date: Sat, 23 May 2020 14:41:57 +0200 Subject: [PATCH 8/8] Solving a segfault --- src/key_bindings/autocompletion.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/key_bindings/autocompletion.c b/src/key_bindings/autocompletion.c index 53d9e01..d53e156 100644 --- a/src/key_bindings/autocompletion.c +++ b/src/key_bindings/autocompletion.c @@ -15,9 +15,14 @@ char *get_start_of_current_arg(buffer_t *buffer) { + char *p; + if (!buffer->buffer) return (NULL); - return (memrchr(buffer->buffer, ' ', buffer->pos) + 1); + p = memrchr(buffer->buffer, ' ', buffer->pos); + if (!p) + return (NULL); + return (p + 1); } void print_results(my_window *window, unsigned count, char **results) @@ -83,6 +88,8 @@ int complete_command(int key, buffer_t *buffer, env_t *env) if (!buffer->buffer || !p) return (0); str = malloc(buffer->pos - (p - buffer->buffer) + 2); + if (!str) + return (0); strncpy(str, p, buffer->pos - (p - buffer->buffer)); str[buffer->pos - (p - buffer->buffer)] = '\0'; strcat(str, "*");