undo-cxx C++17/20 library provides a undo/redo subsystem (linear or restricted non-linear).
- v0.3.2, security patch for github workflow; fix arch detections in dummy project - affect generating undo-cxx_config.hh
- v0.3.1, added
newest_item()for #1 - v0.3.0, build passed for c++20
- v0.2.5, upgrade undo-log.hh, undo-util.hh, undo-zcore.hh, and cxx-macros.cmake
- v0.2.3, upgrade cmake scripts
- v0.2.2, fixes around the project files
- v0.2.1, first implementation of Undoable/Redoable
- Highly configurable/customizable
- Undo/Redo subsystem
- restricted non-linear undo (batch undo+erase+redo)
- todo: full-functional non-linear
- limitless undo/redo levels, or limited with
max_size(n)
- Bundled with Command subsystem
- undoable/redoable
- Composite command (
undo_cxx::composite_cmd_t<>): composite multi-commands as one (groupable) - Composite memento (
undo_cxx::state_t<>) for composite-command
The following code is a part of a word-processor:
#include <undo_cxx.hh> namespace dp { namespace undo { namespace test { template<typename State> class FontStyleCmd : public undo_cxx::cmd_t<State> { public: ~FontStyleCmd() {} FontStyleCmd() {} FontStyleCmd(std::string const &default_state_info) : _info(default_state_info) {} UNDO_CXX_DEFINE_DEFAULT_CMD_TYPES(FontStyleCmd, undo_cxx::cmd_t); protected: void do_execute(CmdSP &sender, ContextT &) override { UNUSED(sender); // ... do sth to add/remove font style to/from // current selection in current editor ... std::cout << "<<" << _info << ">>" << '\n'; } MementoPtr save_state_impl(CmdSP &sender, ContextT &) override { return std::make_unique<Memento>(sender, _info); } void undo_impl(CmdSP &sender, ContextT &, Memento &memento) override { memento = _info; memento.command(sender); } void redo_impl(CmdSP &sender, ContextT &, Memento &memento) override { memento = _info; memento.command(sender); } private: std::string _info{"make italic"}; }; template<typename State> class UndoCmd : public undo_cxx::base_undo_cmd_t<State> { public: ~UndoCmd() {} using undo_cxx::base_undo_cmd_t<State>::base_undo_cmd_t; UndoCmd(std::string const &default_state_info) : _info(default_state_info) {} UNDO_CXX_DEFINE_DEFAULT_CMD_TYPES(UndoCmd, undo_cxx::base_undo_cmd_t); protected: void do_execute(CmdSP &sender, ContextT &ctx) override { std::cout << "<<" << _info << ">>" << '\n'; Base::do_execute(sender, ctx); } MementoPtr save_state_impl(CmdSP &sender, ContextT &) override { return std::make_unique<Memento>(sender, _info); } void undo_impl(CmdSP &sender, ContextT &, Memento &memento) override { memento = "do 'undo'"; // auto sp = typename Memento::CmdSP(this); memento.command(sender); } void redo_impl(CmdSP &sender, ContextT &, Memento &memento) override { memento = "do 'un-undo' again"; memento.command(sender); } private: std::string _info{"do 'undo'"}; }; template<typename State> class RedoCmd : public undo_cxx::base_redo_cmd_t<State> { public: ~RedoCmd() {} using undo_cxx::base_redo_cmd_t<State>::base_redo_cmd_t; RedoCmd(std::string const &default_state_info) : _info(default_state_info) {} UNDO_CXX_DEFINE_DEFAULT_CMD_TYPES(RedoCmd, undo_cxx::base_redo_cmd_t); protected: void do_execute(CmdSP &sender, ContextT &ctx) override { std::cout << "<<" << _info << ">>" << '\n'; Base::do_execute(sender, ctx); } MementoPtr save_state_impl(CmdSP &sender, ContextT &) override { return std::make_unique<Memento>(sender, _info); } void undo_impl(CmdSP &sender, ContextT &, Memento &memento) override { memento = "do 'redo'"; memento.command(sender); } void redo_impl(CmdSP &sender, ContextT &, Memento &memento) override { memento = "do 'un-redo' again"; memento.command(sender); } private: std::string _info{"do 'redo'"}; }; }}} // namespace dp::undo::test void test_undo_sys() { using namespace dp::undo::test; using namespace dp::undo::bugs; using State = std::string; using M = undo_cxx::undoable_cmd_system_t<State>; using UndoCmdT = UndoCmd<State>; using RedoCmdT = RedoCmd<State>; using FontStyleCmdT = FontStyleCmd<State>; M undoable_cmd_system; // do some stuffs undoable_cmd_system.invoke<FontStyleCmdT>("italic state1"); undoable_cmd_system.invoke<FontStyleCmdT>("italic-bold state2"); undoable_cmd_system.invoke<FontStyleCmdT>("underline state3"); undoable_cmd_system.invoke<FontStyleCmdT>("italic state4"); // and try to undo or redo undoable_cmd_system.invoke<UndoCmdT>("undo 1"); undoable_cmd_system.invoke<UndoCmdT>("undo 2"); undoable_cmd_system.invoke<RedoCmdT>("redo 1"); undoable_cmd_system.invoke<UndoCmdT>("undo 3"); undoable_cmd_system.invoke<UndoCmdT>("undo 4"); } int main() { test_undo_sys(); return 0; }
- gcc 10+: passed
- clang 12+: passed
- msvc build tool 16.7.2, 16.8.5 (VS2019 or Build Tool) passed
ninja is optional for faster building.
# configure cmake -S . -B build/ -G Ninja # build cmake --build build/ # install cmake --install build/ # Or:cmake --build build/ --target install # # Sometimes sudo it: # sudo cmake --build build/ --target install # Or manually: # cmake --install build/ --prefix ./install --strip # sudo cp -R ./install/include/* /usr/local/include/ # sudo cp -R ./install/lib/cmake/undo_cxx /usr/local/lib/cmake/UNDO_CXX_BUILD_TESTS_EXAMPLES=OFFUNDO_CXX_BUILD_DOCS=OFF- ...
Thanks to JetBrains for donating product licenses to help develop undo-cxx
Apache 2.0