{"id":14811387,"url":"https://github.com/mikew/nvim-drawer","last_synced_at":"2025-10-28T11:31:57.936Z","repository":{"id":254930048,"uuid":"847476151","full_name":"mikew/nvim-drawer","owner":"mikew","description":"A Drawer plugin for Neovim. AKA \"persistent split\" / \"persistent window\".","archived":false,"fork":false,"pushed_at":"2024-09-25T00:17:32.000Z","size":53,"stargazers_count":28,"open_issues_count":11,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-01T15:03:41.831Z","etag":null,"topics":["drawer","neovim","neovim-plugin","nvim","nvim-plugin","persistent","split","window"],"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/mikew.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}},"created_at":"2024-08-25T23:22:29.000Z","updated_at":"2025-02-01T06:22:23.000Z","dependencies_parsed_at":"2024-09-13T14:52:46.484Z","dependency_job_id":null,"html_url":"https://github.com/mikew/nvim-drawer","commit_stats":null,"previous_names":["mikew/nvim-drawer"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mikew%2Fnvim-drawer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mikew%2Fnvim-drawer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mikew%2Fnvim-drawer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mikew%2Fnvim-drawer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mikew","download_url":"https://codeload.github.com/mikew/nvim-drawer/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238645884,"owners_count":19506922,"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","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":["drawer","neovim","neovim-plugin","nvim","nvim-plugin","persistent","split","window"],"created_at":"2024-09-18T08:00:47.624Z","updated_at":"2025-10-28T11:31:51.564Z","avatar_url":"https://github.com/mikew.png","language":"Lua","funding_links":[],"categories":["Lua"],"sub_categories":[],"readme":"# nvim-drawer\n\nA Drawer plugin for Neovim.\n\nEver wanted your terminal or file explorer to be at the bottom, have the same\nheight, and appear on all tabs at a consistent size? And when you just want to\nhide it, you don't want to have to do that across all tabs?\n\nThen this plugin is for you.\n\n## Installation\n\n```lua\n{\n  'mikew/nvim-drawer',\n  opts = {},\n  config = function(_, opts)\n    local drawer = require('nvim-drawer')\n    drawer.setup(opts)\n\n    -- See usage and examples below.\n  end\n}\n```\n\n## Features\n\nhttps://github.com/user-attachments/assets/008b0d7f-2edc-408c-9422-0fa7b7bc72ed\n\n- Attach to any side of the screen.\n- Floating drawers.\n- Automatically claim buffers.\n- Size is consistent across tabs.\n- Open/close state is consistent across tabs.\n- Drawers can be zoomed to take up the whole screen.\n- Drawers remember what buffer they were editing.\n- Has a tab system.\n- When the last non-drawer is closed in a tab, the tab (or vim) is closed.\n- Simple API.\n- Uses buffers and is very flexible.\n\n## About\n\nAt its core, nvim-drawer just creates and hides windows and tries _really_ hard\nto keep them consistent across tabs. You could also call a \"drawer\" a\npersistent window, or a persistent split.\n\nSince windows in vim require a buffer, nvim-drawer creates a scratch buffer for\nyou.\n\n## Usage\n\nFirst, you need to create a drawer via `create_drawer`:\n\n```lua\nlocal drawer = require('nvim-drawer')\n\ndrawer.create_drawer({\n  size = 15,\n  position = 'bottom',\n})\n```\n\nWhen opened, this drawer will be at the bottom of the screen, 15 lines tall,\nediting a scratch buffer.\n\nThis doesn't do much, you get a nice scratch space, but to get the most out of\nit, you need to use the API and add some key mappings.\n\nYour drawer has methods like ...\n\n- `open()`: Open the drawer.\n- `close()`: Close the drawer.\n- `toggle()`: Toggle the drawer.\n- `focus()`: Focus the drawer.\n- `go()`: Go to a different tab.\n\n... and callbacks like:\n\n- `on_did_create_buffer`: Called after a buffer is created.\n- `on_did_open_window`: Called after a drawer is opened.\n- `on_did_close`: Called after a drawer is closed.\n\n## Examples\n\n### Terminal\n\nhttps://github.com/user-attachments/assets/a4818838-5c9a-4e68-87eb-396c7e781a11\n\n```lua\nlocal drawer = require('nvim-drawer')\n\ndrawer.create_drawer({\n  size = 15,\n  position = 'below',\n\n  -- Automatically claim any opened terminals.\n  does_own_buffer = function(context)\n    return context.bufname:match('term://') ~= nil\n  end,\n\n  on_vim_enter = function(event)\n    -- Open the drawer on startup.\n    event.instance.open({\n      focus = false,\n    })\n\n    -- Example keymaps:\n    -- C-`: focus the drawer.\n    -- \u003cleader\u003etn: open a new terminal.\n    -- \u003cleader\u003ett: go to the next terminal.\n    -- \u003cleader\u003etT: go to the previous terminal.\n    -- \u003cleader\u003etz: zoom the terminal.\n    vim.keymap.set('n', '\u003cC-`\u003e', function()\n      event.instance.focus_or_toggle()\n    end)\n    vim.keymap.set('t', '\u003cC-`\u003e', function()\n      event.instance.focus_or_toggle()\n    end)\n    vim.keymap.set('n', '\u003cleader\u003etn', function()\n      event.instance.open({ mode = 'new' })\n    end)\n    vim.keymap.set('n', '\u003cleader\u003ett', function()\n      event.instance.go(1)\n    end)\n    vim.keymap.set('n', '\u003cleader\u003etT', function()\n      event.instance.go(-1)\n    end)\n    vim.keymap.set('n', '\u003cleader\u003etz', function()\n      event.instance.toggle_zoom()\n    end)\n  end,\n\n  -- When a new buffer is created, switch it to a terminal.\n  on_did_create_buffer = function()\n    vim.fn.termopen(os.getenv('SHELL'))\n  end,\n\n  -- Remove some UI elements.\n  on_did_open_buffer = function()\n    vim.opt_local.number = false\n    vim.opt_local.signcolumn = 'no'\n    vim.opt_local.statuscolumn = ''\n  end,\n\n  -- Scroll to the end when changing tabs.\n  on_did_open = function()\n    vim.cmd('$')\n  end,\n})\n```\n\n### nvim-tree\n\nhttps://github.com/user-attachments/assets/5aad5f84-ccd2-4b25-9b32-369f01b508d3\n\n```lua\nlocal drawer = require('nvim-drawer')\n\ndrawer.create_drawer({\n  size = 40,\n  position = 'right',\n  should_reuse_previous_bufnr = false,\n  should_close_on_bufwipeout = false,\n\n  on_vim_enter = function(event)\n    --- Open the drawer on startup.\n    event.instance.open({\n      focus = false,\n    })\n\n    --- Example mapping to toggle.\n    vim.keymap.set('n', '\u003cleader\u003ee', function()\n      event.instance.focus_or_toggle()\n    end)\n  end,\n\n  --- Ideally, we would just call this here and be done with it, but\n  --- mappings in nvim-tree don't seem to apply when re-using a buffer in\n  --- a new tab / window.\n  on_did_create_buffer = function()\n    local nvim_tree_api = require('nvim-tree.api')\n    nvim_tree_api.tree.open({ current_window = true })\n  end,\n\n  --- This gets the tree to sync when changing tabs.\n  on_did_open = function()\n    local nvim_tree_api = require('nvim-tree.api')\n    nvim_tree_api.tree.reload()\n\n    vim.opt_local.number = false\n    vim.opt_local.signcolumn = 'no'\n    vim.opt_local.statuscolumn = ''\n  end,\n\n  --- Cleans up some things when closing the drawer.\n  on_did_close = function()\n    local nvim_tree_api = require('nvim-tree.api')\n    nvim_tree_api.tree.close()\n  end,\n})\n```\n\n### nvim-spectre\n\nhttps://github.com/user-attachments/assets/6a5595b4-e5ed-4260-9037-431eccef3477\n\n```lua\nlocal drawer = require('nvim-drawer')\n\ndrawer.create_drawer({\n  position = 'below',\n  size = 30,\n\n  does_own_window = function(context)\n    return context.bufname:match('spectre') ~= nil\n  end,\n\n  on_vim_enter = function(event)\n    vim.keymap.set('n', '\u003cleader\u003eS', function()\n      -- If the drawer has never been opened, call spectre. Once its\n      -- window opens, it will be claimed by the drawer, and we can use\n      -- the drawer API afterwards.\n      if\n        #vim.tbl_keys(event.instance.state.windows_and_buffers) == 0\n      then\n        require('spectre').toggle()\n      else\n        event.instance.focus_or_toggle()\n      end\n    end)\n  end,\n\n  -- Remove some UI elements.\n  on_did_open_buffer = function()\n    vim.opt_local.number = false\n    vim.opt_local.signcolumn = 'no'\n    vim.opt_local.statuscolumn = ''\n  end,\n})\n```\n\n### `NOTES.md` / `.plan`\n\nhttps://github.com/user-attachments/assets/99161d29-6c41-4209-947e-d20dcea8dd89\n\n```lua\nlocal drawer = require('nvim-drawer')\n\ndrawer.create_drawer({\n  position = 'float',\n  -- Technically unused when using `position = 'float'`.\n  size = 40,\n\n  win_config = {\n    anchor = 'NC',\n    margin = 2,\n    border = 'rounded',\n    width = '100%',\n    height = 10,\n  },\n\n  -- Automatically claim any opened NOTES.md file.\n  does_own_buffer = function(context)\n    return context.bufname:match('NOTES.md') ~= nil\n  end,\n\n  on_vim_enter = function(event)\n    vim.keymap.set('n', '\u003cleader\u003enn', function()\n      event.instance.focus_or_toggle()\n    end)\n    vim.keymap.set('n', '\u003cleader\u003enz', function()\n      event.instance.toggle_zoom()\n    end)\n  end,\n\n  on_did_create_buffer = function()\n    vim.cmd('edit NOTES.md')\n  end,\n})\n```\n\n## API\n\n[API.md](API.md)\n\n## Alternatives\n\n- [nvim-ide](https://github.com/ldelossa/nvim-ide)\n- [edgy.nvim](https://github.com/folke/edgy.nvim)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmikew%2Fnvim-drawer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmikew%2Fnvim-drawer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmikew%2Fnvim-drawer/lists"}