move all code relative to readline into separate file
[calc.git] / readline.c
diff --git a/readline.c b/readline.c
new file mode 100644 (file)
index 0000000..4b234f4
--- /dev/null
@@ -0,0 +1,140 @@
+#include <malloc.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <readline/readline.h>
+#include <readline/history.h>
+
+#include "debug.h"
+#include "parser.h"
+
+#include "readline.h"
+
+/* constants */
+
+#define HISTORY_LEN 10
+
+/* macros */
+
+/* gobal variables */
+
+char **completion_list = NULL;
+
+/* completion function */
+
+char *generator (const char *text, int state)
+{
+    static int index, len;
+    char *name;
+
+    if (!state) {
+        index = 0;
+        len = strlen(text);
+    }
+
+    while ((name = completion_list[index++])) {
+        if (strncmp (name, text, len) == 0) {
+            return strdup (name);
+        }
+    }
+
+    return NULL;
+}
+
+char **completion (const char *text, __attribute__((unused)) int start, __attribute__((unused)) int end)
+{
+    rl_attempted_completion_over = 1;
+    return rl_completion_matches (text, generator);
+}
+
+/* edit line */
+char *edit_line = NULL;
+int edit_hook ()
+{
+    static int state = 0;
+    if (edit_line) {
+        if (state == 0) {
+            state = 1;
+        } else {
+            state = 0;
+            free (edit_line);
+            edit_line = NULL;
+        }
+    }
+    return rl_insert_text (edit_line);
+}
+
+/* history management */
+
+void history ()
+{
+    HIST_ENTRY **entries = history_list ();
+    if (entries == NULL) {
+        VERBOSE (WARNING, fprintf (stdout, "no history\n"));
+    } else {
+        int i = 0;
+        while (entries[i] != NULL) {
+            printf ("%d: %s\n", history_length - i, entries[i]->line);
+            i++;
+        }
+    }
+}
+
+/* init readline */
+
+void init_read_line ()
+{
+    /* completion list*/
+    completion_list = generate_completion_list ();
+    rl_attempted_completion_function = completion;
+
+    /* edit program */
+    rl_startup_hook = edit_hook;
+
+    /* readline parameters */
+    rl_variable_bind ("blink-matching-paren", "On");
+    //rl_set_screen_size (50, 40);
+}
+
+/* read line */
+
+int read_line (char **buffer, char *prompt)
+{
+    if ((*buffer = readline (prompt)) == NULL) {
+       return 1;
+    }
+
+    /* check empty line */
+    if (strlen (*buffer) == 0) {
+        free (*buffer);
+        *buffer = NULL;
+    }
+
+    return 0;
+}
+
+/* manage history */
+
+void manage_history (char *buffer)
+{
+    /* add line into history */
+    add_history (buffer);
+    VERBOSE (INFO, fprintf (stdout, "line (%d/%d): '%s'\n",
+                            where_history (), history_length, buffer));
+    if (history_length > HISTORY_LEN) {
+        HIST_ENTRY *last = remove_history (0);
+        if (last) {
+            free_history_entry (last);
+        }
+    }
+}
+
+/* clean readline */
+
+void clean_read_line (char *buffer)
+{
+    free_completion_list (completion_list);
+    if (buffer) {
+        free (buffer);
+    }
+}