{"id":29929736,"url":"https://github.com/petertriho/nvim-mundo","last_synced_at":"2026-04-16T17:42:25.915Z","repository":{"id":306751729,"uuid":"1027085718","full_name":"petertriho/nvim-mundo","owner":"petertriho","description":"Lua rewrite of vim-mundo","archived":false,"fork":false,"pushed_at":"2025-07-27T10:41:32.000Z","size":43,"stargazers_count":1,"open_issues_count":2,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-07-27T12:31:21.313Z","etag":null,"topics":["lua","neovim","neovim-lua-plugin","neovim-plugin","plugin"],"latest_commit_sha":null,"homepage":"","language":"Lua","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/petertriho.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-07-27T09:29:29.000Z","updated_at":"2025-07-27T10:41:36.000Z","dependencies_parsed_at":"2025-07-27T12:31:25.632Z","dependency_job_id":"73b5950a-082b-4ea6-b114-6c8683e9a65a","html_url":"https://github.com/petertriho/nvim-mundo","commit_stats":null,"previous_names":["petertriho/nvim-mundo"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/petertriho/nvim-mundo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/petertriho%2Fnvim-mundo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/petertriho%2Fnvim-mundo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/petertriho%2Fnvim-mundo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/petertriho%2Fnvim-mundo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/petertriho","download_url":"https://codeload.github.com/petertriho/nvim-mundo/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/petertriho%2Fnvim-mundo/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268290392,"owners_count":24226630,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-01T02:00:08.611Z","response_time":67,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["lua","neovim","neovim-lua-plugin","neovim-plugin","plugin"],"created_at":"2025-08-02T16:01:08.384Z","updated_at":"2026-04-16T17:42:25.883Z","avatar_url":"https://github.com/petertriho.png","language":"Lua","funding_links":[],"categories":["Other Standard Feature Enhancement"],"sub_categories":["Undo"],"readme":"# nvim-mundo\n\n\u003e [!CAUTION]\n\u003e This plugin was generated with the help of AI. It is a proof-of-concept and is not actively maintained. No support will be provided.\n\nA Lua rewrite of the [vim-mundo](https://github.com/simnalamburt/vim-mundo) plugin for Neovim. Visualizes the Vim undo tree in a graphical format with proper tree visualization and unified diff support.\n\n## Features\n\n- **Undo tree visualization**: See your undo history as a branching tree with vertical lines\n- **Interactive navigation**: Move through undo states with keyboard shortcuts\n- **Live preview**: See unified diffs of changes as you navigate\n- **Proper diff format**: LCS-based unified diff with context lines and @@ headers\n- **Search functionality**: Find specific changes in your undo history\n- **Playback mode**: Replay changes step by step\n- **Pure Lua**: No Python dependencies required\n- **Fixed focus issues**: Cursor stays in target buffer, no auto-jumping to Mundo window\n\n## Installation\n\n### Using Lazy.nvim\n\n```lua\n{\n  \"petertriho/nvim-mundo\",\n  cmd = { \"MundoToggle\", \"MundoShow\", \"MundoHide\" },\n  keys = {\n    { \"\u003cleader\u003eu\", \"\u003cCMD\u003eMundoToggle\u003cCR\u003e\", desc = \"Toggle Mundo Undo Tree\" },\n  },\n  config = function()\n    require('mundo').setup({\n      -- Your configuration here\n    })\n  end,\n}\n```\n\n### Using other plugin managers\n\nAdd the plugin directory to your plugin manager configuration.\n\n## Usage\n\n### Commands\n\n- `:MundoToggle` - Toggle the Mundo window\n- `:MundoShow` - Show the Mundo window\n- `:MundoHide` - Hide the Mundo window\n\n### Default Key Mappings (in Mundo window)\n\n- `\u003cCR\u003e/o` - Preview/revert to selected state\n- `j/\u003cdown\u003e` - Move to next/older undo state\n- `k/\u003cup\u003e` - Move to previous/newer undo state\n- `J` - Move to next/older write state\n- `K` - Move to previous/newer write state\n- `gg` - Move to top of undo tree\n- `G` - Move to bottom of undo tree\n- `P` - Play changes to selected state\n- `d` - Show diff in vertical split\n- `i` - Toggle inline diff mode\n- `/` - Search for changes\n- `n/N` - Next/previous search match\n- `p` - Show diff with current buffer\n- `r` - Show diff (same as `d`)\n- `?` - Toggle help\n- `q/\u003cEsc\u003e/\u003cC-c\u003e` - Quit Mundo\n- `\u003c2-LeftMouse\u003e` - Mouse click to select state\n- `\u003cTab\u003e/\u003cC-w\u003ep` - Return to target buffer\n\n## Configuration\n\nnvim-mundo supports the same configuration variables as the original vim-mundo via `vim.g` variables, plus Lua-style setup configuration:\n\n### Using vim.g variables (original vim-mundo compatibility)\n\n```vim\n\" Window layout\nlet g:mundo_width = 45                     \" Width of the Mundo window\nlet g:mundo_preview_height = 15            \" Height of the preview window\nlet g:mundo_preview_bottom = 0             \" Show preview at bottom (1) or right (0)\nlet g:mundo_right = 0                      \" Show Mundo on right side (1) or left (0)\n\n\" Display options\nlet g:mundo_help = 0                       \" Show help by default (1) or not (0)\nlet g:mundo_disable = 0                    \" Disable the plugin (1) or enable (0)\nlet g:mundo_header = 1                     \" Show header in graph window (1) or not (0)\nlet g:mundo_verbose_graph = 1              \" Show detailed graph (1) or simple (0)\nlet g:mundo_mirror_graph = 0               \" Mirror the graph horizontally (1) or not (0)\nlet g:mundo_inline_undo = 0                \" Show inline diffs in graph (1) or not (0)\n\n\" Behavior\nlet g:mundo_close_on_revert = 0            \" Close Mundo after reverting (1) or not (0)\nlet g:mundo_return_on_revert = 1           \" Return to original buffer after revert (1) or not (0)\nlet g:mundo_auto_preview = 1               \" Auto-update preview when moving (1) or not (0)\nlet g:mundo_auto_preview_delay = 250       \" Delay for auto-preview in milliseconds\n\n\" Playback and timing\nlet g:mundo_playback_delay = 60            \" Delay between playback steps in milliseconds\n\n\" Status lines\nlet g:mundo_preview_statusline = \"Mundo Preview\"  \" Statusline for preview window\nlet g:mundo_tree_statusline = \"Mundo\"             \" Statusline for tree window\n\n\" Custom symbols for graph visualization\nlet g:mundo_symbols = {\n    \\ 'current': '@',                     \" Symbol for current undo state\n    \\ 'node': 'o',                        \" Symbol for regular undo states\n    \\ 'saved': 'w',                       \" Symbol for saved/written states\n    \\ 'vertical': '|'                     \" Symbol for vertical tree lines\n    \\ }\n\n\" Custom mappings (dictionary) - all original vim-mundo mappings\nlet g:mundo_mappings = {\n    \\ '\u003cCR\u003e': 'preview',\n    \\ 'o': 'preview',\n    \\ 'j': 'move_older',\n    \\ 'k': 'move_newer',\n    \\ '\u003cdown\u003e': 'move_older',\n    \\ '\u003cup\u003e': 'move_newer',\n    \\ 'J': 'move_older_write',\n    \\ 'K': 'move_newer_write',\n    \\ 'gg': 'move_top',\n    \\ 'G': 'move_bottom',\n    \\ 'P': 'play_to',\n    \\ 'd': 'diff',\n    \\ 'i': 'toggle_inline',\n    \\ '/': 'search',\n    \\ 'n': 'next_match',\n    \\ 'N': 'previous_match',\n    \\ 'p': 'diff_current_buffer',\n    \\ 'r': 'diff',\n    \\ '?': 'toggle_help',\n    \\ 'q': 'quit',\n    \\ '\u003c2-LeftMouse\u003e': 'mouse_click'\n    \\ }\n```\n\n### Using Lua setup (modern Neovim style)\n\n```lua\nrequire(\"mundo\").setup({\n    -- Window positioning\n    width = 45,                    -- Graph window width\n    preview_height = 15,           -- Preview window height\n    preview_bottom = false,        -- Preview window at bottom\n    right = false,                 -- Open on right side\n\n    -- Display options\n    help = false,                  -- Show help by default\n    disable = false,               -- Disable the plugin\n    header = true,                 -- Show header\n    verbose_graph = true,          -- Show detailed graph\n    mirror_graph = false,          -- Mirror the graph horizontally\n    inline_undo = false,           -- Show inline diffs\n\n    -- Behavior\n    close_on_revert = false,       -- Close after reverting\n    return_on_revert = true,       -- Return to original buffer after revert\n    auto_preview = true,           -- Auto-update preview\n    auto_preview_delay = 250,      -- Delay for auto-preview (ms)\n\n    -- Playback\n    playback_delay = 60,           -- Delay between playback steps (ms)\n\n    -- Status lines\n    preview_statusline = \"Mundo Preview\",  -- Preview window statusline\n    tree_statusline = \"Mundo\",             -- Tree window statusline\n\n    -- Custom symbols for graph visualization\n    symbols = {\n        current = \"@\",                 -- Symbol for current undo state\n        node = \"o\",                    -- Symbol for regular undo states  \n        saved = \"w\",                   -- Symbol for saved/written states\n        vertical = \"|\",                -- Symbol for vertical tree lines\n    },\n\n    -- Navigation (internal settings)\n    map_move_newer = \"k\",          -- Key to move to newer undo\n    map_move_older = \"j\",          -- Key to move to older undo\n    map_up_down = true,            -- Use arrow keys for navigation\n\n    -- Custom mappings (all original vim-mundo mappings supported)\n    mappings = {\n        [\"\u003cCR\u003e\"] = \"preview\",\n        [\"o\"] = \"preview\",\n        [\"j\"] = \"move_older\",\n        [\"k\"] = \"move_newer\",\n        [\"\u003cdown\u003e\"] = \"move_older\",\n        [\"\u003cup\u003e\"] = \"move_newer\",\n        [\"J\"] = \"move_older_write\",\n        [\"K\"] = \"move_newer_write\",\n        [\"gg\"] = \"move_top\",\n        [\"G\"] = \"move_bottom\",\n        [\"P\"] = \"play_to\",\n        [\"d\"] = \"diff\",\n        [\"i\"] = \"toggle_inline\",\n        [\"/\"] = \"search\",\n        [\"n\"] = \"next_match\",\n        [\"N\"] = \"previous_match\",\n        [\"p\"] = \"diff_current_buffer\",\n        [\"r\"] = \"diff\",\n        [\"?\"] = \"toggle_help\",\n        [\"q\"] = \"quit\",\n        [\"\u003c2-LeftMouse\u003e\"] = \"mouse_click\",\n    },\n})\n```\n\n### Configuration precedence\n\nConfiguration is applied in this order (later overrides earlier):\n1. Default values\n2. Lua `setup()` options (for modern Neovim configuration)\n3. `vim.g` variables (highest precedence, matching original vim-mundo behavior)\n\nThis allows you to set baseline configuration with `setup()` and override specific options with `vim.g` variables, just like the original vim-mundo plugin.\n\n## Symbol Customization\n\nnvim-mundo allows you to customize the symbols used in the undo tree visualization:\n\n### Default Symbols\n\n- `@` - Current undo state (where you are now)\n- `o` - Regular undo states  \n- `w` - Saved/written states (states where you saved the file)\n- `|` - Vertical tree lines connecting undo states\n\n### Custom Symbol Examples\n\n#### Using vim.g variables:\n```vim\nlet g:mundo_symbols = {\n    \\ 'current': '★',\n    \\ 'node': '●',\n    \\ 'saved': '■',\n    \\ 'vertical': '│'\n    \\ }\n```\n\n#### Using Lua setup:\n```lua\nrequire(\"mundo\").setup({\n    symbols = {\n        current = \"★\",        -- Current state\n        node = \"●\",           -- Regular states\n        saved = \"■\",          -- Saved states  \n        vertical = \"│\",       -- Tree lines\n    }\n})\n```\n\n#### Unicode Examples:\n```lua\n-- Fancy Unicode symbols\nsymbols = {\n    current = \"→\",         -- Arrow for current\n    node = \"◦\",            -- Hollow circle for nodes\n    saved = \"◾\",          -- Black square for saves\n    vertical = \"┆\",        -- Dashed vertical line\n}\n\n-- Emoji symbols (fun but may affect alignment)\nsymbols = {\n    current = \"🔥\",        -- Fire for current\n    node = \"⚪\",           -- White circle for nodes  \n    saved = \"💾\",          -- Floppy disk for saves\n    vertical = \"┃\",        -- Thick vertical line\n}\n\n-- ASCII alternatives\nsymbols = {\n    current = \"C\",         -- Simple letter\n    node = \"n\",            -- Simple letter\n    saved = \"S\",           -- Simple letter  \n    vertical = \"I\",        -- Capital I\n}\n```\n\n#### Partial Customization:\nYou can customize just some symbols while keeping others as defaults:\n\n```lua\nrequire(\"mundo\").setup({\n    symbols = {\n        current = \"🎯\",      -- Only change current symbol\n        -- node, saved, vertical remain default (@, o, w, |)\n    }\n})\n```\n\n## Differences from vim-mundo\n\nThis Lua implementation provides the core functionality of vim-mundo with some differences:\n\n### Advantages\n\n- **No Python dependency**: Pure Lua implementation\n- **Better Neovim integration**: Uses modern Neovim APIs\n- **Proper unified diff**: LCS-based diff algorithm with context lines\n- **Fixed focus issues**: No unwanted cursor jumping between windows\n- **Tree visualization**: Vertical lines connecting undo states like original Mundo\n- **Modular architecture**: Clean separation of concerns for maintainability\n- **Type annotations**: Full lua-language-server support with @class, @param, @return annotations\n- **Simpler codebase**: Easier to understand and modify\n- **Local configuration**: Easy to customize in your dotfiles\n\n### Limitations\n\n- **Simplified branching**: Complex branching scenarios may not be fully visualized\n- **Missing advanced features**: Some edge cases and advanced features from the original may not be implemented\n\n## API\n\n```lua\nlocal mundo = require(\"mundo\")\n\n-- Setup with custom configuration\nmundo.setup({\n    width = 50,\n    auto_preview = false,\n})\n\n-- Programmatic control\nmundo.show() -- Show Mundo\nmundo.hide() -- Hide Mundo\nmundo.toggle() -- Toggle Mundo\nmundo.move(1) -- Move down in tree\nmundo.move(-1) -- Move up in tree\nmundo.preview() -- Preview/revert to current state\nmundo.diff() -- Show diff in split\n```\n\n## Recent Improvements\n\n- **Fixed cursor focus issues**: Cursor no longer auto-jumps back to Mundo window\n- **Proper tree visualization**: Added vertical lines (`|`) between undo states like original Mundo\n- **Enhanced navigation**: j/k keys now skip vertical lines and jump directly between nodes\n- **Unified diff format**: Implemented LCS-based diff algorithm with proper @@ headers and context lines\n- **Better syntax highlighting**: Uses 'diff' filetype for proper syntax highlighting in preview\n- **Modular refactor**: Broke down 1184-line monolith into 8 focused modules for better maintainability\n- **Type annotations**: Added comprehensive lua-language-server type annotations for better IDE support\n- **Unit tests**: Comprehensive test suite with 58+ tests covering all modules\n- **Configurable symbols**: Customize tree symbols (@, o, w, |) for personalized visualization\n\n## Testing\n\nThe plugin includes a comprehensive test suite with tests covering all modules:\n\n### Running Tests\n\n```bash\n# Run all tests\nnvim --headless -l test.lua\n\n# Or use the Makefile\nmake test\n\n# Run specific test modules\nmake test-config      # Config module tests\nmake test-utils       # Utils module tests\nmake test-node        # Node module tests\nmake test-tree        # Tree module tests\nmake test-graph       # Graph module tests\nmake test-symbols     # Symbol configuration tests\nmake test-integration # Integration tests\n```\n\n### Test Structure\n\n- **`tests/test_framework.lua`**: Custom test framework with assertions\n- **`tests/test_config.lua`**: Configuration module tests\n- **`tests/test_utils.lua`**: Utility functions tests\n- **`tests/test_node.lua`**: Node structure tests\n- **`tests/test_tree.lua`**: Tree data and diff algorithm tests\n- **`tests/test_graph.lua`**: Graph rendering tests  \n- **`tests/test_symbols.lua`**: Symbol configuration tests\n- **`tests/test_integration.lua`**: Integration and API tests\n\n### Test Features\n\n- **Assertion library**: `equals`, `not_equals`, `is_true`, `is_false`, `is_nil`, `contains`, `throws`\n- **Test organization**: Grouped tests with setup/teardown support\n- **Mocking**: Vim API mocking for headless testing\n- **Performance tracking**: Test execution time measurement\n- **Detailed reporting**: Clear pass/fail status with error messages\n\n## Requirements\n\n- Neovim 0.7+\n- `undofile` enabled for persistent undo history (recommended)\n\n## Recommended Vim Settings\n\n```vim\n\" Enable persistent undo\nset undofile\nset undodir=~/.vim/undo\n```\n\nOr in Lua:\n\n```lua\nvim.opt.undofile = true\nvim.opt.undodir = vim.fn.expand(\"~/.vim/undo\")\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpetertriho%2Fnvim-mundo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpetertriho%2Fnvim-mundo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpetertriho%2Fnvim-mundo/lists"}