1

I want to implement something similar to Org mode M-RET into neovim. In Org mode it creates new list item or heading depending on what line the point is on.

I'm thinking of a mapping in neovim that copies everything from the beginning of the current line until the first alphanumeric character of the line and puts it on a new line. For example, with cursor at the end, it would transform this:

* list item
    * inner list item

into this:

* list item
    * inner list item
    * 

I think it could be done with :s but i couldn't make it work (:s/(^[^\w]*)(.*)/\1\2\n\1) and it would replace the whole line, which is unnecessary.

Ideally it should work in insert mode and shouldn't rewrite any registers.

1

You could start with this:

function! NewBullet()
    let l = getline('.')
    let l = substitute(l, '\w.*$','', '')
    return "\n" . l
endfunction

inoremap <expr> <F1> NewBullet()

Map-expression calls the function and inserts the returned text. Here a newline and the prefix of the line.

See :help :map-expression.

  • Perfect, except the new line has double indentation because of autoindent. I added another substitute command to remove all whitespace at the begining of the line. – matj1 Dec 21 '18 at 15:29
1

:substitute Command

The problem with the command you tried is that you used \n where you needed to use \r. (See :help s/\r.)

I don't really share your aversion to substituting the entire line, but we'll avoid that too:

:s/\v^(\W*).*\zs/\r\1

Insert Mode Mapping

To use this from insert mode, you can include it in an insert mode mapping:

:inoremap <F1> <Esc>:s/\v^(\W*).*\zs/\r\1<CR>A

How It Works

  • \v – using "very magic"
  • ^ – the start of the line
  • (\W*) – as many non-alphanumeric characters* as possible, grouped into a capture group.
  • .* – as many characters as possible (i.e. the rest of the line)
  • \zs – set the start of the match (and thus the start of the replacement) to here

The replacement:

  • \r – A newline
  • \1 – The captured group.

* \W is equivalent to [0-9A-Za-z_] which is close enough to "non-alphanumeric" for your purposes.

Avoid :substitute Entirely

It's also possible just to use regular editing commands to perform this task:

:inoremap <F1> <Esc>0y/\w<CR>o<Esc>pA

To see how this works, just try typing out the commands in the mapping's rhs manually!

  • I don't have aversion to substituting the entire line, i just think it could be done better, but it's better than overwriting registers. – matj1 Dec 21 '18 at 13:45
  • @matj1 Neither solution in my answer substitutes the entire line. – Rich Dec 21 '18 at 14:14
  • If you don’t want the code to overwrite any registers, including the yank, unnamed, and search pattern registers, you’ll need a function that saves them before performing the edit and restores them afterwards. – Rich Dec 21 '18 at 14:44

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.