18
#include <lib/linenoise.h>
19
#include <readline/history.h>
20
#include <readline/readline.h>
22
#define DEFAULT_HISTORY_FILE "~/.history"
24
rl_compentry_func_t *rl_completion_entry_function;
25
rl_completion_func_t *rl_attempted_completion_function;
27
static rl_command_func_t *complcb_function;
28
static const char *complcb_text;
29
static linenoiseCompletions *complcb_lc;
31
char *readline(const char *prompt) {
32
return linenoise(prompt != NULL ? prompt : "");
35
void readline_free(char *line) {
41
static void completion_callback(const char *text, linenoiseCompletions *lc) {
44
complcb_function(0, '\t');
47
int rl_bind_key(int key, rl_command_func_t *function) {
49
complcb_function = function;
50
linenoiseSetCompletionCallback(completion_callback);
57
int rl_complete(int ignore, int invoking_key) {
58
const char *last_word;
60
char **matches, **match, buff[SHELL_INPUT_BUFF_SZ];
62
if (invoking_key != '\t') {
66
end = strlen(complcb_text);
67
last_word = complcb_text + end;
68
while ((last_word >= complcb_text) && !isspace(*last_word)) {
71
start = ++last_word - complcb_text;
73
if (rl_attempted_completion_function != NULL) {
74
matches = rl_attempted_completion_function(last_word, start, end);
80
if (matches == NULL) {
81
matches = rl_completion_matches(last_word,
82
(rl_completion_entry_function != NULL)
83
? rl_completion_entry_function
84
: rl_filename_completion_function);
85
if (matches == NULL) {
90
strncpy(&buff[0], complcb_text, start);
91
for (match = matches + 1; *match != NULL; ++match) {
92
strcpy(&buff[start], *match);
93
linenoiseAddCompletion(complcb_lc, &buff[0]);
101
char **rl_completion_matches(const char *text,
102
rl_compentry_func_t *entry_func) {
104
char **matches, **tmp, *match;
107
match = entry_func(text, 0);
112
matches_sz = 3 * sizeof *matches; /* +1 for null-term array */
113
matches = malloc(matches_sz);
114
if (matches == NULL) {
116
return NULL; /* error: no memory */
119
matches[0] = (char *)text;
123
while (NULL != (match = entry_func(text, ++ind))) {
124
matches[ind + 1] = match;
125
matches_sz += sizeof *matches;
126
tmp = realloc(matches, matches_sz);
129
free(matches[ind-- + 1]);
132
return NULL; /* error: no memory */
137
matches[ind + 1] = NULL;
142
char *rl_filename_completion_function(const char *text, int state) {
143
static DIR *dir = NULL;
144
static char path[PATH_MAX], name[NAME_MAX];
145
static size_t path_len, name_len;
147
const char *slash, *tmp;
148
char filename[PATH_MAX];
151
/* parse path and name */
154
while (NULL != (tmp = strchr(tmp, '/'))) {
160
strcpy(&name[0], text);
163
strncpy(&path[0], text, (slash - text + 1));
164
path[slash - text + 1] = '\0';
165
strcpy(&name[0], slash + 1);
167
path_len = strlen(&path[0]);
168
name_len = strlen(&name[0]);
175
dir = opendir(&path[0]);
177
return NULL; /* error: see errno */
181
while (NULL != (dent = readdir(dir))) {
182
if (strncmp(&name[0], &dent->d_name[0], name_len) == 0) {
183
strcpy(&filename[0], &path[0]);
184
strcpy(&filename[path_len], &dent->d_name[0]);
185
return strdup(&filename[0]);
195
void add_history(const char *line) {
196
linenoiseHistoryAdd(line);
199
void stifle_history(int max) {
200
linenoiseHistorySetMaxLen(max);
203
int read_history(const char *filename) {
205
filename = DEFAULT_HISTORY_FILE;
208
if (-1 == linenoiseHistoryLoad(filename)) {
215
int write_history(const char *filename) {
217
filename = DEFAULT_HISTORY_FILE;
220
if (-1 == linenoiseHistorySave(filename)) {
227
void readline_init(void) {
229
rl_completion_entry_function = NULL;
230
rl_attempted_completion_function = NULL;
233
complcb_function = NULL;