nvim-treesitter / nvim-treesitter-textobjects

Apache License 2.0
2.18k stars 195 forks source link

TextYankPost receives visual = true for treesitter objects #240

Open asmodeus812 opened 2 years ago

asmodeus812 commented 2 years ago

Describe the bug When executing regular yanking operations such as yaf, yaa, yif, yia etc. TextYankPost event payload receives an incorrect visual=true as opposed to visual = false, which is what is received for regular built in text objects (yiw, yap etc). Therefore when yanking the function body, the highlight is not observed, as compared to yanking the word, which does correctly highlight it. Obviously happening since the auto command configures visual = false, but the even data receives visual = true. The following observations were made - The event received by vim.highlight is as if it was done in visual mode. Excerpt from vim.highlight which demonstrates why yaf highlight does not work with the above auto command.

opts = opts or {}
  local event = opts.event or vim.v.event
  local on_macro = opts.on_macro or false
  **local on_visual = (opts.on_visual ~= false)**

  if not on_macro and vim.fn.reg_executing() ~= '' then
    return
  end
  if event.operator ~= 'y' or event.regtype == '' then
    return
  end
  **if not on_visual and event.visual then
    return
  end**

To Reproduce Having installed and configured treesitter and treesitter text objects plugins only

local status_ok, configs = pcall(require, "nvim-treesitter.configs")
if not status_ok then
    vim.notify("Unable to load of find plugin nvim-treesitter", vim.log.levels.ERROR)
    return
end

vim.cmd [[
      augroup GENERAL
        autocmd!
        autocmd TextYankPost * lua require('vim.highlight').on_yank({timeout = 250, on_visual = false})
      augroup END
]]

configs.setup({
    textobjects = {
        select = {
            enable = true,
            keymaps = {
                ["aa"] = "@parameter.outer",
                ["ia"] = "@parameter.inner",
                ["af"] = "@function.outer",
                ["if"] = "@function.inner",
                ["ac"] = "@class.outer",
                ["ic"] = "@class.inner",
            },
        },
    }
})

Having the following (dummy) piece of code

int main(int argc, char **argv) {
  int k = 12;
  k++;
  printf("Hello, World!\n");
  printf("Hello, kval! %d\n", k);
  printf("Hello, argc! %d\n", argc);
  for (size_t i = 0; i < argc; i++) {
    printf("%s\n", argv[i]);
  }
  fflush(stdout);
  return 0;
}

Executing yaw, this is what vim.highlight reports for vim.v.event

{
  inclusive = true,
  operator = "y",
  regcontents = { " main" },
  regname = "",
  regtype = "v",
  visual = false
}

Executing yaf, this is what vim.highlight reports for vim.v.event

{
  inclusive = true,
  operator = "y",
  regcontents = { "int main(int argc, char **argv) {", "  int k = 12;", "  k++;", '  printf("Hello, World!\\n");', '  pr
intf("Hello, kval! %d\\n", k);', '  printf("Hello, argc! %d\\n", argc);', "  for (size_t i = 0; i < argc; i++) {", '
printf("%s\\n", argv[i]);', "  }", "  fflush(stdout);", "  return 0;", "}" },
  regname = "",
  regtype = "v",
  visual = true
}

Expected behavior When yanking a custom object, the event will not mark the action/operation as if it was being done in visual mode

Output of :checkhealth nvim_treesitter

========================================================================

Output of nvim --version

NVIM v0.7.2
Build type: Release
LuaJIT 2.1.0-beta3
Compiled by runner@fv-az164-457

Features: +acl +iconv +tui
See ":help feature-compile"

   system vimrc file: "$VIM/sysinit.vim"
  fall-back for $VIM: "/share/nvim"

Bug was initially reported in neovim repo, but was redirected to here instead - https://github.com/neovim/neovim/issues/19687

akdevservices commented 2 years ago

The same problem. vim.highlight.on_yank with on_visual set to true works as expected.

laytan commented 2 years ago

I did some digging to see what is going on and found some more information:

Under the hood, the plugin has to enter visual mode to make our precise selection to be yanked, this is why vim sets visual to true in the TextYankPost event.

I then looked for other plugins that add textobjects and found mini.ai and targets.vim. Both also enter visual mode and also have the issue with highlight.on_yank described here.

The source for highlight.on_yank is pretty closed off as wel, there is no way to override the option as it is given in the user created auto command. And there is no way of editing vim.v.event from outside of the same auto command, see https://neovim.io/doc/user/eval.html#v:event.

So the only possible solution/workaround I can come up with is adding to the plugin's configuration, something like:

{
    textobjects = {
        highlight_on_yank = {
            enabled = true,
            higroup = 'Search',
            timeout = 100,
        },
    },
}

And after doing our selection, manually calling vim.highlight.range() with the configured settings.

@theHamsta sorry if mentioning is wrong, but I think you are the lead maintainer: do you have any thoughts on this and would a PR from me be welcome that adds this configuration and calling of vim.highlight.range()?