crepl

An intuitive calculator REPL.
git clone git://git.knutsen.co/crepl
Log | Files | Refs | README | LICENSE

commit 3b01d7d6fc61e75421d6133e505b709f7c605c58
parent 0615e712b31c255559e50c64329c4ba1acacf1b1
Author: Demonstrandum <moi@knutsen.co>
Date:   Tue, 23 Jun 2020 11:24:26 +0100

Save and manage history.

Diffstat:
MMakefile | 30+++++++++++++++++++++---------
MREADME.md | 28++++++++++++++++++++++++++++
Msrc/main.c | 52++++++++++++++++++++++++++++++++++++++++++----------
Msrc/prelude.c | 11++++++-----
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; }