diff --git a/CHANGELOG.md b/CHANGELOG.md index dd97e5e946..0c9989b26b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,6 +46,7 @@ Feature #6995: Localize the "show effect duration" option Feature #7058: Implement TestModels (T3D) console command Feature #7087: Block resolution change in the Windowed Fullscreen mode + Feature #7125: Remembering console commands between sessions Feature #7130: Ability to set MyGUI logging verbosity Feature #7148: Optimize string literal lookup in mwscript Feature #7194: Ori to show texture paths diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 8fe63bc7b6..d56ae789e6 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -749,7 +749,7 @@ void OMW::Engine::prepareEngine() mWindowManager = std::make_unique(mWindow, mViewer, guiRoot, mResourceSystem.get(), mWorkQueue.get(), mCfgMgr.getLogPath(), mScriptConsoleMode, mTranslationDataStorage, mEncoding, - Version::getOpenmwVersionDescription(mResDir), shadersSupported); + Version::getOpenmwVersionDescription(mResDir), shadersSupported, mCfgMgr); mEnvironment.setWindowManager(*mWindowManager); mInputManager = std::make_unique(mWindow, mViewer, mScreenCaptureHandler, diff --git a/apps/openmw/mwgui/console.cpp b/apps/openmw/mwgui/console.cpp index ded51f139e..5a936d2862 100644 --- a/apps/openmw/mwgui/console.cpp +++ b/apps/openmw/mwgui/console.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include "../mwscript/extensions.hpp" #include "../mwscript/interpretercontext.hpp" @@ -133,10 +134,11 @@ namespace MWGui } } - Console::Console(int w, int h, bool consoleOnlyScripts) + Console::Console(int w, int h, bool consoleOnlyScripts, Files::ConfigurationManager& cfgMgr) : WindowBase("openmw_console.layout") , mCompilerContext(MWScript::CompilerContext::Type_Console) , mConsoleOnlyScripts(consoleOnlyScripts) + , mCfgMgr(cfgMgr) { setCoord(10, 10, w - 10, h / 2); @@ -153,6 +155,15 @@ namespace MWGui // compiler Compiler::registerExtensions(mExtensions, mConsoleOnlyScripts); mCompilerContext.setExtensions(&mExtensions); + + // command history file + initConsoleHistory(); + } + + Console::~Console() + { + if (mCommandHistoryFile && mCommandHistoryFile.is_open()) + mCommandHistoryFile.close(); } void Console::onOpen() @@ -341,7 +352,12 @@ namespace MWGui // Add the command to the history, and set the current pointer to // the end of the list if (mCommandHistory.empty() || mCommandHistory.back() != cm) + { mCommandHistory.push_back(cm); + + if (mCommandHistoryFile && mCommandHistoryFile.good()) + mCommandHistoryFile << cm << std::endl; + } mCurrent = mCommandHistory.end(); mEditString.clear(); mHistory->setTextCursor(mHistory->getTextLength()); @@ -553,4 +569,43 @@ namespace MWGui ReferenceInterface::resetReference(); setSelectedObject(MWWorld::Ptr()); } + + void Console::initConsoleHistory() + { + const auto filePath = mCfgMgr.getUserConfigPath() / "console_history.txt"; + const size_t retrievalLimit = Settings::Manager::getSize("console history buffer size", "General"); + + std::ifstream historyFile(filePath); + std::string line; + + // Read the previous session's commands from the file + while (std::getline(historyFile, line)) + { + // Truncate the list if it exceeds the retrieval limit + if (mCommandHistory.size() >= retrievalLimit) + mCommandHistory.pop_front(); + mCommandHistory.push_back(line); + } + + historyFile.close(); + + mCurrent = mCommandHistory.end(); + try + { + mCommandHistoryFile.exceptions(std::fstream::failbit | std::fstream::badbit); + mCommandHistoryFile.open(filePath, std::ios_base::trunc); + + // Update the history file + for (const auto& histObj : mCommandHistory) + mCommandHistoryFile << histObj << std::endl; + mCommandHistoryFile.close(); + + mCommandHistoryFile.open(filePath, std::ios_base::app); + } + catch (const std::ios_base::failure& e) + { + Log(Debug::Error) << "Error: Failed to write to console history file " << filePath << " : " << e.what() + << " : " << std::generic_category().message(errno); + } + } } diff --git a/apps/openmw/mwgui/console.hpp b/apps/openmw/mwgui/console.hpp index 306c7f63f1..e092bf5690 100644 --- a/apps/openmw/mwgui/console.hpp +++ b/apps/openmw/mwgui/console.hpp @@ -8,6 +8,7 @@ #include #include #include +#include #include "../mwbase/windowmanager.hpp" @@ -34,8 +35,10 @@ namespace MWGui StringList mCommandHistory; StringList::iterator mCurrent; std::string mEditString; + std::ofstream mCommandHistoryFile; - Console(int w, int h, bool consoleOnlyScripts); + Console(int w, int h, bool consoleOnlyScripts, Files::ConfigurationManager& cfgMgr); + ~Console(); void onOpen() override; @@ -82,8 +85,9 @@ namespace MWGui Compiler::Extensions mExtensions; MWScript::CompilerContext mCompilerContext; std::vector mNames; - bool mConsoleOnlyScripts; + bool mConsoleOnlyScripts; + Files::ConfigurationManager& mCfgMgr; bool compile(const std::string& cmd, Compiler::Output& output); /// Report error to the user. @@ -97,6 +101,8 @@ namespace MWGui /// \note The list may contain duplicates (if a name is a keyword and an identifier at the same /// time). void listNames(); + + void initConsoleHistory(); }; } #endif diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index b313aba0f9..3e4f1fb122 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -123,7 +123,7 @@ namespace MWGui WindowManager::WindowManager(SDL_Window* window, osgViewer::Viewer* viewer, osg::Group* guiRoot, Resource::ResourceSystem* resourceSystem, SceneUtil::WorkQueue* workQueue, const std::filesystem::path& logpath, bool consoleOnlyScripts, Translation::Storage& translationDataStorage, ToUTF8::FromType encoding, - const std::string& versionDescription, bool useShaders) + const std::string& versionDescription, bool useShaders, Files::ConfigurationManager& cfgMgr) : mOldUpdateMask(0) , mOldCullMask(0) , mStore(nullptr) @@ -178,6 +178,7 @@ namespace MWGui , mEncoding(encoding) , mVersionDescription(versionDescription) , mWindowVisible(true) + , mCfgMgr(cfgMgr) { int w, h; SDL_GetWindowSize(window, &w, &h); @@ -335,7 +336,7 @@ namespace MWGui trackWindow(mTradeWindow, "barter"); mGuiModeStates[GM_Barter] = GuiModeState({ mInventoryWindow, mTradeWindow }); - auto console = std::make_unique(w, h, mConsoleOnlyScripts); + auto console = std::make_unique(w, h, mConsoleOnlyScripts, mCfgMgr); mConsole = console.get(); mWindows.push_back(std::move(console)); trackWindow(mConsole, "console"); diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index dd02ba2169..100cd21139 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -126,7 +126,8 @@ namespace MWGui WindowManager(SDL_Window* window, osgViewer::Viewer* viewer, osg::Group* guiRoot, Resource::ResourceSystem* resourceSystem, SceneUtil::WorkQueue* workQueue, const std::filesystem::path& logpath, bool consoleOnlyScripts, Translation::Storage& translationDataStorage, - ToUTF8::FromType encoding, const std::string& versionDescription, bool useShaders); + ToUTF8::FromType encoding, const std::string& versionDescription, bool useShaders, + Files::ConfigurationManager& cfgMgr); virtual ~WindowManager(); /// Set the ESMStore to use for retrieving of GUI-related strings. @@ -585,6 +586,8 @@ namespace MWGui void setCullMask(uint32_t mask) override; uint32_t getCullMask() override; + + Files::ConfigurationManager& mCfgMgr; }; } diff --git a/docs/source/reference/modding/settings/general.rst b/docs/source/reference/modding/settings/general.rst index 84c4a19f44..e706cba28c 100644 --- a/docs/source/reference/modding/settings/general.rst +++ b/docs/source/reference/modding/settings/general.rst @@ -100,3 +100,16 @@ Zero disables the log viewer. This setting can only be configured by editing the settings configuration file. +console history buffer size +--------------------------- + +:Type: platform dependant unsigned integer +:Range: >= 0 +:Default: 4096 + +Number of console history objects to retrieve from previous session. If the number of history +objects in the file exceeds this value, history objects will be erased starting from the oldest. +This operation runs on every new session. See :doc:`../paths` for location of the history file. + +This setting can only be configured by editing the settings configuration file. + diff --git a/files/settings-default.cfg b/files/settings-default.cfg index fe93e019bf..3c6395a63e 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -396,6 +396,9 @@ preferred locales = en # Buffer size for the in-game log viewer (press F10 to toggle). Zero disables the log viewer. log buffer size = 65536 +# Number of console history objects to retrieve from previous session. +console history buffer size = 4096 + [Shaders] # Force rendering with shaders. By default, only bump-mapped objects will use shaders.