{"id":32629697,"url":"https://github.com/relf108/nvim-unstack","last_synced_at":"2026-01-17T00:48:00.896Z","repository":{"id":312045186,"uuid":"890167737","full_name":"relf108/nvim-unstack","owner":"relf108","description":"A Lua implementation of mattboehm's vim-unstack (https://github.com/mattboehm/vim-unstack)","archived":false,"fork":false,"pushed_at":"2025-08-28T07:11:43.000Z","size":34,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-18T14:40:56.785Z","etag":null,"topics":["lua","neovim","neovim-plugin","vim"],"latest_commit_sha":null,"homepage":"","language":"Lua","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/relf108.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":"FUNDING.yml","license":"LICENSE","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},"funding":{"github":"relf108"}},"created_at":"2024-11-18T05:25:34.000Z","updated_at":"2025-08-28T07:11:46.000Z","dependencies_parsed_at":"2025-08-28T13:26:48.753Z","dependency_job_id":"5d1d50a3-f26d-4302-8623-a3d0436cab1e","html_url":"https://github.com/relf108/nvim-unstack","commit_stats":null,"previous_names":["relf108/nvim-unstack"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/relf108/nvim-unstack","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/relf108%2Fnvim-unstack","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/relf108%2Fnvim-unstack/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/relf108%2Fnvim-unstack/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/relf108%2Fnvim-unstack/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/relf108","download_url":"https://codeload.github.com/relf108/nvim-unstack/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/relf108%2Fnvim-unstack/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":281896640,"owners_count":26580138,"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-10-30T02:00:06.501Z","response_time":61,"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-plugin","vim"],"created_at":"2025-10-30T22:45:31.728Z","updated_at":"2026-01-17T00:48:00.887Z","avatar_url":"https://github.com/relf108.png","language":"Lua","funding_links":["https://github.com/sponsors/relf108"],"categories":[],"sub_categories":[],"readme":"\u003c!--toc:start--\u003e\n\n- [⚡️ Features](#️-features)\n- [🎯 Supported Languages](#-supported-languages)\n- [📋 Installation](#-installation)\n- [☄ Getting started](#-getting-started)\n- [⚙ Configuration](#-configuration)\n- [🧰 Commands](#-commands)\n- [🔧 API](#-api)\n- [🎨 Customization](#-customization)\n- [⌨ Contributing](#-contributing)\n- [🗞 Wiki](#-wiki)\n- [🎭 Motivations](#-motivations)\n\u003c!--toc:end--\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ch1 align=\"center\"\u003envim-unstack\u003c/h1\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n    A powerful Neovim plugin for parsing and navigating stack traces from multiple programming languages.\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n    Quickly jump to files and line numbers from stack traces with configurable layouts and visual indicators.\n\u003c/p\u003e\n\n## ⚡️ Features\n\n- **Multi-language support**: Built-in regex parsers for Python, Node.js, Ruby, Go, C#, Perl, and GDB/LLDB\n- **Flexible layouts**: Open files in tabs, vertical splits, horizontal splits, or floating windows\n- **Visual indicators**: Optional signs to highlight stack trace lines\n- **Multiple input methods**: Parse from visual selection, clipboard, or tmux paste buffer\n- **Configurable keymaps**: Customize the key binding for stack trace parsing\n- **Easy extension**: Simple API for adding custom language parsers\n- **Zero dependencies**: Pure Lua implementation with no external requirements\n\n## 🎯 Supported Languages\n\nnvim-unstack comes with built-in support for parsing stack traces from:\n\n- **Python** - Standard Python tracebacks with file paths and line numbers\n- **Pytest** - Pytest test failure tracebacks and assertion errors\n- **Node.js** - JavaScript stack traces with file locations\n- **Ruby** - Ruby exception backtraces\n- **Go** - Go panic stack traces and error messages\n- **C#** - .NET exception stack traces\n- **Perl** - Perl error messages with file references\n- **GDB/LLDB** - Debugger stack traces and breakpoint information\n\nNew language parsers can be easily added - see the [Customization](#-customization) section.\n\n## 📋 Installation\n\n\u003cdiv align=\"center\"\u003e\n\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003ePackage manager\u003c/th\u003e\n\u003cth\u003eSnippet\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd\u003e\n\n[wbthomason/packer.nvim](https://github.com/wbthomason/packer.nvim)\n\n\u003c/td\u003e\n\u003ctd\u003e\n\u003cdiv align=\"left\"\u003e\n\n```lua\n-- Stable version\nuse {\"relf108/nvim-unstack\", tag = \"*\" }\n-- Development version\nuse {\"relf108/nvim-unstack\"}\n```\n\n\u003c/div\u003e\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\n\n[junegunn/vim-plug](https://github.com/junegunn/vim-plug)\n\n\u003c/td\u003e\n\u003ctd\u003e\n\u003cdiv align=\"left\"\u003e\n\n```vim\n\" Stable version\nPlug 'relf108/nvim-unstack', { 'tag': '*' }\n\" Development version\nPlug 'relf108/nvim-unstack'\n```\n\n\u003c/div\u003e\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\n\n[folke/lazy.nvim](https://github.com/folke/lazy.nvim)\n\n\u003c/td\u003e\n\u003ctd\u003e\n\u003cdiv align=\"left\"\u003e\n\n```lua\n-- Stable version\n{ \"relf108/nvim-unstack\", version = \"*\" }\n-- Development version\n{ \"relf108/nvim-unstack\" }\n-- With configuration\n{\n\t\"relf108/nvim-unstack\",\n\tevent = \"VeryLazy\", -- Enable lazy loading\n\tversion = \"*\",\n\topts = {\n\t\tdebug = false, -- Disable debug logging (default)\n\t\tshowsigns = true, -- Enable signs (default)\n\t\tlayout = \"tab\", -- Use tab layout (default)\n\t\tmapkey = \"\u003cleader\u003es\", -- set keybinding (default)\n\t},\n}\n-- Lazy load on invocation\n{\n\t\"relf108/nvim-unstack\",\n\tversion = \"*\",\n\tlazy = true,\n\tcmd = \"NvimUnstack\",\n\tkeys = { { \"\u003cleader\u003ect\", \"\u003ccmd\u003eNvimUnstack\u003ccr\u003e\", mode = { \"v\" } } },\n\topts = {\n\t\tmapkey = false, -- Skip mapping during setup so it doesn't conflict with `keys` config\n\t},\n}\n```\n\n\u003c/div\u003e\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n\u003c/div\u003e\n\n## ☄ Getting started\n\n### Basic Setup\n\nAfter installation, you can start using nvim-unstack immediately with the default configuration:\n\n```lua\nrequire(\"nvim-unstack\").setup()\n```\n\n### Quick Usage\n\n1. **Visual Selection**: Select a stack trace (or part of one) and press `\u003cleader\u003es` to open the referenced files\n2. **From Clipboard**: Use `:UnstackFromClipboard` to parse a stack trace from your system clipboard\n3. **From Tmux**: Use `:UnstackFromTmux` to parse a stack trace from tmux paste buffer\n\n### Example\n\nGiven this Python traceback:\n\n```\nTraceback (most recent call last):\n  File \"/path/to/myproject/main.py\", line 42, in main\n    result = process_data(data)\n  File \"/path/to/myproject/utils.py\", line 15, in process_data\n    return transform(data)\n```\n\nOr this Pytest failure:\n\n```\n=================================== FAILURES ===================================\n____________________________ test_my_function __________________________________\n\n    def test_my_function():\n\u003e       assert result == expected\nE       AssertionError: assert 15 == 10\n\ntests/test_example.py:42: AssertionError\n```\n\nSimply select the traceback text and press `\u003cleader\u003es`. The plugin will:\n\n- Parse the file paths and line numbers\n- Open each file at the specified line\n- Display them according to your configured layout (tabs by default)\n\n## ⚙ Configuration\n\nnvim-unstack can be customized with the following options:\n\n```lua\nrequire(\"nvim-unstack\").setup({\n  -- Print debug information (default: false)\n  debug = false,\n\n  -- Layout for opening files (default: \"tab\")\n  -- Options: \"tab\", \"vsplit\", \"split\", \"floating\"\n  layout = \"tab\",\n\n  -- Key mapping for visual selection unstacking (default: \"\u003cleader\u003es\")\n  mapkey = \"\u003cleader\u003es\",\n\n  -- Show signs on lines from stack trace (default: true)\n  showsigns = true,\n})\n```\n\n### Configuration Options Explained\n\n#### Layout Options\n\n- **`\"tab\"`** (default): Opens all files as vertical splits in a new tab\n- **`\"vsplit\"`**: Opens each file in a new vertical split\n- **`\"split\"`**: Opens each file in a new horizontal split\n- **`\"floating\"`**: Opens each file in a floating window\n\n#### Visual Signs\n\nWhen `showsigns = true`, nvim-unstack will place visual indicators (`\u003e\u003e`) next to the lines referenced in the stack trace, making them easy to spot.\n\n#### Debug Mode\n\nEnable `debug = true` to see detailed logging about:\n\n- Which language parser was selected\n- What files and line numbers were extracted\n- Any parsing errors or warnings\n\n## 🧰 Commands\n\nnvim-unstack provides several commands for different use cases:\n\n| Command                 | Description                                     |\n| ----------------------- | ----------------------------------------------- |\n| `:NvimUnstack`          | Parse stack trace from current visual selection |\n| `:UnstackFromClipboard` | Parse stack trace from system clipboard         |\n| `:UnstackFromTmux`      | Parse stack trace from tmux paste buffer        |\n\n### Command Usage Examples\n\n```vim\n\" Parse visual selection (or use the default \u003cleader\u003es keymap)\n:'\u003c,'\u003eNvimUnstack\n\n\" Parse from clipboard\n:UnstackFromClipboard\n\n\" Parse from tmux buffer\n:UnstackFromTmux\n```\n\n## 🔧 API\n\nnvim-unstack provides a Lua API for programmatic usage:\n\n### Core Functions\n\n```lua\nlocal nvim_unstack = require(\"nvim-unstack\")\n\n-- Parse and open files from visual selection\nnvim_unstack.unstack()\n\n-- Parse from system clipboard\nnvim_unstack.unstack_from_clipboard()\n\n-- Parse from tmux paste buffer\nnvim_unstack.unstack_from_tmux()\n\n-- Setup with custom configuration\nnvim_unstack.setup({\n  layout = \"floating\",\n  mapkey = \"\u003cleader\u003eu\"\n})\n```\n\n### Advanced Usage\n\n```lua\n-- Custom keymapping examples\nvim.keymap.set(\"v\", \"\u003cleader\u003eu\", function()\n  require(\"nvim-unstack\").unstack()\nend, { desc = \"Unstack visual selection\" })\n\nvim.keymap.set(\"n\", \"\u003cleader\u003euc\", function()\n  require(\"nvim-unstack\").unstack_from_clipboard()\nend, { desc = \"Unstack from clipboard\" })\n\nvim.keymap.set(\"n\", \"\u003cleader\u003eut\", function()\n  require(\"nvim-unstack\").unstack_from_tmux()\nend, { desc = \"Unstack from tmux\" })\n```\n\n## 🎨 Customization\n\n### Adding New Language Parsers\n\nYou can extend nvim-unstack to support additional languages by creating custom regex parsers. Here's the structure:\n\n```lua\n-- Example: Custom Java parser\n-- Save to nvim-unstack/regex\n\nlocal java = {}\n\n-- Regex pattern to match Java stack trace lines\njava.regex = vim.regex([[at .*(\\(.*\\.java:[0-9]\\+\\))]])\n\n-- Function to extract file and line number from matched line\nfunction java.format_match(line, lines, index)\n    local file = line:match(\"%((.*)%.java:\")\n    local line_num = line:match(\":([0-9]+)%)\")\n\n    if file and line_num then\n        return { file .. \".java\", line_num }\n    end\n\n    return nil\nend\n\nreturn java\n```\n\n### Custom Layout Configurations\n\nYou can create wrapper functions for specific layout preferences:\n\n```lua\n-- Quick functions for different layouts\nlocal function unstack_floating()\n    local original_layout = require(\"nvim-unstack.config\").options.layout\n    require(\"nvim-unstack.config\").options.layout = \"floating\"\n    require(\"nvim-unstack\").unstack()\n    require(\"nvim-unstack.config\").options.layout = original_layout\nend\n\n-- Create custom commands\nvim.api.nvim_create_user_command(\"UnstackFloat\", unstack_floating, {})\n```\n\n### Sign Customization\n\nCustomize the appearance of stack trace line indicators:\n\n```lua\nrequire(\"nvim-unstack\").setup({\n  showsigns = true\n})\n\n-- Override sign appearance after setup\nvim.fn.sign_define(\"UnstackLine\", {\n    text = \"▶\",\n    texthl = \"DiagnosticError\",\n    linehl = \"CursorLine\",\n})\n```\n\n## ⌨ Contributing\n\nPRs and issues are always welcome. Make sure to provide as much context as possible when opening one.\n\n## 🗞 Wiki\n\nYou can find guides and showcase of the plugin on [the Wiki](https://github.com/relf108/nvim-unstack/wiki)\n\n## 🎭 Motivations\n\nAfter using (and loving) [mattboehm's vim-unstack](https://github.com/mattboehm/vim-unstack) for about a year I've collected a short list of gripes that I think are worth taking the time to fix, unfortunately the repo is no longer maintained so I've decided to rip out the regex and rewrite it in Lua.\n\n- Lack of configurability, it's v-splits or nothin' pal and god help you if you want line numbers in those splits.\n- Not extendable, stack trace parsing is incredibly useful in a wide array of languages and it should be easy for users of the plugin to add their favourites.\n- Written in vimscript, this is fine and the plugin still works in neovim but it creates a barrier to entry when trying to contribute code and I think the Lua ecosystem has a lot to offer.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frelf108%2Fnvim-unstack","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frelf108%2Fnvim-unstack","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frelf108%2Fnvim-unstack/lists"}