nvim-treesitter / nvim-treesitter-textobjects

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Expose way to integrate with external repeatable engine

ghostbuster91 opened this issue · comments

Is your feature request related to a problem? Please describe.
As you know I created https://github.com/ghostbuster91/nvim-next as a separate entity to handle repeating motions. I already integrated it with few of the other plugins that I use. Now I would like to also integrate it with the nvim-treesitter-textobjects, however I don't see an easy way to plug it into.

Describe the solution you'd like
I would like hook nvim-next into the nvim-treesitter-textobjects plugin. My current solution requires nvim-treesitter-textobjects to expose on-attach callback or some equivalent of it. However, I am open to other suggestions.

Below is a snippet that I developed so far based on the content of move.lua module.

local move = require("nvim-next.move")

local nxo_mode_functions = {
    "goto_next_start",
    "goto_next_end",
    "goto_previous_start",
    "goto_previous_end",
    "goto_next",
    "goto_previous",
}
return function(ts_move)
    local M = {}

    local prev_start, next_start = move.make_repeatable_pair(function(opts)
        ts_move.goto_previous_start(unpack(opts.args or {}))
    end, function(opts)
        ts_move.goto_next_start(unpack(opts.args or {}))
    end)

    M.goto_previous_start = prev_start
    M.goto_next_start = next_start

    local prev_end, next_end = move.make_repeatable_pair(function(opts)
        ts_move.goto_previous_end(unpack(opts.args or {}))
    end, function(opts)
        ts_move.goto_next_end(unpack(opts.args or {}))
    end)

    M.goto_previous_end = prev_end
    M.goto_next_end = next_end

    local prev, next = move.make_repeatable_pair(function(opts)
        ts_move.goto_previous(unpack(opts.args or {}))
    end, function(opts)
        ts_move.goto_next(unpack(opts.args or {}))
    end)

    M.goto_prev = prev
    M.goto_next = next

    M.attach = function(config)
        for _, function_call in ipairs(nxo_mode_functions) do
            for mapping, query_metadata in pairs(config.move[function_call]) do
                local mapping_description, query, query_group

                if type(query_metadata) == "table" then
                    query = query_metadata.query
                    query_group = query_metadata.query_group or "textobjects"
                    mapping_description = query_metadata.desc
                else
                    query = query_metadata
                    query_group = "textobjects"
                    mapping_description = "nvim-next:" .. " " .. query_metadata
                end

                local fn = function()
                    M[function_call](query, query_group)
                end

                vim.keymap.set(
                    { "n", "x", "o" },
                    mapping,
                    fn,
                    { --[[ buffer = bufnr ]] silent = true, remap = false, desc = mapping_description }
                )
            end
        end
    end

    return M
end

Notice that I don't have the access to the bufnr

and here is the client-side usage of it:

local ts_move = require "nvim-treesitter.textobjects.move"
next_integrations.treesitter_textobjects(ts_move).attach({ move = {
    goto_next_start = {
        ["]m"] = "@function.outer",
    },
} })

As you can see I calling am this function manually which is not ideal as the treesitter may not be available for every file.

Describe alternatives you've considered
I guess that an alternative to exposing on_attach callback would be expose a public interface for repeatable engine to be implemented be external vendors.

Additional context
Add any other context or screenshots about the feature request here.

Currently we find it hard to maintain the project and even if we support hooks we cannot guarantee it will work over the updates. I think more elegant way is to tell users to just pass the kepmap configurations to your plugin and you can map the keys using the move functions that we provide? That will ensure more compatibility and customisability and I think you'll need to do the same for many other plugins

Currently we find it hard to maintain the project and even if we support hooks we cannot guarantee it will work over the updates

Sure, that is totally understandable.

I think more elegant way is to tell users to just pass the kepmap configurations to your plugin and you can map the keys using the move functions that we provide?

Yes, that is what I did, the only problem with that is that those key mappings should be done only if tresitter queries are available for the current buffer.

However I worked it around by implementing that integration (nvim-next <-> textobjects) as a treesitter plugin so that I can hook into the on_attach callback.

I guess there is no more to do here. Thanks!

@ghostbuster91 I'm glad you've found a way :)