Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Repeatable movement across modules with ; and , #1077

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

Repeatable movement across modules with ; and , #1077

heygent opened this issue Jul 22, 2024 · 2 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
new-module Request for the new module
Projects
None yet
Development

No branches or pull requests

2 participants