Merge pull request #2262 from myk002/myk_history_repo

Allow lua scripts to access a commandline history without a terminal
develop
Myk 2022-08-15 16:29:22 -07:00 committed by GitHub
commit 859414ac3b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 62 additions and 1 deletions

@ -524,6 +524,20 @@ Input & Output
lock. Using an explicit ``dfhack.with_suspend`` will prevent lock. Using an explicit ``dfhack.with_suspend`` will prevent
this, forcing the function to block on input with lock held. this, forcing the function to block on input with lock held.
* ``dfhack.getCommandHistory(history_id, history_filename)``
Returns the list of strings in the specified history. Intended to be used by
GUI scripts that don't have access to a console and so can't use
``dfhack.lineedit``. The ``history_id`` parameter is some unique string that
the script uses to identify its command history, such as the script's name. If
this is the first time the history with the given ``history_id`` is being
accessed, it is initialized from the given file.
* ``dfhack.addCommandToHistory(history_id, history_filename, command)``
Adds a command to the specified history and saves the updated history to the
specified file.
* ``dfhack.interpreter([prompt[,history_filename[,env]]])`` * ``dfhack.interpreter([prompt[,history_filename[,env]]])``
Starts an interactive lua interpreter, using the specified prompt Starts an interactive lua interpreter, using the specified prompt
@ -837,6 +851,7 @@ can be omitted.
* ``dfhack.getGitXmlExpectedCommit()`` * ``dfhack.getGitXmlExpectedCommit()``
* ``dfhack.gitXmlMatch()`` * ``dfhack.gitXmlMatch()``
* ``dfhack.isRelease()`` * ``dfhack.isRelease()``
* ``dfhack.isPrerelease()``
Return information about the DFHack build in use. Return information about the DFHack build in use.
@ -890,7 +905,6 @@ can be omitted.
from ``dfhack.TranslateName()``), use ``print(dfhack.df2console(text))`` to from ``dfhack.TranslateName()``), use ``print(dfhack.df2console(text))`` to
ensure proper display on all platforms. ensure proper display on all platforms.
* ``dfhack.utf2df(string)`` * ``dfhack.utf2df(string)``
Convert a string from UTF-8 to DF's CP437 encoding. Convert a string from UTF-8 to DF's CP437 encoding.

@ -66,6 +66,7 @@ changelog.txt uses a syntax similar to RST, with a few special sequences:
- ``Gui::getSelectedItem()``, ``Gui::getAnyItem()``: added support for the artifacts screen - ``Gui::getSelectedItem()``, ``Gui::getAnyItem()``: added support for the artifacts screen
## Lua ## Lua
- History: added ``dfhack.getCommandHistory(history_id, history_filename)`` and ``dfhack.addCommandToHistory(history_id, history_filename, command)`` so gui scripts can access a commandline history without requiring a terminal.
- ``tile-material``: fix the order of declarations. The ``GetTileMat`` function now returns the material as intended (always returned nil before). Also changed the license info, with permission of the original author. - ``tile-material``: fix the order of declarations. The ``GetTileMat`` function now returns the material as intended (always returned nil before). Also changed the license info, with permission of the original author.
- ``widgets.EditField``: new ``onsubmit2`` callback attribute is called when the user hits Shift-Enter. - ``widgets.EditField``: new ``onsubmit2`` callback attribute is called when the user hits Shift-Enter.
- ``widgets.EditField``: new function: ``setCursor(position)`` sets the input cursor. - ``widgets.EditField``: new function: ``setCursor(position)`` sets the input cursor.

@ -1359,6 +1359,38 @@ static void OpenRandom(lua_State *state)
lua_pop(state, 1); lua_pop(state, 1);
} }
/*********************************
* Commandline history repository *
**********************************/
static std::map<std::string, CommandHistory> commandHistories;
static CommandHistory * ensureCommandHistory(std::string id,
std::string src_file) {
if (!commandHistories.count(id)) {
commandHistories[id].load(src_file.c_str());
}
return &commandHistories[id];
}
static int getCommandHistory(lua_State *state)
{
std::string id = lua_tostring(state, 1);
std::string src_file = lua_tostring(state, 2);
std::vector<std::string> entries;
ensureCommandHistory(id, src_file)->getEntries(entries);
Lua::PushVector(state, entries);
return 1;
}
static void addCommandToHistory(std::string id, std::string src_file,
std::string command) {
CommandHistory *history = ensureCommandHistory(id, src_file);
history->add(command);
history->save(src_file.c_str());
}
/************************ /************************
* Wrappers for C++ API * * Wrappers for C++ API *
************************/ ************************/
@ -1450,6 +1482,12 @@ static const LuaWrapper::FunctionReg dfhack_module[] = {
WRAP_VERSION_FUNC(gitXmlMatch, git_xml_match), WRAP_VERSION_FUNC(gitXmlMatch, git_xml_match),
WRAP_VERSION_FUNC(isRelease, is_release), WRAP_VERSION_FUNC(isRelease, is_release),
WRAP_VERSION_FUNC(isPrerelease, is_prerelease), WRAP_VERSION_FUNC(isPrerelease, is_prerelease),
WRAP(addCommandToHistory),
{ NULL, NULL }
};
static const luaL_Reg dfhack_funcs[] = {
{ "getCommandHistory", getCommandHistory },
{ NULL, NULL } { NULL, NULL }
}; };
@ -3113,6 +3151,7 @@ void OpenDFHackApi(lua_State *state)
OpenRandom(state); OpenRandom(state);
LuaWrapper::SetFunctionWrappers(state, dfhack_module); LuaWrapper::SetFunctionWrappers(state, dfhack_module);
luaL_setfuncs(state, dfhack_funcs, 0);
OpenModule(state, "gui", dfhack_gui_module, dfhack_gui_funcs); OpenModule(state, "gui", dfhack_gui_module, dfhack_gui_funcs);
OpenModule(state, "job", dfhack_job_module, dfhack_job_funcs); OpenModule(state, "job", dfhack_job_module, dfhack_job_funcs);
OpenModule(state, "units", dfhack_units_module, dfhack_units_funcs); OpenModule(state, "units", dfhack_units_module, dfhack_units_funcs);

@ -32,6 +32,7 @@ distribution.
#include <assert.h> #include <assert.h>
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <vector>
namespace tthread namespace tthread
{ {
class mutex; class mutex;
@ -114,6 +115,12 @@ namespace DFHack
{ {
history.pop_front(); history.pop_front();
} }
/// adds the current list of entries to the given vector
void getEntries(std::vector<std::string> &entries)
{
for (auto &entry : history)
entries.push_back(entry);
}
private: private:
std::size_t capacity; std::size_t capacity;
std::deque <std::string> history; std::deque <std::string> history;