3

N.B. my question title might be poor, so feel free to improve it.

Background

I want to write a command to move my cursor to the body of my email, add blank lines, and change to insert mode. Previously, I used the following for new emails.

nnoremap gb <C-Home>/^$<CR>:nohlsearch<CR>o

mutt would create a new email in vim, then I'd press gb. The cursor would move to the top of the email (<C-Home>), find the first blank line and immediately stop highlighting (/^$<CR>:nohlsearch<CR>), create a new line and start editing a new line (o).

However, I often reply to an email, and I wanted to automatically create another "buffer" empty line below my cursor position. Hence, I changed the command to this following.

nnoremap gb <C-Home>/^$<CR>:nohlsearch<CR>o<Esc>ko

This would do as above, then get into normal mode <Esc>, move up (k), and create another new line to edit o.

Conditional

I wanted to create a conditional. After searching for the first blank line (<C-Home>/^$<CR>:nohlsearch<CR>), if this were the last line of the email, I'd be editing a new email, so just o. Otherwise, I'd be replying, so o<Esc>ko. The following doesn't work, because I've mangled together different syntaxes, but it should give an idea of what I want.

nnoremap gb <C-Home>/^$<CR>:nohlsearch<CR>|if line('.') != line('$')|o<Esc>k|endif|o

I suspect nnoremap <expr> gb ... is useful, but I'm not sure how to use it.

  • 5
    You may want to create a function for this and call it with nnoremap gb :call YourFunction()<CR>. In the function you can do all your mapping is currently doing and have a more nicer view. – nobe4 Mar 7 '16 at 10:24
  • 2
    @Nobe4 I think part of my problem is confusion between remap, remap <expr>, function and command. I'm not sure what I'm writing where. I'm not sure exactly what syntax to use for this function, as obviously my last piece of code is a hybrid of different things (and doesn't work as is). Could you possibly write an answer with the function code itself? – Sparhawk Mar 7 '16 at 10:38
  • Done, check my answer and ask if you have any question – nobe4 Mar 7 '16 at 10:44
  • 3
    @Sparhawk: As a general heads up in vimscript a command is an operation that you start from the command mode which you enter with : (example :echo "foo"). A function is a set of commands that you define in your .vimrc or another .vim file, you can call the function from the command line mode :call YourFunction(). Finally a mapping is the fact to assign an action to a key or a key sequence (e.g. :map <C-a> :call YourFunction()<CR> says to Vim "When I press Ctrl-a do as if I had press : followed by call YourFunction followed by Enter). – statox Mar 7 '16 at 12:34
  • 2
    @Sparhawk: gg is a normal mode mapping so if you want to use it in a function you have to say to vim "Use gg as if I was in normal mode" you do that with normal gg. In the command line using :normal gg will be the same as typing gg in normal mode. Actually the best I can advise to you is to learnVimScriptTheHardWay it might be a lot of reading but you'll find an answer to 98% of your questions there and you can ask the 2% remaining on this site ;-) – statox Mar 7 '16 at 13:11
4

There you go, I'm not sure to have understood perfectly your use case, bu you can add your workflow to this example :

function! Mail()
  normal! gg
  call search('^$')
  nohlsearch
  if line('.') != line('$')
    normal! o
    normal! k
  endif
  normal! o
  startinsert
endfunction

nnoremap gb :call Mail()<CR>

Note that you can execute normal! to prevent mapping to be used.

  • Oh, one small problem. It doesn't leave me in insert mode at the end. I can just append i to nnoremap gb ..., but is there a more elegant way (by modifying the function instead)? – Sparhawk Mar 7 '16 at 20:53
  • 1
    Yes, let me update my answer – nobe4 Mar 7 '16 at 20:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.