Giter Club home page Giter Club logo

hydra.nvim's Introduction

Yuriy Artemyev

I am terminal geek:) My dotfiles containes 30000 lines.
Also, I am a Neovim fan and create Neovim plugins I want to use myself!

Projects:

And several others plugins:

Anurag's GitHub stats

hydra.nvim's People

Contributors

anuvyklack avatar escwxyz avatar frederick888 avatar lostl1ght avatar miversen33 avatar pk-kampanart avatar tornaxo7 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

hydra.nvim's Issues

Feature Request: Allow `foreign_keys = 'compose'`

A Brief Use Case

Let's suppose that the user wants to have a hydra for the <C-W> mappings, so they write the following configuration.

local hydra = require'hydra'
hydra {
  name = 'Window',
  body = '<C-W>',
  heads = {
    {'h', '<C-W>h'},
    {'j', '<C-W>j'},
    {'k', '<C-W>k'},
    {'l', '<C-W>l'},
  },
}

Now let's suppose the following.

  • The user pressed <C-W>l to move to the window in the right, triggering the l head, which means that the hydra state is on.
  • The user pressed q to close that window and nothing happened, since the q head doesn't exist.
  • The user pressed q again desperately trying to close it.
  • The q macro has started to be recorded.

The Proposal

I think that would be nice to have an option to set foreign_keys to compose, or another meaningful name, in order to evaluate the mappings resulted of the composition of the hydra's body with the non-head key pressed. Still using the previous situation as example, if the proposed option was enabled, the first time that the used pressed q would trigger the <C-W>q mapping.

This would be useful for the following cases.

  • When there's too much mappings derived from a body and the user doesn't want to write all those heads, but they still wants the valid derived mappings to behave similar as it were a head.
  • When a key mapping doesn't make much sense to be a head, since the user doesn't expect to keep pressing another heads afterwards.
    • E.g., when we press <C-W>= to balance the windows, we usually don't intend to perform another window mappings.

Hints window stays open after exit

Firstly, thanks very much for this plugin and sharing on Reddit. The git example is a life-changer. I've tried implementing a simple LSP example, but run into a snag when playing around with options.

It appears that the hints window will stay open if the 'on_exit' config function isn't defined for pink hydras. The below function displays the erroneous behavior:

local hint = [[
 _r_: rename      _R_: references        _d_: definition     _D_: declaration
            _[_: prev diagnostic         _]_: next diagnostic
            _p_: diagnostic loclist      _o_: line diagnostics
            _q_: exit
]]

Hydra({
  name = "LSP",
  hint = hint,
  config = {
    color = 'pink',
    invoke_on_body = true,
    -- Uncomment the below to make the hint pop-up correctly go away when 'q' is pressed
    -- on_exit = function() end,
    hint = {
        position = 'bottom',
        border = 'rounded'
    },
  },
  mode = {'n','x'},
  body = '<leader>r',
  heads = {
    { 'r', vim.lsp.buf.rename },
    { 'R', vim.lsp.buf.references },
    { 'd', vim.lsp.buf.definition },
    { 'D', vim.lsp.buf.declaration },
    { 'o', vim.lsp.diagnostic.open_float },
    { ']', vim.diagnostic.goto_next, { nowait = true }},
    { '[', vim.diagnostic.goto_prev, { nowait = true }},
    { 'p', vim.diagnostic.setloclist , { nowait = true }},
    { 'q',     nil , { exit = true, nowait = true }},
  }
})

<cmd>ls<CR> closes head and has no effect (shows no results)

Consider this simple mapping

local M = {}
-- keep buffers simple and fast
M.window_hdyra = Hydra({
   body = '<leader>b',
   heads = {
      -- TODO
      { 's', '<cmd>ls<CR>' }, -- show buffers
      { 'l', '<cmd>bn<CR>' }, -- next buffer
      { 'h', '<cmd>bp<CR>' }, -- previous buffer
      { 'a', '<cmd>ba<CR>' }, -- add current buffer
      { 'q', '<cmd>bd<CR>' }, -- delete current buffer
      { '<Esc>', nil,  { exit = true, desc = false } },
   },
})
return M

Pressing <leader>b and pressing s shows nothing, whereas I would expect the same output as :ls<CR> in the command prompt.
The other commands work as expected.

Probably a 3 letter prefix should be chosen, as buffer commands are not very common once harpoon + completer is set up.
For example, :b ab autocompletes buffers and :e ab paths for me.

Cannot use `_` as a head

It appears that a single _ character cannot be used as a head.

Example:

hydra({
    config = {
        exit = true,
    },
    name = "Change case",
    mode = "n",
    body = "gyc",
    heads = {
        {"_", function() require("textcase").operator("to_snake_case") end },
        {"-", function() require("textcase").operator("to_dash_case") end },

        { "<Esc>", nil, { exit = true } },
    },
})

... fails, as soon as gyc is typed, an error is shown:

E5108: Error executing lua: ...vim/site/pack/packer/start/hydra.nvim/lua/hydra/init.lua:648: attempt to index a nil value
stack traceback:
        ...vim/site/pack/packer/start/hydra.nvim/lua/hydra/init.lua:648: in function '_make_hint_buffer'
        ...vim/site/pack/packer/start/hydra.nvim/lua/hydra/init.lua:482: in function '_show_hint'
        ...vim/site/pack/packer/start/hydra.nvim/lua/hydra/init.lua:424: in function '_enter'
        ...vim/site/pack/packer/start/hydra.nvim/lua/hydra/init.lua:212: in function <...vim/site/pack/packer/start/hydra.nvim/lua/hydra/init.
lua:212>

Changing it to this:

hydra({
    config = {
        exit = true,
    },
    name = "Change case",
    mode = "n",
    body = "gyc",
    heads = {
        {"x", function() require("textcase").operator("to_snake_case") end },
        {"-", function() require("textcase").operator("to_dash_case") end },

        { "<Esc>", nil, { exit = true } },
    },
})

works (x and - can now be used as expected as heads).

Thanks for your hard work on this great plugin!

Bug: When reaching top of buffer amaranth hydra exits.

Upon reaching of the top of the buffer using u in this hydra it exits but the hint is still present. No error seems to happen.

Hydra({
     name = "Move",
     mode = "n", 
     body = "<Space>z",
     config = {
         timeout = false,
         color = 'amaranth',
     },
     heads = {
        -- Move Up and Down 
        { "u"    , "<C-u>"},
        { "d"    , "<C-d>", {desc = "^/v"} },
        { "l"    , "zh"},
        { "r"    , "zl", {desc = "</>"}},

        -- Move Faster
        { "U"    , "<C-b>"},
        { "D"    , "<C-f>", {desc = "page ^/v"}},
        { "R"    , "zL"},
        { "L"    , "zR", {desc = "half screen </>"}},

        -- Move view around cursor
        { "t"    , "zt"},
        { "b"    , "zb", {desc = "around line ^/v"}},
        { "m"    , "zz", {desc = "middle"}},
        { "l"    , "zs"},
        { "r"    , "ze", {desc = "</>"}},
    },
})

After latest update cant use :activate()

Error:
image
Setup:

local Hydra = require('hydra')
local dap = require'dap'

local hint = [[
 _n_: step over   _s_: Continue/Start   _b_: Breakpoint     _K_: Eval
 _i_: step into   _x_: Quit             ^ ^                 ^ ^
 _o_: step out    _X_: Stop             ^ ^
 _c_: to cursor   _C_: Close UI
 ^
 ^ ^              _q_: exit
]]

local dap_hydra = Hydra({
   hint = hint,
   config = {
      color = 'pink',
      invoke_on_body = true,
      hint = {
         position = 'bottom',
         border = 'rounded'
      },
   },
	 name = 'dap',
   mode = {'n','x'},
   body = '<leader>dh',
   heads = {
      { 'n', dap.step_over, { silent = true } },
      { 'i', dap.step_into, { silent = true } },
      { 'o', dap.step_out, { silent = true } },
      { 'c', dap.run_to_cursor, { silent = true } },
      { 's', dap.continue, { silent = true } },
      { 'x', ":lua require'dap'.disconnect({ terminateDebuggee = false })<CR>", {exit=true, silent = true } },
      { 'X', dap.close, { silent = true } },
      { 'C', ":lua require('dapui').close()<cr>:DapVirtualTextForceRefresh<CR>", { silent = true } },
      { 'b', dap.toggle_breakpoint, { silent = true } },
			{ 'K', ":lua require('dap.ui.widgets').hover()<CR>", { silent = true } },
			-- { 'K', ":lua require('dapui').eval(nil, {enter=true})<CR>", { silent = true } },
      -- { 'B', function() gitsigns.blame_line{ full = true } end },
      { 'q', nil, { exit = true, nowait = true } },
   }
})
Hydra.spawn = function(head)
	if head == 'dap-hydra' then
		dap_hydra:activate()
	end
end     

And then finally I call it from which-key keymapping:
require'hydra'.spawn('dap-hydra')

Commands that finish in insert mode will input `<Plug>(Hydra1_wait)` and leave invalid floating window open

Commands that finish in insert mode will input <Plug>(Hydra1_wait) and there will be a floating window left open, unable to interact with it afterwards. For example it happens for :startinsert and telescope's pickers.

require('hydra') {
  mode = 'n',
  body = '<Leader>',
  hint = 'Commands that end in insert mode:',
  config = {
    invoke_on_body = true,
  },
  heads = {
    {
      'i',
      function()
        vim.api.nvim_command('startinsert')
      end
    },
    {
      't',
      require('telescope.builtin').find_files
    },
  },
}

System information

NVIM v0.8.0-dev-1025-gfb39bba5a
Windows 10

Error after switch session by `nvim-session-manager`

After I switch session by nvim-session-manager and I want to use hydra to manage window

It shows error like
image

E5108: Error executing lua: ...k/packer/start/hydra.nvim/lua/hydra/hint/auto_window.lua:101: Invalid buffer id: 3
stack traceback:
        [C]: in function 'nvim_open_win'
        ...k/packer/start/hydra.nvim/lua/hydra/hint/auto_window.lua:101: in function 'show'
        ...vim/site/pack/packer/start/hydra.nvim/lua/hydra/init.lua:502: in function '_enter'
        ...vim/site/pack/packer/start/hydra.nvim/lua/hydra/init.lua:259: in function <...vim/site/pack/packer/start/hydra.nvim/lua/hydra/init.lua:258>
Press ENTER or type command to continue

How to use Hydra without define keymap in `head`

I'm migrating to hydra from which-key. With the later, I just need define key name and description inside which-key module without having to defining keybinding inside. Is it possible with hydra. Put nil in head's rhs doesn't work because keymap is not activated :(

Does not handle new cmdheight=0 in NeoVim HEAD / 0.8+

NeoVim HEAD / 0.8+ contains a new feature where cmdheight can be set to 0 to remove the command line. This seems to confuse hydra; the pop up at the bottom with the hints is offset by an additional line and shows a duplicate of one of the buffers, in a window that occupies only one line.

Not sure how urgent you consider a fix here to be - to be fair this feature in NeoVim is very new and bugfixes are still coming to NeoVim itself. But wanted to put it on your radar.

Thanks for your hard work on this great plugin!

Hint bar stays at old position after Neovim resizes

Steps to reproduce

Hydra version: b763432

  1. Trigger Hydra
  2. Make Neovim taller (I'm using tmux so I just made the tmux pane taller)
  3. Trigger Hydra again

Expected outcome

Hydra hint bar is right above status bar

Actual outcome

Hydra hint bar stays at its old position, which is in the middle of my current buffer (I temporarily bumped up timeout to capture the screenshot)

image

Configuration:

local Hydra = require('hydra')
local splits = require('smart-splits')

Hydra({
  name = "Split movements and resizing",
  mode = 'n',
  body = '<C-w>',
  config = {
    timeout = 250,
  },
  heads = {
    { 'h', [[<cmd>try | wincmd h | catch /^Vim\%((\a\+)\)\=:E11:/ | close | endtry<CR>]] },
    { 'j', [[<cmd>try | wincmd j | catch /^Vim\%((\a\+)\)\=:E11:/ | close | endtry<CR>]] },
    { 'k', [[<cmd>try | wincmd k | catch /^Vim\%((\a\+)\)\=:E11:/ | close | endtry<CR>]] },
    { 'l', [[<cmd>try | wincmd l | catch /^Vim\%((\a\+)\)\=:E11:/ | close | endtry<CR>]] },
    { 'H', splits.resize_left },
    { 'J', splits.resize_down },
    { 'K', splits.resize_up },
    { 'L', splits.resize_right },
  },
})

Bug: { mode = } doesn't work on pink hydras

Hydra

hint = [[
^^^^    Draw
^^^^-------------
Arrows: _<C-h>_ _<C-j>_ _<C-k>_ _<C-l>_
Box (select box with visual block first): _<C-f>_
^ ^				_<Esc>_: exit
]]

Hydra({
	name = 'Draw',
	hint = hint,
	config = {
		color = 'pink',
		invoke_on_body = true,
		hint = {
			position = 'bottom',
			border = 'rounded'
		},
		on_enter = function()
			vim.cmd[[setlocal ve=all]]
		end,
		on_exit = function()
			-- vim.opt.virtualedit = false
			vim.cmd[[setlocal ve=]]
		end
	},
	mode = {'n'},
	body = '<leader>draw',
	heads = {
		{ '<C-h>', '<C-v>h:VBox<CR>' },
		{ '<C-j>', '<C-v>j:VBox<CR>' },
		{ '<C-k>', '<C-v>k:VBox<CR>' },
		{ '<C-l>', '<C-v>l:VBox<CR>' },
		{ '<C-f>', ':VBox<CR>', { mode = 'v' }},
		{ '<Esc>', nil, { exit = true, nowait = true } },
	}
})

Error message

E5108: Error executing lua: vim/keymap.lua:0: invalid key: mode
stack traceback:
        [C]: in function 'nvim_buf_set_keymap'
        vim/keymap.lua: in function 'set'
        ...packer/start/keymap-layer.nvim/lua/keymap-layer/init.lua:492: in function '_setup_layer_keymaps'
        ...packer/start/keymap-layer.nvim/lua/keymap-layer/init.lua:320: in function 'enter'
        ...packer/start/keymap-layer.nvim/lua/keymap-layer/init.lua:181: in function <...packer/start/keymap-layer.nvim/lua/keymap-layer/init.lua:181>

Empty hints after deleting all buffers.

I have a Buffer hydra for managing buffers, with the following head that lets me close all buffers except the one I’m focused on:

{'o', ':%bd|e#|bd#<cr>', { exit = true }},

After running this head, all Hydra hints become empty pane’s without text. I’m guessing the Hydra hint buffer is getting caught in the list, but hydra doesn’t handle it gracefully. Other plugins seem to be able to recreate their buffers when I re-open their various panes/windows so I think this is a hydra specific improvement needed.

[Bug/Feature?] Executing commands inside a hydra does not trigger autocommands

When using hydras to manage buffers or handle side scrolling

  Hydra({
    name = 'Buffer management',
    mode = 'n',
    body = '<leader>b',
    color = 'teal',
    config = {
      hint = { border = border },
      invoke_on_body = true,
      on_enter = function() vim.cmd('BeaconOff') end,
      on_exit = function() vim.cmd('BeaconOn') end,
    },
    heads = {
      { 'l', '<Cmd>BufferLineCycleNext<CR>', { desc = 'Next buffer' } },
      { 'h', '<Cmd>BufferLineCyclePrev<CR>', { desc = 'Prev buffer' } },
      { 'p', '<Cmd>BufferLineTogglePin<CR>', { desc = 'Pin buffer' } },
      { 'c', '<Cmd>BufferLinePick<CR>', { desc = 'Pin buffer' } },
      { 'd', '<Cmd>Bwipeout<CR>', { desc = 'delete buffer' } },
      { 'D', '<Cmd>BufferLinePickClose<CR>', { desc = 'Pick buffer to close', exit = true } },
      { '<Esc>', nil, { exit = true, desc = 'Quit' } },
    },
  })

  Hydra({
    name = 'Side scroll',
    mode = 'n',
    body = 'z',
    heads = {
      { 'h', '5zh' },
      { 'l', '5zl', { desc = '←/→' } },
      { 'H', 'zH' },
      { 'L', 'zL', { desc = 'half screen ←/→' } },
    },
  })

When using the side scroll hydra for example, using other plugins that rely on autocommands such as indent-blankline are not updated till the hydra is exited. Similarly, when deleting buffers in the first hydra it seems git signs is unable to update till the hydra is exited causing errors.

I hope this explains the issue I'm describing and there is an obvious cause. Please let me know if this is more specific to my config than I'm assuming, I've so far assumed it was a conscious choice to disable autocommands, and I'm wondering if it's possible to provide an option to enable autocommands.

Example of execution on entry

Hello, This is a great plugin. I have a hack for invoke_on_body that may work better for navigation type Hydras. I have a lot of buffers that I often toggle between. I previously used vim-submode to enable this. In vim-submode, the entry into any submode will first trigger the action and wait for further keystrokes. In hydra you enter a mode and then you have to type another key to get an action. If you only want to move to the left buffer for example this would require 1 more keystroke than vim-submode.

This hack for navigating between buffers would eliminate the need for the extra keystroke:

local buf_config = {
 config = {
  invoke_on_body = true,
  on_enter = function()
    -- Each hydra must be named by it's hydra head action name
    vim.api.nvim_input(statusline.get_name())
  end,
}}

-- Buffer navigation maps
local buf_head = {
  { "h", "<C-w>h", { desc = "←" } },
  { "l", "<C-w>l", { desc = "→" } },
  { "j", "<C-w>j", { desc = "↑" } },
  { "k", "<C-w>k", { desc = "↓" } },

}

for _,key in ipairs({'l', 'k', 'j', 'h'} ) do
  Hydra(
  {
    name = key,
    mode = { 'n', 't'},
    config = buf_config,
    body = "<leader>" .. key,
    heads = buf_head,
  })
end

With the above, h would immediately move to the left buffer and wait for further inputs.

Thanks,

-mp

Can't use <Plug> for mapping

How to use <Plug> to trigger a command?
Example :

local hint = [[_p_: Pick buffer]]
local hydra = require'hydra'
     hydra.setup{
     hint = hint,
     heads = {
           {'p','<Plug>(cokeline-pick-select)'},
     }.
}

But it seems didn't work
E492: Not an editor command: (cokeline-pick-select)

How to call user defined hydra

Awesome plugin (I was waiting for this for long time - it is the only thing that I wish nvim had from emcas)
What I proper way to call my custom hydra?
In my case I defined it under:
<leader>dh
But calling :normal <leader>dh wont work.
Maybe we could get additional option for Hydra({ reference = xyz })
if we call - require'hydra'.xyz() from cmd or lua this would open user defined hydra?
or something similar way to call user defined hydras would be cool.

Bug: The hydra does not pickup the body correctly.

I tried using <Leader>s for my split management hydra. But it was not recognized.
Instead it would register the space and s. As i use space as my leader i remaped it to nop. So it would trigger a substitution and put me in insert mode.

Temp fix: hard code my leader which is space. so put <Space>s as the body.

Lualine Mode not working

Im trying to customize my Lualine A section with Hydra's name, but using require('hydra.statusline').get_name with conditioning using require('hydra.statusline').is_active shows nothing .

local hydra = require("hydra.statusline")

require'lualine'.setup {
  options = {
    icons_enabled = true,
    theme = 'auto',
    -- component_separators = {'', ''},
    -- section_separators = {'', ''},
    disabled_filetypes = {
      statusline = {},
      winbar = {},
    },
    ignore_focus = {},
    always_divide_middle = true,
    globalstatus = true,
    refresh ={
      statusline = 1000,
      tabline = 1000,
      winbar = 1000,
    }
  },
  sections = {
    lualine_a = {'mode',{hydra.get_name, cond = hydra.is_active}},
    -- lualine_a = {hydra_status.get_name()},
    lualine_b = {'branch'},
    lualine_c = {'filename', {gps.get_location, cond = gps.is_available}},
    lualine_x = {'filetype', 'fileformat', 'encoding'},
    lualine_y = {'progress'},
    lualine_z = {'location'}
  },
  inactive_sections = {
    lualine_a = {},
    lualine_b = {},
    lualine_c = {'filename'},
    lualine_x = {'location'},
    lualine_y = {},
    lualine_z = {}
  },
  tabline = {},
  extensions = {}
}

`cmdline` hint reduces `cmdheight` to 1 temporarily

It's me again :P

I have cmdheight=2, and after the recent change that updated default hint type to cmdline, I noticed that it reduces my cmdheight to one when the hint is shown:

image

Btw I actually later posted to neovim/neovim#19478 and it seems that we'd better avoid caching cmdheight since e.g. nvim_win_set_height(), Ctrl-W_ and etc can also override cmdheight and currently it's not possible to get an event to track these changes.

how to set no wrap

image

Seems the wrap makes my last line gone. How to disable wrap in the floating window?

Hydra Telescope Heads

Hi,

I have a Hydra mode for my telescope mappings which is as follows:

local Hydra = require("hydra")

local function cmd(command)
  return table.concat({ "<Cmd>", command, "<CR>" })
end

local hint = [[
 _f_: files          _p_: projects
 _t_: live grep      _s_: grep string
 _H_: header         _S_: symbols
 _R_: register       _P_: plugins
 _h_: vim help       _c_: execute command
 _k_: keymaps        _;_: commands history
 _O_: options        _?_: search history
 _/_: search in file _m_: make
 _r_: recently opened files

 ^
 _<Enter>_: Telescope   _q_: Exit
]]

Hydra({
  name = "Telescope",
  hint = hint,
  config = {
    invoke_on_body = true,
    hint = {
      position = "middle",
      border = "rounded",
    },
  },
  mode = "n",
  body = "<Leader>s",
  heads = {
    { "c", cmd("Telescope commands"), { desc = "execute command" } },
    { "f", cmd("Telescope find_files") },
    { "t", cmd("Telescope live_grep") },
    { "h", cmd("Telescope help_tags"), { desc = "vim help" } },
    { "H", cmd("Telescope heading") },
    { "k", cmd("Telescope keymaps") },
    { "O", cmd("Telescope vim_options") },
    { "m", cmd("Telescope make") },
    { "p", cmd("Telescope projects"), { desc = "projects" } },
    { "P", cmd("Telescope packer") },
    { "r", cmd("Telescope oldfiles"), { desc = "recently opened files" } },
    { "R", cmd("Telescope registers") },
    { "s", cmd("Telescope grep_string"), { desc = "Text under cursor" } },
    { "S", cmd("Telescope symbols") },
    { "/", cmd("Telescope current_buffer_fuzzy_find"), { desc = "search in file" } },
    { "?", cmd("Telescope search_history"), { desc = "search history" } },
    { ";", cmd("Telescope command_history"), { desc = "command-line history" } },
    { "<Enter>", cmd("Telescope"), { exit = true, desc = "list all pickers" } },
    { "q", nil, { exit = true, nowait = true } },
  },
})

Since a couple of days whenever I call Telescope via a head Telescope is always started in normal mode despite the following config for telescope:

telescope.setup({
    defaults = {
      initial_mode = "insert",
    }
})    

When starting Telescope via :Telescope live_grep it starts in insert mode as expected.

Thanks

Hydra to draw boxes and arrows with `venn.nvim`

Draw boxes with venn.nvim.

local hint = [[
^^^^    Draw
^^^^-------------
Arrows: _<C-h>_ _<C-j>_ _<C-k>_ _<C-l>_
Box (select box with visual block first): _<C-f>_
^ ^				_<Esc>_: exit
]]

Hydra({
	name = 'Draw',
	hint = hint,
	config = {
		color = 'pink',
		invoke_on_body = true,
		hint = {
			position = 'bottom',
			border = 'rounded'
		},
		on_enter = function()
			vim.opt_local.virtualedit = 'all'
		end,
		on_exit = function()
			vim.opt_local.virtualedit = ''
		end
	},
	mode = {'n'},
	body = '<leader>draw',
	heads = {
		{ '<C-h>', '<C-v>h:VBox<CR>' },
		{ '<C-j>', '<C-v>j:VBox<CR>' },
		{ '<C-k>', '<C-v>k:VBox<CR>' },
		{ '<C-l>', '<C-v>l:VBox<CR>' },
		{ '<C-f>', ':VBox<CR>', { mode = 'v' }},
		{ '<Esc>', nil, { exit = true, nowait = true } },
	}
})

cursor jumps out of window on window movements, windowing wiki page

Consider

local Hydra = require('hydra')
M.window_hdyra = Hydra({
   body = '<C-w>',
   heads = {
      { 'h', '<C-w>h' },
      { 'j', '<C-w>j' },
      { 'k', '<C-w>k' },
      { 'l', '<C-w>l' },
      { '<Esc>', nil,  { exit = true, desc = false } },
   },
})

And having 2 windows positioned side by side.
From the left one starting, pressing C-w l (activates hydra), l
moves the cursor to the commandline window,

Also, I dont understand why the example in the wiki uses { 'k', pcmd('wincmd k', 'E11', 'close') },.

Personally I would favor having a simpler example to get people started with hydra: only 1. movements hjkl, 2. basic resizing (<,>,+,-,=), 3. splits (s,v), 4. simple swap C-w shift, 5. closing and only window (c, o), 6. exiting

Personally I think buffers are more efficiently managed in combination with harpoon + :b and autocompleter (I use nvim-comp).
Combining both seems like overkill to me, at least for starters.

on_enter/on_exit throw error for non-pink

I'm working on a few hydras to handle different editor states and I ran into an issue using the on_enter and on_exit config options.

E5108: Error executing lua: ...hydra.nvim/lua/hydra/init.lua:421: Expected lua string
stack traceback:
        [C]: in function '__newindex'
        ...hydra.nvim/lua/hydra/init.lua:421: in function '_exit'
        ...hydra.nvim/lua/hydra/init.lua:209: in function <...hydra.nvim/lua/hydra/init.lua:209>

After doing some testing, I found that on_enter and on_exit always throw this error using any color but pink. I checked the docs and didn't see mention of this being limited to pink.

Here's a test I came up with:

hydra({
  name = "OnTest",
  config = {
    color = 'amaranth',

    invoke_on_body = true,
    on_enter = function()
      vim.bo.modifiable = false
    end,
    on_exit = function()
      vim.cmd 'echo'
    end
  },
  mode = 'n',
  body = '<leader>t',
  heads = {
    {'r', nil, { exit = true }}
  }
})

[Bug] Hint window disapear while changing tab.

I have extended the comunity hydra to support tabs. But the hint window disapears. It is a minor inconvinience but can be a bit frustrating not knowing if i'm still in the hydra. Here is a gif demonstrating the bug:
hydradisapear

Invalid fold jump will exit hydra leaving hint window open

I really like the idea of the plugin as I've configured which-key.nvim before for similar effect. Sadly (but maybe luckily?) I've quickly encountered this minor problem which leaves floating hint window open while hydra is no longer in effect.

Steps to reproduce:

  1. Setup hydra like this:
require('hydra') {
  mode = 'n',
  body = 'z',
  hint = 'Fold',
  heads = {
    { 'j', 'zj' },
    { 'k', 'zk' },
  },
}
  1. Open some file with indented text.
  2. Move around indents using starting from z then j or k multiple times.
  3. Attempt invalid move, for example try to move to previous indent when already at the first.
  4. Notice keys no longer work as configured by calling hydra.
  5. Notice floating hint window is still open.

System information

NVIM v0.8.0-dev-1025-gfb39bba5a
Windows 10

LSP Hydra Example

I've never used emacs before, but was super intrigued when I came across this plugin. Right now I'm using AstroVim and navigating between LSP diagnostics and applying fixes to each one means I have to do ]d<leader>la to go to the next diagnostic, then open the telescope window to pick a code action for each diagnostic. I whipped this up and added some symbol navigation using Aerial. My hope is that others find it just as useful as I did :)

local Hydra = require('hydra')
local aerial = require('aerial')

local hint = [[
 _d_: next diagnostic   _D_: previous diagnostic  _a_: code action
 _n_: next symbol       _N_: previous symbol      _s_: toggle symbol tree
 ^                      _q_: exit
]]

Hydra({
  hint = hint,
  name = 'LSP Hydra',
  config = {
    invoke_on_body = true,
    color = 'pink',
    hint = {
      position = 'bottom',
      border = 'rounded'
    },
    on_enter = function ()
        aerial.open()
    end,
    on_exit = function ()
        aerial.close()
    end
  },
  mode = {'n'},
  body = '<leader>L',
  heads = {
    {
      'd',
      function ()
        vim.diagnostic.goto_next()
      end,
    },
    {
      'D',
      function ()
        vim.diagnostic.goto_prev()
      end,
    },
    {
      'n',
      function ()
        aerial.next()
      end,
    },
    {
      'N',
      function ()
        aerial.next(-1)
      end,
    },
    {
      's',
      function ()
        if aerial.is_open() then
          aerial.close()
        else
          aerial.open()
        end
      end,
    },
    {
      'a',
      function ()
        vim.lsp.buf.code_action()
        return '<Ignore>'
      end,
    },
    {
      'q',
      nil,
      { exit = true, nowait = true}
    }
  }
})

image

bug: random text is printed in input field when head calls `vim.ui.select()`

If a hydra is defined like so, invoking a function that calls vim.ui.select() in one of its heads:

local take_input = function()
	vim.ui.select({ "a", "b", "c" }, {
		prompt = "Input: ",
		on_select = function(selected)
			print(selected)
		end,
	})
end
hydra({
	name = "input test",
	mode = "n",
	body = "t",
	heads = {
		{ "s", take_input, { desc = "Take input" } },
	},
})

Upon invoking the head, text from hydra is printed in the input field of the selection

image

Problems with Sample Git Hydra

Hello,

I am using the sample git hydra and found it to be really annoying, that the main buffer is not redrawn whenever I execute a head of the hydra.
Suppose I am editing a file and have 3 different hunks. Now when I'm editing the line with hunk#1 and invoke the hydra's body and then execute the hydra's head 's' e.g. 'stage hunk', I would expect the hunk to be staged immediately. However, what happens is that the stage command is "stored" and only executed, when I exit out of the hydra's body, e.g. press 'ESC'.
Same goes for jumping between hunks, undoing hunks, etc.

recording.mp4

I am not sure if this is on this plugins end or on gitsigns, maybe someone can help me?

Best Regards

example: window resize without dependencies

Here is my simple one for window resizing, which should hopefully attract more users.
I find resizing manually always annoying, because neovim does not show size markers (horizontal and vertical lines of a drawing program) and neither percentag size [due to shell limitations and not using sixels etc].

M.window_hdyra = Hydra({
   body = '<C-w>',
   heads = {
      -- The following depend highly on your workflow
      -- { 'h', '<C-w>h' },
      -- { 'j', '<C-w>j' },
      -- { 'k', '<C-w>k' },
      -- { 'l', '<C-w>l' },
      -- other use cases: scrolling (C-d,C-u,C-e,C-y), copy+paste
      { 's', '<C-w>s' },
      { 'v', '<C-w>v' },
      { '+', '<C-w>+' },
      { '-', '<C-w>-' },
      { '>', '<C-w>>' },
      { '<', '<C-w><' },
      { '=', '<C-w>=' },
      { 'q', '<cmd>close<CR>' },
      { 'o', '<cmd>only<CR>' },
      { '_', '<C-w>_' },
      { '|', '<C-w>|' },
      { '<Esc>', nil,  { exit = true, desc = false } },
   },
})

Feature - Enable hydra only for particular buff type

The issue I have now: DAP spawns multiple windows (watches, repl, etc), next to my code, thus when enabling DAP_hydra - I use buffer option to only attach hydra hotkeys to my active buffer (source code). This way I can edit other dap spawned windows no problem (without conflicts with hydra).
Problem is - if dap steps into another python file, hydra wont work in that file.
So I wish we could attach hotkeys based on file type eg. something like :
hydra_ftype = active_buff.file_type
This way hydra would not affect Dap repl, dap watches, but it will work when stepping source code around files.

Simple Hydra to Move to / Rezize windows

First of all, thank you so much for this stellar plugin. This plugin means so much to me. Thank you again for making this 💯
When I try it out, then I think to myself "Is it possible for a Hydra to activate another Hydra". And it's there! Hydra:activate()

Here I have my simple Hydra to move / resize windows, without interfering with <C-w>s & <C-w>v.
I want to make a quick video about this. Do you have any suggestions what should I include / emphasize for the viewers? Thank you :)

local Hydra = require("hydra")

Hydra({
	name = "Change / Resize Window",
	mode = { "n" },
	body = "<C-w>",
	config = {
		color = "pink",
	},
	heads = {
		-- move between windows
		{ "<C-h>", "<C-w>h" },
		{ "<C-j>", "<C-w>j" },
		{ "<C-k>", "<C-w>k" },
		{ "<C-l>", "<C-w>l" },

		-- resizing window
		{ "H", "<C-w>3<" },
		{ "L", "<C-w>3>" },
		{ "K", "<C-w>2+" },
		{ "J", "<C-w>2-" },

		-- equalize window sizes
		{ "e", "<C-w>=" },

		-- close active window
		{ "Q", ":q<cr>" },
		{ "<C-q>", ":q<cr>" },

		-- exit this Hydra
		{ "q", nil, { exit = true, nowait = true } },
		{ ";", nil, { exit = true, nowait = true } },
		{ "<Esc>", nil, { exit = true, nowait = true } },
	},
})

Meta-key as body

I tried to use <M-d> as my body for debug. But seems Hydra didn't recognize Meta.

My config is in the follow:

local Hydra = require "hydra"

local hint = [[
 Debug
 t: Debug Test
 b: Toggle breakpoint
 c: Continue
 s: Step over
 S: Step into
 q, <ESC>: Terminate and Quit
]]

Hydra {
  name = "Draw Diagram",
  hint = hint,
  config = {
    color = "pink",
    invoke_on_body = true,
    hint = {
      border = "rounded",
    },
    on_enter = function() vim.o.virtualedit = "all" end,
  },
  mode = "n",
  body = "<M-d>",
  heads = {
    { "t", "<CMD>GoDebug -t<CR>" },
    { "b", "<CMD>lua require'dap'.toggle_breakpoint()<CR>" },
    { "c", "<cmd>lua require'dap'.continue()<CR>" },
    { "s", "<cmd>lua require'dap'.step_over()<CR>" },
    { "S", "<cmd>lua require'dap'.step_into()<CR>" },
    { "q", "<cmd>lua require'dap'.terminate() <CR>", { exit = true } },
    { "<Esc>", "<cmd>lua require'dap'.terminate()<CR>", { exit = true } },
  },
}

[Feature Request] New hydra that can be entered without waiting for a head.

Here is the feature:
I have an hydra but i want to enter it without having to press any head.

Motivation:
Sometimes I want to enter an hydra but mess up the first key of a head, then the hydra is not entered and neovim interprets my following key presses messing everything up.

If this is possible and fits in the plugin view how should it be implemented ?
I thought that adding a boolean field in the config table would be a reasonable option.

Disabling indent-blankline.nvim in hydra windows

I am currently using a plugin called indent-blankline.nvim that draws guides for indentation with the exception of some filetypes and buffers that you can manually specify within its config. I'm trying to add hydra buffers to this list, but I can't seem to find out what the buffer name is for hydra floating windows, so that I can disable it.
2022-08-07_23-16

Error when switch buffer

When buffer switch got following error:
It may be caused by hydra floating windows not exited properly. The hydra timer is still running but the hydra floating window is destroyed.

E5555: API call: Buffer is not 'modifiable'                                                                                                                                           
Error detected while processing function <lambda>2371[1]..<SNR>97_render_lines_from_timer[7]..<SNR>97_render_lines[86]..<SNR>101_delete_all_lines:                                    
line    1:                                                                                                                                                                            
E5555: API call: Buffer is not 'modifiable'                                                                                                                                           
Error detected while processing function <lambda>2457[1]..<SNR>97_render_lines_from_timer[7]..<SNR>97_render_lines[86]..<SNR>101_delete_all_lines:    

Hydra wont unbind keys on quit in dap buffers

I'm using dap hydra like its shown in this post - #3 (comment)
Hydra is remapping i key to step-into, works ok (blocks insert mode as expected).
After leaving hydra - insert works ok in normal buffers. But using 'i' key in dap watches is still behaving as 'step into' :
image
Both of above mappings are not visible in normal editable buffers (python code buffers, in my case). But they are preset in all dap-ui buffers (including watches - this makes it impossible to add watch expr) - https://github.com/rcarriga/nvim-dap-ui

[Feature] reserve highlights of Hydra after changing colorscheme

Problem:

Hydra's highlights will be cleared after changing the colorscheme, which happens when the colorscheme, for example dracula and monokai, use hi clear to clear all highlights.
图片

Hydra define its highlight stuffs (HydraBlue, HydraAmaranth, HydraTeal, HydraPink, HydraHint) in plugin folder so the highlights will be loaded only once.
How about using autocmd Colorscheme to reserve these highlights? I am afraid of this way may override user defined Hydra highlight though the default color is great.

Bug: { exit = true } doesn't work correctly for pink Hydras

I have this Pink Hydra example:

Hydra({
	name = "Change Window",
	mode = { "n" },
	body = "<C-w>",
	config = {
		color = "pink",
	},
	heads = {
		{ "<C-h>", "<C-w>h" },
		{ "<C-j>", "<C-w>j" },
		{ "<C-k>", "<C-w>k" },
		{ "<C-l>", "<C-w>l" },

		{
			"p",
			function()
				print("hello man")
			end,
			{ exit = true },
		},

		{ "q", nil, { exit = true, nowait = true } },
	},
})

Expected behavior when pressing <C-w>p: hello man gets printed.
Actual behavior: nothing happens.

If Hydra gets entered with other heads, p works correctly.
If Hydra head is p, it does nothing or some other weird behaviors.

Latest hydra update - complain about config=nil

I use default example:

Hydra({
   name = 'Side scroll',
   mode = 'n',
   body = 'z',
   heads = {
      { 'h', '5zh' },
      { 'l', '5zl', { desc = '←/→' } },
      { 'H', 'zH' },
      { 'L', 'zL', { desc = 'half screen ←/→' } },
   }
})

And since today update hydra is giving config == nil error. Adding config = {} above fixes the issue, but still I wanted to report this.

Hydra + which-key ?

I've been using which-key for some time now, and I was wondering how can I add Hydra to my stack without conflicting with it?

  1. If I don't hide the trigger on which-key, which-key takes precedence, and until I press one of the mapped keys, I don't see the Hydra menu.
  2. If I hide the trigger on which-key, it also hides the Hydra menu

Any ideas on how to make it work?

I know it seems more like a which-key issue than Hydra, but like me, I'm pretty sure a lot of users also use it. So it would be nice if they could work side-by-side.

Thanks!

having problem when body, heads use different modes

reproduce code: (nvim 0.7.2)

local Hydra = require("hydra")

local setup = function()
  Hydra({
    name = "object select",
    config = {
      color = "pink",
      buffer = true,
      invoke_on_body = true,
      on_enter = function()
        treesitter_incsel.init_selection()
      end,
    },
    mode = { "n" },
    body = "gs",
    heads = {
      { "a", [[:lua require'nvim-treesitter.incremental_selection'.node_incremental()<cr>]], { private = true, mode = "v" } },
      { "d", [[:lua require'nvim-treesitter.incremental_selection'.node_decremental()<cr>]], { private = true, mode = "v" } },
    },
  })
end

setup()

in this usecase, i want to bind nmap gs body trigger .init_selection, after that function, nvim will enter visual mode, so the two heads need to be pink and vmap.

did i do something wong here?

oh, the errors:

Error detected while processing /home/haoliang/.config/nvim/init.vim:
line  425:
E5108: Error executing lua ....config/nvim/plugged/hydra.nvim/lua/hydra/layer/init.lua:233: attempt to index a nil value
stack traceback:
        ....config/nvim/plugged/hydra.nvim/lua/hydra/layer/init.lua:233: in function '_constructor'
        ...iang/.config/nvim/plugged/hydra.nvim/lua/hydra/class.lua:14: in function 'Layer'
        ...liang/.config/nvim/plugged/hydra.nvim/lua/hydra/init.lua:473: in function '_setup_pink_hydra'
        ...liang/.config/nvim/plugged/hydra.nvim/lua/hydra/init.lua:249: in function '_constructor'
        ...iang/.config/nvim/plugged/hydra.nvim/lua/hydra/class.lua:14: in function 'Hydra'
        /home/haoliang/.config/nvim/lua/locals/plugins/hydra.lua:7: in function 'setup'
        /home/haoliang/.config/nvim/lua/locals/plugins/init.lua:19: in function 'setup'
        [string ":lua"]:1: in main chunk

Request: support for margins for the hint floating window

Thanks for this wonderful plugin.

It would be nice if there is an option to set the margin(or offset).
My use case: I have a scroll bar on the right(from satellite.nvim plugin) and if I set hint window position to middle-right, hint window is covering this. By setting the margin value, the hint window can be moved little to the left to allow the scrollbar to be visible.
image

silent options doesn't work anymore

After update I've discovered that silent doesn't work in heads and I see command appearing in the command like and from time to time lualine disappears from screen.

        heads = {
            { 'h' , ':BufferLineCyclePrev<cr>', { silent = true, desc = 'Prev buffer'} },
            { 'l' , ':BufferLineCycleNext<cr>', { silent = true, desc = 'Next buffer' } },
            { 'q', nil, { exit = true, nowait = true } },
        }

Feature: toggle hydra hint window

Example use case:

  1. Press hydra body or body + head, now hint window is visible
  2. Execute cmd to toggle hydra window, hydra is still active but the window is hidden
  3. Execute cmd to make hydra window visible again

For example, it would be nice to use with dap or git

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.