commit 3b01d7d6fc61e75421d6133e505b709f7c605c58
parent 0615e712b31c255559e50c64329c4ba1acacf1b1
Author: Demonstrandum <moi@knutsen.co>
Date: Tue, 23 Jun 2020 11:24:26 +0100
Save and manage history.
Diffstat:
4 files changed, 97 insertions(+), 24 deletions(-)
diff --git a/Makefile b/Makefile
@@ -1,19 +1,31 @@
-CC=gcc
-CFLAGS=-Wall -Wpedantic
-TARGET=crepl
-OBJS=main.o prelude.o parse.o displays.o error.o execute.o
-LINKS=-lm -lreadline
+CC := gcc
+CFLAGS := -Wall -Wpedantic
+TARGET := crepl
+OBJS := main.o prelude.o parse.o displays.o error.o execute.o
+LINKS := -lm -lreadline
-all: clean $(OBJS)
+ifeq ($(PREFIX),)
+ PREFIX := /usr/local
+endif
+
+all: clean $(TARGET)
+ @printf "\033[1mBuilt \`$(TARGET)' successfully.\033[0m\n"
+
+$(TARGET): $(OBJS)
$(CC) -o $(TARGET) $(LINKS) $(OBJS)
- @printf "\n\033[1mBuilt \`$(TARGET)' successfully.\033[0m\n"
-prelude.o: error.o
- $(CC) -c $(CFLAGS) src/prelude.c
+install: $(TARGET)
+ @echo "Installing to $(PREFIX)/bin/$(TARGET)."
+ install -d $(PREFIX)/bin
+ install -m 755 $(TARGET) $(PREFIX)/bin
main.o: prelude.o parse.o error.o
$(CC) -c $(CFLAGS) src/main.c
+prelude.o: error.o
+ $(CC) -c $(CFLAGS) src/prelude.c
+
+
parse.o: error.o
$(CC) -c $(CFLAGS) src/parse.c
diff --git a/README.md b/README.md
@@ -0,0 +1,28 @@
+# CREPL
+> **C**alculator **REPL**
+
+A command line calculator read-eval-print-loop,
+with intuitive mathematical notation as syntax.
+
+## Install
+
+You'll need `git` (if cloning), a C compiler (e.g. `gcc`)
+and `make` (`build-essential` / `base-devel`).
+
+### Clone
+Clone / Download this repositroy however you like, e.g.
+```console
+git clone "https://github.com/Demonstrandum/crepl.git"
+```
+
+Then change directory into it:
+```console
+cd crepl
+```
+
+### Build & Install
+```console
+make # Builds and compiles the project.
+sudo make install # Installs the program system wide.
+```
+
diff --git a/src/main.c b/src/main.c
@@ -1,9 +1,11 @@
#include <stdio.h>
-#include <readline/readline.h>
-#include <readline/history.h>
-
#include <stdlib.h>
#include <string.h>
+#include <signal.h>
+#include <sys/stat.h>
+
+#include <readline/readline.h>
+#include <readline/history.h>
#include "prelude.h"
#include "error.h"
@@ -12,25 +14,54 @@
static const char *PROMPT = "::> ";
+void sigint_handle(int _)
+{
+ printf("\b\b "); // Obsucre '^C' output.
+ printf("\nInterrupted, [Ctrl-D] to stop inputting.\n");
+ rl_on_new_line();
+ rl_replace_line("", 0);
+ rl_redisplay();
+}
+
int main(int argc, char **argv)
{
+ // Welcome messsage.
printf("\033[1m");
printf("CREPL — Calculator Read Eval Print Loop");
printf("\033[0m");
puts(" (" COMPILER ") (" __DATE__ ")");
- puts("Type \"exit\" or [Ctrl+D] (i.e. EOF) to quit.");
+ puts("Type \"exit\" or [Ctrl-D] (i.e. EOF) to quit.");
+
+ // Configure readline.
+ rl_clear_signals();
+ rl_bind_key('\t', rl_insert);
+ signal(SIGINT, sigint_handle);
+
+ // Create or fetch history file.
+ char cache_loc[128] = "~/.cache/";
+ char *tmp = NULL;
- rl_bind_key('\t', rl_complete);
+ if ((tmp = getenv("XDG_CACHE_HOME")) != NULL)
+ strcpy(cache_loc, tmp);
+ else if ((tmp = getenv("HOME")) != NULL)
+ sprintf(cache_loc, "%s/.cache/", tmp);
+
+ mkdir(cache_loc, 0777);
+ strcat(cache_loc, "/crepl.history");
+ read_history(cache_loc);
char *response = NULL;
do {
- response = readline(PROMPT);
- add_history(response);
+ char *line = readline(PROMPT);
- if (response == NULL
- || strcmp("exit", downcase(trim(response))) == 0)
+ if (line == NULL
+ || strcmp("exit", downcase(trim(line))) == 0)
break;
+ if (response == NULL || strcmp(line, response) != 0)
+ add_history(line);
+ response = line;
+
// Try to lex & parse the input.
ParseNode *tree = parse(response);
@@ -46,9 +77,10 @@ int main(int argc, char **argv)
printf("#=> %s\n", response);
free_parsenode(tree);
- free(response);
} while (true);
+ write_history(cache_loc);
+
printf("\r\033[2K");
printf("Buh-bye.\n");
diff --git a/src/prelude.c b/src/prelude.c
@@ -2,15 +2,16 @@
char *trim(char *str)
{
- while (isspace(*str))
- ++str;
+ char *p = strdup(str);
+ while (isspace(*p))
+ ++p;
- char *end = str + strlen(str) - 1;
- while (end > str && isspace(*end))
+ char *end = p + strlen(p) - 1;
+ while (end > p && isspace(*end))
--end;
*(end + 1) = '\0';
- return str;
+ return p;
}