#include "ml_util.h" #include #include const std::vector commands { "eval", "type", "parse", "do", "if", "for", "while", "scope", "quote", "defun", "define", "lambda", "benchmark", "=", "!=", ">", "<", ">=", "<=", "+", "-", "*", "/", "%", "list", "insert", "index", "remove", "len", "push", "pop", "head", "tail", "first", "last", "range", "map", "filter", "reduce", "exit", "quit", "print", "input", "random", "include", "read-file", "write-file", "read-url", "system-cmd", "ls-dir", "is-file?", "is-dir?", "parse-csv", "parse-json", "get-universal-time", "date-to-str", "str-to-date", "date-add", "debug", "sprintf", "display", "string-replace", "string-regex?", "string-pad", "int", "float", "string", "benchmark", "thread-create", "thread-under-lock", "thread-sleep", "threads-join", "try", "throw", "usql" }; std::string get_history_file_dir() { // TODO not portable and in function std::string file{"/.ml_history.txt"}; const char *t = std::getenv("HOME"); if (t == nullptr) return "/tmp/" + file; else return std::string{t} + "/" + file; } // TODO fujtajbl MlEnvironment * repl_env = nullptr; void setup_linenoise(const MlEnvironment &env) { repl_env = (MlEnvironment*) &env; std::string history_file = get_history_file_dir(); linenoiseHistorySetMaxLen(500); linenoiseSetCompletionCallback(completion); linenoiseSetHintsCallback(hints); linenoiseSetMultiLine(1); linenoiseHistoryLoad(history_file.c_str()); } void linenoise_line_read(char *line) { linenoiseHistoryAdd(line); } void close_linenoise() { std::string history_file = get_history_file_dir(); linenoiseHistorySave(history_file.c_str()); } size_t last_token_index( std::string str ) { // remove trailing white space while( !str.empty() && std::isspace( str.back() ) ) str.pop_back() ; // locate the last white space return str.find_last_of( "() \t\n" ) ; } void completion(const char *buf, linenoiseCompletions *lc) { if (buf != nullptr) { std::string str{buf}; const auto pos = last_token_index(str); if (pos == std::string::npos) return; // cannot find what to complete std::string token = str.substr(pos+1); std::string begining = str.substr(0, pos+1); // TODO optimize not to get all lambdas, but those begining with token std::vector lambdas = repl_env->get_lambdas_list(); lambdas.insert(end(lambdas), begin(commands), end(commands)); for (std::vector::iterator t = lambdas.begin(); t != lambdas.end(); ++t) { if(t->find(token) == 0) { std::string completion_string = begining + *t; linenoiseAddCompletion(lc, completion_string.c_str()); } } } } char *hints(const char *buf, int *color, int *bold) { // if (!strcasecmp(buf,"hello")) { // *color = 35; // *bold = 0; // return " World"; // } return nullptr; }