Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 31 additions & 24 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,53 +2,60 @@
NAME = ft
CC = clang
CFLAGS = -Wall -Werror -Wextra -g
INCLUDE = -I ./app/include

SRC = main.c
SRC += init_and_free_cli.c
SRC += is_valid_option.c
SRC += is_valid_arg.c
SRC += is_valid_name.c
SRC += input_validation.c
SRC += building_project.c
SRC += cli_utils.c
SRC += write_in_files.c

OBJS = $(SRC:.c=.o)
OBJ = $(addprefix ./app/obj/, $(OBJS))
OBJ_DIR = ./app/obj
INCLUDE = -I app/include

# Fontes organizados por subdiretórios
SRC = \
app/src/main.c \
app/src/cli/init_and_free_cli.c \
app/src/cli/is_valid_option.c \
app/src/cli/is_valid_arg.c \
app/src/cli/is_valid_name.c \
app/src/cli/input_validation.c \
app/src/core/building_project.c \
app/src/core/write_in_files.c \
app/src/utils/cli_utils.c \
app/src/commands/cmd_new.c \
app/src/dispatcher/dispatcher.c \
app/src/parser/parser.c \
app/src/fs/fs_create_dir.c \
app/src/fs/fs_create_file.c \
app/src/fs/fs_read_file.c

OBJ_DIR = app/obj
OBJS = $(SRC:app/src/%.c=$(OBJ_DIR)/%.o)

RM = rm -rf

VPATH = ./app/src

LOCAL_INSTALL = /usr/local/bin


# Garante que o subdiretório de destino existe antes de compilar
$(OBJ_DIR)/%.o: %.c
$(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@
@mkdir -p $(dir $@)
$(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@

all: obj_dir $(NAME)

$(NAME): $(OBJ)
$(CC) $(CFLAGS) $(OBJ) $(LIBFT) -o $(NAME)
$(NAME): $(OBJS)
$(CC) $(CFLAGS) $(OBJS) -o $(NAME)

clean:
$(RM) $(OBJ)
$(RM) $(OBJS)
$(RM) $(OBJ_DIR)

fclean: clean
$(RM) $(NAME)

install: $(NAME)
cp $(NAME) $(LOCAL_INSTALL)
cp ./ft_templates/ $(LOCAL_INSTALL) -r

re: fclean all

obj_dir:
@if [ ! -d "$(OBJ_DIR)" ]; then\
mkdir $(OBJ_DIR);\
else\
echo "make: Nothing to be done for 'all'.";\
fi
@mkdir -p $(OBJ_DIR)

.PHONY= all clean fclean re install $(NAME)
134 changes: 134 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,137 @@ ft new project minishell

![giff exemplo do ft cli](./assets/ft_cli_ex.gif)


# Prompts

Como podemos aprimorar este projeto? Por exemplo, que arquitetura de projeto poderiamos usar? E, como otimizar o código para facilitar a inclusão de novas funcionalidades?

Como podemos aprimorar um projeto em C que é uma CLI para criar arquivos para começar um projeto em C? Hoje o projeto executa apenas o comando `ft new project minishell` criando os arquivos: minishell/app/includes/minishell.h, minishell/app/src/main.c, minishell/.gitignore, minishell/README.md e minishell/Makefile. Por exemplo, que arquitetura de projeto poderiamos usar? E, como otimizar o código para facilitar a inclusão de novas funcionalidades?

# Projeto refatoração

Já tememos uma CLI que cria um template básico. Agora a evolução natural é transformar isso em uma ferramenta extensível, modular e sustentável.

## Separação sujerida:

| Módulo | Responsabilidade |
| --------------- | ---------------------------- |
| parser | Interpretar argv |
| dispatcher | Chamar comando correto |
| commands | Lógica específica do comando |
| file_generator | Criar diretórios e arquivos |
| template_engine | Substituir variáveis |
| fs | Abstração de filesystem |

## Implementar `Command Pattern` em C

Mesmo em C, podemos simular orientação a objetos usando struct + function pointers.

**Exemplo**:

```C
//Nova estrutura para comando
typedef struct s_command
{
const char *name;
int (*execute)(int argc, char **argv);
} t_command;

//Registro de comandos, uma array de comandos
t_command commands[] = {
{"new", cmd_new},
{"init", cmd_init},
{NULL, NULL}
};

//Dispatcher
int dispatch_command(const char *cmd, int argc, char **argv)
{
for (int i = 0; commands[i].name != NULL; i++)
{
if (strcmp(commands[i].name, cmd) == 0)
return commands[i].execute(argc, argv);
}
printf("Unknown command\n");
return 1;
}
```

Com isso para adicionar um novo comando fazemos:

1- Criar arquivo em `commands/`

2- Registrar no array

Zero impacto no core.

## Orientações de projeto:

1- Uma função = uma responsabilidade

2- Evitar funções com mais de 30 linhas

3- Evitar dependência circular entre módulos

4- Header minimalista

5- Nunca incluir header desnecessário

## Ordem para execução de tarefas:

Etapa 1:
Refatorar para Command Pattern + separação por módulos

getopt(), getopt_long()

Etapa 2:
Criar sistema de templates externo

Etapa 3:
Criar arquitetura de projeto mais robusta

Etapa 4:
Adicionar novos comandos

Etapa 5:
Testes + documentação

## Sugestão de comportamento

```markdown
sequenceDiagram
participant User
participant Main
participant Parser
participant Dispatcher
participant CmdNew
participant FileGenerator
participant TemplateEngine
participant ft_fs

User->>Main: ft new project minishell

Main->>Parser: parse(argc, argv)
Parser-->>Main: CLIContext { command="new", args }

Main->>Dispatcher: dispatch(context)

Dispatcher->>CmdNew: execute(context)

CmdNew->>FileGenerator: create_project_structure(context)

FileGenerator->>ft_fs: create_dir("minishell/")
FileGenerator->>ft_fs: create_dir("minishell/app/")
FileGenerator->>ft_fs: create_dir("minishell/app/src/")
FileGenerator->>ft_fs: create_dir("minishell/app/includes/")

CmdNew->>TemplateEngine: render("main.c.tpl", context)
TemplateEngine-->>CmdNew: rendered_main.c

CmdNew->>FileGenerator: create_file(path, rendered_main.c)

FileGenerator->>ft_fs: write_file(path, content)

CmdNew-->>Dispatcher: SUCCESS
Dispatcher-->>Main: EXIT_SUCCESS
```
14 changes: 14 additions & 0 deletions app/include/command.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#ifndef COMMAND_H
# define COMMAND_H

# include <stddef.h>
# include "ft_cli.h"

int cmd_new_execute(t_cli_context *ctx);

t_command g_commands[] = {
{"new", cmd_new_execute},
{NULL, NULL}
};

#endif
20 changes: 20 additions & 0 deletions app/include/fs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#ifndef FS_H
# define FS_H

# include <stdio.h>
# include <string.h>
# include <stdlib.h>
# include <unistd.h>
# include <ctype.h>

# include <sys/stat.h>
# include <sys/types.h>
# include <dirent.h>
# include <fcntl.h>

int fs_create_dir(const char *path);
int fs_create_file(const char *path);
char *fs_read_file(const char *path);
// int fs_exists(const char *path);

#endif
22 changes: 22 additions & 0 deletions app/include/ft_cli.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,24 @@ typedef struct s_cli
char *include;
} t_cli;

typedef struct s_cli_context
{
char *command;
char *type;
char *project_name;
int verbose;
} t_cli_context;

typedef int (*t_command_fn)(t_cli_context *ctx);

typedef struct s_command
{
const char *name;
t_command_fn execute;
} t_command;



void init_cli(t_cli *data, int argc, char **argv);
void free_cli(t_cli *data);
int is_valid_option(t_cli *data);
Expand All @@ -38,4 +56,8 @@ void write_in_files(t_cli *data);
char *join(char *s1, char *s2);
char *strmapi(char const *s, int (*f)(int));


int parse_args(int argc, char **argv, t_cli_context *ctx);
int dispatch_command(t_cli_context *ctx);

#endif
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loading