countunique
countunique

Reputation: 4296

Mapping has unintended effect

I created a mapping to move the current line up by one line.

:map _ ddkP

It works, except that when executed on the first line, it deletes the first line.

I would expect that nothing would happen, because they I execute dd, k, P on the first line, nothing happens. Where am I going wrong?

Upvotes: 3

Views: 58

Answers (2)

romainl
romainl

Reputation: 196476

When you do dd, k, P, the commands are executed separately:

  1. the current line is deleted
  2. the cursor moves up one line
  3. the previously yanked line is pasted above the current line

Because they are isolated, a failure in one command doesn't prevent the execution of further commands. In your case, Vim couldn't move up one line but it can perfectly paste above the current line.

When executed as a single command, as a macro, a failure in a command stops the execution of the whole macro and further commands are not executed.

In your example, the first step, dd, works, but k can't move the cursor on the line above the current line and everything is stopped: Vim never even tries to execute P.

One way to deal with that "first line" issue would be to write a function like in Birei's answer.

Another way would be to use a different command that throws an error when you are on the first line.

nnoremap _ :move-2<CR>

With the added benefit of not clogging your clipboard/registers.

See this page on the Vim wiki.

Upvotes: 8

Birei
Birei

Reputation: 36252

You have to use a map command that evaluates an expression, so you have to add <expr> and use a function that checks if your cursor is in the first line of the file.

So, add this function to your vimrc file:

function! Swap()
    if line('.') > 1 
        return 'ddkP'
    endif
    return ''
endfunction

and use the following map command:

:map <expr> _ Swap()

This way it will only will swap lines when the if condition succeeds.

Upvotes: 1

Related Questions