294 lines
5.3 KiB
C
294 lines
5.3 KiB
C
#include <stddef.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <math.h>
|
|
#include "linenoise.h"
|
|
#include "rax.h"
|
|
|
|
|
|
rax *rt;
|
|
|
|
#define INSERT(key) raxInsert(rt, (unsigned char*)(key), sizeof((key)), NULL, NULL);
|
|
|
|
|
|
int
|
|
index_of_last_symbol_char(const char *buf)
|
|
{
|
|
int n = strlen(buf);
|
|
while (n) {
|
|
if (strchr(" []", buf[n - 1])) {
|
|
break;
|
|
}
|
|
n--;
|
|
}
|
|
return n;
|
|
}
|
|
|
|
|
|
int
|
|
longest_completion(const char *buf, int buffer_length)
|
|
{
|
|
int longest = 0;
|
|
raxIterator iter;
|
|
raxStart(&iter, rt);
|
|
raxSeek(&iter, ">=", (unsigned char*)buf, buffer_length);
|
|
while(raxNext(&iter)) {
|
|
if (strncmp((const char *)iter.key, buf, buffer_length))
|
|
break;
|
|
if (iter.key_len > longest) {
|
|
longest = iter.key_len;
|
|
};
|
|
}
|
|
raxStop(&iter);
|
|
return longest;
|
|
}
|
|
|
|
|
|
void
|
|
prefixed_completion(const char *buf, linenoiseCompletions *lc, int prefix_length)
|
|
{
|
|
raxIterator iter;
|
|
|
|
/* Get a buffer large enough to hold the largest possible completion. */
|
|
int buffer_length = strlen(buf);
|
|
int completion_buffer_size = prefix_length + longest_completion(buf, buffer_length) + 1;
|
|
char *completion_buffer = malloc(completion_buffer_size);
|
|
if (NULL == completion_buffer)
|
|
return;
|
|
|
|
/* Prepare the prefix and trim it from the front of the buf. */
|
|
memcpy(completion_buffer, buf, prefix_length);
|
|
buf += prefix_length;
|
|
buffer_length -= prefix_length;
|
|
|
|
raxStart(&iter, rt);
|
|
raxSeek(&iter, ">=", (unsigned char*)buf, buffer_length);
|
|
while(raxNext(&iter)) {
|
|
if (strncmp((const char *)iter.key, buf, buffer_length))
|
|
break;
|
|
completion_buffer[prefix_length] = 0;
|
|
strlcat(completion_buffer + prefix_length, (const char *)iter.key, completion_buffer_size);
|
|
linenoiseAddCompletion(lc, (const char *)completion_buffer);
|
|
}
|
|
raxStop(&iter);
|
|
free(completion_buffer);
|
|
}
|
|
|
|
|
|
void
|
|
simple_completion(const char *buf, linenoiseCompletions *lc)
|
|
{
|
|
int buffer_length = strlen(buf);
|
|
raxIterator iter;
|
|
raxStart(&iter, rt);
|
|
raxSeek(&iter, ">=", (unsigned char*)buf, buffer_length);
|
|
while(raxNext(&iter)) {
|
|
if (strncmp((const char *)iter.key, buf, buffer_length))
|
|
break;
|
|
linenoiseAddCompletion(lc, (const char *)iter.key);
|
|
}
|
|
raxStop(&iter);
|
|
}
|
|
|
|
|
|
void
|
|
completion(const char *buf, linenoiseCompletions *lc)
|
|
{
|
|
int prefix_length = index_of_last_symbol_char(buf);
|
|
if (prefix_length) {
|
|
prefixed_completion(buf, lc, prefix_length);
|
|
} else {
|
|
simple_completion(buf, lc);
|
|
}
|
|
}
|
|
|
|
|
|
int
|
|
main()
|
|
{
|
|
char *line;
|
|
linenoiseSetCompletionCallback(completion);
|
|
rt = raxNew();
|
|
INSERT("=")
|
|
INSERT(">")
|
|
INSERT("<")
|
|
INSERT("!=")
|
|
INSERT("<>")
|
|
INSERT("<=")
|
|
INSERT(">=")
|
|
INSERT("%")
|
|
INSERT("mod")
|
|
INSERT("*")
|
|
INSERT("mul")
|
|
INSERT("+")
|
|
INSERT("add")
|
|
INSERT("-")
|
|
INSERT("sub")
|
|
INSERT("/")
|
|
INSERT("div")
|
|
INSERT("lshift")
|
|
INSERT("rshift")
|
|
INSERT("bool")
|
|
INSERT("branch")
|
|
INSERT("clear")
|
|
INSERT("cmp")
|
|
INSERT("cons")
|
|
INSERT("concat")
|
|
INSERT("dip")
|
|
INSERT("dup")
|
|
INSERT("first")
|
|
INSERT("i")
|
|
INSERT("inscribe")
|
|
INSERT("loop")
|
|
INSERT("pop")
|
|
INSERT("rest")
|
|
INSERT("stack")
|
|
INSERT("swaack")
|
|
INSERT("swap")
|
|
INSERT("fn")
|
|
INSERT("eq")
|
|
INSERT("gt")
|
|
INSERT("lt")
|
|
INSERT("neq")
|
|
INSERT("le")
|
|
INSERT("ge")
|
|
INSERT("--")
|
|
INSERT("?")
|
|
INSERT("and")
|
|
INSERT("++")
|
|
INSERT("or")
|
|
INSERT("!-")
|
|
INSERT("<{}")
|
|
INSERT("<<{}")
|
|
INSERT("abs")
|
|
INSERT("anamorphism")
|
|
INSERT("app1")
|
|
INSERT("app2")
|
|
INSERT("app3")
|
|
INSERT("appN")
|
|
INSERT("at")
|
|
INSERT("average")
|
|
INSERT("b")
|
|
INSERT("binary")
|
|
INSERT("ccccons")
|
|
INSERT("ccons")
|
|
INSERT("clear")
|
|
INSERT("cleave")
|
|
INSERT("clop")
|
|
INSERT("cmp")
|
|
INSERT("codi")
|
|
INSERT("codireco")
|
|
INSERT("dinfrirst")
|
|
INSERT("dipd")
|
|
INSERT("disenstacken")
|
|
INSERT("divmod")
|
|
INSERT("down_to_zero")
|
|
INSERT("drop")
|
|
INSERT("dupd")
|
|
INSERT("dupdd")
|
|
INSERT("dupdip")
|
|
INSERT("dupdipd")
|
|
INSERT("enstacken")
|
|
INSERT("first")
|
|
INSERT("flatten")
|
|
INSERT("fork")
|
|
INSERT("fourth")
|
|
INSERT("gcd")
|
|
INSERT("genrec")
|
|
INSERT("grabN")
|
|
INSERT("grba")
|
|
INSERT("hypot")
|
|
INSERT("ifte")
|
|
INSERT("ii")
|
|
INSERT("infra")
|
|
INSERT("infrst")
|
|
INSERT("make_generator")
|
|
INSERT("mod")
|
|
INSERT("neg")
|
|
INSERT("not")
|
|
INSERT("nulco")
|
|
INSERT("null")
|
|
INSERT("nullary")
|
|
INSERT("of")
|
|
INSERT("pam")
|
|
INSERT("pm")
|
|
INSERT("popd")
|
|
INSERT("popdd")
|
|
INSERT("popop")
|
|
INSERT("popopop")
|
|
INSERT("popopd")
|
|
INSERT("popopdd")
|
|
INSERT("product")
|
|
INSERT("quoted")
|
|
INSERT("range")
|
|
INSERT("range_to_zero")
|
|
INSERT("reco")
|
|
INSERT("rest")
|
|
INSERT("reverse")
|
|
INSERT("roll>")
|
|
INSERT("roll<")
|
|
INSERT("rollup")
|
|
INSERT("rolldown")
|
|
INSERT("rrest")
|
|
INSERT("run")
|
|
INSERT("second")
|
|
INSERT("shift")
|
|
INSERT("shunt")
|
|
INSERT("size")
|
|
INSERT("small")
|
|
INSERT("spiral_next")
|
|
INSERT("split_at")
|
|
INSERT("split_list")
|
|
INSERT("sqr")
|
|
INSERT("stackd")
|
|
INSERT("step_zero")
|
|
INSERT("stuncons")
|
|
INSERT("sum")
|
|
INSERT("swapd")
|
|
INSERT("swons")
|
|
INSERT("swoncat")
|
|
INSERT("tailrec")
|
|
INSERT("take")
|
|
INSERT("ternary")
|
|
INSERT("third")
|
|
INSERT("tuck")
|
|
INSERT("unary")
|
|
INSERT("uncons")
|
|
INSERT("unit")
|
|
INSERT("unquoted")
|
|
INSERT("unstack")
|
|
INSERT("unswons")
|
|
INSERT("while")
|
|
INSERT("x")
|
|
INSERT("step")
|
|
INSERT("_step0")
|
|
INSERT("_step1")
|
|
INSERT("_stept")
|
|
INSERT("times")
|
|
INSERT("_times0")
|
|
INSERT("_times1")
|
|
INSERT("_timest")
|
|
INSERT("map")
|
|
INSERT("_map?")
|
|
INSERT("_mape")
|
|
INSERT("_map0")
|
|
INSERT("_map1")
|
|
INSERT("_map2")
|
|
INSERT("_\\/_")
|
|
INSERT("/\\")
|
|
INSERT("\\/")
|
|
/*
|
|
raxShow(rt);
|
|
*/
|
|
|
|
while (1) {
|
|
line = linenoise("eh? ");
|
|
if (NULL == line) {
|
|
printf("\n");
|
|
break;
|
|
}
|
|
linenoiseHistoryAdd(line);
|
|
}
|
|
}
|