In (Neo)Vim, I want to configure a key as if it passed through one-way mirror.
For example, in normal mode, when I type <Leader>, the command :echo "w: Separate Window f: Open File c: Configure Settings" run (so I can get help from at the bottom of the screen), but the <Leader> still has influence on following keys --- such as w, f, c, and so on --- and <Leader><KEY> works properly.
I mapped lots keys with <Leader>, so it will be very helpful for me to display a short manual about keys follow <Leader> at the bottom of the screen when I type <Leader>.
Thanks.
First, <leader> is not a special key at all. It's a placeholder expanded by Vim to the current value of mapleader whenever it is used. Assuming your mapleader is , (as instructed in :help mapleader), the mapping below:
nnoremap <leader>f :find *
will be registered as:
nnoremap ,f :find *
Second, when Vim detects that the key you just pressed is part of several custom or built-in commands it waits a bit for you to press more keys in order to decide what to do. With , as your mapleader, pressing , will always puzzle Vim because , is an actual command in its own right and you have a bunch of custom mappings starting with ,. In this situation, Vim waits for a full second before deciding you actually wanted , and not ,f.
Third, you would almost certainly need to write a completely separate mapping mechanism for achieving you idea. A mechanism that would:
listen to key presses,
trigger a specific function when you press <leader>,
that prints something helpful in the command-line,
and waits indefinitely for another key to be pressed.
This doesn't sound trivial at all. Did you take a look at the "scripts" section of http://www.vim.org?
Four, the whole point of a mapping is to map a common action to an easy to remember shortcut. You definitely have too many mappings if you can't remember all of them. Maybe it's time to reconsider the root issue instead of looking for a workaround?
You can do that with the following mapping:
:nnoremap <Leader> :echo "w: Separate Window f: Open File c: Configure Settings"<Bar>call feedkeys((exists('g:mapleader') ? g:mapleader : '\'), 't')<CR>
This uses feedkeys() to send the <Leader> again after the help has been shown. However, this solution has the key timeout downsides already mentioned by #romainl: The message will only appear after the 'timeoutlen' delay, and then you have to press the correct mapping key within 'timeoutlen'.
alternative
I would rather print the help on <Leader><Leader>. There are no timeout issues here. If you have pressed <Leader> and then fail to remember what's the next key, just press <Leader> again, read the help, and then start again with the (now memorized) full mapping!
Related
The following items are useful to me in editing text, and I was wondering if vim had something for this built out of the box (though I didn't see it on the https://vimhelp.org/index.txt.html#index.txt page), or I had to create mappings for it:
Forward-delete a character. This is X in normal mode.
Forward-delete all text to the right of the cursor on the line. This is the inverse of ctrl-u.
Are either of these mappings available? And if not, are there 'standard' mappings for this that are common (for example, how it might be done in another unix program).
Note that this is the keyboard I have -- there is only one delete key (which acts like a normal backspace key) and there is no backspace key:
Note: for forward-delete, I am currently mapping ctrl-d as:
"Ctrl-d to forward-delete when in insert or command mode
noremap! <C-d> <Delete>
However, this interferes with the tab in insert mode (which I don't use) and the help-options in command mode (which I do use!) so I may have to modify this later, or hopefully someone suggests a better solution.
though I didn't see it on the https://vimhelp.org/index.txt.html#index.txt page
If you can't find it in the documentation, then it doesn't exist.
You can use fn+delete for "Forward-delete a character".
"Forward-delete all text to the right of the cursor on the line" is ctrl+k in MacOS, but Vim has its own use for that combo, :help i_ctrl-k so it is up to you to create a mapping for it.
Something like:
inoremap <key> <C-o>ld$
Relatively new to VIM and having a great time using it.
One very minor annoyance I've been having is command mode character navigation when I want to revise a command. I'm used to using readline shortcuts on the regular (non-vim) command line but these shortcuts don't seem to work in : command mode.
For example, using ctrl + b to go back a character ends up sending me to the start of the line, or using alt + f to go forward a word ends up clearing the line and exiting command mode.
The only way I've found to navigate in command mode is to use the arrow keys, but I'm under the impression you should avoid the arrow keys in vim for max efficiency.
What is the standard way to navigate around in : command mode? Do vim users usually use the arrow keys here? Is there a different way to modify commands?
As a more concrete example, I've been using vimgrep a lot to search through files. I'll do a command like:
:vimgrep /font-family/j my-project/**/*.less | cope
Later, I'll want to use the same search but look for a different property, so I hit : then ctrl + p to access my previous vimgrep. Now here I have to use the arrow keys to navigate backwards to the search string and modify it. It would be much faster if I could use readline to navigate backwards by word then delete by word.
For small edits, Backspace and light use of the cursor keys should be fine. For anything larger, I would advise to use the command-line window:
In the command-line window the command line can be edited just like editing
text in any window.
So, there's no need to mentally switch to readline key mappings; just use the full editing power (including any custom mappings) of Vim!
You can switch via <C-F> from the command-line, or directly enter it (from normal mode) by pressing q: instead of :. All the details can be found at :help cmdline-window.
I like this question. Long time vim user, but new-ish here, so I can't vote it up. But indeed, perhaps unofficially, many vim fans feel that most of the time the goal is to not have your hands leave home row position (fingers move, hands relatively still).
I will admit, when it comes to command mode, I use the arrows. With P being on my pinky finger, I would miss-hit ctrl-P a lot, and it's faster to slide my right hand down (on my Natural keyboard) and find the up-arrow by quick feel, instantly, to do the same thing. Once I'm there, left-right arrows are also easy to find without looking or delay. Also Ctrl-arrows let you skip by word.
One of the great things about vim is the :help. I have easily spent tens of hours over the years reading through it, and it solves 95% of my problems if I have enough time and working-memory to push deep enough into it.
Here is what I found for :help readline:
READLINE readline.vim ft-readline-syntax
The readline library is primarily used by the BASH shell, which adds
quite a few commands and options to the ones already available. To
highlight these items as well you can add the following to your
|vimrc| or just type it in the command line before loading a file with
the readline syntax:
let readline_has_bash = 1
This will add highlighting for the commands that BASH (version 2.05a
and later, and part earlier) adds.
Give it a try! (I am using vim 7.4)
You can see a list of the default key binds with :help cmdline-history (scroll down a bit) and :help ex-edit-index.
You can remap this with cnoremap:
cnoremap <C-b> <Left>
cnoremap <C-a> <C-b>
" .. Probably more
Note that using cmap will probably get you into problems here since the right-hand side is the currently mapped action, whereas with cnoremap the right-hand side it will always use the native Vim action.
<C-W><C-O> or <C-W>o invoke the vim single-window command which maximizes the current vim split, and annoyingly (if you keep typing it by accident) closes all others.
I want to remap it to <C-W><C-_> which doesn't close other windows.
In .vimrc I have
map <c-w><c-o> <c-w><c-_>
map <c-w>o <c-w><c-_>
This works if I type C-W and then o or C-O in quick succession.
However, if I type C-W, then wait a second, and then type o or C-O the mappings I have set up are bypassed, and the single-window command is invoked.
Should I use some other map variation?
Another thing you can do is modify the 'timeout' and 'timeoutlen' settings:
For example :set timeoutlen=3000 will set the mapping timeout to 3 seconds instead of 1 (default).
Reference on :help 'timeout' and :help 'timeoutlen'.
The difference between mappings and the built-in two-key mappings like <C-w>o is that the former timeout, whereas the latter wait indefinitely for the second key press. To completely override the behavior with a mapping, you'd have to define an (expression-) mapping for <C-w>, and handle the second key inside the mapping with getchar() (which also waits indefinitely).
But please think carefully whether such effort is really needed: If you're prone to fat-fingering keys or pressing the wrong ones, your use of Vim will be severely hampered. Better learn through the quick feedback that you've pressed something wrong, and try to work on improving your muscle memory!
How about putting set hidden into your .vimrc, so after closing all the splits they don't get closed, only put to background? After that you can list all the opened buffers via :ls command for example.
But regards to your mapping, maybe you could try unmapping (or yet even better nunmap - which unmaps a command only in normal mode) o first, and then map it.
I want to map a key so that it will do the following actions in Vim. Suppose I am editing a file; I want it set up so that if I press F2, I will accomplish the same thing I would if I did the following:
press ESC
type colon (:)
type w
press Enter
press ESC again
type i to go back to insert mode
Is this possible?
Yes it's possible, but it doesn't do what you want if the cursor is at the end of line.
To get file saved on F2 in insert mode, use the following mapping:
:imap <F2> <C-O>:w<CR>
Literal answer: Yes. You can use this:
:inoremap <F2> <Esc>:w<CR>I
but it won’t do exactly what you want (the cursor will be at the wrong place).
Anton beat me to the less literal (but correct) answer.
The best answer, though, is this: Don't use Vim incorrectly. You should never spend so much time in insert mode that you need a shortcut to get out of it, save the file, and then get back in. With all other editors, you’re in “insert mode” all the time, and only temporarily pop into a menu or dialog or whatever; in Vim, you should learn to reverse this. Only pop into insert mode to edit or add something; never use arrow keys to move the cursor while in insert mode; spend the majority of your time in command (normal) mode, and after a bit of adjustment to the new paradigm, you will find that your editing speed has increased.
Writing the mapping is almost easier than your description.
First, you need to determine from which mode the mapping will be used, because that determines what :map variant you will use. You’ll probably want to use this in insert mode, so you’ll use :inoremap.
The format of the mapping is:
:..noremap {keys} {rhs}
You want <F2> (see :help key-notation) for keys. For {rhs}, just concatenate the keys listed in your description.
To persist the mapping, add it to ~/.vimrc. (See :help vimrc.)
P.S. The alternative given by Anton Kovalenko is probably better for what you’re trying to do, but here I’ve given you the general recipe for future key mappings.
In Vim you often need to assign a key for your own custom action. But there are so many key combinations that already have an action mapped to them by default. How do you choose free key combinations when you need to assign you custom action to one?
In these situations I usually get lost and just assign my action to a custom command instead of a key, like :docoolstuff instead of a simple keypress.
And, by the way, do you often remap a default action to use a custom action on this key combination instead?
Personally, I bind custom command to leader - {key}. For example:
let mapleader = ','
nnoremap <leader>s : so $MYVIMRC<CR>
nnoremap <leader>v : tabe $MYVIMRC<CR>
I can press ,v to open vimrc in a new tab.
I use F1-F12 which work reliably enough for me. That's more keys than most would ever need. The higher keys are in my static setup, the lower ones are used for throw-away bindings.
Don't forget alt-gr+key, which gives you a whole new set of characters to bind to. But mapleader, as suggested in the accepted answer, is the most standard practice.