#include "wrap-string.hpp" #include "wrap-vector.hpp" #include "eng-malloc.hpp" #include "luastack.hpp" #include "luaconsole.hpp" #include "util.hpp" #include #include LuaConsole::LuaConsole() { lua_state_ = LuaCoreStack::newstate(eng::l_alloc); clear_raw_input(); } LuaConsole::~LuaConsole() { lua_close(lua_state_); } static LuaConsole::StringVec split_words(const eng::string &raw) { LuaConsole::StringVec result; eng::string acc; for (char c : raw) { if ((c == ' ')||(c == '\n')||(c == '\r')) { if (!acc.empty()) { result.push_back(acc); acc = ""; } } else { acc += c; } } if (!acc.empty()) { result.push_back(acc); } return result; } LuaConsole::StringVec LuaConsole::get_command() { StringVec result = words_; words_.clear(); return result; } void LuaConsole::clear_raw_input() { raw_input_ = ""; lines_ = 0; prompt_ = "> "; } void LuaConsole::add(eng::string line) { for (int i = 0; i < int(line.size()); i++) { if (line[i] == '\n') line[i] = ' '; } raw_input_ += line; raw_input_ += '\n'; lines_ += 1; prompt_ = ">> "; words_.clear(); // Try to interpret it as a slash-command. if ((lines_ == 1)&&(raw_input_[0] == '/')) { words_ = split_words(raw_input_.substr(1)); if ((words_.size() == 1) && (sv::valid_int64(words_[0]))) { eng::string num = words_[0]; words_.clear(); words_.push_back("choose"); words_.push_back(num); } clear_raw_input(); return; } // Translate lua expression, deal with initial prefix. eng::string partial; eng::string lua_mode; if (sv::has_prefix(raw_input_, "?=")) { lua_mode = "luaprobe"; partial = eng::string("return ") + raw_input_.substr(2); } else if (sv::has_prefix(raw_input_, "?")) { lua_mode = "luaprobe"; partial = raw_input_.substr(1); } else if (sv::has_prefix(raw_input_, "=")) { lua_mode = "luainvoke"; partial = eng::string("return ") + raw_input_.substr(1); } else { lua_mode = "luainvoke"; partial = raw_input_; } // Try to parse the lua expression { LuaVar result; LuaExtStack LS(lua_state_, result); eng::string errmsg = LS.load(result, partial, "stdin"); if (errmsg.empty()) { words_.push_back(lua_mode); words_.emplace_back(sv::rtrim(partial)); clear_raw_input(); } else if (errmsg.find("") != std::string::npos) { // We have an incomplete expression. // Do nothing, just let the user type more stuff. } else { words_.push_back("syntax"); words_.push_back(errmsg); clear_raw_input(); } } } void CommonCommands::do_command(const StringVec &words) { if (words.size() == 0) { return; } if (words[0] == "view") { if (words.size() == 1) { return do_view_command(); } else { return do_syntax_error("/view takes no arguments"); } } if (words[0] == "moveto") { if ((words.size() == 3) && sv::valid_int64(words[1]) && sv::valid_int64(words[2])) { return do_moveto_command(sv::to_int64(words[1]), sv::to_int64(words[2])); } else { return do_syntax_error("/moveto [x] [y]"); } } if (words[0] == "quit") { if (words.size() == 1) { return do_quit_command(); } else { return do_syntax_error("/quit takes no arguments"); } } if (words[0] == "cpl") { if (words.size() == 1) { return do_cpl_command(); } else { return do_syntax_error("/cpl takes no arguments"); } } if (words[0] == "work") { if (words.size() == 1) { return do_work_command(); } else { return do_syntax_error("/work takes no arguments"); } } if (words[0] == "display") { if (words.size() == 1) { return do_display_command(); } else { return do_syntax_error("/display takes no arguments"); } } if (words[0] == "aborthttp") { if (words.size() == 1) { return do_aborthttp_command(); } else { return do_syntax_error("/aborthttp takes no arguments"); } } if (words[0] == "connect") { if ((words.size() == 2)&&(sv::valid_hostname(words[1]))) { return do_connect_command(words[1]); } else { return do_syntax_error("/connect [hostname]"); } } if (words[0] == "luainvoke") { if (words.size() == 2) { return do_luainvoke_command(words[1]); } else { return do_syntax_error("/luainvoke [command]"); } } if (words[0] == "luaprobe") { if (words.size() == 2) { return do_luaprobe_command(words[1]); } else { return do_syntax_error("/luainvoke [command]"); } } return do_unknown_command(words[0]); }