#include "parser.h" #include "usql.h" #include "linenoise.h" #include "debug.h" using namespace std::chrono; const std::vector commands { "select", "create", "load", "table" }; std::string get_history_file_dir() { std::string file{"/.usql_history.txt"}; const char *t = std::getenv("HOME"); if (t == nullptr) return "/tmp/" + file; else return std::string{t} + "/" + file; } 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); for (const auto & command : commands) { if (command.find(token) == 0) { std::string completion_string = begining + command; 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; } void setup_linenoise() { 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()); } void repl() { std::string code; std::string input; setup_linenoise(); usql::USql uSql{}; while (true) { char *line = linenoise(">>> "); if (line == nullptr) break; linenoise_line_read(line); input = std::string(line); if (input == "!quit" || input == "!q") break; else if (input == "!export" || input == "!x") { std::cout << "File to export to: "; std::getline(std::cin, input); //write_file_contents(input, code); } else if (!input.empty()) { try { time_point start_time = high_resolution_clock::now(); auto result = uSql.execute(input); time_point end_time = high_resolution_clock::now(); std::cout << input << std::endl; std::cout << "run time: " << duration_cast(end_time - start_time).count() << " ms " << std::endl <print(); code += input + "\n"; } catch (std::exception &e) { std::cerr << e.what() << std::endl; } } } close_linenoise(); } void debug() { usql::USql uSql{}; for (const auto &command : k_debug_sql_commands) { time_point start_time = high_resolution_clock::now(); auto result = uSql.execute(command); time_point end_time = high_resolution_clock::now(); std::cout << command << std::endl; std::cout << "run time: " << duration_cast(end_time - start_time).count() << " ms " << std::endl << std::endl; result->print(); } std::cout << std::endl << std::endl; } int main(int argc, char *argv[]) { #ifdef NDEBUG repl(); #else debug(); #endif return 0; }