|
|
|
@ -277,65 +277,6 @@ static string dfhack_version_desc()
|
|
|
|
|
return s.str();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static std::string getScriptHelp(std::string path, std::string helpprefix)
|
|
|
|
|
{
|
|
|
|
|
ifstream script(path.c_str());
|
|
|
|
|
|
|
|
|
|
if (script.good())
|
|
|
|
|
{
|
|
|
|
|
std::string help;
|
|
|
|
|
if (getline(script, help) &&
|
|
|
|
|
help.substr(0,helpprefix.length()) == helpprefix)
|
|
|
|
|
{
|
|
|
|
|
help = help.substr(helpprefix.length());
|
|
|
|
|
while (help.size() && help[0] == ' ')
|
|
|
|
|
help = help.substr(1);
|
|
|
|
|
return help;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return "No help available.";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void listScripts(PluginManager *plug_mgr, std::map<string,string> &pset, std::string path, bool all, std::string prefix = "")
|
|
|
|
|
{
|
|
|
|
|
std::vector<string> files;
|
|
|
|
|
Filesystem::listdir(path, files);
|
|
|
|
|
|
|
|
|
|
path += '/';
|
|
|
|
|
for (size_t i = 0; i < files.size(); i++)
|
|
|
|
|
{
|
|
|
|
|
if (hasEnding(files[i], ".lua"))
|
|
|
|
|
{
|
|
|
|
|
string help = getScriptHelp(path + files[i], "--");
|
|
|
|
|
string key = prefix + files[i].substr(0, files[i].size()-4);
|
|
|
|
|
if (pset.find(key) == pset.end()) {
|
|
|
|
|
pset[key] = help;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (plug_mgr->ruby && plug_mgr->ruby->is_enabled() && hasEnding(files[i], ".rb"))
|
|
|
|
|
{
|
|
|
|
|
string help = getScriptHelp(path + files[i], "#");
|
|
|
|
|
string key = prefix + files[i].substr(0, files[i].size()-3);
|
|
|
|
|
if (pset.find(key) == pset.end()) {
|
|
|
|
|
pset[key] = help;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (all && !files[i].empty() && files[i][0] != '.' && files[i] != "internal" && files[i] != "test")
|
|
|
|
|
{
|
|
|
|
|
listScripts(plug_mgr, pset, path+files[i]+"/", all, prefix+files[i]+"/");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void listAllScripts(map<string, string> &pset, bool all)
|
|
|
|
|
{
|
|
|
|
|
vector<string> paths;
|
|
|
|
|
Core::getInstance().getScriptPaths(&paths);
|
|
|
|
|
for (string path : paths)
|
|
|
|
|
listScripts(Core::getInstance().getPluginManager(), pset, path, all);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
struct ScriptArgs {
|
|
|
|
|
const string *pcmd;
|
|
|
|
@ -442,60 +383,52 @@ command_result Core::runCommand(color_ostream &out, const std::string &command)
|
|
|
|
|
return CR_NOT_IMPLEMENTED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// List of built in commands
|
|
|
|
|
static const std::set<std::string> built_in_commands = {
|
|
|
|
|
"ls" ,
|
|
|
|
|
"help" ,
|
|
|
|
|
"tags" ,
|
|
|
|
|
"type" ,
|
|
|
|
|
"load" ,
|
|
|
|
|
"unload" ,
|
|
|
|
|
"reload" ,
|
|
|
|
|
"enable" ,
|
|
|
|
|
"disable" ,
|
|
|
|
|
"plug" ,
|
|
|
|
|
"keybinding" ,
|
|
|
|
|
"alias" ,
|
|
|
|
|
"fpause" ,
|
|
|
|
|
"cls" ,
|
|
|
|
|
"die" ,
|
|
|
|
|
"kill-lua" ,
|
|
|
|
|
"script" ,
|
|
|
|
|
"hide" ,
|
|
|
|
|
"show" ,
|
|
|
|
|
"sc-script"
|
|
|
|
|
};
|
|
|
|
|
bool is_builtin(color_ostream &con, const string &command) {
|
|
|
|
|
CoreSuspender suspend;
|
|
|
|
|
auto L = Lua::Core::State;
|
|
|
|
|
Lua::StackUnwinder top(L);
|
|
|
|
|
|
|
|
|
|
static bool try_autocomplete(color_ostream &con, const std::string &first, std::string &completed)
|
|
|
|
|
{
|
|
|
|
|
std::vector<std::string> possible;
|
|
|
|
|
if (!lua_checkstack(L, 1) ||
|
|
|
|
|
!Lua::PushModulePublic(con, L, "helpdb", "is_builtin")) {
|
|
|
|
|
con.printerr("Failed to load helpdb Lua code\n");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check for possible built in commands to autocomplete first
|
|
|
|
|
for (auto const &command : built_in_commands)
|
|
|
|
|
if (command.substr(0, first.size()) == first)
|
|
|
|
|
possible.push_back(command);
|
|
|
|
|
Lua::Push(L, command);
|
|
|
|
|
|
|
|
|
|
auto plug_mgr = Core::getInstance().getPluginManager();
|
|
|
|
|
for (auto it = plug_mgr->begin(); it != plug_mgr->end(); ++it)
|
|
|
|
|
{
|
|
|
|
|
const Plugin * plug = it->second;
|
|
|
|
|
for (size_t j = 0; j < plug->size(); j++)
|
|
|
|
|
{
|
|
|
|
|
const PluginCommand &pcmd = (*plug)[j];
|
|
|
|
|
if (pcmd.isHotkeyCommand())
|
|
|
|
|
continue;
|
|
|
|
|
if (pcmd.name.substr(0, first.size()) == first)
|
|
|
|
|
possible.push_back(pcmd.name);
|
|
|
|
|
if (!Lua::SafeCall(con, L, 1, 1)) {
|
|
|
|
|
con.printerr("Failed Lua call to helpdb.is_builtin.\n");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return lua_toboolean(L, -1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void get_commands(color_ostream &con, vector<string> &commands) {
|
|
|
|
|
CoreSuspender suspend;
|
|
|
|
|
auto L = Lua::Core::State;
|
|
|
|
|
Lua::StackUnwinder top(L);
|
|
|
|
|
|
|
|
|
|
if (!lua_checkstack(L, 1) ||
|
|
|
|
|
!Lua::PushModulePublic(con, L, "helpdb", "get_commands")) {
|
|
|
|
|
con.printerr("Failed to load helpdb Lua code\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!Lua::SafeCall(con, L, 0, 1)) {
|
|
|
|
|
con.printerr("Failed Lua call to helpdb.get_commands.\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool all = (first.find('/') != std::string::npos);
|
|
|
|
|
Lua::GetVector(L, commands);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::map<string, string> scripts;
|
|
|
|
|
listAllScripts(scripts, all);
|
|
|
|
|
for (auto iter = scripts.begin(); iter != scripts.end(); ++iter)
|
|
|
|
|
if (iter->first.substr(0, first.size()) == first)
|
|
|
|
|
possible.push_back(iter->first);
|
|
|
|
|
static bool try_autocomplete(color_ostream &con, const std::string &first, std::string &completed)
|
|
|
|
|
{
|
|
|
|
|
std::vector<std::string> commands, possible;
|
|
|
|
|
|
|
|
|
|
for (auto &command : commands)
|
|
|
|
|
if (command.substr(0, first.size()) == first)
|
|
|
|
|
possible.push_back(command);
|
|
|
|
|
|
|
|
|
|
if (possible.size() == 1)
|
|
|
|
|
{
|
|
|
|
@ -651,30 +584,6 @@ static std::string sc_event_name (state_change_event id) {
|
|
|
|
|
return "SC_UNKNOWN";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string getBuiltinCommand(std::string cmd)
|
|
|
|
|
{
|
|
|
|
|
std::string builtin = "";
|
|
|
|
|
|
|
|
|
|
// Check our list of builtin commands from the header
|
|
|
|
|
if (built_in_commands.count(cmd))
|
|
|
|
|
builtin = cmd;
|
|
|
|
|
|
|
|
|
|
// Check for some common aliases for built in commands
|
|
|
|
|
else if (cmd == "?" || cmd == "man")
|
|
|
|
|
builtin = "help";
|
|
|
|
|
|
|
|
|
|
else if (cmd == "dir")
|
|
|
|
|
builtin = "ls";
|
|
|
|
|
|
|
|
|
|
else if (cmd == "clear")
|
|
|
|
|
builtin = "cls";
|
|
|
|
|
|
|
|
|
|
else if (cmd == "devel/dump-rpc")
|
|
|
|
|
builtin = "devel/dump-rpc";
|
|
|
|
|
|
|
|
|
|
return builtin;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void help_helper(color_ostream &con, const string &entry_name) {
|
|
|
|
|
CoreSuspender suspend;
|
|
|
|
|
auto L = Lua::Core::State;
|
|
|
|
@ -753,9 +662,9 @@ command_result Core::runCommand(color_ostream &con, const std::string &first_, v
|
|
|
|
|
return CR_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
command_result res;
|
|
|
|
|
if (!first.empty())
|
|
|
|
|
{
|
|
|
|
|
if (first.empty())
|
|
|
|
|
return CR_NOT_IMPLEMENTED;
|
|
|
|
|
|
|
|
|
|
if (first.find('\\') != std::string::npos)
|
|
|
|
|
{
|
|
|
|
|
con.printerr("Replacing backslashes with forward slashes in \"%s\"\n", first.c_str());
|
|
|
|
@ -767,8 +676,8 @@ command_result Core::runCommand(color_ostream &con, const std::string &first_, v
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// let's see what we actually got
|
|
|
|
|
string builtin = getBuiltinCommand(first);
|
|
|
|
|
if (builtin == "help")
|
|
|
|
|
command_result res;
|
|
|
|
|
if (first == "help" || first == "man" || first == "?")
|
|
|
|
|
{
|
|
|
|
|
if(!parts.size())
|
|
|
|
|
{
|
|
|
|
@ -803,15 +712,15 @@ command_result Core::runCommand(color_ostream &con, const std::string &first_, v
|
|
|
|
|
help_helper(con, parts[0]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (builtin == "tags")
|
|
|
|
|
else if (first == "tags")
|
|
|
|
|
{
|
|
|
|
|
tags_helper(con);
|
|
|
|
|
}
|
|
|
|
|
else if (builtin == "load" || builtin == "unload" || builtin == "reload")
|
|
|
|
|
else if (first == "load" || first == "unload" || first == "reload")
|
|
|
|
|
{
|
|
|
|
|
bool all = false;
|
|
|
|
|
bool load = (builtin == "load");
|
|
|
|
|
bool unload = (builtin == "unload");
|
|
|
|
|
bool load = (first == "load");
|
|
|
|
|
bool unload = (first == "unload");
|
|
|
|
|
if (parts.size())
|
|
|
|
|
{
|
|
|
|
|
for (auto p = parts.begin(); p != parts.end(); p++)
|
|
|
|
@ -845,12 +754,12 @@ command_result Core::runCommand(color_ostream &con, const std::string &first_, v
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
con.printerr("%s: no arguments\n", builtin.c_str());
|
|
|
|
|
con.printerr("%s: no arguments\n", first.c_str());
|
|
|
|
|
}
|
|
|
|
|
else if( builtin == "enable" || builtin == "disable" )
|
|
|
|
|
else if( first == "enable" || first == "disable" )
|
|
|
|
|
{
|
|
|
|
|
CoreSuspender suspend;
|
|
|
|
|
bool enable = (builtin == "enable");
|
|
|
|
|
bool enable = (first == "enable");
|
|
|
|
|
|
|
|
|
|
if(parts.size())
|
|
|
|
|
{
|
|
|
|
@ -885,14 +794,14 @@ command_result Core::runCommand(color_ostream &con, const std::string &first_, v
|
|
|
|
|
else if (!plug->can_set_enabled())
|
|
|
|
|
{
|
|
|
|
|
res = CR_NOT_IMPLEMENTED;
|
|
|
|
|
con.printerr("Cannot %s plugin: %s\n", builtin.c_str(), part.c_str());
|
|
|
|
|
con.printerr("Cannot %s plugin: %s\n", first.c_str(), part.c_str());
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
res = plug->set_enabled(con, enable);
|
|
|
|
|
|
|
|
|
|
if (res != CR_OK || plug->is_enabled() != enable)
|
|
|
|
|
con.printerr("Could not %s plugin: %s\n", builtin.c_str(), part.c_str());
|
|
|
|
|
con.printerr("Could not %s plugin: %s\n", first.c_str(), part.c_str());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -914,11 +823,11 @@ command_result Core::runCommand(color_ostream &con, const std::string &first_, v
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (builtin == "ls" || builtin == "dir")
|
|
|
|
|
else if (first == "ls" || first == "dir")
|
|
|
|
|
{
|
|
|
|
|
ls_helper(con, parts);
|
|
|
|
|
}
|
|
|
|
|
else if (builtin == "plug")
|
|
|
|
|
else if (first == "plug")
|
|
|
|
|
{
|
|
|
|
|
const char *header_format = "%30s %10s %4s %8s\n";
|
|
|
|
|
const char *row_format = "%30s %10s %4i %8s\n";
|
|
|
|
@ -964,7 +873,7 @@ command_result Core::runCommand(color_ostream &con, const std::string &first_, v
|
|
|
|
|
con.color(COLOR_RESET);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (builtin == "type")
|
|
|
|
|
else if (first == "type")
|
|
|
|
|
{
|
|
|
|
|
if (!parts.size())
|
|
|
|
|
{
|
|
|
|
@ -972,15 +881,13 @@ command_result Core::runCommand(color_ostream &con, const std::string &first_, v
|
|
|
|
|
return CR_WRONG_USAGE;
|
|
|
|
|
}
|
|
|
|
|
con << parts[0];
|
|
|
|
|
string builtin_cmd = getBuiltinCommand(parts[0]);
|
|
|
|
|
bool builtin = is_builtin(con, parts[0]);
|
|
|
|
|
string lua_path = findScript(parts[0] + ".lua");
|
|
|
|
|
string ruby_path = findScript(parts[0] + ".rb");
|
|
|
|
|
Plugin *plug = plug_mgr->getPluginByCommand(parts[0]);
|
|
|
|
|
if (builtin_cmd.size())
|
|
|
|
|
if (builtin)
|
|
|
|
|
{
|
|
|
|
|
con << " is a built-in command";
|
|
|
|
|
if (builtin_cmd != parts[0])
|
|
|
|
|
con << " (aliased to " << builtin_cmd << ")";
|
|
|
|
|
con << std::endl;
|
|
|
|
|
}
|
|
|
|
|
else if (IsAlias(parts[0]))
|
|
|
|
@ -1008,7 +915,7 @@ command_result Core::runCommand(color_ostream &con, const std::string &first_, v
|
|
|
|
|
return CR_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (builtin == "keybinding")
|
|
|
|
|
else if (first == "keybinding")
|
|
|
|
|
{
|
|
|
|
|
if (parts.size() >= 3 && (parts[0] == "set" || parts[0] == "add"))
|
|
|
|
|
{
|
|
|
|
@ -1056,7 +963,7 @@ command_result Core::runCommand(color_ostream &con, const std::string &first_, v
|
|
|
|
|
<< Gui::getFocusString(Core::getTopViewscreen()) << endl;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (builtin == "alias")
|
|
|
|
|
else if (first == "alias")
|
|
|
|
|
{
|
|
|
|
|
if (parts.size() >= 3 && (parts[0] == "add" || parts[0] == "replace"))
|
|
|
|
|
{
|
|
|
|
@ -1092,7 +999,7 @@ command_result Core::runCommand(color_ostream &con, const std::string &first_, v
|
|
|
|
|
<< " alias list" << endl;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (builtin == "fpause")
|
|
|
|
|
else if (first == "fpause")
|
|
|
|
|
{
|
|
|
|
|
World::SetPauseState(true);
|
|
|
|
|
if (auto scr = Gui::getViewscreenByType<df::viewscreen_new_regionst>())
|
|
|
|
@ -1101,7 +1008,7 @@ command_result Core::runCommand(color_ostream &con, const std::string &first_, v
|
|
|
|
|
}
|
|
|
|
|
con.print("The game was forced to pause!\n");
|
|
|
|
|
}
|
|
|
|
|
else if (builtin == "cls")
|
|
|
|
|
else if (first == "cls" || first == "clear")
|
|
|
|
|
{
|
|
|
|
|
if (con.is_console())
|
|
|
|
|
((Console&)con).clear();
|
|
|
|
@ -1111,11 +1018,11 @@ command_result Core::runCommand(color_ostream &con, const std::string &first_, v
|
|
|
|
|
return CR_NEEDS_CONSOLE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (builtin == "die")
|
|
|
|
|
else if (first == "die")
|
|
|
|
|
{
|
|
|
|
|
std::_Exit(666);
|
|
|
|
|
}
|
|
|
|
|
else if (builtin == "kill-lua")
|
|
|
|
|
else if (first == "kill-lua")
|
|
|
|
|
{
|
|
|
|
|
bool force = false;
|
|
|
|
|
for (auto it = parts.begin(); it != parts.end(); ++it)
|
|
|
|
@ -1132,7 +1039,7 @@ command_result Core::runCommand(color_ostream &con, const std::string &first_, v
|
|
|
|
|
" profiling and coverage monitoring.\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (builtin == "script")
|
|
|
|
|
else if (first == "script")
|
|
|
|
|
{
|
|
|
|
|
if(parts.size() == 1)
|
|
|
|
|
{
|
|
|
|
@ -1145,7 +1052,7 @@ command_result Core::runCommand(color_ostream &con, const std::string &first_, v
|
|
|
|
|
return CR_WRONG_USAGE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (builtin=="hide")
|
|
|
|
|
else if (first == "hide")
|
|
|
|
|
{
|
|
|
|
|
if (!getConsole().hide())
|
|
|
|
|
{
|
|
|
|
@ -1154,7 +1061,7 @@ command_result Core::runCommand(color_ostream &con, const std::string &first_, v
|
|
|
|
|
}
|
|
|
|
|
return CR_OK;
|
|
|
|
|
}
|
|
|
|
|
else if (builtin=="show")
|
|
|
|
|
else if (first == "show")
|
|
|
|
|
{
|
|
|
|
|
if (!getConsole().show())
|
|
|
|
|
{
|
|
|
|
@ -1163,7 +1070,7 @@ command_result Core::runCommand(color_ostream &con, const std::string &first_, v
|
|
|
|
|
}
|
|
|
|
|
return CR_OK;
|
|
|
|
|
}
|
|
|
|
|
else if (builtin == "sc-script")
|
|
|
|
|
else if (first == "sc-script")
|
|
|
|
|
{
|
|
|
|
|
if (parts.empty() || parts[0] == "help" || parts[0] == "?")
|
|
|
|
|
{
|
|
|
|
@ -1257,7 +1164,7 @@ command_result Core::runCommand(color_ostream &con, const std::string &first_, v
|
|
|
|
|
return CR_WRONG_USAGE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if (builtin == "devel/dump-rpc")
|
|
|
|
|
else if (first == "devel/dump-rpc")
|
|
|
|
|
{
|
|
|
|
|
if (parts.size() == 1)
|
|
|
|
|
{
|
|
|
|
@ -1333,9 +1240,6 @@ command_result Core::runCommand(color_ostream &con, const std::string &first_, v
|
|
|
|
|
return CR_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return CR_NOT_IMPLEMENTED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool Core::loadScriptFile(color_ostream &out, string fname, bool silent)
|
|
|
|
|
{
|
|
|
|
|
if(!silent) {
|
|
|
|
|