summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Sluift/Console.cpp')
-rw-r--r--Sluift/Console.cpp418
1 files changed, 209 insertions, 209 deletions
diff --git a/Sluift/Console.cpp b/Sluift/Console.cpp
index 623a38f..ef0b1a4 100644
--- a/Sluift/Console.cpp
+++ b/Sluift/Console.cpp
@@ -28,256 +28,256 @@ using namespace Swift;
* Adds the backtrace to the error message.
*/
static int traceback(lua_State* L) {
- if (!lua_isstring(L, 1)) {
- return 1;
- }
- lua_getglobal(L, "debug");
- if (!lua_istable(L, -1)) {
- lua_pop(L, 1);
- return 1;
- }
- lua_getfield(L, -1, "traceback");
- if (!lua_isfunction(L, -1)) {
- lua_pop(L, 2);
- return 1;
- }
- lua_pushvalue(L, 1);
- lua_pushinteger(L, 2);
- lua_call(L, 2, 1);
- return 1;
+ if (!lua_isstring(L, 1)) {
+ return 1;
+ }
+ lua_getglobal(L, "debug");
+ if (!lua_istable(L, -1)) {
+ lua_pop(L, 1);
+ return 1;
+ }
+ lua_getfield(L, -1, "traceback");
+ if (!lua_isfunction(L, -1)) {
+ lua_pop(L, 2);
+ return 1;
+ }
+ lua_pushvalue(L, 1);
+ lua_pushinteger(L, 2);
+ lua_call(L, 2, 1);
+ return 1;
}
Console::Console(lua_State* L, Terminal* terminal) : L(L), terminal(terminal), previousNumberOfReturnArguments(0) {
- terminal->setCompleter(this);
+ terminal->setCompleter(this);
}
Console::~Console() {
}
void Console::run() {
- while (true) {
- lua_settop(L, 0);
- try {
- if (!readCommand()) {
- return;
- }
- int result = call(L, 0, true);
- if (result != 0) {
- throw std::runtime_error(getErrorMessage());
- }
-
- // Clear the previous results
- for (int i = 0; i < previousNumberOfReturnArguments; ++i) {
- lua_pushnil(L);
- lua_setglobal(L, ("_" + boost::lexical_cast<std::string>(i+1)).c_str());
- }
-
- // Store the results
- for (int i = 0; i < lua_gettop(L); ++i) {
- lua_pushvalue(L, i+1);
- lua_setglobal(L, ("_" + boost::lexical_cast<std::string>(i+1)).c_str());
- }
- previousNumberOfReturnArguments = lua_gettop(L);
-
- // Print results
- if (lua_gettop(L) > 0) {
- lua_getglobal(L, "print");
- lua_insert(L, 1);
- if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0) {
- throw std::runtime_error("Error calling 'print': " + getErrorMessage());
- }
- }
- }
- catch (const std::exception& e) {
- terminal->printError(e.what());
- }
- }
+ while (true) {
+ lua_settop(L, 0);
+ try {
+ if (!readCommand()) {
+ return;
+ }
+ int result = call(L, 0, true);
+ if (result != 0) {
+ throw std::runtime_error(getErrorMessage());
+ }
+
+ // Clear the previous results
+ for (int i = 0; i < previousNumberOfReturnArguments; ++i) {
+ lua_pushnil(L);
+ lua_setglobal(L, ("_" + boost::lexical_cast<std::string>(i+1)).c_str());
+ }
+
+ // Store the results
+ for (int i = 0; i < lua_gettop(L); ++i) {
+ lua_pushvalue(L, i+1);
+ lua_setglobal(L, ("_" + boost::lexical_cast<std::string>(i+1)).c_str());
+ }
+ previousNumberOfReturnArguments = lua_gettop(L);
+
+ // Print results
+ if (lua_gettop(L) > 0) {
+ lua_getglobal(L, "print");
+ lua_insert(L, 1);
+ if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0) {
+ throw std::runtime_error("Error calling 'print': " + getErrorMessage());
+ }
+ }
+ }
+ catch (const std::exception& e) {
+ terminal->printError(e.what());
+ }
+ }
}
int Console::tryLoadCommand(const std::string& originalCommand) {
- std::string command = originalCommand;
+ std::string command = originalCommand;
- // Replace '=' by 'return' (for compatibility with Lua console)
- if (boost::algorithm::starts_with(command, "=")) {
- command = "return " + command.substr(1);
- }
+ // Replace '=' by 'return' (for compatibility with Lua console)
+ if (boost::algorithm::starts_with(command, "=")) {
+ command = "return " + command.substr(1);
+ }
- std::string commandAsExpression = "return " + command;
+ std::string commandAsExpression = "return " + command;
- // Try to load the command as an expression
- if (luaL_loadbuffer(L, commandAsExpression.c_str(), commandAsExpression.size(), "=stdin") == 0) {
- return 0;
- }
- lua_pop(L, 1);
+ // Try to load the command as an expression
+ if (luaL_loadbuffer(L, commandAsExpression.c_str(), commandAsExpression.size(), "=stdin") == 0) {
+ return 0;
+ }
+ lua_pop(L, 1);
- // Try to load the command as a regular command
- return luaL_loadbuffer(L, command.c_str(), command.size(), "=stdin");
+ // Try to load the command as a regular command
+ return luaL_loadbuffer(L, command.c_str(), command.size(), "=stdin");
}
bool Console::readCommand() {
- boost::optional<std::string> line = terminal->readLine(getPrompt(true));
- if (!line) {
- return false;
- }
- std::string command = *line;
- while (true) {
- int result = tryLoadCommand(command);
-
- // Check if we need to read more
- if (result == LUA_ERRSYNTAX) {
- std::string errorMessage(lua_tostring(L, -1));
- if (boost::algorithm::ends_with(errorMessage, "'<eof>'")) {
- lua_pop(L, 1);
-
- // Read another line
- boost::optional<std::string> line = terminal->readLine(getPrompt(false));
- if (!line) {
- return false;
- }
- command = command + "\n" + *line;
- continue;
- }
- }
- if (!command.empty()) {
- terminal->addToHistory(command);
- }
- if (result != 0) {
- throw std::runtime_error(getErrorMessage());
- }
- return true;
- }
+ boost::optional<std::string> line = terminal->readLine(getPrompt(true));
+ if (!line) {
+ return false;
+ }
+ std::string command = *line;
+ while (true) {
+ int result = tryLoadCommand(command);
+
+ // Check if we need to read more
+ if (result == LUA_ERRSYNTAX) {
+ std::string errorMessage(lua_tostring(L, -1));
+ if (boost::algorithm::ends_with(errorMessage, "'<eof>'")) {
+ lua_pop(L, 1);
+
+ // Read another line
+ boost::optional<std::string> line = terminal->readLine(getPrompt(false));
+ if (!line) {
+ return false;
+ }
+ command = command + "\n" + *line;
+ continue;
+ }
+ }
+ if (!command.empty()) {
+ terminal->addToHistory(command);
+ }
+ if (result != 0) {
+ throw std::runtime_error(getErrorMessage());
+ }
+ return true;
+ }
}
std::string Console::getErrorMessage() const {
- if (lua_isnil(L, -1)) {
- return "<null error>";
- }
- const char* errorMessage = lua_tostring(L, -1);
- return errorMessage ? errorMessage : "<error is not a string>";
+ if (lua_isnil(L, -1)) {
+ return "<null error>";
+ }
+ const char* errorMessage = lua_tostring(L, -1);
+ return errorMessage ? errorMessage : "<error is not a string>";
}
int Console::call(lua_State* L, int numberOfArguments, bool keepResult) {
- // Put traceback function on stack below call
- int tracebackIndex = lua_gettop(L) - numberOfArguments;
- lua_pushcfunction(L, traceback);
- lua_insert(L, tracebackIndex);
+ // Put traceback function on stack below call
+ int tracebackIndex = lua_gettop(L) - numberOfArguments;
+ lua_pushcfunction(L, traceback);
+ lua_insert(L, tracebackIndex);
- int result = lua_pcall(L, numberOfArguments, keepResult ? LUA_MULTRET : 0, tracebackIndex);
+ int result = lua_pcall(L, numberOfArguments, keepResult ? LUA_MULTRET : 0, tracebackIndex);
- // Remove traceback
- lua_remove(L, tracebackIndex);
+ // Remove traceback
+ lua_remove(L, tracebackIndex);
- return result;
+ return result;
}
std::string Console::getPrompt(bool firstLine) const {
- lua_getglobal(L,firstLine ? "_PROMPT" : "_PROMPT2");
- const char* rawPrompt = lua_tostring(L, -1);
- std::string prompt;
- if (rawPrompt) {
- prompt = std::string(rawPrompt);
- }
- else {
- prompt = firstLine ? "> " : ">> ";
- }
- lua_pop(L, 1);
- return prompt;
+ lua_getglobal(L,firstLine ? "_PROMPT" : "_PROMPT2");
+ const char* rawPrompt = lua_tostring(L, -1);
+ std::string prompt;
+ if (rawPrompt) {
+ prompt = std::string(rawPrompt);
+ }
+ else {
+ prompt = firstLine ? "> " : ">> ";
+ }
+ lua_pop(L, 1);
+ return prompt;
}
static void addMatchingTableKeys(lua_State* L, const std::string& match, std::vector<std::string>& result) {
- for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
- const char* rawKey = lua_tostring(L, -2);
- if (rawKey) {
- std::string key(rawKey);
- if (boost::starts_with(key, match) && !(match == "" && boost::starts_with(key, "_"))) {
- result.push_back(key);
- }
- }
- }
+ for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
+ const char* rawKey = lua_tostring(L, -2);
+ if (rawKey) {
+ std::string key(rawKey);
+ if (boost::starts_with(key, match) && !(match == "" && boost::starts_with(key, "_"))) {
+ result.push_back(key);
+ }
+ }
+ }
}
static void addMatchingTableValues(lua_State* L, const std::string& match, std::vector<std::string>& result) {
- for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
- const char* rawValue = lua_tostring(L, -1);
- if (rawValue) {
- std::string key(rawValue);
- if (boost::starts_with(key, match) && !(match == "" && boost::starts_with(key, "_"))) {
- result.push_back(key);
- }
- }
- }
+ for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
+ const char* rawValue = lua_tostring(L, -1);
+ if (rawValue) {
+ std::string key(rawValue);
+ if (boost::starts_with(key, match) && !(match == "" && boost::starts_with(key, "_"))) {
+ result.push_back(key);
+ }
+ }
+ }
}
std::vector<std::string> Console::getCompletions(const std::string& input, int start, int end) {
- std::string prefix = input.substr(boost::numeric_cast<size_t>(start), boost::numeric_cast<size_t>(end - start));
-
- std::vector<std::string> tokens;
- if (end) {
- tokens = Lua::tokenize(input.substr(0, boost::numeric_cast<size_t>(end)));
- }
-
- // Don't autocomplete strings
- if (!tokens.empty() && ((*tokens.rbegin())[0] == '\'' || (*tokens.rbegin())[0] == '"')) {
- return std::vector<std::string>();
- }
-
- std::vector<std::string> context;
- for (std::vector<std::string>::reverse_iterator i = tokens.rbegin(); i != tokens.rend(); ++i) {
- if (std::isalpha((*i)[0]) || (*i)[0] == '_') {
- if (i != tokens.rbegin()) {
- context.push_back(*i);
- }
- }
- else if (*i != "." && *i != ":") {
- break;
- }
- }
-
- // Drill into context
- int top = lua_gettop(L);
- lua_pushglobaltable(L);
- for (std::vector<std::string>::reverse_iterator i = context.rbegin(); i != context.rend(); ++i) {
- if (lua_istable(L, -1) || lua_isuserdata(L, -1)) {
- lua_getfield(L, -1, i->c_str());
- if (!lua_isnil(L, 1)) {
- continue;
- }
- }
- lua_settop(L, top);
- return std::vector<std::string>();
- }
-
- // Collect all keys from the table
- std::vector<std::string> result;
- if (lua_istable(L, -1)) {
- addMatchingTableKeys(L, prefix, result);
- }
-
- // Collect all keys from the metatable
- if (lua_getmetatable(L, -1)) {
- lua_getfield(L, -1, "__index");
- if (lua_istable(L, -1)) {
- addMatchingTableKeys(L, prefix, result);
- }
- lua_pop(L, 1);
-
- lua_getfield(L, -1, "_completions");
- if (lua_isfunction(L, -1)) {
- lua_pushvalue(L, -3);
- if (lua_pcall(L, 1, 1, 0) != 0) {
- throw std::runtime_error("Error calling '_completions': " + getErrorMessage());
- }
- }
- if (lua_istable(L, -1)) {
- addMatchingTableValues(L, prefix, result);
- }
- lua_pop(L, 2);
- }
-
- lua_settop(L, top);
-
- return result;
+ std::string prefix = input.substr(boost::numeric_cast<size_t>(start), boost::numeric_cast<size_t>(end - start));
+
+ std::vector<std::string> tokens;
+ if (end) {
+ tokens = Lua::tokenize(input.substr(0, boost::numeric_cast<size_t>(end)));
+ }
+
+ // Don't autocomplete strings
+ if (!tokens.empty() && ((*tokens.rbegin())[0] == '\'' || (*tokens.rbegin())[0] == '"')) {
+ return std::vector<std::string>();
+ }
+
+ std::vector<std::string> context;
+ for (std::vector<std::string>::reverse_iterator i = tokens.rbegin(); i != tokens.rend(); ++i) {
+ if (std::isalpha((*i)[0]) || (*i)[0] == '_') {
+ if (i != tokens.rbegin()) {
+ context.push_back(*i);
+ }
+ }
+ else if (*i != "." && *i != ":") {
+ break;
+ }
+ }
+
+ // Drill into context
+ int top = lua_gettop(L);
+ lua_pushglobaltable(L);
+ for (std::vector<std::string>::reverse_iterator i = context.rbegin(); i != context.rend(); ++i) {
+ if (lua_istable(L, -1) || lua_isuserdata(L, -1)) {
+ lua_getfield(L, -1, i->c_str());
+ if (!lua_isnil(L, 1)) {
+ continue;
+ }
+ }
+ lua_settop(L, top);
+ return std::vector<std::string>();
+ }
+
+ // Collect all keys from the table
+ std::vector<std::string> result;
+ if (lua_istable(L, -1)) {
+ addMatchingTableKeys(L, prefix, result);
+ }
+
+ // Collect all keys from the metatable
+ if (lua_getmetatable(L, -1)) {
+ lua_getfield(L, -1, "__index");
+ if (lua_istable(L, -1)) {
+ addMatchingTableKeys(L, prefix, result);
+ }
+ lua_pop(L, 1);
+
+ lua_getfield(L, -1, "_completions");
+ if (lua_isfunction(L, -1)) {
+ lua_pushvalue(L, -3);
+ if (lua_pcall(L, 1, 1, 0) != 0) {
+ throw std::runtime_error("Error calling '_completions': " + getErrorMessage());
+ }
+ }
+ if (lua_istable(L, -1)) {
+ addMatchingTableValues(L, prefix, result);
+ }
+ lua_pop(L, 2);
+ }
+
+ lua_settop(L, top);
+
+ return result;
}