DISABLE FDs (REMOVE ME).
[jackhill/mal.git] / objc / mal_readline.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <unistd.h>
4
5 #if USE_READLINE
6 #include <readline/readline.h>
7 #include <readline/history.h>
8 #include <readline/tilde.h>
9 #else
10 #include <editline/readline.h>
11 #endif
12
13 int history_loaded = 0;
14
15 char HISTORY_FILE[] = "~/.mal-history";
16
17 void load_history() {
18 if (history_loaded) { return; }
19 int ret;
20 char *hf = tilde_expand(HISTORY_FILE);
21 if (access(hf, F_OK) != -1) {
22 // TODO: check if file exists first, use non-static path
23 #if USE_READLINE
24 ret = read_history(hf);
25 #else
26 FILE *fp = fopen(hf, "r");
27 char *line = malloc(80); // getline reallocs as necessary
28 size_t sz = 80;
29 while ((ret = getline(&line, &sz, fp)) > 0) {
30 add_history(line); // Add line to in-memory history
31 }
32 free(line);
33 fclose(fp);
34 #endif
35 history_loaded = 1;
36 }
37 free(hf);
38 }
39
40 void append_to_history() {
41 char *hf = tilde_expand(HISTORY_FILE);
42 #ifdef USE_READLINE
43 append_history(1, hf);
44 #else
45 #if defined(RL_READLINE_VERSION)
46 HIST_ENTRY *he = history_get(history_base+history_length-1);
47 #else
48 // libedit-2 segfaults if we add history_base
49 HIST_ENTRY *he = history_get(history_length-1);
50 #endif
51 FILE *fp = fopen(hf, "a");
52 if (fp) {
53 fprintf(fp, "%s\n", he->line);
54 fclose(fp);
55 }
56 #endif
57 free(hf);
58 }
59
60
61 // line must be freed by caller
62 char *_readline (char prompt[]) {
63 char *line;
64
65 load_history();
66
67 line = readline(prompt);
68 if (!line) return NULL; // EOF
69 add_history(line); // Add input to in-memory history
70
71 append_to_history(); // Flush new line of history to disk
72
73 return line;
74 }
75