Sitelet https://github.com/mawkler/demicolon.nvim
Skip to content

Latest commit

 

History

89 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

demicolon.nvim

Demicolon lets you repeat more motions than just f/F/t/T with ; (forward) and , (backward): It repeats all ]/[-prefixed motions. One such motion is ]d/[d (next/previous diagnostic). Here are some more examples. You can also make non-[/]-prefixed motion repeatable. See Custom Jumps section.

demicolon.mp4

Installation

With lazy.nvim:

{
  'mawkler/demicolon.nvim',
  dependencies = {
    'nvim-treesitter/nvim-treesitter',
    'nvim-treesitter/nvim-treesitter-textobjects',
  },
  opts = {}
}

Usage

After pressing a ]/[-prefixed key, for example ]q, Demicolon lets you repeat its motion with ; and ,.

Of course, Demicolon also lets you repeat t/T/f/F with ;/,. See :help t, :help T, :help f, and :help F respectively for more information.

Examples of repeatable motions

Below are some examples of motions, both built-in and provided by plugins.

Native Neovim motions

Motion Jumps to next/pevious... Help page with more information
]d/[d Next/previous diagnostic (any severity) :help ]d/:help [d
]q/[q Item in quickfix list :help ]q/:help [q
]l/[l Item in location list :help ]l/:help [l
]<C-q>/[<C-q> File in quickfix list :help ]CTRL-Q/:help [CTRL-Q
]<C-l>/[<C-l> File in location list :help ]CTRL-L/:help [CTRL-L
]z/[z Fold :help z]/:help z[
]s/[s Spelling mistake :help ]s/:help [s

For a list of more native motions see :help ]

Demicolon lets you repeat any nvim-treesitter-textobjects motion. For example: ]f to "jump to next function", ]c to "jump to next class", etc.

Note

To use treesitter text-objects you need to configure textobjects.move in nvim-treesitter-textobjects.

Gitsigns motions

Motion Jumps to next/pevious... Help page with more information
]c/[c Git hunk :help gitsigns.nav_hunk()

Neotest motions

Motion Jumps to next/pevious... Help page with more information
]t/[t Test :help neotest.jump
]T/[T Failed test :help neotest.jump

VimTeX motions

Note that these mappings are only created in normal mode and visual mode. For some reason they don't work when created for operator-pending mode.

Motion Jumps to next/pevious... Help page with more information
]]/[[ Section start :help vimtex-motions
][/[] Section end :help vimtex-motions
]r/[r Frame start :help vimtex-motions
]R/[R Frame end :help vimtex-motions
]n/[n Math start :help vimtex-motions
]N/[N Math end :help vimtex-motions
]//[/ Comment start :help vimtex-motions
]*/[* Comment end :help vimtex-motions
]m/[m Environment start :help vimtex-motions
]M/[M Environment end :help vimtex-motions

Configuration

Default options:

opts = {
  -- Create default keymaps
  keymaps = {
    -- Create t/T/f/F key mappings
    horizontal_motions = true,
    -- Create ; and , key mappings. Set it to 'stateless', 'stateful', or false to
    -- not create any mappings. 'stateless' means that ;/, move right/left.
    -- 'stateful' means that ;/, will remember the direction of the original
    -- jump, and `,` inverts that direction (Neovim's default behaviour).
    repeat_motions = 'stateless',
    -- Keys that shouldn't be repeatable (because they aren't motions), excluding the prefix `]`/`[`
    -- If you have custom motions that use one of these, make sure to remove that key from here
    disabled_keys = { 'p', 'I', 'A', 'f', 'i' },
  },
}

Use other repeat keys than ;/,

If you’d rather use keymaps other than ; and ,, for example n and N, you can disable Demicolon’s default repeat mappings and create your own. Here's an example:

Click here to see the code
require('demicolon').setup({
  keymaps = {
    repeat_motions = false, -- Don't create ; and , keymaps
  },
})

local map, nxo = vim.keymap.set, { 'n', 'x', 'o' }

-- Stateless: always forward/backward
map(nxo, 'n', require('demicolon.repeat_jump').forward)
map(nxo, 'N', require('demicolon.repeat_jump').backward)

-- Or, stateful (remember the original motion’s direction)
-- map(nxo, 'n', require('demicolon.repeat_jump').next)
-- map(nxo, 'N', require('demicolon.repeat_jump').prev)

Custom jumps

If you have custom motions that don't start with ]/[ that you want to make repetable (for example for flash.nvim) you can create your own custom repeatable jumps using repeatably_do() in demicolon.jump. repeatably_do() takes a funcion as its first argument and options to be passed to that function as its second argument. Make sure that the options include a boolean forward field to determine whether the action should be forward or backward.

eyeliner.nvim integration

eyeliner.nvim can highlight unique letters in words when you press t/T/f/F. Below is my recommended configuration for using eyeliner.nvim together with Demicolon.

NOTE: make sure to set keymaps.horizontal_motions = false in your demicolon setup if you want to use this config.

return {
  'jinh0/eyeliner.nvim',
  -- keys = { 't', 'f', 'T', 'F' }, -- Uncomment this to lazy load eyeliner.nvim
  config = function()
    require('eyeliner').setup({
      highlight_on_key = true,
      default_keymaps = false,
      dim = true, -- Optional
    })

    local function eyeliner_jump(key)
      local forward = vim.list_contains({ 't', 'f' }, key)
      return function()
        require('eyeliner').highlight({ forward = forward })
        return require('demicolon.jump').horizontal_jump(key)()
      end
    end

    local nxo = { 'n', 'x', 'o' }
    local opts = { expr = true }

    vim.keymap.set(nxo, 'f', eyeliner_jump('f'), opts)
    vim.keymap.set(nxo, 'F', eyeliner_jump('F'), opts)
    vim.keymap.set(nxo, 't', eyeliner_jump('t'), opts)
    vim.keymap.set(nxo, 'T', eyeliner_jump('T'), opts)
  end,
}

Full recommended config

Here is a full configuration, including nvim-treesitter-textobjects and eyeliner.nvim:

Click here to see the code
require('lazy').setup({
  {
    'nvim-treesitter/nvim-treesitter-textobjects',
    dependencies = 'nvim-treesitter/nvim-treesitter',
    build = ':TSUpdate',
    config = function()
      require('nvim-treesitter.configs').setup({
        ensure_installed = 'all',
        textobjects = {
          move = {
            enable = true,
            goto_next_start = {
              [']f'] = '@function.outer',
              [']a'] = '@argument.outer',
              [']m'] = '@method.outer',
              -- ...
            },
            goto_previous_start = {
              ['[f'] = '@function.outer',
              ['[a'] = '@argument.outer',
              ['[m'] = '@method.outer',
              -- ...
            },
          },
        },
      })
    end,
  },
  {
    'jinh0/eyeliner.nvim',
    keys = { 't', 'f', 'T', 'F' },
    config = function()
      require('eyeliner').setup({
        highlight_on_key = true,
        dim = true,
        default_keymaps = false,
      })

      local function eyeliner_jump(key)
        local forward = vim.list_contains({ 't', 'f' }, key)
        return function()
          require('eyeliner').highlight({ forward = forward })
          return require('demicolon.jump').horizontal_jump(key)()
        end
      end

      local map, nxo, opts = vim.keymap.set, { 'n', 'x', 'o' }, { expr = true }

      map(nxo, 'f', eyeliner_jump('f'), opts)
      map(nxo, 'F', eyeliner_jump('F'), opts)
      map(nxo, 't', eyeliner_jump('t'), opts)
      map(nxo, 'T', eyeliner_jump('T'), opts)
    end,
  },
  {
    'mawkler/demicolon.nvim',
    dependencies = {
      'nvim-treesitter/nvim-treesitter',
      'nvim-treesitter/nvim-treesitter-textobjects',
    },
    opts = {
      keymaps = {
        horizontal_motions = false,
        -- `f` is removed from this table because we have mapped it to
        -- `@function.outer` with nvim-treesitter-textobjects
        disabled_keys = { 'p', 'I', 'A', 'i' },
      },
    },
  },
})

Here's the full list of available treesitter textobjects.

Credit

nvim-treesitter-textobjects is used at the core of Demicolon's repeat logic. Credit to them for making an awesome plugin!

About

Overloaded ; and , keys in Neovim

Topics

Resources

Stars

132 stars

Watchers

2 watching

Forks

Used by

Contributors

Languages