Search code examples
vimvim-pluginneovim

How to change vim command execution priority?


I made :wincmd h<CR> shortcut to <leader>h, and mapleader is <Space> to me

but When I do <leader>h, I feel quite long delay to execute this action,

so I searched commands about <leader>h by :map <leader>h and

I found that I have serveral commands start with <Space>h like below

n  <Space>hp    @<Plug>(GitGutterPreviewHunk)
n  <Space>hu    @<Plug>(GitGutterUndoHunk)
n  <Space>hs    @<Plug>(GitGutterStageHunk)
x  <Space>hs    @<Plug>(GitGutterStageHunk)
n  <Space>h    * :wincmd h<CR>

enter image description here

I think because of map priority, <Space>h is performed last,

I want to change execution priority <Space>h to first place.

because <Space>h is the best easy way shortcut to me for :windcmd h.

How do I change priority order of map?

==== edit ====

I think vim wait for next character from h, then How can I eliminate delay for <Space>h?

  1. <nowait> is not working (I don't know why)
  2. remapping for plugin is not working

==== edit2 ==== (it still not work thought adopt first answer)

init.vim

""Source file
source $HOME/.config/nvim/ascii_art.vim

""Plugin-install
call plug#begin('~/.vim/plugged')
Plug 'neoclide/coc.nvim', {'branch': 'release'}
Plug 'tweekmonster/gofmt.vim'
Plug 'tpope/vim-fugitive'
Plug 'vim-utils/vim-man'
Plug 'mbbill/undotree'
Plug 'sheerun/vim-polyglot'
Plug 'junegunn/fzf', { 'do': { -> fzf#install() } }
Plug 'junegunn/fzf.vim'
Plug 'stsewd/fzf-checkout.vim'
Plug 'vuciv/vim-bujo'
Plug 'tpope/vim-dispatch'
Plug 'theprimeagen/vim-be-good', {'do': './install.sh'}
Plug 'vim-airline/vim-airline'
Plug 'gruvbox-community/gruvbox'
Plug 'vifm/vifm.vim'
"Theme
Plug 'colepeters/spacemacs-theme.vim'
Plug 'sainnhe/gruvbox-material'
Plug 'phanviet/vim-monokai-pro'
Plug 'flazz/vim-colorschemes'
Plug 'chriskempson/base16-vim'
" fuzzy find files
Plug 'ctrlpvim/ctrlp.vim' 
" git gutter
Plug 'airblade/vim-gitgutter'
Plug 'scrooloose/nerdcommenter'
"NerdTree plugins (NerdTree makes vim too slow, so now it unstalled)
"Plug 'scrooloose/nerdtree'
"Plug 'Xuyuanp/nerdtree-git-plugin'
"Plug 'tiagofumo/vim-nerdtree-syntax-highlight'
"Plug 'ryanoasis/vim-devicons'
Plug 'mattn/emmet-vim'
Plug 'vimwiki/vimwiki' "take note
Plug 'mhinz/vim-startify' "easy way to save and load session
call plug#end()

""General-setting
language en_US
syntax on
set number
set relativenumber
set guicursor=
set relativenumber
set nohlsearch
set hidden
set noerrorbells
set tabstop=4 softtabstop=4
set shiftwidth=4 "tab key spaces, = set sw
set expandtab "instead of tab, insert spaces
set smartindent
set nu
set nowrap
set smartcase
set noswapfile
set undofile
set incsearch
set termguicolors
set scrolloff=8 "Scroll offset
set noshowmode
set cmdheight=2
set updatetime=50
set shortmess+=c
set cursorline
set hlsearch "highlight searched words
"NOTE :eol is end of the line
set listchars=eol:↲,tab:→\ ,trail:~,extends:>,precedes:<,space:␣ 
set nolist "set list => $ is end of the line
"Fold setting: when auto save and load fold
set foldcolumn=2 
autocmd BufWinLeave *.* mkview
autocmd BufWinEnter *.* silent! loadview 

highlight ColorColumn ctermbg=0 guibg=lightgrey

""Color Theme
colorscheme gruvbox 
"cursorline termguicolors
set background=dark
let g:gruvbox_contrast='soft'

let loaded_matchparen = 1
let mapleader = " "

""Status-line
set statusline=
set statusline+=%#IncSearch#
set statusline+=\ %y
set statusline+=\ %r
set statusline+=%#CursorLineNr#
set statusline+=\ %F
set statusline+=%= "Right side settings
set statusline+=%#Search#
set statusline+=\ %l/%L
set statusline+=\ [%c]

""Key-bindings
nnoremap <leader>gc :GCheckout<CR>
nnoremap <leader>ghw :h <C-R>=expand("<cword>")<CR><CR>
nnoremap <leader>prw :CocSearch <C-R>=expand("<cword>")<CR><CR>
nnoremap <leader>pw :Rg <C-R>=expand("<cword>")<CR><CR>
nnoremap <nowait> <leader>j :wincmd j<CR>
nnoremap <nowait> <leader>k :wincmd k<CR>
nnoremap <nowait> <leader>l :wincmd l<CR>
"bug report:: :wincmd h is mapped with below mapping, 
"> but can not use shortcuts for  GigGutterPreviewHunk, GitGutterUndoHunk, GitGutterStageHunk
autocmd filetype * nnoremap <nowait> <buffer> <leader>h :wincmd h<CR>
"nnoremap <nowait> <leader>h :wincmd h<CR>
nnoremap <leader>u :UndotreeShow<CR>
"nnoremap <leader>pv :wincmd v<bar> :Ex <bar> :vertical resize 30<CR>
nnoremap <leader>pv :call ToggleNetrw() <bar> :vertical resize 30<CR>
nnoremap <Leader>ps :Rg<SPACE>
nnoremap <C-p> :GFiles<CR>
nnoremap <Leader>pf :Files<CR>
nnoremap <Leader><CR> :<c-u>call <sid>Goto_definition() <CR>
nnoremap <F4> :so ~/.config/nvim/init.vim<CR>
nnoremap <Left> :vertical resize -2<CR>
nnoremap <Right> :vertical resize +2<CR>
nnoremap <Up> :resize +2<CR>
nnoremap <Down> :resize -2<CR>
nnoremap <Leader>rp :resize 100<CR>
nnoremap <Leader>ee oif err != nil {<CR>log.Fatalf("%+v\n", err)<CR>}<CR><esc>kkI<esc>
vnoremap J :m '>+1<CR>gv=gv
vnoremap K :m '<-2<CR>gv=gv
vnoremap X "_d
"built-in mapping disable
nnoremap Q <Nop>
" vim TODO
nmap <Leader>tu <Plug>BujoChecknormal
nmap <Leader>th <Plug>BujoAddnormal
let g:bujo#todo_file_path = $HOME . "/.cache/bujo"
" GoTo code navigation.
nmap <leader>gd <Plug>(coc-definition)
nmap <leader>gy <Plug>(coc-type-definition)
nmap <leader>gi <Plug>(coc-implementation)
nmap <leader>gr <Plug>(coc-references)
nmap <leader>rr <Plug>(coc-rename)
nmap <leader>g[ <Plug>(coc-diagnostic-prev)
nmap <leader>g] <Plug>(coc-diagnostic-next)
nmap <silent> <leader>gp <Plug>(coc-diagnostic-prev-error)
nmap <silent> <leader>gn <Plug>(coc-diagnostic-next-error)
nnoremap <leader>cr :CocRestart
nnoremap <silent> K :call <SID>show_documentation()<CR>
"quickly enter new line in normal mode
nnoremap <Leader>o o<Esc>

nmap ghs <Plug>(GitGutterStageHunk)
xmap ghs <Plug>(GitGutterStageHunk)
nmap ghu <Plug>(GitGutterUndoHunk)
nmap ghp <Plug>(GitGutterPreviewHunk)

"Emmet key
let g:user_emmet_mode="n"
let g:user_emmet_leader_key="," "default leader_key is <c-y> with trailing ,(comma)

" coc config
let g:coc_global_extensions = [
  \ 'coc-snippets',
  \ 'coc-pairs',
  \ 'coc-tsserver',
  \ 'coc-eslint',
  \ 'coc-prettier',
  \ 'coc-json',
  \ 'coc-marketplace',
  \ ]
"coc snippet
" Use <C-l> for trigger snippet expand.
imap <C-l> <Plug>(coc-snippets-expand)
" Use <C-j> for select text for visual placeholder of snippet.
vmap <C-j> <Plug>(coc-snippets-select)
" Use <C-j> for jump to next placeholder, it's default of coc.nvim
let g:coc_snippet_next = '<c-j>'
" Use <C-k> for jump to previous placeholder, it's default of coc.nvim
let g:coc_snippet_prev = '<c-k>'
" Use <C-j> for both expand and jump (make expand higher priority.)
imap <C-j> <Plug>(coc-snippets-expand-jump)


inoremap jk <ESC>
vmap ++ <plug>NERDCommenterToggle
nmap ++ <plug>NERDCommenterToggle

let g:NERDTreeIgnore = ['^node_modules$']

" ctrlp
let g:ctrlp_user_command = ['.git/', 'git --git-dir=%s/.git ls-files -oc --exclude-standard']

" Highlight currently open buffer in NERDTree
autocmd BufEnter * call SyncTree()

" Remap for rename current word
nmap <F2> <Plug>(coc-rename)


"Functions
"show documetation function
function! s:show_documentation()
  if (index(['vim','help'], &filetype) >= 0)
    execute 'h '.expand('<cword>')
  else
    call CocAction('doHover')
  endif
endfunction
"sync open file with NERDTree, Check if NERDTree is open or active
function! IsNERDTreeOpen()        
  return exists("t:NERDTreeBufName") && (bufwinnr(t:NERDTreeBufName) != -1)
endfunction 
" Call NERDTreeFind iff NERDTree is active, current window contains a modifiable, file, and we're not in vimdiff
function! SyncTree()
  if &modifiable && IsNERDTreeOpen() && strlen(expand('%')) > 0 && !&diff
    NERDTreeFind
    wincmd p
  endif
endfunction 
" autocomplete functions for neoclide/coc.nvim
"---------------------------------------------------------------------------
" Use tab for trigger completion with characters ahead and navigate.
" NOTE: Use command ':verbose imap <tab>' to make sure tab is not mapped by
" other plugin before putting this into your config.
inoremap <silent><expr> <TAB>
      \ pumvisible() ? "\<C-n>" :
      \ <SID>check_back_space() ? "\<TAB>" :
      \ coc#refresh()
inoremap <expr><S-TAB> pumvisible() ? "\<C-p>" : "\<C-h>"
function! s:check_back_space() abort
  let col = col('.') - 1
  return !col || getline('.')[col - 1]  =~# '\s'
endfunction
" Use <c-space> to trigger completion.
if has('nvim')
  inoremap <silent><expr> <c-space> coc#refresh()
else
  inoremap <silent><expr> <c-@> coc#refresh()
endif
" Use <cr> to confirm completion, `<C-g>u` means break undo chain at current
" position. Coc only does snippet and additional edit on confirm.
" <cr> could be remapped by other vim plugin, try `:verbose imap <CR>`.
if exists('*complete_info')
 inoremap <expr> <cr> complete_info()["selected"] != "-1" ? "\<C-y>" : "\<C-g>u\<CR>"
else
 inoremap <expr> <cr> pumvisible() ? "\<C-y>" : "\<C-g>u\<CR>"
endif
"open implementation to the right split view(custom function)
"buggy: If you quit after invoke this function, this function will not work(it will quit your only window)
let s:first_open=1
function! s:Goto_definition() abort 
    if s:first_open
        rightbelow vs "same as :vertical split and :wincmd l
        normal K 
        wincmd h
        let s:first_open=0
    else 
        wincmd l "If right split window exists then quit
        q
        rightbelow vs
        normal K
        wincmd h
    endif
endfunction
"---------------------------------------------------------------------------

"" netrw settings
let g:netrw_liststyle=3 "Tree style
let g:netrw_banner = 0 "Remove banner
let g:netrw_browse_split = 4 "Open file in previous window
let g:netrw_altv = 1 "Open vertical split window to the right side
let g:netrw_preview=1 "Preview in right side 
set nocompatible "Limit search for your project
set path+=** "Search all subdirectories with recursively
set wildmenu "Show multifiles on one line when you :find
"Root directory:make current directory to root directory
nnoremap <leader>` :Ntree<CR> 
let g:NetrwIsOpen=0
function! ToggleNetrw()
    if g:NetrwIsOpen
        let i = bufnr("$")
        while (i >= 1)
            if (getbufvar(i, "&filetype") == "netrw")
                silent exe "bwipeout " . i 
            endif
            let i-=1
        endwhile
        let g:NetrwIsOpen=0
    else
        let g:NetrwIsOpen=1
        silent Lexplore
    endif
endfunction
let g:netrw_list_hide= netrw_gitignore#Hide()

"=================Unorganized settings==================
"jsx comment 
let g:NERDCustomDelimiters={
    \ 'javascript': { 'left': '//', 'right': '', 'leftAlt': '{/*', 'rightAlt': '*/}' },
\}
"vimwiki setup
"let g:vimwiki_list = [{'path': '~/vimwiki/',
                      "\ 'syntax': 'markdown', 'ext': '.md'}]

=== edit for Result (now working) ===

for :map <leader>h now show like this picture enter image description here

what I did

  1. add 4 snippets from answer
  2. :PlugUpdate => I was out of date.
  3. remove <nowait>
  4. :echo hasmapto('<Plug>(GitGutterStageHunk)', 'n') output 1

when upto 2 step, it didn't work, but after remove nowait it works something interfereing commands, but I don't know exact reason.


Solution

  • The mappings that include <Leader>h as a prefix will cause this interference. Vim will wait for a timeout or additional keypress before executing your <Leader>h mapping, since it wants to check whether you meant to press one of the longer mappings...

    The easiest way to fix this is set alternate mappings for the vim-gitgutter commands. If you set up different mappings for those in your vimrc, vim-gitgutter itself will not create its mappings which are causing the interference.

    The vim-gitgutter README suggests using g as an alternative prefix for these:

    To set your own mappings for these, for example if you prefer g-based maps:

    nmap ghs <Plug>(GitGutterStageHunk)
    nmap ghu <Plug>(GitGutterUndoHunk)
    

    So just go ahead and create mappings for the four keybindings that are breaking your <Leader>h. Add these four lines to your vimrc:

    nmap ghs <Plug>(GitGutterStageHunk)
    xmap ghs <Plug>(GitGutterStageHunk)
    nmap ghu <Plug>(GitGutterUndoHunk)
    nmap ghp <Plug>(GitGutterPreviewHunk)
    

    The xmap (for staging in Visual mode) is technically not required, you could keep using <Leader>hs there without interference... But on the other hand you might want to keep those consistent between Normal and Visual mode, so I'd recommend remapping that one too.

    The reason why <noway> doesn't work to fix this is that <nowait> only works on <buffer>-local mappings, when they shadow global mappings. It doesn't work when all your mappings are global. (In that case, Vim prefers to force you to resolve the conflicts, rather than make then longest mappings always unaccessible.)