92 lines
2.9 KiB
C++
92 lines
2.9 KiB
C++
|
|
#include "ml_util.h"
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
#include <filesystem>
|
|
|
|
const std::vector<std::string> commands {
|
|
"eval", "type", "parse", "do", "if", "for", "while", "scope", "quote", "defn",
|
|
"def", "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() {
|
|
std::string filename{".ml_history.txt"};
|
|
const char *t = std::getenv("HOME");
|
|
|
|
if (t == nullptr) return std::filesystem::temp_directory_path() / filename;
|
|
else return std::filesystem::path(std::string{t}) /filename;
|
|
}
|
|
|
|
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);
|
|
|
|
// PERF optimize not to get all lambdas, but those beginning with token
|
|
std::vector<std::string> lambdas = repl_env->get_lambdas_list();
|
|
lambdas.insert(end(lambdas), begin(commands), end(commands));
|
|
|
|
for (const auto & lambda : lambdas) {
|
|
if(lambda.find(token) == 0) {
|
|
std::string completion_string = begining + lambda;
|
|
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;
|
|
}
|