dfhack/plugins/hotkeys.cpp

165 lines
4.5 KiB
C++

#include <map>
#include <string>
#include <vector>
2014-06-01 21:48:34 -06:00
#include "modules/Gui.h"
#include "modules/Screen.h"
2014-06-01 21:48:34 -06:00
2022-07-15 10:44:24 -06:00
#include "LuaTools.h"
2014-06-01 21:48:34 -06:00
#include "PluginManager.h"
DFHACK_PLUGIN("hotkeys");
using std::map;
using std::string;
using std::vector;
using namespace DFHack;
static const std::string MENU_SCREEN_FOCUS_STRING = "dfhack/lua/hotkeys/menu";
2014-06-01 21:48:34 -06:00
static map<string, string> current_bindings;
static vector<string> sorted_keys;
static bool can_invoke(const string &cmdline, df::viewscreen *screen)
2014-06-01 21:48:34 -06:00
{
vector<string> cmd_parts;
split_string(&cmd_parts, cmdline, " ");
if (toLower(cmd_parts[0]) == "hotkeys")
return false;
return Core::getInstance().getPluginManager()->CanInvokeHotkey(cmd_parts[0], screen);
}
static void add_binding_if_valid(const string &sym, const string &cmdline, df::viewscreen *screen)
2014-06-01 21:48:34 -06:00
{
if (!can_invoke(cmdline, screen))
return;
current_bindings[sym] = cmdline;
sorted_keys.push_back(sym);
string keyspec = sym + "@" + MENU_SCREEN_FOCUS_STRING;
2014-06-01 21:48:34 -06:00
Core::getInstance().AddKeyBinding(keyspec, "hotkeys invoke " + int_to_string(sorted_keys.size() - 1));
}
static void find_active_keybindings(df::viewscreen *screen)
{
current_bindings.clear();
sorted_keys.clear();
vector<string> valid_keys;
2022-07-26 12:35:31 -06:00
2014-06-01 21:48:34 -06:00
for (char c = 'A'; c <= 'Z'; c++)
{
valid_keys.push_back(string(&c, 1));
}
for (int i = 1; i < 10; i++)
{
valid_keys.push_back("F" + int_to_string(i));
}
2022-07-15 10:44:24 -06:00
valid_keys.push_back("`");
2014-06-01 21:48:34 -06:00
auto current_focus = Gui::getFocusString(screen);
for (int shifted = 0; shifted < 2; shifted++)
{
for (int ctrl = 0; ctrl < 2; ctrl++)
{
for (int alt = 0; alt < 2; alt++)
{
for (auto it = valid_keys.begin(); it != valid_keys.end(); it++)
{
string sym;
if (shifted) sym += "Shift-";
if (ctrl) sym += "Ctrl-";
if (alt) sym += "Alt-";
sym += *it;
auto list = Core::getInstance().ListKeyBindings(sym);
for (auto invoke_cmd = list.begin(); invoke_cmd != list.end(); invoke_cmd++)
{
if (invoke_cmd->find(":") == string::npos)
{
add_binding_if_valid(sym, *invoke_cmd, screen);
}
else
{
vector<string> tokens;
split_string(&tokens, *invoke_cmd, ":");
string focus = tokens[0].substr(1);
if (prefix_matches(focus, current_focus))
{
auto cmdline = trim(tokens[1]);
add_binding_if_valid(sym, cmdline, screen);
}
}
}
}
}
}
}
}
static bool close_hotkeys_screen()
{
auto screen = Core::getTopViewscreen();
if (Gui::getFocusString(screen) != MENU_SCREEN_FOCUS_STRING)
2014-06-01 21:48:34 -06:00
return false;
Screen::dismiss(Core::getTopViewscreen());
std::for_each(sorted_keys.begin(), sorted_keys.end(), [](const string &sym){
Core::getInstance().ClearKeyBindings(sym + "@" + MENU_SCREEN_FOCUS_STRING);
});
2014-06-01 21:48:34 -06:00
sorted_keys.clear();
return true;
}
static bool invoke_command(const size_t index)
2014-06-01 21:48:34 -06:00
{
if (sorted_keys.size() <= index)
return false;
2014-06-01 21:48:34 -06:00
auto cmd = current_bindings[sorted_keys[index]];
if (close_hotkeys_screen()) {
2014-06-01 21:48:34 -06:00
Core::getInstance().setHotkeyCmd(cmd);
return true;
2014-06-01 21:48:34 -06:00
}
return false;
2014-06-01 21:48:34 -06:00
}
static command_result hotkeys_cmd(color_ostream &out, vector <string> & parameters)
{
if (parameters.size() != 2 || parameters[0] != "invoke")
return CR_WRONG_USAGE;
2014-06-01 21:48:34 -06:00
int index;
std::stringstream index_raw(parameters[1]);
index_raw >> index;
return invoke_command(index) ? CR_OK : CR_WRONG_USAGE;
2014-06-01 21:48:34 -06:00
}
2022-11-04 18:42:38 -06:00
static int getHotkeys(lua_State *L) {
find_active_keybindings(Gui::getCurViewscreen(true));
Lua::PushVector(L, sorted_keys);
Lua::Push(L, current_bindings);
return 2;
}
DFHACK_PLUGIN_LUA_COMMANDS {
DFHACK_LUA_COMMAND(getHotkeys),
DFHACK_LUA_END
};
2014-06-01 21:48:34 -06:00
DFhackCExport command_result plugin_init ( color_ostream &out, std::vector <PluginCommand> &commands)
{
commands.push_back(
PluginCommand(
2022-07-25 22:54:34 -06:00
"hotkeys",
"Invoke hotkeys from the interactive menu.",
2022-07-25 22:54:34 -06:00
hotkeys_cmd));
2014-06-01 21:48:34 -06:00
return CR_OK;
}