Mapping 1 command to multiple key combinations in vim - vim

Im using nerdtree plugin in vim.
With let NERDTreeMapActivateNode="<Right>" a tree node opens up bs using the right arrow key.
But I want also the left arrow key do the same. Is that even possible that 2 Keymappings can do the same thing? If so, how?

Yes, it is definitely possible to have a single command mapped to many key sequences:
nnoremap a diw
nnoremap b diw
nnoremap c diw
But this is a special case, where the mapping is done internally by a plugin and it is arbitrarily limited to one.
Apparently, the plugin sets the filetype of its buffer as nerdtree, so you might be able to deal with this in an agnostic way by mapping <Left> to <Right> only in the desired context:
" after/ftplugin/nerdtree.vim (relative to your `.vim` or `vimfiles`)
nmap <buffer> <Left> <Right>
But a better solution would probably be to use the plugin's own :help NERDTreeKeymapAPI.

created a file ~/.vim/nerdtree_plugin/mymapping.vim
call NERDTreeAddKeyMap({
\ 'key': '<Left>',
\ 'callback': 'FunctionLEFTkey',
\ 'quickhelpText': 'echo full path of current node',
\ 'scope': 'DirNode' })
function! FunctionLEFTkey(dummy_node_arg_required_cozof_scope)
execute 'normal' g:NERDTreeMapActivateNode
endfunction
call NERDTreeAddKeyMap({
\ 'key': '<Right>',
\ 'callback': 'FunctionRIGHTkey',
\ 'quickhelpText': 'echo full path of current node',
\ 'scope': 'all' })
function! FunctionRIGHTkey()
execute 'normal' g:NERDTreeMapActivateNode
endfunction
Pressing Leftarrow in nerdtree closes or opens a directory node.
Pressing Rightarrow in nerdtree closes or open a directory or opens a
file.
Works as long NERDTreeMapActivateNode (in vimrc) isn't set to Leftarrow or Rightarrow key because then only this key can toggle NERDTreeMapActivateNode and NERDTreeAddKeyMap doesn't work anymore.

Related

Hitting ENTER on quickfix error jumps to an empty buffer

I'm using GVim 8.1 on Windows 10 with no external plugins.
I have the following set up in my .gvimrc file:
let g:build_file_abs_path = fnamemodify(findfile("windows-build.bat", ";."), ":p:h")
" This build script is a basic wrapper for 'clang.exe file.c -o file.exe' style invocation
let &makeprg=g:build_file_abs_path . "\\windows-build.bat"
nnoremap <silent> <C-B> :cd <C-R>=g:build_file_abs_path<CR> <bar> make! <bar> copen <bar> redraw <bar> cd -<CR>
Now, this automatically opens a quickfix window with the correct compiler output. However, when I press ENTER over the error, the cursor jumps to the buffer for the affected file, yet it is completely blank with a single line. Furthermore, this occurs as I use :cn and :cp commands inside the quickfix window. e.g:
Images showing these two states:
before
after
Please note that:
:verbose nmap <CR> returns no mappings, so there is not conflict there.
I would appreciate it if someone could provide some insight as to how to avoid the buffer becoming empty and actually jump to the error in the appropriate file. Many thanks.
Thanks to Christian Brabandt's comment, I was able to solve the issue. I was misunderstanding the distinction between the working directories of vim and the build script. I made the following changes:
let &makeprg="cd " . g:build_file_abs_path . " && windows-build.bat"
nnoremap <silent> <C-B> :make! <bar> copen <bar> redraw <CR>

How to make Vim plugin NERDTree's <CR> behave more like `go`?

In NERDTree, <CR> is same as shortcut o which in its help doc is described as below:
Default key: o
Map option: NERDTreeMapActivateNode
Applies to: files and directories.
If a file node is selected, it is opened in the previous window.
If a directory is selected it is opened or closed depending on its current
state.
If a bookmark that links to a directory is selected then that directory
becomes the new root.
If a bookmark that links to a file is selected then that file is opened in the
previous window.
I want to open a file with the cursor just remained in the NERDTree.
I found it's just the action that shortcut go does. But go can only be applied to files while o is applied to files and directories.
In the NERDTree's help doc:
Default key: go
Map option: None
Applies to: files.
If a file node is selected, it is opened in the previous window, but the
cursor does not move.
The key combo for this mapping is always "g" + NERDTreeMapActivateNode (see
NERDTree-o).
More specifically, I want <CR> to behave as o when applied to directories, and go when files.
There is no Customisation flag to do that.
Is there any good way to implement it including modifying the source script?
Thanks a lot!
It seems that it can be accomplished using custom mappings which unfortunately cannot be defined usual way in your .vimrc. You need to distinguish if the node is a 'FileNode' or a 'DirNode' so the mappings must be specified in a file like ~/.vim/nerdtree_plugin/mymappings.vim.
call NERDTreeAddKeyMap({
\ 'key': '<CR>',
\ 'scope': 'DirNode',
\ 'callback': 'NERDTreeCustomActivateDirNode',
\ 'quickhelpText': 'open or close a dirctory',
\ 'override': 1 })
function! NERDTreeCustomActivateDirNode(node)
call a:node.activate()
endfunction
call NERDTreeAddKeyMap({
\ 'key': '<CR>',
\ 'scope': 'FileNode',
\ 'callback': 'NERDTreeCustomPreviewNodeCurrent',
\ 'quickhelpText': 'open a file with the cursor in the NERDTree',
\ 'override': 1 })
function! NERDTreeCustomPreviewNodeCurrent(node)
call a:node.open({'stay': 1, 'where': 'p', 'keepopen': 1})
endfunction
I found the inspiration in /autoload/nerdtree/ui_glue.vim.
More information in :h NERDTreeKeymapAPI.
(I don't have NERDTree so it is not tested.)

use search in "browse oldfiles" list?

Is there a way to search the list of recently used file in Vim? The list can be displayed using
browse old
but / does not work. I am aware of some plugins (e.g. MRU) but would prefer to not use a plugin.
Here's a short scriptlet that opens the file list in a scratch buffer. As a bonus, it defines a local <Enter> mapping to :edit the current file. With this, you can search with all built-in commands like /:
:new +setl\ buftype=nofile | 0put =v:oldfiles | nnoremap <buffer> <CR> :e <C-r>=getline('.')<CR><CR>
If you really want to avoid a plugin:
:new The old files will be printed into this buffer
:redir #X where X is a temporary register`
:silent echo(v:oldfiles) 'Silent' is there to not actually print onto your screen
:redir END
"Xp paste the temporary register
(optional) Do some regex-fu to put each file on its own line.
Put the above into a function and voila. Also :help redir
It's actually not very hard to write a simple (simplistic?) MRU command with completion that works like :edit or :split:
" this is our 'main' function: it couldn't be simpler
function! MRU(arg)
execute 'edit ' . a:arg
endfunction
" the completion function, again it's very simple
function! MRUComplete(ArgLead, CmdLine, CursorPos)
return filter(copy(v:oldfiles), 'v:val =~ a:ArgLead')
endfunction
" the actual command
" it accepts only one argument
" it's set to use the function above for completion
command! -nargs=1 -complete=customlist,MRUComplete MRU call MRU(<f-args>)
Here is a .vimrc version of code above. Just add following lines to .vimrc and map to desired keys (in my case it is 'o). In addition define patterns to remove "junk" files. Also cursor is placed at the top for convenience.
Most hard thing is to map an Enter inside nested nmap. ^V is the result of doubled Ctrl-V. ^R is the result of Ctrl-V+Ctrl-R. ^M is the result of Ctrl-V+Enter. You need manually repeat those symbols - not just Copy/Paste. Spent hours to understand this magic - so I'm glad to share. This technology lets you add own macroses in .vimrc.
" Browse Old Files
nnoremap <silent> 'o :enew<CR>:set buftype=nofile<CR>:set nobuflisted<CR>:exe "0put =v:oldfiles"<CR>:nmap <buffer> ^V^V^M :e ^V^V^R=getline('.')^V^V^M^V^V^M<CR>:g/\v(stdout\|nerd\|fugitive)/d<CR>:0<CR>
This is my take on Ingo's answer above for my .vimrc:
Opens the old files in either a vertical split or tab, then maps enter to open file under cursor! magic!
" open old files list and map enter to open line
" vertical split
noremap <leader>vv :vnew +setl\ buftype=nofile <bar> 0put =v:oldfiles <bar> nnoremap <lt>buffer> <lt>CR> :e <lt>C-r>=getline('.')<lt>CR><lt>CR><CR><CR>
" in new tab
noremap <leader>vt :tabnew +setl\ buftype=nofile <bar> 0put =v:oldfiles <bar> nnoremap <lt>buffer> <lt>CR> :e <lt>C-r>=getline('.')<lt>CR><lt>CR <CR><CR>

Arrow keys in vim (linux) in insert mode broken for me

When I use the arrow keys in vim in insert mode I get letters inserted instead of movement.
Up produces an A
Down produces a B
Left products a D
Right produces a C
Does anyone know what would cause this?
Thanks in advance
If these keys work fine in normal mode, but do not in insert then you must have some mappings to the first one or two characters (normally <Up> is either <Esc>[A (terminals that use CSI) or <Esc>OA (xterm)). Try checking out output of
verbose imap <Esc>
, there should be not much mappings starting with <Esc> in insert mode (I have none, for example). I can say, that with arrow keys working normally in insert mode, using
inoremap <Esc> <Esc>
produces just the same behavior as if you had problems with terminal recognition or had 'compatible' set.
Your vim seems to be starting in the vi compatibility mode. Do this
Open Vim editor,
Get the path of your home directory by typing :echo $HOME
Check if you have .vimrc file in $HOME location,(if you don't have create it)
Add the following line line to .vimrc file
:set nocompatible
Find more solutions for the same problem here ( Especially if your problem is terminal related, the re-mapping of keys solution might work for you )
The following worked for me. Just put it in your .vimrc
:set term=cons25
Open Vim editor.
Get the path of your home directory by typing: :echo $HOME.
Check if you have .vimrc file in $HOME location, and if you don't have create it.
Add the following line line to .vimrc file: :set nocompatible
Reference: http://vim.wikia.com/wiki/Fix_arrow_keys_that_display_A_B_C_D_on_remote_shell
None of the answer here worked for me. I'm in Linux, with konsole/yakuake terminal and tmux. This fix works for me:
nnoremap <silent> <ESC>OA <ESC>ki
nnoremap <silent> <ESC>OB <ESC>ji
nnoremap <silent> <ESC>OC <ESC>hi
nnoremap <silent> <ESC>OD <ESC>li
inoremap <silent> <ESC>OA <ESC>ki
inoremap <silent> <ESC>OB <ESC>ji
inoremap <silent> <ESC>OC <ESC>hi
inoremap <silent> <ESC>OD <ESC>li

Unable to eliminate T in Vim's Taglist

I have the following code in .vimrc
" to eliminate the effect of the line 1560 in taglist.vim
if v:version >= 700
nnoremap <buffer> <silent> t
\
nnoremap <buffer> <silent> <C-t>
\
endif
The command does what it should do. However, the command gives also me the following error at Vim's startup
No mapping found
No mapping found
How can you eliminate the keyboard shortcut, such that you do not get the message in Taglist but you can still use the default "T" for browsing up in Dvorak?
Delete it. I don't use taglist, but the example you gave in your post does nothing.
It is supposed to map something to something, but the right side is missing, i.e. something is supposed to being mapped to "t" and "C-t", but that something isn't defined.
Or, you can do this:
:silent nnoremap <buffer> <silent> t (and analoguous for the second line)
(mapping stays but the message will not be displayed)

Resources