mirror of
https://github.com/zoriya/ash.git
synced 2026-05-29 17:32:20 +00:00
Merge pull request #62 from AnonymusRaccoon/autocompletion
Autocompletion
This commit is contained in:
@@ -46,7 +46,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
|
||||
|
||||
@@ -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);
|
||||
+3
-1
@@ -27,4 +27,6 @@ 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);
|
||||
int get_max_eof(char *ignoreeof);
|
||||
int skip_eof(buffer_t *buffer, env_t *env);
|
||||
int skip_eof(buffer_t *buffer, env_t *env);
|
||||
|
||||
#define MAX(x, y) ((x) < (y) ? (y) : (x))
|
||||
+1
-1
@@ -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++) {
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
** EPITECH PROJECT, 2020
|
||||
** ash
|
||||
** File description:
|
||||
** autocompletion
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include "shell.h"
|
||||
#include "utility.h"
|
||||
#include <glob.h>
|
||||
#include <malloc.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
char *get_start_of_current_arg(buffer_t *buffer)
|
||||
{
|
||||
char *p;
|
||||
|
||||
if (!buffer->buffer)
|
||||
return (NULL);
|
||||
p = memrchr(buffer->buffer, ' ', buffer->pos);
|
||||
if (!p)
|
||||
return (NULL);
|
||||
return (p + 1);
|
||||
}
|
||||
|
||||
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]) - 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] + prefix_length);
|
||||
putchar('\n');
|
||||
}
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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);
|
||||
if (!str)
|
||||
return (0);
|
||||
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)
|
||||
complete_current(buffer, result.gl_pathv[0]);
|
||||
else
|
||||
print_results(env->window, result.gl_pathc, result.gl_pathv);
|
||||
}
|
||||
globfree(&result);
|
||||
free(str);
|
||||
return (0);
|
||||
}
|
||||
@@ -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}
|
||||
};
|
||||
@@ -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)
|
||||
|
||||
+2
-1
@@ -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));
|
||||
@@ -57,7 +58,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;
|
||||
|
||||
Reference in New Issue
Block a user