nvim-treesitter-textobjects
nvim-treesitter-textobjects copied to clipboard
Smarter Inner Object Whitespace Selection
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
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
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:
Using the neovim directive offset!
does not help.
https://neovim.io/doc/user/treesitter.html#ts-directive-offset!
I had two open PRs for smarting selecting objects at https://github.com/nvim-treesitter/nvim-treesitter-textobjects/pull/150.
I don't think inner objects should include whitespace at all. Only outer objects should include surrounding whitespace.