Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add hooks to define the source per buffer in mini.diff #949

Open
2 tasks done
nicoe opened this issue Jun 7, 2024 · 1 comment
Open
2 tasks done

Add hooks to define the source per buffer in mini.diff #949

nicoe opened this issue Jun 7, 2024 · 1 comment
Labels
feature-request Request for a feature to existing module mini.diff

Comments

@nicoe
Copy link

nicoe commented Jun 7, 2024

Contributing guidelines

Module(s)

mini.diff

Description

I started to use mini.diff and it works great, thanks for all the work!

In my job, I'm using both mercurial and git, so I quickly felt the need to have a source for mercurial.
But I didn't found a way to select the right source from the detected VCS managing the file in the buffer.

I ended up creating a source that is handling both but I find it quite ugly. I wonder if it wouldn't be interesting to plug a function somewhere so that the source used by the buffer can be programmatically decided.

For the record here is what I've written (it might be useful to someone) but it's a quick hack and this is nearly my first time writing some lua so I've probably made a lot of mistakes :)

    {
        "echasnovski/mini.diff",
        version=false,
        opts = function(_, opts)
            local MiniDiff = require("mini.diff")
            local git_hg = { name = 'git_hg' }
            local git_source = MiniDiff.gen_source.git()

            git_or_hg = function(path)
                local vcs = { type = nil }
                local cwd = vim.fn.fnamemodify(path, ':h')
                local hg_run = vim.system({ 'hg', 'root' }, { cwd = cwd, stdin = false, stdout = false, stderr = false }):wait()
                local git_run = vim.system({ 'git', 'rev-parse' }, { cwd = cwd, stdin = false, stdout = false, stderr = false }):wait()
                if hg_run.code == 0 then
                    return 'hg'
                elseif git_run.code == 0 then
                    return 'git'
                else
                    return nil
                end
            end

            git_hg.attach = function(buf_id)
                local path = vim.api.nvim_buf_get_name(buf_id)
                if path == '' or vim.fn.filereadable(path) ~= 1 then return false end
                local vcs = git_or_hg(path)
                if vcs == 'git' then
                    git_source.attach(buf_id)
                elseif vcs == 'hg' then
                    local p, stdout_feed = nil, {}
                    local on_exit = function(exit_code)
                        p:close()
                        if exit_code ~= 0 or stdout_feed[1] == nil then
                            vim.schedule_wrap(function()
                                MiniDiff.disable(buf_id)
                            end)()
                            return
                        end
                        vim.schedule_wrap(function()
                            MiniDiff.set_ref_text(buf_id, table.concat(stdout_feed, ''))
                        end)()
                    end
                    local stdout = vim.uv.new_pipe()
                    p = vim.uv.spawn('hg', { args = { 'cat', '--rev', 's0', path }, stdio = { nil, stdout, nil } }, on_exit)

                    local git_read_stream = function(stream, feed)
                        local callback = function(err, data)
                            if data ~= nil then return table.insert(feed, data) end
                            if err then feed[1] = nil end
                            stream:close()
                        end
                        stream:read_start(callback)
                    end
                    git_read_stream(stdout, stdout_feed)
                else
                    vim.schedule_wrap(function()
                        MiniDiff.disable(buf_id)
                    end)()
                end
            end

            git_hg.detach = function(buf_id)
                local path = vim.api.nvim_buf_get_name(buf_id)
                if path == '' or vim.fn.filereadable(path) ~= 1 then return false end
                local vcs = git_or_hg(path)
                if vcs == 'git' then
                    git_source.detach(buf_id)
                end
            end

            return {
                source=git_hg,
            }
        end,
        config = function(_, opts)
            require("mini.diff").setup(opts)
        end,
    },
@nicoe nicoe added the feature-request Request for a feature to existing module label Jun 7, 2024
@echasnovski
Copy link
Owner

Thanks for the suggestion! Glad you're liking 'mini.diff' so far :)

I ended up creating a source that is handling both but I find it quite ugly. I wonder if it wouldn't be interesting to plug a function somewhere so that the source used by the buffer can be programmatically decided.

Yes, this was the intended solution for this kind of problems. I'll take a look at how this can be made easier, but it will probably happen after the next stable 'mini.nvim' release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature-request Request for a feature to existing module mini.diff
Projects
None yet
Development

No branches or pull requests

2 participants