nvim-treesitter / nvim-treesitter-textobjects

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Swap operands

znd4 opened this issue · comments

Is your feature request related to a problem? Please describe.
imagine you write out something like this

df["column_1"] - df["long_column_name"].a_couple().of_transformations()

But you realize that you actually want to swap these.

you've gotten okay at vim motions, so you F-D0P, but then realize you've still got a ways to go:

- df["long_column_name"].a_couple().of_transformations()df["column_1"] 

Thankfully your cursor's in a convenient place, so you can easily add a minus sign in the middle:

- df["long_column_name"].a_couple().of_transformations()-df["column_1"] 

You've still got to 0dw to clear up the leading - . Finally, you're in a state where your format-on-save hooks will clean things up:

df["long_column_name"].a_couple().of_transformations()-df["column_1"] 

Describe the solution you'd like
I'd like to be able to add an @operand mapping to my swap configuration, e.g.:

		swap = {
			enable = true,
			swap_next = {
				["<leader>o"] = "@operand",
			},
			swap_previous = {
				["<leader>O"] = "@operand",
			},
		},

Describe alternatives you've considered

I guess there might be a swapping-specific plugin that I could look for. If it doesn't exist, I suppose I could try to implement it, although I'd rather try to implement it in this project if it's possible (I don't know what's involved in creating a textobject for treesitter)

Additional context
nil

I love this idea, I've been wanting it for a while. Not sure I'll be able to implement it for every language we support, but I'll try 😃

I've run into some unexpected behavior when swapping operands within chained associative operations.

The Problem

To see what I mean, consider the following expression:

1 + 2 + 3

Treesitter parses this into an AST with two binary_expression's. They look like:

binary_expression (1 + 2 + 3)
left: integer (1)
right: binary_expression (2 + 3)

and

binary_expression (2 + 3)
left: integer (2)
right: integer (3)

So there are two swaps that I can make, corresponding to the two binary_expression's:

  • 1 and 2 + 3
  • 2 and 3

However, as a user, I want to imagine this expression as a list of integer's joined by +, where any two adjacent elements can be swapped. In this case, the second possible swap stays the same, but the first one changes:

  • 1 and 2 <- different from above
  • 2 and 3

Proposed Solutions

  1. We ask that users change their expectations to match treesitter's.
    1. This would probably require people to use unnecessary parentheses so that they're on the same page as treesitter about what the operands are in a given situation.
    2. Example: 1 + (2 + 3)
  2. We make treesitter match my (and probably most users') expectations.
    1. This would require treesitter-textobjects to check that two nodes share a common ancestor that's a binary_expression, rather than just a common parent like it does now.
    2. This would be a large refactor as far as I can tell.
  3. We disable swapping, or the capturing of the operand textobject, for nested binary_expression's that all have the same operator.
    1. This would also be a large refactor to my knowledge.
  4. We don't implement this feature, disappointing users like @zdog234 and I.

@zdog234 @theHamsta, what do you make of these options?