{"id":15654290,"url":"https://github.com/ghostbuster91/nvim-next","last_synced_at":"2025-04-14T19:33:19.298Z","repository":{"id":90052813,"uuid":"588952476","full_name":"ghostbuster91/nvim-next","owner":"ghostbuster91","description":null,"archived":false,"fork":false,"pushed_at":"2024-10-09T20:14:52.000Z","size":54,"stargazers_count":34,"open_issues_count":4,"forks_count":4,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-28T07:51:11.681Z","etag":null,"topics":["lua","neovim","nvim","nvim-plugin"],"latest_commit_sha":null,"homepage":"","language":"Lua","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ghostbuster91.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"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}},"created_at":"2023-01-14T15:35:18.000Z","updated_at":"2025-03-13T22:10:04.000Z","dependencies_parsed_at":"2024-02-11T00:22:42.970Z","dependency_job_id":"499fdd94-e4c9-4ede-804e-e1af9dbf07e6","html_url":"https://github.com/ghostbuster91/nvim-next","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ghostbuster91%2Fnvim-next","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ghostbuster91%2Fnvim-next/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ghostbuster91%2Fnvim-next/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ghostbuster91%2Fnvim-next/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ghostbuster91","download_url":"https://codeload.github.com/ghostbuster91/nvim-next/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248945799,"owners_count":21187391,"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":["lua","neovim","nvim","nvim-plugin"],"created_at":"2024-10-03T12:50:28.859Z","updated_at":"2025-04-14T19:33:19.272Z","avatar_url":"https://github.com/ghostbuster91.png","language":"Lua","readme":"# nvim-next\n\nRepeat-able movements reborn!\n\nBy default vim allows repeating default movements like `f`/`F`/`t`/`T` and others using `;` and `,`.\nHowever, the builtin mechanism is not extendable and as soon as we start using some custom movements we are left to implement\nthe repeating on your own. Some plugins provide that options some don't. But even when they do,\nthey do it in a way that steals `;` for themselves.\n\nWhile I don't use repeating movements often with default motions,\nI would like to use them with motions like next-treesitter-method, next-diagnostic, next-git-change, etc that comes from many different plugins.\n\nThis plugin is a repeatable movements engine that other plugins can hook into.\nYou can think of it as of `nvim-cmp` but for movements.\n\nThe idea is that other plugins like for example git-signs will expose logic to perform some movement,\nand then we will wrap it with an adapter and plug into that engine.\n\n## Current state of the project\n\nI have been using this plugin for a while now and it seems to be working fine.\nSure my usage-patterns might not cover every use-case so if you find a bug please raise an issue.\n\n## Getting started\n\nFirst you need to initialize nvim-next. This will map `;` and `,` to respective nvim-next functions.\n\n```lua\nrequire(\"nvim-next\").setup({\n   default_mappings = {\n       repeat_style = \"original\",\n   },\n})\n```\n\nThe `repeat_style` parameter controls if the repetition preserves the `original` direction of the move, or if it uses the direction (`directional`) of the repeat key: `;` - forward, `,` - backward.\n\nYou might also want to override the builtin `f`/`t` functions to have a consistent behavior with the rest of the movements.\nThe easiest way to do this is by extending the setup configuration:\n\n```lua\nlocal next = require(\"nvim-next\").setup({\n   default_mappings = {\n       repeat_style = \"original\",\n   },\n   items = {\n     nvim_next_builtins.f,\n     nvim_next_builtins.t\n   }\n})\n```\n\nAlternatively, you can map it on your own:\n\n```lua\nlocal functions = require(\"nvim-next.builtins.functions\")\nlocal f_backward, f_forward = next.make_repeatable_pair(functions.F, functions.f)\nvim.keymap.set(\"n\", \"f\", f_forward)\nvim.keymap.set(\"n\", \"F\", f_backward)\n```\n\n## 3rd party integrations\n\nNvim-next comes with multiple integrations out of the box for many popular plugins. Can't find your favorite one? Don't hesitate and create an issue. PRs are more than welcome.\n\n- [Gitsigns](#gitsigns)\n- [Diagnostics](#diagnostics)\n- [Treesitter text-objects](#treesitter-text-objects)\n- [Quickfix](#quickfix-list)\n\n### [Gitsigns](https://github.com/lewis6991/gitsigns.nvim)\n\n```lua\nlocal next_integrations = require(\"nvim-next.integrations\")\nrequire(\"gitsigns\").setup({\n    on_attach = function(bufnr)\n        local gs = package.loaded.gitsigns\n\n        local function map(mode, l, r, opts)\n            opts = opts or {}\n            opts.buffer = bufnr\n            vim.keymap.set(mode, l, r, opts)\n        end\n\n        local nngs = next_integrations.gitsigns(gs)\n        -- Navigation\n        map('n', ']c', function()\n            if vim.wo.diff then return ']c' end\n            vim.schedule(function() nngs.next_hunk() end)\n            return '\u003cIgnore\u003e'\n        end, { expr = true })\n\n        map('n', '[c', function()\n            if vim.wo.diff then return '[c' end\n            vim.schedule(function() nngs.prev_hunk() end)\n            return '\u003cIgnore\u003e'\n        end, { expr = true })\n    end,\n})\n```\n\n### Diagnostics\n\n```lua\nlocal next_integrations = require(\"nvim-next.integrations\")\nlocal nndiag = next_integrations.diagnostic()\nvim.keymap.set(\"n\", \"[d\", nndiag.goto_prev({ severity = { min = diag.severity.WARN } }), { desc = \"previous diagnostic\" })\nvim.keymap.set(\"n\", \"]d\", nndiag.goto_next({ severity = { min = diag.severity.WARN } }), { desc = \"next diagnostic\" })\n```\n\n### [Treesitter text-objects](https://github.com/nvim-treesitter/nvim-treesitter-textobjects)\n\n```lua\n-- first initialize intgration module\nrequire(\"nvim-next.integrations\").treesitter_textobjects()\n-- setup treesitter\nrequire(\"nvim-treesitter.configs\").setup({\n    textobjects = {\n        swap = {\n            enable = true,\n            swap_next = {\n                [\"\u003cleader\u003ea\"] = \"@parameter.inner\",\n            },\n            swap_previous = {\n                [\"\u003cleader\u003eA\"] = \"@parameter.inner\",\n            },\n        },\n    },\n    nvim_next = {\n        enable = true,\n        textobjects = {\n            --instead of defining the move section in the textobjects scope we move it under nvim_next\n            move = {\n                goto_next_start = {\n                    [\"]m\"] = \"@function.outer\",\n                    [\"]]\"] = { query = \"@class.outer\", desc = \"Next class start\" },\n                },\n                goto_next_end = {\n                    [\"]M\"] = \"@function.outer\",\n                    [\"][\"] = \"@class.outer\",\n                },\n                goto_previous_start = {\n                    [\"[m\"] = \"@function.outer\",\n                    [\"[[\"] = \"@class.outer\",\n                },\n                goto_previous_end = {\n                    [\"[M\"] = \"@function.outer\",\n                    [\"[]\"] = \"@class.outer\",\n                },\n            }\n        }\n    }\n})\n```\n\n### Quickfix list\n\n```lua\nlocal next_integrations = require(\"nvim-next.integrations\")\nlocal nqf = next_integrations.quickfix()\nvim.keymap.set(\"n\", \"[d\", nqf.cprevious, { desc = \"previous quickfix list item\" })\nvim.keymap.set(\"n\", \"]d\", nqf.cnext, { desc = \"next quickfix list item\" })\n```\n\n## Writing a custom adapter\n\nThe protocol for `func_next` and `func_prev` is defined as follows:\nThey need to accept a structure:\n\n```lua\n{ result = nil --here goes results of whatever your function returned,\n               --nil if that is a first invocation ,\n  repeating = true --if the call is repeated, false otherwise\n  args = {} -- table with original arguments\n}\n```\n\nExample:\n\n```lua\nlocal next_move = require(\"nvim-next.move\")\nlocal prev_qf_item, next_qf_item = next_move.make_repeatable_pair(function(_)\n    local status, err = pcall(vim.cmd, \"cprevious\")\n    if not status then\n        vim.notify(\"No more items\", vim.log.levels.INFO)\n    end\nend, function(_)\n    local status, err = pcall(vim.cmd, \"cnext\")\n    if not status then\n        vim.notify(\"No more items\", vim.log.levels.INFO)\n    end\nend)\n\nmap(\"n\", \"]q\", next_qf_item, { desc = \"nvim-next: next qfix\" })\nmap(\"n\", \"[q\", prev_qf_item, { desc = \"nvim-next: prev qfix\" })\n```\n\n# Credits\n\nThe initial code for that plugin was created by @kiyoon during work at https://github.com/nvim-treesitter/nvim-treesitter-textobjects/pull/359\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fghostbuster91%2Fnvim-next","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fghostbuster91%2Fnvim-next","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fghostbuster91%2Fnvim-next/lists"}