From f43f11cd142a06e7c236f0e23a31d4af40273ff4 Mon Sep 17 00:00:00 2001 From: m600x Date: Fri, 3 Feb 2017 12:36:25 +0100 Subject: [PATCH] Rebase init --- 42sh/Makefile | 34 ++++-- 42sh/includes/completion.h | 96 ++++++++++++++++ 42sh/includes/minishell.h | 10 +- 42sh/src/completion/c_binary.c | 39 +++++++ 42sh/src/completion/c_clear.c | 60 ++++++++++ 42sh/src/completion/c_files.c | 63 +++++++++++ 42sh/src/completion/c_init.c | 64 +++++++++++ 42sh/src/completion/c_matching.c | 38 +++++++ 42sh/src/completion/c_parser.c | 81 ++++++++++++++ 42sh/src/completion/c_pathsolver.c | 173 +++++++++++++++++++++++++++++ 42sh/src/completion/c_printer.c | 93 ++++++++++++++++ 42sh/src/completion/c_single.c | 40 +++++++ 42sh/src/completion/c_sizing.c | 65 +++++++++++ 42sh/src/completion/c_terminal.c | 65 +++++++++++ 42sh/src/completion/completion.c | 104 +++++++++++++++++ 42sh/src/line-editing/get_touch.c | 4 +- 16 files changed, 1010 insertions(+), 19 deletions(-) create mode 100644 42sh/includes/completion.h create mode 100644 42sh/src/completion/c_binary.c create mode 100644 42sh/src/completion/c_clear.c create mode 100644 42sh/src/completion/c_files.c create mode 100644 42sh/src/completion/c_init.c create mode 100644 42sh/src/completion/c_matching.c create mode 100644 42sh/src/completion/c_parser.c create mode 100644 42sh/src/completion/c_pathsolver.c create mode 100644 42sh/src/completion/c_printer.c create mode 100644 42sh/src/completion/c_single.c create mode 100644 42sh/src/completion/c_sizing.c create mode 100644 42sh/src/completion/c_terminal.c create mode 100644 42sh/src/completion/completion.c diff --git a/42sh/Makefile b/42sh/Makefile index e240d66b..bd707f4a 100644 --- a/42sh/Makefile +++ b/42sh/Makefile @@ -1,14 +1,14 @@ -#* ************************************************************************** *# -#* *# -#* ::: :::::::: *# -#* Makefile :+: :+: :+: *# -#* +:+ +:+ +:+ *# -#* By: wescande +#+ +:+ +#+ *# -#* +#+#+#+#+#+ +#+ *# -#* Created: 2016/08/29 21:32:58 by wescande #+# #+# *# -#* Updated: 2016/09/27 20:14:55 by wescande ### ########.fr *# -#* *# -#* ************************************************************************** *# +# **************************************************************************** # +# # +# ::: :::::::: # +# Makefile :+: :+: :+: # +# +:+ +:+ +:+ # +# By: wescande +#+ +:+ +#+ # +# +#+#+#+#+#+ +#+ # +# Created: 2016/08/29 21:32:58 by wescande #+# #+# # +# Updated: 2017/02/03 12:26:23 by alao ### ########.fr # +# # +# **************************************************************************** # NAME = 42sh @@ -29,6 +29,18 @@ INC_DIR = includes/ OBJ_DIR = objs/ SRC_BASE = \ +completion/c_binary.c\ +completion/c_clear.c\ +completion/c_files.c\ +completion/c_init.c\ +completion/c_matching.c\ +completion/c_parser.c\ +completion/c_pathsolver.c\ +completion/c_printer.c\ +completion/c_single.c\ +completion/c_sizing.c\ +completion/c_terminal.c\ +completion/completion.c\ builtin/bt_read_get.c\ builtin/bt_read_parse.c\ builtin/bt_read_term.c\ diff --git a/42sh/includes/completion.h b/42sh/includes/completion.h new file mode 100644 index 00000000..782e24d2 --- /dev/null +++ b/42sh/includes/completion.h @@ -0,0 +1,96 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* completion.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: alao +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2016/02/18 11:13:04 by alao #+# #+# */ +/* Updated: 2017/02/03 12:23:05 by alao ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef COMPLETION_H +# define COMPLETION_H + +# include "minishell.h" + +/* +** Autocompletion list for the valid candidates from the parser. +** id : ID of the item. +** name : Name of the item. +** type : Type of the item. +** len : Length of the name. +** cursor : Boolean to know which item is currently selected. +** next : Pointer to the next item of the list. +** prev : Pointer to the previous item of the list. +*/ + +typedef struct s_clst +{ + int id; + char *name; + int type; + int len; + int cursor; + struct s_clst *next; + struct s_clst *prev; +} t_clst; + +/* +** Autocompletion structure composed as follow: +** rcmd : The raw command from the begining to the cursor position. +** ircmd : Cursor position. +** cpath : Placeholder for the solved path. Later used for the parser. +** match : Part of the command to match when searching. +** home : Path to home for the ~ solving. +** pwd : Current folder to solve local path. +** trail : The rest of the command after the position. +** prompt : Size of the prompt. +** c_sx : Size of the longest word from the list. +** c_sy : Size of the list in number of item. +** c_pline : Number of item per line when printing. +** c_line : Number of line required to move to terminal up. +** win_x : Size of the window in length. +** lst : List of the item corresponding to the completion. +*/ + +typedef struct s_comp +{ + char *rcmd; + int ircmd; + char *cpath; + char *match; + char *home; + char *pwd; + char *trail; + int prompt; + int c_sx; + int c_sy; + int c_pline; + int c_line; + int win_x; + int key; + t_clst *lst; +} t_comp; + +int completion(long int key); +void c_init(t_data *s, long int input); +int c_matching(t_data *s, t_comp *c); +int c_seek_binary(t_data *s, t_comp *c); +int c_seek_files(t_data *s, t_comp *c); +int c_parser(t_comp *c, char *path, char *name); +int c_sizing(t_comp *c); + +int c_single(t_comp *c); + +void c_term_mv_down(t_comp *c); +void c_term_mv_back(t_comp *c); +void c_printer(t_comp *c); + +int c_clear(t_data *s); +char *path_solver(t_comp *c, char *cmd, char *cwd); + +int test(t_comp *c); + +#endif diff --git a/42sh/includes/minishell.h b/42sh/includes/minishell.h index a2b32c83..d3959f46 100644 --- a/42sh/includes/minishell.h +++ b/42sh/includes/minishell.h @@ -6,7 +6,7 @@ /* By: jhalford +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2016/11/10 13:07:44 by jhalford #+# #+# */ -/* Updated: 2017/02/02 14:46:23 by jhalford ### ########.fr */ +/* Updated: 2017/02/03 12:16:52 by alao ### ########.fr */ /* */ /* ************************************************************************** */ @@ -24,6 +24,7 @@ # include "builtin.h" # include "job_control.h" # include "glob.h" +# include "completion.h" # include # include @@ -32,11 +33,6 @@ # include # include -struct s_comp -{ - int a; -}; - # define SHELL_OPTS_JOBC (1 << 0) # define SHELL_OPTS_LC (1 << 1) # define SHELL_MODE_INPUT (1 << 2) @@ -54,7 +50,7 @@ struct s_data char **argv; t_flag opts; t_line line; - t_comp comp; + t_comp *comp; t_exec exec; t_jobc jobc; }; diff --git a/42sh/src/completion/c_binary.c b/42sh/src/completion/c_binary.c new file mode 100644 index 00000000..fd46eb81 --- /dev/null +++ b/42sh/src/completion/c_binary.c @@ -0,0 +1,39 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* c_binary.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: alao +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2017/01/09 13:30:57 by alao #+# #+# */ +/* Updated: 2017/01/11 14:08:08 by alao ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "completion.h" + +/* +** Retrieve the path from the env and cycle through it to find the matching +** element with the c_parser() function +*/ + +int c_seek_binary(t_data *s, t_comp *c) +{ + char *tmp; + char **paths; + int i; + + DG("SB: Start"); + i = 0; + tmp = NULL; + if (!(tmp = ft_strdup(ft_getenv(s->env, "PATH")))) + return (-1); + DG("SB: Path extracted [%s]", tmp); + paths = ft_strsplit(tmp, ':'); + c->match = ft_strdup(c->rcmd); + while (paths[i]) + c_parser(c, paths[i++], c->rcmd); + tmp ? ft_memdel((void *)&tmp) : (0); + paths ? ft_sstrfree(paths) : (0); + return (0); +} diff --git a/42sh/src/completion/c_clear.c b/42sh/src/completion/c_clear.c new file mode 100644 index 00000000..1cc89271 --- /dev/null +++ b/42sh/src/completion/c_clear.c @@ -0,0 +1,60 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* c_clear.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: alao +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2017/01/10 11:37:43 by alao #+# #+# */ +/* Updated: 2017/01/31 18:55:16 by alao ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "completion.h" + +/* +** Clear the list from the memory +*/ + +static void c_clear_lst(t_comp *c) +{ + t_clst *c_lst; + t_clst *p_lst; + + c_lst = c->lst; + c->lst->prev ? (c->lst = c->lst->prev) : (0); + c_lst->prev->next = NULL; + while (c_lst->next) + { + c_lst->name ? ft_memdel((void *)&c_lst->name) : (0); + c_lst->prev = NULL; + p_lst = c_lst; + c_lst = c_lst->next; + p_lst->next = NULL; + p_lst ? ft_memdel((void *)&p_lst) : (0); + } + c_lst->name ? ft_memdel((void *)&c_lst->name) : (0); + c_lst ? ft_memdel((void *)&c_lst) : (0); +} + +/* +** Clear the structure of the autocompletion from the memory and call the above +** function +*/ + +int c_clear(t_data *s) +{ + t_comp *ptr; + + ptr = s->comp; + ptr->rcmd ? ft_memdel((void *)&ptr->rcmd) : (0); + ptr->match ? ft_memdel((void *)&ptr->match) : (0); + ptr->cpath ? ft_memdel((void *)&ptr->cpath) : (0); + ptr->home ? ft_memdel((void *)&ptr->home) : (0); + ptr->pwd ? ft_memdel((void *)&ptr->pwd) : (0); + ptr->trail ? ft_memdel((void *)&ptr->trail) : (0); + if (ptr->lst && ptr->lst->name) + c_clear_lst(ptr); + s->comp = NULL; + return (0); +} diff --git a/42sh/src/completion/c_files.c b/42sh/src/completion/c_files.c new file mode 100644 index 00000000..98046317 --- /dev/null +++ b/42sh/src/completion/c_files.c @@ -0,0 +1,63 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* c_files.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: alao +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2017/01/09 13:31:21 by alao #+# #+# */ +/* Updated: 2017/01/11 14:06:50 by alao ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "completion.h" + +/* +** Clear the binary from c->rcmd ans save the result in c->match. Return the +** path part of it if exist or NULL. +*/ + +static char *c_slicer(t_comp *c) +{ + char *tmp; + char *rt; + int i; + + i = 0; + tmp = NULL; + rt = NULL; + while (c->rcmd[i] != ' ') + i++; + c->rcmd[i] == ' ' ? i++ : (0); + if (i == (int)ft_strlen(c->rcmd)) + return (NULL); + tmp = ft_strsub(c->rcmd, i, ft_strlen(c->rcmd) - i); + i = ft_strlen(tmp) - 1; + while (i > 0 && tmp[i] && tmp[i] != '/') + i--; + tmp[i] == '/' ? i++ : (0); + rt = ft_strsub(tmp, 0, i); + if (i <= (int)ft_strlen(tmp) - i + 1) + c->match = ft_strsub(tmp, i, ft_strlen(tmp) - i); + DG("From [%s] to path [%s] and match [%s]", tmp, rt, c->match); + tmp ? ft_memdel((void *)&tmp) : (0); + return (rt); +} + +/* +** Files searching +*/ + +int c_seek_files(t_data *s, t_comp *c) +{ + DG("Seek Files"); + (void)s; + char *path; + + path = c_slicer(c); + c->cpath = path_solver(c, path, NULL); + DG("Solved as [%s]", c->cpath); + path ? ft_memdel((void *)&path) : (0); + c_parser(c, c->cpath, c->match); + return (0); +} diff --git a/42sh/src/completion/c_init.c b/42sh/src/completion/c_init.c new file mode 100644 index 00000000..36247c0c --- /dev/null +++ b/42sh/src/completion/c_init.c @@ -0,0 +1,64 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* c_init.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: alao +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2017/01/09 11:21:16 by alao #+# #+# */ +/* Updated: 2017/02/03 12:28:49 by alao ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "completion.h" + +/* +** Trim if there's many commands in a raw separed with a semi colon. +*/ + +static char *c_trimmer(char *cmd, int st, int nd) +{ + char *rt; + int len; + + rt = NULL; + len = ft_strlen(cmd); + if (st == len) + st--; + while (st && cmd[st] && cmd[st] != ';') + st--; + cmd[st] == ';' ? st++ : (0); + while (nd < len && cmd[nd] && cmd[nd] != ';' && cmd[nd] != ' ') + nd++; + rt = ft_strsub(cmd, st, nd - st); + return (rt); +} + +/* +** Init the completion structure by populating the default value from the main +** structure data and call for the c_matching() function. +*/ + +void c_init(t_data *s, long int input) +{ + struct winsize win; + + if (!(s->comp = (t_comp *)malloc((sizeof(t_comp))))) + return ; + s->comp->rcmd = c_trimmer(s->line.input, s->line.pos, s->line.pos); + if (ft_strlen(s->line.input) > s->line.pos) + s->comp->trail = ft_strsub(s->line.input, s->line.pos, ft_strlen(s->line.input) - s->line.pos); + else + s->comp->trail = NULL; + s->comp->ircmd = s->line.pos; + s->comp->match = NULL; + s->comp->cpath = NULL; + s->comp->lst = NULL; + ioctl(0, TIOCGWINSZ, &win); + s->comp->win_x = win.ws_col; + s->comp->home = ft_strdup(ft_getenv(s->env, "HOME")); + s->comp->pwd = ft_strdup(ft_getenv(s->env, "PWD")); + s->comp->key = input; + s->comp->prompt = s->line.prompt_size; + c_matching(s, s->comp); +} diff --git a/42sh/src/completion/c_matching.c b/42sh/src/completion/c_matching.c new file mode 100644 index 00000000..43774657 --- /dev/null +++ b/42sh/src/completion/c_matching.c @@ -0,0 +1,38 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* c_matching.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: alao +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2016/10/15 13:27:14 by alao #+# #+# */ +/* Updated: 2017/02/03 12:06:23 by alao ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "completion.h" + +/* +** Start the parsing for the autocompletion. If a space is found in the command +** it will call c_seek_files() function. If not, it assume it will be a binary +** so the function c_seek_binary() is called instead. +** Once that done, the printing function should occur. +** NOT YET IMPLEMENTED +*/ + +int c_matching(t_data *s, t_comp *c) +{ + if (!(ft_strchr(c->rcmd, ' '))) + c_seek_binary(s, c); + else + c_seek_files(s, c); + if (c->lst) +// { + c_sizing(c); +// DG("Seek Binary end [%d]", c->lst->prev->id); +// test(c); +// } +// else +// DG("Seek Binary end No result"); + return (0); +} diff --git a/42sh/src/completion/c_parser.c b/42sh/src/completion/c_parser.c new file mode 100644 index 00000000..cf73b457 --- /dev/null +++ b/42sh/src/completion/c_parser.c @@ -0,0 +1,81 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* c_parser.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: alao +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2017/01/09 13:52:07 by alao #+# #+# */ +/* Updated: 2017/01/31 18:34:54 by alao ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "completion.h" + +/* +** Add the matching element to the list +*/ + +static void c_add_to_lst(t_comp *c, t_clst *node) +{ + DG("PARSER: Adding node [%s]", node->name); + if (c->lst == NULL) + { + c->lst = node; + node->next = node; + node->prev = node; + node->cursor = 1; + node->id = 1; + } + else + { + node->id = c->lst->prev->id + 1; + c->lst->prev->next = node; + node->prev = c->lst->prev; + node->next = c->lst; + c->lst->prev = node; + } +} + +/* +** Determine if the element should be added to the list. If so, the node is +** created and the function above is called to add it. +*/ + +static int c_storing(t_comp *c, char *value, unsigned char type) +{ + t_clst *tmp; + + if (ft_strncmp(".", value, 1) == 0 || ft_strncmp("..", value, 2) == 0) + return (0); + if (c->match && ft_strnequ(c->match, value, ft_strlen(c->match)) != 1) + return (0); + if (c->match && ft_strequ(c->match, value)) + return (0); + if (!(tmp = (t_clst *)malloc(sizeof(t_clst)))) + return (-1); + tmp->name = ft_strdup(value); + tmp->len = ft_strlen(tmp->name); + tmp->type = (int)type; + tmp->cursor = 0; + c_add_to_lst(c, tmp); + return (0); +} + +/* +** Cycle through the path specified. +*/ + +int c_parser(t_comp *c, char *path, char *name) +{ + DG("PARSER: Search for [%s] in [%s]", name, path); + DIR *rep; + struct dirent *dirc; + + if (!(rep = opendir(path))) + return (-1); + while ((dirc = readdir(rep))) + c_storing(c, dirc->d_name, dirc->d_type); + closedir(rep); + return (0); +} diff --git a/42sh/src/completion/c_pathsolver.c b/42sh/src/completion/c_pathsolver.c new file mode 100644 index 00000000..adbf7c8f --- /dev/null +++ b/42sh/src/completion/c_pathsolver.c @@ -0,0 +1,173 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* c_pathsolver.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: alao +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2016/10/25 18:21:54 by alao #+# #+# */ +/* Updated: 2017/01/11 14:14:09 by alao ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "completion.h" + +void ft_sstrdelete(char **s) +{ + int i; + + i = 0; + while (s[i]) + { + ft_memdel((void *)&s[i++]); + } + ft_memdel((void *)&s); +} + +int ft_sstrlen(char **s) +{ + int i; + + i = 0; + while (s[i]) + i++; + return (i); +} + +char *ft_sstrtostr(char **s, char *sep) +{ + char *tmp; + char *tmp2; + int i; + + tmp = NULL; + tmp2 = NULL; + tmp = ft_strjoin(s[0], sep); + i = 1; + while (s[i]) + { + tmp2 = ft_strjoin(tmp, s[i]); + ft_memdel((void *)&tmp); + tmp = ft_strjoin(tmp2, sep); + ft_memdel((void *)&tmp2); + i++; + } + return (tmp); +} + +static char *tilde(t_comp *c, char *cmd) +{ + char *t_home; + char *t_sub; + char *rt; + int l_cmd; + + t_home = NULL; + t_sub = NULL; + rt = NULL; + l_cmd = ft_strlen(cmd); + if ((t_home = ft_strdup(c->home))) + if ((t_sub = ft_strsub(cmd, 1, (l_cmd - 1)))) + rt = ft_strjoin(t_home, t_sub); + t_home ? ft_memdel((void *)&t_home) : (0); + t_sub ? ft_memdel((void *)&t_sub) : (0); + return (rt); +} + +/* +** BUILTINS: Advanced dots purge if the first is not enough. Remove a /path/ +** from the raw command if .. is found. Delete the . . +*/ + +static char *dots_purge(char **scwd, char **scmd, int i) +{ + char *tmp; + char *rt; + int j; + + tmp = NULL; + rt = NULL; + ((j = ft_sstrlen(scwd)) > 0) ? (j--) : (0); + (!(scwd[1])) ? (scwd[0] = ft_strdup("/")) : (0); + while (scmd[i] && scwd[0]) + { + if (!(ft_strcmp(scmd[i], ".")) || !(ft_strcmp(scmd[i], scwd[j])) || + !(ft_strcmp(scmd[i], ".."))) + (!(ft_strcmp(scmd[i], ".."))) ? (ft_memdel((void *)&scwd[j])) : (0); + else if ((scwd[j + 1] = ft_strdup(scmd[i]))) + scwd[j + 2] = NULL; + i++; + ((j = ft_sstrlen(scwd)) > 0) ? (j--) : (0); + (!(scwd[0])) ? (scwd[0] = ft_strdup("/")) : (0); + } + rt = ft_sstrtostr(scwd, "/"); + tmp = ft_strjoin("/", rt); + tmp ? ft_memdel((void *)&rt) : (0); + rt = ft_strsub(tmp, 0, (ft_strlen(tmp) - 1)); + tmp ? ft_memdel((void *)&tmp) : (0); + return (rt); +} + +/* +** BUILTINS: Solve the dots pattern in the path +*/ + +static char *dots(char *cmd, char *cwd, int i) +{ + char *tmp; + char **scmd; + char **scwd; + + tmp = NULL; + if (!(ft_strcmp(cmd, ".")) || !(ft_strcmp(cmd, "./"))) + return (ft_strdup(cwd)); + if (!ft_strcmp(cmd, "..") && cwd && (i = ft_strlen(cwd))) + { + while (cwd[i] != '/') + i--; + (i) ? (tmp = ft_strncpy(ft_strnew(i), cwd, i)) : (0); + } + if (!tmp && cwd && (i = ft_strlen(cwd))) + { + scmd = ft_strsplit(cmd, '/'); + scwd = ft_strsplit(cwd, '/'); + tmp = dots_purge(scwd, scmd, 0); + scmd ? ft_sstrdelete(scmd) : (0); + scwd ? ft_sstrdelete(scwd) : (0); + } + if (!cwd) + tmp = ft_strdup("/"); + return (tmp); +} + +/* +** BUILTINS: Determine the type of commands and redistribute it +*/ + +char *path_solver(t_comp *c, char *cmd, char *cwd) +{ + char *dir; + char *tmp; + char *ncmd; + + dir = NULL; + tmp = NULL; + ncmd = cmd ? ft_strtrim(cmd) : NULL; + cwd = getcwd(cwd, 512); + !cwd ? cwd = ft_strdup(c->pwd) : (0); + if (!ncmd || (*ncmd != '.' && *ncmd != '~' && *ncmd != '/')) + { + tmp = ft_strjoin(cwd, "/"); + dir = ncmd ? ft_strjoin(tmp, ncmd) : ft_strdup(cwd); + tmp ? ft_memdel((void *)&tmp) : (0); + } + else + { + (*ncmd == '~') ? (dir = tilde(c, ncmd)) : (0); + (*ncmd == '.') ? (dir = dots(ncmd, cwd, 0)) : (0); + (*ncmd == '/') ? (dir = ft_strdup(ncmd)) : (0); + } + cwd ? ft_memdel((void *)&cwd) : (0); + ncmd ? ft_memdel((void *)&ncmd) : (0); + return (dir); +} diff --git a/42sh/src/completion/c_printer.c b/42sh/src/completion/c_printer.c new file mode 100644 index 00000000..9162bf7f --- /dev/null +++ b/42sh/src/completion/c_printer.c @@ -0,0 +1,93 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* c_printer.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: alao +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2017/01/10 12:55:39 by alao #+# #+# */ +/* Updated: 2017/01/19 15:49:34 by alao ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "completion.h" + +/* +** AUTOCOMPLETION: Print the name with or without an underline and colored upon +** file type as follow: +** - (4) Folder: Red "\e[1;31m" +** - (10) Symlink: Cyan "\e[96m" +*/ + +static void c_printer_node(t_clst *lst) +{ + DG("File [%s] type [%d]", lst->name, (int)lst->type); + lst->cursor ? ft_putstr(tgetstr("us", NULL)) : (0); + lst->cursor ? (ft_putstr_fd("\033[31m", 2)) : (0); + lst->type == 4 ? ft_putstr_fd("\e[1;31m", 2) : (0); + lst->type == 10 ? ft_putstr_fd("\e[1;96m", 2) : (0); + ft_putstr_fd(lst->name, 2); + ft_putstr_fd("\033[00m", 2); + if (lst->type == 4) + ft_putstr_fd("/", 2); + else if (lst->type == 10) + ft_putstr_fd("@", 2); + else + ft_putstr_fd(" ", 2); + lst->cursor ? ft_putstr(tgetstr("ue", NULL)) : (0); +} + +/* +** AUTOCOMPLETION: Cycle through the line to print on the same line the +** number of time to fill it PER LINE and add 2 space after the print to +** accomodate the trailing / for folder and a space in between. +*/ + +static int c_printer_line(t_comp *c, t_clst *lst, int loop, int i) +{ + t_clst *ptr; + + ptr = lst->next; + c_printer_node(lst); + while (loop) + { + i = 1; + while (i++ < (c->c_line)) + { + if (ptr == c->lst) + return (0); + ptr = ptr->next; + } + if (ptr != c->lst) + { + i = lst->len; + while (i++ < (c->c_sx + 1)) + ft_putstr(" "); + c_printer_node(ptr); + lst = ptr; + ptr = ptr->next; + } + loop--; + } + return (0); +} + +/* +** AUTOCOMPLETION: Control the number of time it cycle for LINE +*/ + +void c_printer(t_comp *c) +{ + t_clst *ptr; + int loop; + + ptr = c->lst; + loop = c->c_line; + while (loop) + { + c_printer_line(c, ptr, c->c_pline, 1); + loop > 1 ? ft_putstr(tgetstr("do", NULL)) : (0); + ptr = ptr->next; + loop--; + } +} diff --git a/42sh/src/completion/c_single.c b/42sh/src/completion/c_single.c new file mode 100644 index 00000000..d10227d8 --- /dev/null +++ b/42sh/src/completion/c_single.c @@ -0,0 +1,40 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* c_single.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: alao +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2017/01/31 14:01:22 by alao #+# #+# */ +/* Updated: 2017/01/31 18:57:59 by alao ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "completion.h" + + +int c_single(t_comp *c) +{ + DG("SINGLE"); + DG("Containing [%s] match [%s] Candidat [%s]", c->rcmd, c->match, c->lst->name); + char *tmp; + char *rt; + int new_pos; + + tmp = NULL; + rt = NULL; + new_pos = c->ircmd + (ft_strlen(c->lst->name) - ft_strlen(c->match)) + 1; + tmp = ft_strsub(c->rcmd, 0, ft_strlen(c->rcmd) - ft_strlen(c->match)); + rt = ft_strjoin(tmp, c->lst->name); + tmp ? ft_memdel((void *)&tmp) : (0); + if (c->trail) + { + tmp = ft_strjoin(rt, " "); + rt ? ft_memdel((void *)&rt) : (0); + rt = ft_strjoin(tmp, c->trail); + } + DG("Resulting RCMD as [%s] with new position [%d] from [%d]", rt, new_pos, c->ircmd); + rt ? ft_memdel((void *)&rt) : (0); + c_clear(data_singleton()); + return (0); +} diff --git a/42sh/src/completion/c_sizing.c b/42sh/src/completion/c_sizing.c new file mode 100644 index 00000000..76e616dc --- /dev/null +++ b/42sh/src/completion/c_sizing.c @@ -0,0 +1,65 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* c_sizing.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: alao +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2017/01/10 08:50:26 by alao #+# #+# */ +/* Updated: 2017/01/19 15:45:35 by alao ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "completion.h" + +/* +** Get the max length from the list +*/ + +static void c_max_length(t_comp *s) +{ + t_clst *tmp; + int max_x; + int max_y; + + if (s->lst && s->lst->name && s->lst == s->lst->next) + { + s->c_sx = s->lst->len; + s->c_sy = 1; + } + else if (s->lst && s->lst->name) + { + max_x = s->lst->len; + max_y = 1; + tmp = s->lst->next; + while (tmp != s->lst) + { + (max_x < tmp->len) ? (max_x = tmp->len) : (0); + max_y++; + tmp = tmp->next; + } + s->c_sx = max_x; + s->c_sy = max_y; + } +} + +/* +** Determine the number of column and row is possible using the list size +** by adding the length of the name plus 2 for the potential trailing / for +** folder. +*/ + +int c_sizing(t_comp *c) +{ + c->lst && c->lst->name ? c_max_length(c) : 0; + c->c_pline = c->win_x / (c->c_sx + 2); + c->c_line = 0; + while ((c->c_line * c->c_pline) < c->c_sy) + c->c_line++; + if (c->win_x < c->c_sx) + { + c->c_pline = 0; + c->c_line = 0; + } + return (0); +} diff --git a/42sh/src/completion/c_terminal.c b/42sh/src/completion/c_terminal.c new file mode 100644 index 00000000..f8c42c89 --- /dev/null +++ b/42sh/src/completion/c_terminal.c @@ -0,0 +1,65 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* c_terminal.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: alao +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2016/10/11 10:44:40 by alao #+# #+# */ +/* Updated: 2017/01/31 13:24:50 by alao ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "completion.h" + +/* +** AUTOCOMPLETION: Move the terminal up by the number of line needed and +** move it back up to the original position +*/ + +void c_term_mv_back(t_comp *c) +{ + DG("Terminal back up"); + int i; + int lcmd; + + i = 0; + while (i != (c->c_line)) + { + ft_putstr(tgetstr("up", NULL)); + i++; + } + ft_putstr(tgetstr("cr", NULL)); + i = 0; + lcmd = 0; + c->rcmd ? lcmd += (int)ft_strlen(c->rcmd) + c->prompt + 1 : 0; + while (i < lcmd) + { + ft_putstr(tgetstr("nd", NULL)); + i++; + } +} + +/* +** AUTOCOMPLETION: Move the terminal down by the number of line needed and +** move it back up to the first line under the prompt +*/ + +void c_term_mv_down(t_comp *c) +{ + DG("Terminal down"); + int i; + + i = 0; + while (i < c->c_line) + { + ft_putstr(tgetstr("do", NULL)); + i++; + } + i = 0; + while (i != (c->c_line - 1)) + { + ft_putstr(tgetstr("up", NULL)); + i++; + } +} diff --git a/42sh/src/completion/completion.c b/42sh/src/completion/completion.c new file mode 100644 index 00000000..87f93f32 --- /dev/null +++ b/42sh/src/completion/completion.c @@ -0,0 +1,104 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* completion.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: alao +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2016/09/20 14:50:33 by alao #+# #+# */ +/* Updated: 2017/02/03 12:30:54 by alao ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "completion.h" + +/* +** DEBUG FUNCTION +*/ + +int test(t_comp *c) +{ + DG("\tAutocompletion dump"); + int i = 1; + t_clst *tmp; + + if (!(c->lst)) + { + DG("Empty list"); + return (0); + } + if (c->lst && c->lst->cursor) + DG("Node [x] ID [%d] [%s]", c->lst->id, c->lst->name); + else + DG("Node [ ] ID [%d] [%s]", c->lst->id, c->lst->name); + if (c->lst->prev != c->lst) + { + tmp = c->lst->next; + while (tmp != c->lst) + { + if (tmp->cursor) + DG("Node [x] ID [%d] [%s]", tmp->id, tmp->name); + else + DG("Node [ ] ID [%d] [%s]", tmp->id, tmp->name); + i++; + tmp = tmp->next; + } + } + DG("List configuration as:"); + DG("Max value: Length (X) %d Number (Y) %d", c->c_sx, c->c_sy); + DG("Translated to [%d] Lines and [%d] Column", c->c_line, c->c_pline); + return (0); +} + +static void c_next_item(t_comp *c) +{ + t_clst *ptr; + + ptr = c->lst; + while (!ptr->cursor) + ptr = ptr->next; + ptr->cursor = 0; + ptr->next->cursor = 1; +} + +int completion(long int input) +{ + t_data *s; + + s = data_singleton(); + + DG("\n\n\t\tAutocompletion input key [%d]\n", (int)input); + if (s->comp == NULL) + { + if (s->line.pos == 0) + return (0); + if (s->line.input[s->line.pos] != ' ' && s->line.input[s->line.pos] != '\0') + return (0); + c_init(s, input); + } + else + { + if (input == 9) + c_next_item(s->comp); + else + DG("Place holder to clear or put the selection in rcmd"); + } + test(s->comp); + if (s->comp && s->comp->lst == NULL) + { + DG("Empty list, flushing autocompletion"); + c_clear(s); + } + else if (s->comp && s->comp->lst == s->comp->lst->next) + { + c_single(s->comp); + return (1); + } + else if (s->comp && s->comp->lst != s->comp->lst->next ) + { + c_term_mv_down(s->comp); + c_printer(s->comp); + c_term_mv_back(s->comp); + } + return (0); +} diff --git a/42sh/src/line-editing/get_touch.c b/42sh/src/line-editing/get_touch.c index 2ecde44c..2edec968 100644 --- a/42sh/src/line-editing/get_touch.c +++ b/42sh/src/line-editing/get_touch.c @@ -6,7 +6,7 @@ /* By: gwojda +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2016/12/19 16:28:49 by gwojda #+# #+# */ -/* Updated: 2017/02/02 18:27:07 by gwojda ### ########.fr */ +/* Updated: 2017/02/03 12:23:44 by alao ### ########.fr */ /* */ /* ************************************************************************** */ @@ -56,6 +56,8 @@ char *ft_read_stdin(void) read(0, &ret, sizeof(int)); while (g_key[j].value && g_key[j].value != ret) ++j; + if (data_singleton()->comp || ret == 9) + completion(ret); if (g_key[j].value) g_key[j].f(); else if (ft_isprint(ret))