nvim-treesitter / nvim-treesitter-textobjects

Apache License 2.0
2.03k stars 182 forks source link

Parameter.outer grabs too much in Ruby #494

Open jacobat opened 9 months ago

jacobat commented 9 months ago

Describe the bug

I have this code and with the cursor on the b in abc I execute the function: nvim-parameter-outer-1 This is what is selected: nvim-parameter-outer-2

Expected behavior I would expect abc, to be selected instead of all the parameters.

Output of :checkhealth nvim-treesitter

nvim-treesitter: require("nvim-treesitter.health").check() Installation ~ - WARNING `tree-sitter` executable not found (parser generator, only needed for :TSInstallFromGrammar, not required for :TSInstall) - OK `node` found v20.7.0 (only needed for :TSInstallFromGrammar) - OK `git` executable found. - OK `cc` executable found. Selected from { vim.NIL, "cc", "gcc", "clang", "cl", "zig" } Version: cc (GCC) 13.2.1 20230801 - OK Neovim was compiled with tree-sitter runtime ABI version 14 (required >=13). Parsers must be compatible with runtime ABI. OS Info: { machine = "x86_64", release = "5.15.90.1-microsoft-standard-WSL2", sysname = "Linux", version = "#1 SMP Fri Jan 27 02:56:13 UTC 2023" } ~ Parser/Features H L F I J - bash ✓ ✓ ✓ . ✓ - c ✓ ✓ ✓ ✓ ✓ - eex ✓ . . . ✓ - elixir ✓ ✓ ✓ ✓ ✓ - elm ✓ . . . ✓ - heex ✓ ✓ ✓ ✓ ✓ - json ✓ ✓ ✓ ✓ . - kdl ✓ ✓ ✓ ✓ ✓ - lua ✓ ✓ ✓ ✓ ✓ - make ✓ . ✓ . ✓ - markdown ✓ . ✓ ✓ ✓ - query ✓ ✓ ✓ ✓ ✓ - ruby ✓ ✓ ✓ ✓ ✓ - vim ✓ ✓ ✓ . ✓ - vimdoc ✓ . . . ✓ - yaml ✓ ✓ ✓ ✓ ✓

Output of nvim --version

NVIM v0.9.2
Build type: Release
LuaJIT 2.1.1694285958

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

Additional context I've disabled all plugins except for nvim-treesitter/nvim-treesitter and nvim-treesitter/nvimtreesitter-textobjects.

Akimcx commented 3 months ago

In a nutshell

Change @parameter.outer to @parameter.inner

Explanation

This isn't a bug, it actually the expected behavior. You can check that by runnig :TSEditQuery textobjects in a ruby file. which will open the corresponding textobjects.scm file

If you search for @parameter.outer you'll see that its actually capturing (method_parameters) which essentially grab all the parameters of the method including the opening and closing parenthesis.

If your search for @parameter.inner you'll see that its actually capturing (method_parameters (_)) which essentially grab the node inside the (method_parameters) i.e all the identifiers (it will match the parameter under the cursor)

jacobat commented 3 months ago

@parameter.inner doesn't select the characters I want. As an example I might want to remove an argument from the argument list. I should be able to do this with "delete outer argument".

It might be that Treesitter text objects are implemented in a specific way, but it goes against regular vim conventions.

By convention the difference between inner and outer is not the difference between one element in a list and all the elements but rather between just the element or the element and some surrounding "padding".

Akimcx commented 3 months ago

Well in that case you'll have to make a custom query to select the characters you want

I managed to make a simple one based on the textobjects.scm of java

(method_parameters "," @_start . (identifier) @parameter.inner (#make-range! "parameter.outer" @_start @parameter.inner)) (method_parameters . (identifier) @parameter.inner . ","? @_end (#make-range! "parameter.outer" @parameter.inner @_end))


- save & quit then open the file again

This should at least work for the methods, but it's pretty straightforward to make it work for the other one as well
alexmozaidze commented 2 months ago

By convention the difference between inner and outer is not the difference between one element in a list and all the elements but rather between just the element or the element and some surrounding "padding".

Absolutely agreed. Usually all parameters are enclosed in a character that is already easily capturable with vanilla Neovim (like () in function arguments, or "" in HTML properties), and having @parameter.outer do the same thing as vanilla, whilst not following vanilla's convention, sounds really unintuitive to me.

For most languages, the current behaviour of @parameter.outer seems redundant, correct me if I'm wrong.