nvim-treesitter-textobjects icon indicating copy to clipboard operation
nvim-treesitter-textobjects copied to clipboard

Smarter Inner Object Whitespace Selection

Open jamesb6626 opened this issue 2 years ago • 3 comments

Is your feature request related to a problem? Please describe. With include_surrounding_whitespace enabled, inner textobjects currently include whitespace in an inconvenient way. In languages such as python, this includes all the whitespace up to and including the newline for the following function, so dif, cif, etc will drag the proceeding function to the cursor.

Describe the solution you'd like Inner objects should include whitespace (when the setting is enabled), but only where that also lies within the outer object selected without whitespace, if possible. The outer object includes the end marker (end for lua, } for C), but not the start of the next function in python. If something bad happens (are there cases with no outer? could outer not contain inner?) then fall back to including no whitespace.

This would make inner selections more expensive (two objects needed) and less robust (breaks if either of inner/outer does something weird), but hopefully will get the correct match.

Since the inner object is likely wrapped by its outer parts, this should probably be used for both preceding and proceeding whitespace (unlike the current behaviour), but some care might be needed for newlines and indent. Maybe, as a first try, exclude one newline followed by an indent (non-newline space, possibly empty) in the whitespace that lies between the inner and outer matches at each end (first match at the start, last match at the end, if they exist)? Not sure whether that will work. The idea is to leave the cursor on the correct line, with the correct indent, after e.g. a python def, and to leave the end and } parts of a lua or C function on their own line after that, again with their current indent. Require that the indent is followed by non-blank for the end case, to make sure its the one we want.

For languages such as lua and C, it might be good to include all whitespace according to the rule. Maps dif, cif would place the start and end bit on the same line, with the cursor between. But this should be optional per filetype, so maybe this should be left for later.

Describe alternatives you've considered Not including surrounding whitespace ruins the well designed behaviour for outer objects. Allowing the user to disable this for inner objects only should be a job for #156, and this could be done by default. Unfortunately, the opposite behaviour is best for languages such as lua and C, where the next non-blank after the inner object is part of the function (end or }), so just disabling the behaviour for inner objects will hurt those cases.

Additional context

Example of current behaviour

Try inner function (vif, dif, cif) on the second line of the following two files with include_surrounding_whitespace true/false.

Lua:

function()
  print("hello world")

end

Python:

def a():
    pass


def b():
    pass

jamesb6626 avatar Sep 03 '22 15:09 jamesb6626

A related observation for Makefiles (:TSInstall make) with following treesitter query in ~/.config/nvim/queries/make/textobjcets.scm:

(rule
  ((recipe) @class.inner)?) @class.outer

Consider following rules in a Makefile:

# Rules
.PHONY: all clean cleanall

all: $(docs)

$(OUTPUT_DIR)%.$(FORMAT): %.graphml $(TEXFILE)
	@echo "Pattern rule"
	$(TEX) $(all_texflags) $<

clean:
	-$(RM) $(foreach ext, $(CLEAN_EXTS), $(docs:%.$(FORMAT)=%.$(ext)))

Screenshot of a vic selection

Screenshot 2022-09-04 at 10 45 17

In my opinion, the @class.inner selection should not contain the linebreak of the targets: prerequisites line and the follow-up line.

Interestingly, playground selects as I would expect: Screenshot 2022-09-04 at 10 47 14

Using the neovim directive offset! does not help. https://neovim.io/doc/user/treesitter.html#ts-directive-offset!

kiryph avatar Sep 04 '22 08:09 kiryph

I had two open PRs for smarting selecting objects at https://github.com/nvim-treesitter/nvim-treesitter-textobjects/pull/150.

stsewd avatar Sep 29 '22 20:09 stsewd

I don't think inner objects should include whitespace at all. Only outer objects should include surrounding whitespace.

myarcana avatar Apr 03 '23 23:04 myarcana