Files
integration/luprex/core/cpp/luaconsole.cpp
2021-10-07 14:58:20 -04:00

109 lines
2.5 KiB
C++

#include <string.h>
#include "luaconsole.hpp"
#include "util.hpp"
#include <iostream>
static bool is_single_letter(const std::string &s) {
return ((s.size() == 1) && (s[0] >= 'a') && (s[0] <= 'z'));
}
LuaConsole::LuaConsole() {
lua_state_ = luaL_newstate();
clear();
}
LuaConsole::~LuaConsole() {
lua_close(lua_state_);
}
void LuaConsole::clear() {
raw_input_ = "";
lines_ = 0;
lua_expression_ = "";
words_.clear();
syntax_ = "";
action_ = DO_NOTHING;
prompt_ = "> ";
}
void LuaConsole::split_words() {
words_.clear();
std::string acc;
for (char c : raw_input_) {
if ((c == ' ')||(c == '\n')||(c == '\r')) {
if (!acc.empty()) {
words_.push_back(acc);
acc = "";
}
} else {
acc += c;
}
}
if (!acc.empty()) {
words_.push_back(acc);
}
}
std::string LuaConsole::get_prompt() {
std::string result = prompt_;
prompt_ = "";
return result;
}
void LuaConsole::add(std::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;
// Try to interpret it as a special command.
if (lines_ == 1) {
split_words();
if (words_.size() >= 1) {
if (is_single_letter(words_[0]) || (util::validinteger(words_[0]))) {
action_ = DO_COMMAND;
return;
}
}
}
words_.clear();
// Translate lua expression with leading '=' to 'return'
std::string partial;
if (raw_input_[0] == '=') {
partial = std::string("return ") + raw_input_.substr(1);
} else {
partial = raw_input_;
}
// Try to parse the lua expression
int top = lua_gettop(lua_state_);
int status = luaL_loadbuffer(lua_state_, partial.c_str(), partial.size(), "=stdin");
if (status == LUA_ERRSYNTAX)
{
const char *eof = "<eof>";
int leof = strlen(eof);
size_t lmsg;
const char *msg = lua_tolstring(lua_state_, -1, &lmsg);
const char *tp = msg + lmsg - leof;
if (strstr(msg, eof) == tp) {
action_ = DO_NOTHING;
} else {
action_ = DO_SYNTAX;
syntax_ = msg;
}
} else {
action_ = DO_LUA;
lua_expression_ = partial;
}
lua_settop(lua_state_, top);
if (action_ == DO_NOTHING) {
prompt_ = ">> ";
}
}