109 lines
2.6 KiB
C
Raw Normal View History

2025-01-04 08:40:31 +01:00
// Written by retoor@molodetz.nl
2025-03-28 06:56:36 +01:00
// This source code provides command-line input functionalities with
// autocomplete and history features using the readline library. It allows users
// to complete commands and manage input history.
2025-01-04 08:40:31 +01:00
2025-03-28 06:56:36 +01:00
// External includes:
2025-01-04 08:40:31 +01:00
// - <readline/readline.h>
// - <readline/history.h>
2025-03-21 03:22:19 +01:00
// - <glob.h>
2025-01-04 08:40:31 +01:00
2025-03-28 06:56:36 +01:00
// MIT License: Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction.
2025-01-04 08:40:31 +01:00
2025-03-28 06:56:36 +01:00
#include "utils.h"
#include <glob.h>
2025-01-04 06:00:03 +01:00
#include <readline/history.h>
2025-03-28 06:56:36 +01:00
#include <readline/readline.h>
2025-01-27 19:06:59 +01:00
#include <stdbool.h>
2025-03-28 06:56:36 +01:00
#include <string.h>
2025-03-27 23:08:00 +01:00
#define HISTORY_FILE "~/.r_history"
2025-01-04 06:00:03 +01:00
2025-01-04 08:40:31 +01:00
bool line_initialized = false;
2025-01-04 06:00:03 +01:00
2025-03-28 06:56:36 +01:00
char *get_history_file() {
static char result[4096];
result[0] = 0;
2025-03-27 23:08:00 +01:00
2025-03-28 06:56:36 +01:00
char *expanded = expand_home_directory(HISTORY_FILE);
strcpy(result, expanded);
free(expanded);
return result;
2025-03-27 23:08:00 +01:00
}
2025-03-28 06:56:36 +01:00
char *line_command_generator(const char *text, int state) {
static int list_index, len = 0;
const char *commands[] = {"help", "exit", "list", "review",
"refactor", "obfuscate", "!verbose", "!dump",
"!model", "!debug", NULL};
if (!state) {
list_index = 0;
len = strlen(text);
}
while (commands[list_index]) {
const char *command = commands[list_index++];
if (strncmp(command, text, len) == 0) {
return strdup(command);
2025-01-04 06:00:03 +01:00
}
2025-03-28 06:56:36 +01:00
}
2025-01-04 06:00:03 +01:00
2025-03-28 06:56:36 +01:00
return NULL;
2025-01-04 06:00:03 +01:00
}
2025-03-28 06:56:36 +01:00
char *line_file_generator(const char *text, int state) {
static int list_index;
glob_t glob_result;
char pattern[1024];
2025-03-21 03:22:19 +01:00
2025-03-28 06:56:36 +01:00
if (!state) {
list_index = 0;
snprintf(pattern, sizeof(pattern), "%s*",
text); // Create a pattern for glob
glob(pattern, GLOB_NOSORT, NULL, &glob_result);
}
2025-03-21 03:22:19 +01:00
2025-03-28 06:56:36 +01:00
if (list_index < glob_result.gl_pathc) {
return strdup(glob_result.gl_pathv[list_index++]);
}
2025-03-21 03:22:19 +01:00
2025-03-28 06:56:36 +01:00
globfree(&glob_result);
return NULL;
2025-03-21 03:22:19 +01:00
}
2025-03-28 06:56:36 +01:00
char **line_command_completion(const char *text, int start, int end) {
rl_attempted_completion_over = 1;
2025-03-21 03:22:19 +01:00
2025-03-28 06:56:36 +01:00
// Check if the input is a file path
if (start > 0 && text[0] != ' ') {
return rl_completion_matches(text, line_file_generator);
}
2025-03-21 03:22:19 +01:00
2025-03-28 06:56:36 +01:00
return rl_completion_matches(text, line_command_generator);
2025-01-04 06:00:03 +01:00
}
2025-01-04 08:40:31 +01:00
void line_init() {
2025-03-28 06:56:36 +01:00
if (!line_initialized) {
rl_attempted_completion_function = line_command_completion;
line_initialized = true;
read_history(get_history_file());
}
2025-01-04 06:00:03 +01:00
}
2025-03-28 06:56:36 +01:00
char *line_read(char *prefix) {
char *data = readline(prefix);
if (!(data && *data)) {
free(data);
return NULL;
}
return data;
2025-01-04 06:00:03 +01:00
}
2025-01-04 08:40:31 +01:00
2025-03-28 06:56:36 +01:00
void line_add_history(char *data) {
add_history(data);
write_history(get_history_file());
2025-03-21 03:22:19 +01:00
}