JoosepAlviste / nvim-ts-context-commentstring

Neovim treesitter plugin for setting the commentstring based on the cursor location in a file.
MIT License
1.16k stars 34 forks source link

Add pre_hook function for calculating commentstring #30

Closed seblj closed 2 years ago

seblj commented 2 years ago

So I have overridden update_commentstring for a few weeks now to be able to calculate a commentstring before doing the comment. However, I don't like that I have to override the entire function and really only want a pre_hook that takes precedence over the internal calculate_commentstring.

So the reason I want this, is to be able to for example uncomment different commentstrings without manually changing. Let's take an example for C. In C you can comment with a comentstring of // %s and /* %s */.

I have configured the commentstring to be // %s but if i encounter a comment with /* %s */ I have to uncomment it manually. For the pre-hook I then want to parse the current line and see which commentstring is used and then based on that maybe switch the commentstring before uncommenting. Therefore I have chosen to pass in the current node and tree as argument to the pre_hook to give the user some context to be able to easily get the language and the type of the node which I would like to use.

I am not entirely sure if I did it correct with the comments on @param over the function, so If this is wrong I would be happy to fix this with your assistance!

JoosepAlviste commented 2 years ago

Hey @seblj, thanks for the PR!

Could you give a specific example for how you would use this (some specific code if you have anything in your config)?

In general, I'm not opposed to this but it seems like using a commenting plugin's pre-commenting hook would be good enough. Is there some reason why a commenting plugin's hook wouldn't work?

seblj commented 2 years ago

Hey @seblj, thanks for the PR!

Could you give a specific example for how you would use this (some specific code if you have anything in your config)?

Yes sure! This is how I plan to use it

local language_commentstrings = {
    c = { '//%s', '/*%s*/' },
}

local parse_line = function(commentstring)
    local a = vim.split(commentstring, '%s', true)
    local current_line = vim.fn.getline('.')
    local first_non_whitespace_col = vim.fn.match(vim.fn.getline('.'), '\\S')

    local first = a[1]:gsub('%s+', '')
    local second = a[2]:gsub('%s+', '')
    local start = string.sub(current_line, first_non_whitespace_col, first_non_whitespace_col + #first):gsub('%s+', '')
    local last = string.sub(current_line, 0 - #second, -1):gsub('%s+', '')

    if first == start then
        if second == last or #second == 0 then
            return commentstring
        end
    end
    return nil
end

context_commentstring = {
    enable = true,
    pre_hook = function(node, language_tree)
        if node:type() == 'comment' then
            local commenstrings = language_commentstrings[language_tree:lang()] or {}
            for _, commentstring in pairs(commenstrings) do
                local found = parse_line(commentstring)
                if found then
                    vim.api.nvim_buf_set_option(0, 'commentstring', found)
                end
            end
        end
    end,
},

And instead of setting the commentstring I would just return it if we change it. I also think returning instead of setting the commentstring yourself is the better way after thinking about it.

In general, I'm not opposed to this but it seems like using a commenting plugin's pre-commenting hook would be good enough. Is there some reason why a commenting plugin's hook wouldn't work?

Yes that would be good enough, but I am using commentary.vim and as far as I know, this does not have a pre-hook. In general I am pretty happy with it, so the only thing that is really missing is a pre-hook IMO. I have looked at Comment.nvim which has a pre-hook, but I haven't gotten around to switching yet. One reason is that is looks like one have to set a mapping for block comments. Default it sets to gb but I have something else mapped to gb, and for now I can't think of anything else of mapping block comments to yet. Plus that I have never missed block comments. Will probably look closer at Comment.nvim in the future though.

JoosepAlviste commented 2 years ago

One thought I had was that maybe pre_hook is not 100% correct name for this, but I think that it will make it easier to understand what you might use it for.

In any case, thanks for the contribution!

seblj commented 2 years ago

If you want we can change it right away so it doesn't break things for people later if you want to change it? I am basically open for whatever name you want

JoosepAlviste commented 2 years ago

Hmm, maybe custom_logic or custom_calculation would be more accurate? Do you have any thoughts?

seblj commented 2 years ago

Both of them are fine for me really. Don't think I prefer any over the other, so you can pick. I can create a new PR with the new name

JoosepAlviste commented 2 years ago

I pushed the change myself directly to main (to custom_calculation). Thanks for thinking along!

seblj commented 2 years ago

Okay awesome!