Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Repeatable movement across modules with ; and , #1077

Open
2 tasks done
heygent opened this issue Jul 22, 2024 · 5 comments
Open
2 tasks done

Repeatable movement across modules with ; and , #1077

heygent opened this issue Jul 22, 2024 · 5 comments
Labels
new-module Request for the new module

Comments

@heygent
Copy link

heygent commented Jul 22, 2024

Contributing guidelines

Module(s)

mini.jump, mini.ai, mini.bracketed

Description

Hi, and thank you for this incredible project, it is slowly conquering my config :)

I think it would be cool if modules that deal with movements were able to make them repeatable with , and ;. Some examples of this behaviour would be:

  • with mini.bracketed, pressing ]i takes you to the next indent, and pressing ; afterwards takes you to the next one again. Pressing , would instead bring you to the previous one. Same could be done with the movements that are local to the buffer, such as treesitter nodes, diagnostics, comment blocks etc.
  • with mini.ai, pressing g[' takes you to the first quote in a pair, pressing ; afterwards does it again. This is also implented in nvim-treesitter/nvim-treesitter-textobjects
  • with mini.jump, this is already working with the ; key. It would be a matter of integrating it with the general mechanism used for the other modules.

There is an implementation of this in https://github.com/nvim-treesitter/nvim-treesitter-textobjects/blob/master/lua/nvim-treesitter/textobjects/repeatable_move.lua
It is written so that other plugins can hook into it, making their respective moves repeatable, but I feel like such a mechanism would be better suited to a project like this, as it is more general in scope and it already has many modules it can be hooked into.

@heygent heygent added the feature-request Request for a feature to existing module label Jul 22, 2024
@echasnovski
Copy link
Owner

Thanks for the suggestion!

An idea of generalizable repeatable jump is interesting and I'll take a look at implementation in 'nvim-treesitter'.

However, my first instinct is that I don't really like the idea of overriding ";" and ",". Not sure why, though. Probably because they are somewhat special and the first one is already taken by 'min.jump'. I'll think about it.

@heygent
Copy link
Author

heygent commented Aug 1, 2024

I ended up monkeypatching the mini functions on my config's side. It's really nice to use, you can use this snippet to try it out (requires nvim-treesitter-textobjects):

local ts_repeat_move = require("nvim-treesitter.textobjects.repeatable_move")

local minibracketed = require('mini.bracketed')

for key, _ in pairs(minibracketed.config) do
  local move_fn = minibracketed[key]
  minibracketed[key] = function(direction, opts)
    local function repeatable_move(inopts)
        move_fn(inopts.forward and 'forward' or 'backward', opts)
    end
    ts_repeat_move.set_last_move(repeatable_move, {
      forward = direction == 'forward' or direction == 'last',
    })
    move_fn(direction, opts)
  end
end

local miniai = require('mini.ai')
local move_cursor = miniai.move_cursor

miniai.move_cursor = function(side, ai_type, id, opts)
  local function repeatable_move_cursor(inopts)
    local new_opts = vim.tbl_extend('force', opts, {
      search_method = inopts.forward and 'next' or 'prev'
    })
    move_cursor(side, ai_type, id, new_opts)
  end
  ts_repeat_move.set_last_move(
    repeatable_move_cursor,
    { forward = opts.search_method ~= 'prev' and opts.search_method ~= 'cover_or_prev' }
  )
  move_cursor(side, ai_type, id, opts)
end

local minijump = require('mini.jump')
local jump = minijump.jump

minijump.jump = function(target, backward, till, number)
  local function repeatable_jump(inopts)
    jump(target, not inopts.forward, till, 1)
  end
  ts_repeat_move.set_last_move(
    repeatable_jump,
    { forward = not backward }
  )
  jump(target, backward, till, number)
end

-- Repeat movement with ; and ,
-- ensure ; goes forward and , goes backward regardless of the last direction
vim.keymap.set({ "n", "x", "o" }, ";", ts_repeat_move.repeat_last_move_next)
vim.keymap.set({ "n", "x", "o" }, ",", ts_repeat_move.repeat_last_move_previous)

-- vim way: ; goes to the direction you were moving.
-- vim.keymap.set({ "n", "x", "o" }, ";", ts_repeat_move.repeat_last_move)
-- vim.keymap.set({ "n", "x", "o" }, ",", ts_repeat_move.repeat_last_move_opposite)

@echasnovski echasnovski added new-module Request for the new module and removed feature-request Request for a feature to existing module labels Oct 7, 2024
@matu3ba
Copy link

matu3ba commented Dec 6, 2024

mini.jump, mini.ai, mini.bracketed

I think this would apply to all plugins, likely even user commands.

I think it would be cool if modules that deal with movements were able to make them repeatable with , and ;. Some examples of this behaviour would be:

If unclear what key is used, then the user should specify such behavior.
, and ; are already taken and useful on same line actions with off by 1 or 2 f/t-movements, which makes it a potential poor fit:

							*;*
;			Repeat latest f, t, F or T [count] times. See |cpo-;|

							*,*
,			Repeat latest f, t, F or T in opposite direction
			[count] times. See also |cpo-;|

@echasnovski
Copy link
Owner

, and ; are already taken and useful on same line actions with off by 1 or 2 f/t-movements, which makes it a potential poor fit:

From the 'mini.nvim' perspective a more important argument is that ; is already used by 'mini.jump'. if it hadn't, overriding both ; and , might have been fine.

@heygent
Copy link
Author

heygent commented Dec 12, 2024

From the 'mini.nvim' perspective a more important argument is that ; is already used by 'mini.jump'. if it hadn't, overriding both ; and , might have been fine.

Yes, mini.jump already extends the default , and ; keymaps to work across line boundaries. This would be about generalizing , and ; to work with all modules that deal with jumps and not just mini.jump.

In my point of view, the fact that these keymaps are already used in mini.jump is a feature rather than a bug, as using these same keys in all modules for the action "repeat the last jump" would provide a consistent user experience. For now, those keys are only useful for single character search.

See also https://github.com/mawkler/demicolon.nvim

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
new-module Request for the new module
Projects
None yet
Development

No branches or pull requests

3 participants