From 13d1168401e1f4a5440f7de43b71d72df7c008f3 Mon Sep 17 00:00:00 2001 From: Sage Vaillancourt Date: Fri, 8 Apr 2022 10:23:12 -0400 Subject: [PATCH] Wire up basic readline history/completion. --- src/examples/pebblisp.pbl | 14 +++++++++-- src/main.c | 51 +++++++++++++++++++++++++++++++++------ 2 files changed, 55 insertions(+), 10 deletions(-) diff --git a/src/examples/pebblisp.pbl b/src/examples/pebblisp.pbl index 0f33e3d..9f83b03 100644 --- a/src/examples/pebblisp.pbl +++ b/src/examples/pebblisp.pbl @@ -14,7 +14,11 @@ (def nl (ch 10)) -(def fore (fn (f list) ((map f list) ""))) +(def fore (fn (action list) + "Apply the given action to each element in list." ( + (map f list) + "" +))) (def first (fn (list) (at 0 list))) @@ -23,6 +27,11 @@ (def config (cat ~ "/.pebblisp.pbl")) +(def loadfile (fn (file-name) + "Read and evaluate the file with the given name." ( + (eval (rf file-name)) +))) + (def reloadConfig (fn () (loadfile config))) (def string (fn (a) (cat "" a))) @@ -65,7 +74,8 @@ (def clock (fn (ti) (cat (hour ti) ":" (zero ti.minute) ":" (zero ti.sec)))) -(def cleanDir (fn () ( +(def cleanDir (fn () + "Get a string of the current directory" ( (def di (cwd)) (if (matches di (cat ~ "*")) (cat "~" (substr (slen ~) 999 di)) diff --git a/src/main.c b/src/main.c index a04ca3f..4df645a 100644 --- a/src/main.c +++ b/src/main.c @@ -8,6 +8,15 @@ #include #include +struct Settings { + int runTests; + int ignoreConfig; + int ignoreLib; + int moreToDo; + const char* configFile; + char historyFile[128]; +} settings; + Object getPrompt(struct Environment* env) { Object prompt = fetchFromEnvironment("prompt", env); @@ -47,11 +56,39 @@ void sigintHandler(unused int signalNumber) cleanObject(&p); } +char* completionGenerator(const char* text, int state) +{ + static size_t i; + static size_t completionLength; + if (state == 0) { + i = 0; + completionLength = strlen(text); + } + + struct ObjectTable* table = &global()->table; + for (; i < table->capacity; i++) { + if (table->elements[i].symbol && strncmp(table->elements[i].symbol, text, completionLength) == 0) { + char* symbol = malloc(sizeof(char) * (strlen(table->elements[i].symbol) + 1)); + strcpy(symbol, table->elements[i].symbol); + i++; + return symbol; + } + } + return NULL; +} + +char** completer(const char* text, int start, int end) +{ + return rl_completion_matches(text, completionGenerator); +} + void repl(struct Environment* env) { + rl_attempted_completion_function = completer; signal(SIGINT, sigintHandler); char* buf; using_history(); + read_history(settings.historyFile); while ((buf = prompt(env)) != NULL) { if (strcmp("q", buf) == 0) { @@ -81,6 +118,7 @@ void repl(struct Environment* env) cleanObject(&o); system(buf); free(buf); + write_history(settings.historyFile); continue; } free(buf); @@ -91,6 +129,7 @@ void repl(struct Environment* env) printColored(output); free(output); printf("\n"); + write_history(settings.historyFile); } } @@ -144,14 +183,6 @@ void setupSegfaultHandler() } #endif -struct Settings { - int runTests; - int ignoreConfig; - int ignoreLib; - int moreToDo; - const char* configFile; -} settings; - #define RUN_TESTS_ARG "--run-tests" #define RUN_DETAILED_TESTS "=detailed" #define IGNORE_CONFIG_ARG "--ignore-config" @@ -160,12 +191,16 @@ struct Settings { void getSettings(int argc, const char* argv[]) { + const char* const home = getenv("HOME"); + settings.runTests = 0; settings.ignoreConfig = 0; settings.ignoreLib = 0; settings.moreToDo = 0; settings.configFile = NULL; + sprintf(settings.historyFile, "%s/.plhist", home); + size_t runTestsLen = strlen(RUN_TESTS_ARG); size_t configFileLen = strlen(CONFIG_FILE_ARG); for (int i = 1; i < argc; i++) {