Finished tab autocompletion, fixed some more memory errors
This commit is contained in:
parent
dceafa7244
commit
3354a97867
1
.gitignore
vendored
1
.gitignore
vendored
@ -3,3 +3,4 @@ build/
|
|||||||
a.out
|
a.out
|
||||||
val/
|
val/
|
||||||
tmp*
|
tmp*
|
||||||
|
test/
|
@ -8,7 +8,7 @@ Work is still in porgress, buf when you will see a "finished" topic assigned to
|
|||||||
* Command input with `left` and `right` arrow, `home` and `end` keys navigation and `backspace`, `delete` support
|
* Command input with `left` and `right` arrow, `home` and `end` keys navigation and `backspace`, `delete` support
|
||||||
* Running commands in separate process and termination them with `ctrl+c`
|
* Running commands in separate process and termination them with `ctrl+c`
|
||||||
* `cd` and `exit` builtin commands
|
* `cd` and `exit` builtin commands
|
||||||
* Files and commands from `/bin` autocompletion on `Tab` keypress
|
* Files and commands from `/usr/bin` autocompletion on `Tab` keypress
|
||||||
|
|
||||||
# Builtin commands
|
# Builtin commands
|
||||||
* `cd`: changes current working directory to the one specified by user. If no arguments provided, shows error.
|
* `cd`: changes current working directory to the one specified by user. If no arguments provided, shows error.
|
||||||
@ -19,5 +19,4 @@ Work is still in porgress, buf when you will see a "finished" topic assigned to
|
|||||||
* Replace linux `echo` command with builtin one with support of environmental variables
|
* Replace linux `echo` command with builtin one with support of environmental variables
|
||||||
* Environmental variables
|
* Environmental variables
|
||||||
* `Ctrl+Z` running programm with `fd`
|
* `Ctrl+Z` running programm with `fd`
|
||||||
* Commands autocompletion
|
|
||||||
* Getting commands path from system `PATH` environment variable
|
* Getting commands path from system `PATH` environment variable
|
@ -19,17 +19,16 @@ bool check_if_executable(char *path, char *file_name)
|
|||||||
|
|
||||||
size_t get_dir_list(char ***dir_list, char *path, int ex)
|
size_t get_dir_list(char ***dir_list, char *path, int ex)
|
||||||
{
|
{
|
||||||
size_t n = 0;
|
|
||||||
*dir_list = malloc(sizeof(char *) * n);
|
|
||||||
|
|
||||||
DIR *dir;
|
DIR *dir;
|
||||||
struct dirent *ent;
|
struct dirent *ent;
|
||||||
|
|
||||||
if ((dir = opendir(path)) == NULL)
|
if ((dir = opendir(path)) == NULL)
|
||||||
{
|
{
|
||||||
perror("opendir");
|
perror("\nOpendir");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t n = 0;
|
||||||
while ((ent = readdir(dir)) != NULL)
|
while ((ent = readdir(dir)) != NULL)
|
||||||
{
|
{
|
||||||
if (ex != 0 && !check_if_executable(path, ent->d_name))
|
if (ex != 0 && !check_if_executable(path, ent->d_name))
|
||||||
@ -53,7 +52,7 @@ size_t get_dir_list(char ***dir_list, char *path, int ex)
|
|||||||
|
|
||||||
size_t get_complete_options(char ***opts, char *line, char **to_complete)
|
size_t get_complete_options(char ***opts, char *line, char **to_complete)
|
||||||
{
|
{
|
||||||
char **args, **folders = malloc(0);
|
char **args = NULL, **folders = malloc(0);
|
||||||
size_t sz;
|
size_t sz;
|
||||||
|
|
||||||
int am = sep_string(line, &args, " ");
|
int am = sep_string(line, &args, " ");
|
||||||
@ -61,27 +60,36 @@ size_t get_complete_options(char ***opts, char *line, char **to_complete)
|
|||||||
char *last_arg = args[am - 1];
|
char *last_arg = args[am - 1];
|
||||||
|
|
||||||
if (am > 0)
|
if (am > 0)
|
||||||
{
|
|
||||||
if (last_arg[0] == '/')
|
|
||||||
{
|
{
|
||||||
int path_depth = sep_string(last_arg, &folders, "/");
|
int path_depth = sep_string(last_arg, &folders, "/");
|
||||||
*to_complete = strdup(folders[path_depth - 1]);
|
*to_complete = strdup(folders[path_depth - 1]);
|
||||||
sz = get_dir_list(opts, last_arg, 0); // pass / + all $folders instead of last_arg
|
|
||||||
}
|
char *curr_pos = NULL;
|
||||||
else if (last_arg[0] == '.' && last_arg[1] == '/')
|
int i = 0;
|
||||||
|
|
||||||
|
if (last_arg[0] == '/')
|
||||||
{
|
{
|
||||||
int path_depth = sep_string(last_arg + 1, &folders, "/");
|
curr_pos = strdup("");
|
||||||
*to_complete = strdup(folders[path_depth - 1]);
|
|
||||||
sz = get_dir_list(opts, get_current_dir_name(), 0); // pass get_current_dir_name() + all $folders instead of get_current_dir_name()
|
|
||||||
}
|
}
|
||||||
else if (strchr(line, ' '))
|
else if (strchr(line, ' '))
|
||||||
{
|
{
|
||||||
int path_depth = sep_string(last_arg, &folders, "/");
|
curr_pos = strdup(".");
|
||||||
*to_complete = strdup(folders[path_depth - 1]);
|
}
|
||||||
sz = get_dir_list(opts, get_current_dir_name(), 0); // pass get_current_dir_name() + all $folders instead of get_current_dir_name()
|
else if (last_arg[0] == '.' && last_arg[1] == '/')
|
||||||
|
{
|
||||||
|
curr_pos = strdup(folders[0]);
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
goto ABSOLUTE;
|
goto ABSOLUTE;
|
||||||
|
|
||||||
|
for (int i = 0; i < (path_depth - 1); i++)
|
||||||
|
{
|
||||||
|
curr_pos = realloc(curr_pos, strlen(curr_pos) + strlen(folders[i]) + 2);
|
||||||
|
curr_pos = strcat(curr_pos, "/");
|
||||||
|
curr_pos = strcat(curr_pos, folders[i]);
|
||||||
|
}
|
||||||
|
sz = get_dir_list(opts, curr_pos, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -93,6 +101,9 @@ size_t get_complete_options(char ***opts, char *line, char **to_complete)
|
|||||||
free_str_arr(args);
|
free_str_arr(args);
|
||||||
free_str_arr(folders);
|
free_str_arr(folders);
|
||||||
|
|
||||||
|
if (sz == -1)
|
||||||
|
return sz;
|
||||||
|
|
||||||
if ((*to_complete)[0] != '\0')
|
if ((*to_complete)[0] != '\0')
|
||||||
{
|
{
|
||||||
sz = filter_options(opts, &sz, *to_complete);
|
sz = filter_options(opts, &sz, *to_complete);
|
||||||
@ -107,7 +118,18 @@ size_t filter_options(char ***comp_list, size_t *size, char *filter_string)
|
|||||||
for (size_t i = 0; i < *size; i++)
|
for (size_t i = 0; i < *size; i++)
|
||||||
insert_tree(child_dirs_root, (*comp_list)[i]);
|
insert_tree(child_dirs_root, (*comp_list)[i]);
|
||||||
|
|
||||||
*size = list_strings_containing(child_dirs_root, filter_string, comp_list);
|
char **folders = NULL;
|
||||||
|
int path_depth = sep_string(filter_string, &folders, "/");
|
||||||
|
|
||||||
|
char *last_option = strdup(filter_string);
|
||||||
|
|
||||||
|
if (path_depth > 0)
|
||||||
|
{
|
||||||
|
free(last_option);
|
||||||
|
last_option = folders[path_depth - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
*size = list_strings_containing(child_dirs_root, last_option, comp_list);
|
||||||
|
|
||||||
free_tree(child_dirs_root);
|
free_tree(child_dirs_root);
|
||||||
|
|
||||||
|
28
src/keys.c
28
src/keys.c
@ -18,8 +18,7 @@ void delete_key(int pos, int *n, char **line)
|
|||||||
remove_on_pos(line, pos + 1);
|
remove_on_pos(line, pos + 1);
|
||||||
(*n)--;
|
(*n)--;
|
||||||
|
|
||||||
char *buff = malloc(1);
|
char *buff = strdup("");
|
||||||
buff[0] = '\0';
|
|
||||||
size_t buff_size = 1;
|
size_t buff_size = 1;
|
||||||
|
|
||||||
append_to_buff(&buff, &buff_size, "\0337", 2);
|
append_to_buff(&buff, &buff_size, "\0337", 2);
|
||||||
@ -68,8 +67,7 @@ void move_right(int *pos, int n)
|
|||||||
*/
|
*/
|
||||||
void home_key(int *pos)
|
void home_key(int *pos)
|
||||||
{
|
{
|
||||||
char *buff = malloc(1);
|
char *buff = strdup("");
|
||||||
buff[0] = '\0';
|
|
||||||
size_t buff_size = 1;
|
size_t buff_size = 1;
|
||||||
|
|
||||||
for (int i = 0; i < *pos; i++)
|
for (int i = 0; i < *pos; i++)
|
||||||
@ -89,8 +87,7 @@ void home_key(int *pos)
|
|||||||
*/
|
*/
|
||||||
void end_key(int *pos, int n)
|
void end_key(int *pos, int n)
|
||||||
{
|
{
|
||||||
char *buff = malloc(1);
|
char *buff =strdup("");
|
||||||
buff[0] = '\0';
|
|
||||||
size_t buff_size = 1;
|
size_t buff_size = 1;
|
||||||
|
|
||||||
for (int i = 0; i < n - *pos; i++)
|
for (int i = 0; i < n - *pos; i++)
|
||||||
@ -118,8 +115,7 @@ void backspace_key(int *pos, int *n, char **line)
|
|||||||
(*n)--;
|
(*n)--;
|
||||||
(*pos)--;
|
(*pos)--;
|
||||||
|
|
||||||
char *buff = malloc(1);
|
char *buff = strdup("");
|
||||||
buff[0] = '\0';
|
|
||||||
size_t buff_size = 1;
|
size_t buff_size = 1;
|
||||||
|
|
||||||
append_to_buff(&buff, &buff_size, "\033[D", 3);
|
append_to_buff(&buff, &buff_size, "\033[D", 3);
|
||||||
@ -152,11 +148,10 @@ void tab_key(int *pos, int *n, char **line)
|
|||||||
*pos = strlen(*line);
|
*pos = strlen(*line);
|
||||||
*n = *pos;
|
*n = *pos;
|
||||||
|
|
||||||
char *buff = malloc(1), *output;
|
char *buff = strdup(""), *output = NULL;
|
||||||
buff[0] = '\0';
|
|
||||||
size_t buff_size = 1;
|
size_t buff_size = 1;
|
||||||
|
|
||||||
char **complete_options, *to_complete;
|
char **complete_options = malloc(0), *to_complete = NULL;
|
||||||
size_t opts_sz = get_complete_options(&complete_options, *line, &to_complete);
|
size_t opts_sz = get_complete_options(&complete_options, *line, &to_complete);
|
||||||
|
|
||||||
if (opts_sz == 1)
|
if (opts_sz == 1)
|
||||||
@ -172,10 +167,14 @@ void tab_key(int *pos, int *n, char **line)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
append_to_buff(&buff, &buff_size, "\x1b[2K\r", 5);
|
||||||
|
|
||||||
append_to_buff(&buff, &buff_size, "\x1b[2K", 4);
|
if ((int)opts_sz < 1)
|
||||||
|
{
|
||||||
|
append_to_buff(&buff, &buff_size, "No suggestions", strlen("No suggestions"));
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < opts_sz; i++)
|
for (int i = 0; i < (int)opts_sz; i++)
|
||||||
{
|
{
|
||||||
append_to_buff(&buff, &buff_size, complete_options[i], strlen(complete_options[i]));
|
append_to_buff(&buff, &buff_size, complete_options[i], strlen(complete_options[i]));
|
||||||
append_to_buff(&buff, &buff_size, " ", 1);
|
append_to_buff(&buff, &buff_size, " ", 1);
|
||||||
@ -207,8 +206,7 @@ void tab_key(int *pos, int *n, char **line)
|
|||||||
*/
|
*/
|
||||||
void printable_key(int *pos, int *n, char c, char **line)
|
void printable_key(int *pos, int *n, char c, char **line)
|
||||||
{
|
{
|
||||||
char *buff = malloc(1);
|
char *buff = strdup("");
|
||||||
buff[0] = '\0';
|
|
||||||
size_t buff_size = 1;
|
size_t buff_size = 1;
|
||||||
|
|
||||||
(*n)++;
|
(*n)++;
|
||||||
|
10
src/shell.c
10
src/shell.c
@ -16,13 +16,12 @@ int (*builtin_func[])(char **) = {
|
|||||||
*/
|
*/
|
||||||
void process_command()
|
void process_command()
|
||||||
{
|
{
|
||||||
char **args;
|
char **args = NULL;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
char *line = malloc(1);
|
char *line = strdup("");
|
||||||
line[0] = '\0';
|
|
||||||
|
|
||||||
char *prompt = compose_prompt();
|
char *prompt = compose_prompt();
|
||||||
|
|
||||||
@ -48,7 +47,7 @@ int process_line(char *line, char ***args)
|
|||||||
{
|
{
|
||||||
int buff_size = ARG_SIZE, pos = 0;
|
int buff_size = ARG_SIZE, pos = 0;
|
||||||
*args = malloc(buff_size * sizeof(char *));
|
*args = malloc(buff_size * sizeof(char *));
|
||||||
char *tok, *rest = strdup(line);
|
char *tok = NULL, *rest = strdup(line);
|
||||||
|
|
||||||
while ((tok = strtok_r(rest, " ", &rest)) != NULL)
|
while ((tok = strtok_r(rest, " ", &rest)) != NULL)
|
||||||
{
|
{
|
||||||
@ -157,8 +156,7 @@ int sh_exit(char **args)
|
|||||||
|
|
||||||
char *compose_prompt()
|
char *compose_prompt()
|
||||||
{
|
{
|
||||||
char *prompt = malloc(1);
|
char *prompt = strdup("");
|
||||||
prompt[0] = '\0';
|
|
||||||
|
|
||||||
prompt = realloc(prompt, strlen(prompt) + 4);
|
prompt = realloc(prompt, strlen(prompt) + 4);
|
||||||
if (getuid() == 0)
|
if (getuid() == 0)
|
||||||
|
17
src/utils.c
17
src/utils.c
@ -36,11 +36,9 @@ void remove_on_pos(char **str, int pos)
|
|||||||
size_t len = strlen(*str);
|
size_t len = strlen(*str);
|
||||||
if (pos <= len)
|
if (pos <= len)
|
||||||
{
|
{
|
||||||
|
|
||||||
for (int i = pos - 1; i < len; i++)
|
for (int i = pos - 1; i < len; i++)
|
||||||
{
|
|
||||||
(*str)[i] = (*str)[i + 1];
|
(*str)[i] = (*str)[i + 1];
|
||||||
}
|
|
||||||
(*str)[len] = '\0';
|
(*str)[len] = '\0';
|
||||||
*str = realloc(*str, len);
|
*str = realloc(*str, len);
|
||||||
}
|
}
|
||||||
@ -50,11 +48,12 @@ void remove_on_pos(char **str, int pos)
|
|||||||
|
|
||||||
int sep_string(char *line, char ***toks, char *sep)
|
int sep_string(char *line, char ***toks, char *sep)
|
||||||
{
|
{
|
||||||
|
free(*toks);
|
||||||
char *tmp_line = strdup(line);
|
char *tmp_line = strdup(line);
|
||||||
int n = 0;
|
int n = 0;
|
||||||
*toks = malloc(sizeof(char *) * n);
|
*toks = malloc(sizeof(char *) * n);
|
||||||
|
|
||||||
char *tmp;
|
char *tmp = NULL;
|
||||||
while ((tmp = strsep(&tmp_line, sep)) != NULL)
|
while ((tmp = strsep(&tmp_line, sep)) != NULL)
|
||||||
{
|
{
|
||||||
n++;
|
n++;
|
||||||
@ -62,18 +61,20 @@ int sep_string(char *line, char ***toks, char *sep)
|
|||||||
(*toks)[n - 1] = strdup(tmp);
|
(*toks)[n - 1] = strdup(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(tmp_line);
|
||||||
|
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *trim_string(char **str)
|
char *trim_string(char **str)
|
||||||
{
|
{
|
||||||
while ((*str)[0] == ' ')
|
while ((*str)[0] == ' ')
|
||||||
memmove(*str, *str + 1, strlen(*str));
|
remove_on_pos(str, 1);
|
||||||
|
|
||||||
for (int i = 1; i < strlen(*str); i++)
|
for (int i = 1; i < strlen(*str); i++)
|
||||||
if ((*str)[i] == ' ' && (*str)[i - 1] == ' ')
|
if ((*str)[i] == ' ' && (*str)[i - 1] == ' ')
|
||||||
{
|
{
|
||||||
memmove(*str + i, *str + i + 1, strlen(*str + i));
|
remove_on_pos(str, i);
|
||||||
i--;
|
i--;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,10 +83,8 @@ char *trim_string(char **str)
|
|||||||
|
|
||||||
void free_str_arr(char **arr)
|
void free_str_arr(char **arr)
|
||||||
{
|
{
|
||||||
|
if (arr)
|
||||||
for (int i = 0; i < sizeof(arr) / sizeof(char *); i++)
|
for (int i = 0; i < sizeof(arr) / sizeof(char *); i++)
|
||||||
{
|
|
||||||
free(arr[i]);
|
free(arr[i]);
|
||||||
}
|
|
||||||
|
|
||||||
free(arr);
|
free(arr);
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user