8

When searching for a phrase in hard-wrapped text, one wants newlines to be treated as spaces. Can one have that happen? Saying /the\_sphrase\_sI\_sseek is a bit awkward.

3
  • 2
    See this answer: unix.stackexchange.com/a/11848 for a custom function (and command) that does what you want. Adjust to your taste.
    – VanLaser
    Feb 26, 2016 at 11:52
  • 1
    The problem with this solution is that it can't make use of incremental search. But cmap <m-space> \_s\+ works well (in nvim).
    – Toothrot
    Feb 26, 2016 at 15:53
  • Whatever floats your boat is ok :)
    – VanLaser
    Feb 26, 2016 at 17:19

2 Answers 2

2

You can automatically replace a space with \_s when searching with:

cnoremap <expr> <Space> index(['/', '?'], getcmdtype()) > -1 ? '\_s' : ' '

Because cnoremap is applied to all the commandline (and not just search), we need an expression mapping to check if we're searching or in another commandline mode (e.g. :).


Because you probably don't always want to search like this, you can trigger this newline-insensitive mode with something like:

fun! StartNewlineSearch()
    cnoremap <expr> <Space> index(['/', '?'], getcmdtype()) > -1 ? '\_s' : ' '

    " Unmap both <Space> and this same mapping when pressing <CR>
    cnoremap <CR> <CR>:cunmap <lt>Space><CR>:cunmap <lt>CR><CR>:cunmap <lt>Esc><CR>

    " And the same for <Esc>
    cnoremap <Esc> <Esc>:cunmap <lt>Space><CR>:cunmap <lt>CR><CR>:cunmap <lt>Esc><CR>
endfun

nnoremap // :call StartNewlineSearch()<CR>/

When pressing // it maps <Space> to \_s, and it unmaps it when pressing <CR> or <Esc>.


You could also map this to a key to toggle the two "modes":

let g:search_mode = 0
fun! ToggleMode()
    if g:search_mode == 0
        cnoremap <expr> <Space> index(['/', '?'], getcmdtype()) > -1 ? '\_s' : ' '
        let g:search_mode = 1
    else
        cunmap <Space>
        let g:search_mode = 0
    endif
    return getcmdline()
endfun

cnoremap <C-@> <C-\>eToggleMode()<CR>
0

The other answser is certainly great.

However, I've found that it has one weakpoint, which is not necessarily negligible: if you abort the special search, i.e. you press //(changed your mind)Escape, you'll get E385: Search hit BOTTOM without match for: ; afterwards you'll get the same error even for plain /Escape, which is a bit annoying.

Probably the fix is easy, but I wanted to explore other ways of solving the same problem, so I came up with another solution:

fun! EnableAutocmdToUnmapSpace()
  augroup UnmapSpaceAug
    autocmd!
    autocmd CmdLineLeave,CmdWinEnter / cunmap <space>
    autocmd CmdLineLeave,CmdWinEnter \? cunmap <space>
  augroup END
endf
fun! s:ctrlSMakesSpaceEOLFriendly()
  augroup UnmapSpaceAug
    autocmd!
  augroup END
  cnoremap <expr> <silent> <C-S> execute(':cnoremap <lt>space> \_s\+\| call EnableAutocmdToUnmapSpace()')
endf
augroup EOLFriendlySpace
  autocmd!
  autocmd CmdLineEnter,CmdWinLeave / execute(':call s:ctrlSMakesSpaceEOLFriendly()')
  autocmd CmdLineEnter,CmdWinLeave \? execute(':call s:ctrlSMakesSpaceEOLFriendly()')
  autocmd CmdLineLeave,CmdWinEnter / cunmap <C-S>
  autocmd CmdLineLeave,CmdWinEnter \? cunmap <C-S>
augroup END

It is slighly longer, but it doesn't suffer the issue I described above. And it works differently:

  • when you start your search with /, Space behaves normally,
  • but if you hit Ctrl-S, then
    1. Space is cnoremapped to \_s\+,
    2. and an autocmd is activated to cunmap it;
  • quite importantly, before mapping Ctrl-S, we first clear the autocmd of point 2 above, because we don't want to cunmap <space> on subsequent searches where we don't hit Ctrl-S.
  • leaving the search cunmaps Ctrl-S.
  • CmdWinEnter is treated as CmdLineLeave and CmdWinLeave as CmdLineEnter, for the reason explained here; it is fundamentally depending on an implementation detail, but that's necessary to deal with the case that you hit / from within the command window, e.g. if you do /Ctrl+F/ from normal mode.
  • To make things work for ?, the autocmd needs that you write \?, not ?, as explained here.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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