VIM: Conditional Key Mapping
Asked Answered
R

1

5

In Vim I want to have a conditional statement in a Key mapping.

If the cursor is at the start of a line, I want this mapping:

imap <F1> <ESC>:syntax sync fromstart<CR>i

but otherwise have this mapping (the only difference is the final character)

imap <F1> <ESC>:syntax sync fromstart<CR>a

In the second mapping the cursor is not put back into the correct place if this mapping is run when the cursor is at the start of a line (when we go back into insert mode with the a )

I'm trying to find for a solution to this specific problem, but I also want to know if you can indeed you put a conditional in a Vim keymapping.

Thanks!

Repellent answered 8/11, 2017 at 20:22 Comment(0)
E
8

The answer to your general question is: Yes, mappings can contain conditional logic. You can do this in a few ways, the simplest is to use an <expr> mapping. Here's an example from the vim wiki:

inoremap <expr> <Esc>      pumvisible() ? "\<C-e>" : "\<Esc>"

This example conditionally maps Esc to either C-e or Esc depending on whether or not the pumvisible() function returns a true or false value. In your case you would need to find (or define) an expression that determines where the cursor is on the line.

Another option is to just write a function that contains all of the logic and map the key to that function rather than an expression.

In your specific case none of this is necessary. Just replace the <Esc> in your mapping with <C-o>, and drop the trailing a or i.

imap <F1> <C-o>:syntax sync fromstart<CR>

In insert mode C-o lets you run one normal mode command, then returns to insert mode. Since your normal mode command does not move the cursor, your should be returned to insert mode where you started.

Eurythermal answered 8/11, 2017 at 20:32 Comment(4)
Thanks @randymorris that's bang on! I have a similar situation that I can't apply the <C-o> trick with: inoremap <C-Del> <Esc>ldei Where I have the same problem with the final i at the end. Any thoughts on that?Repellent
That seems like a really strange mapping... to delete to the end of the word, except the very next character after the cursor. My only suggestion is to try writing a function that does what you want using "getpos()" and "setpos()", the map a key to that function.Eurythermal
Don't take this the wrong way, but are you relatively new to using vim? I ask because this seems like the sort of question that people tend to ask when they get caught up on the block-style cursor that vim uses. Sometimes it takes a while to get used to the fact that the cursor position is actually just prior to the highlighted character, not on the character itself. Honestly, trying to fight that fight by adding mappings like this is going to be a losing battle.Eurythermal
I use Vim a lot but I'm not an advanced user. This is just a hack to get a more Windows-style word deletion. That mapping works in almost all situations, but at the end of the line I really want deaI haven't found another solution that does what I want.Repellent

© 2022 - 2024 — McMap. All rights reserved.