Change behavior when repeating last move from builtin_f_expr and builtin_t_expr
Is your feature request related to a problem? Please describe.
When using repeat_last_moveon operation pending mode, after triggeringbuiltin_f_expr
or builtin_t_expr, it operates on one character less that it would be expected to.
Taking this snippet as an exemple:
vim.keymap.set({ 'n', 'x', 'o' }, ';', ts_repeat_move.repeat_last_move)
If the user presses f(, returns to the first character and presses d;, it would result on:
({ 'n', 'x', 'o' }, ';', ts_repeat_move.repeat_last_move)
t(_d; would result on:
t({ 'n', 'x', 'o' }, ';', ts_repeat_move.repeat_last_move)
Describe the solution you'd like
For f(_d;, it would be expected to behave, as:
{ 'n', 'x', 'o' }, ';', ts_repeat_move.repeat_last_move)
and for t(_d;:
({ 'n', 'x', 'o' }, ';', ts_repeat_move.repeat_last_move)
Additional context
This diverges from the way it works in core nvim and is inconsistent with F, T,
and visual selection behavior.
As far as i can tell, this is only reproducible when repeating moves from builtin_f_expr and
builtin_t_expr on operation pending mode, not with builtin_F_expr and builtin_T_expr.
Because d; is not equal to d:norm! ;<cr>.
Can be fixed with expr (this patch is used on main branch, but I'm not sure if this functionality would still be kept in future):
diff --git a/lua/nvim-treesitter-textobjects/repeatable_move.lua b/lua/nvim-treesitter-textobjects/repeatable_move.lua
index f4aa09b..4d8b3ff 100644
--- a/lua/nvim-treesitter-textobjects/repeatable_move.lua
+++ b/lua/nvim-treesitter-textobjects/repeatable_move.lua
@@ -27,34 +27,19 @@ M.make_repeatable_move = function(move_fn)
end
---@param opts_extend TSTextObjects.MoveOpts?
----@return boolean
+---@return string?
M.repeat_last_move = function(opts_extend)
- if M.last_move then
- local opts ---@type table
- if opts_extend ~= nil then
- opts = vim.tbl_deep_extend("force", {}, M.last_move.opts, opts_extend)
- else
- opts = M.last_move.opts
- end
-
- if M.last_move.func == "f" or M.last_move.func == "t" then
- if opts.forward then
- vim.cmd.normal { vim.v.count1 .. ";", bang = true }
- else
- vim.cmd.normal { vim.v.count1 .. ",", bang = true }
- end
- elseif M.last_move.func == "F" or M.last_move.func == "T" then
- if opts.forward then
- vim.cmd.normal { vim.v.count1 .. ",", bang = true }
- else
- vim.cmd.normal { vim.v.count1 .. ";", bang = true }
- end
- else
- M.last_move.func(opts, unpack(M.last_move.additional_args))
- end
- return true
+ if not M.last_move then
+ return
+ end
+ local opts = vim.tbl_deep_extend("force", M.last_move.opts, opts_extend or {})
+ if M.last_move.func == "f" or M.last_move.func == "t" then
+ return opts.forward and ";" or ","
+ elseif M.last_move.func == "F" or M.last_move.func == "T" then
+ return opts.forward and "," or ";"
+ else
+ return M.last_move.func(opts, unpack(M.last_move.additional_args))
end
- return false
end
M.repeat_last_move_opposite = function()
vim.keymap.set({ 'n', 'x', 'o' }, ';', function() return require 'nvim-treesitter-textobjects.repeatable_move'.repeat_last_move_next() end, { expr = true })
vim.keymap.set({ 'n', 'x', 'o' }, ',', function() return require 'nvim-treesitter-textobjects.repeatable_move'.repeat_last_move_opposite() end, { expr = true })
@phanen Could you open a PR for your fix? Your solution seems good to me.
Closed by #707