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.
2 Answers
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>
- 62,054
- 25
- 192
- 271
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
- Space is
cnoremapped to\_s\+, - and an
autocmdis activated tocunmapit;
- Space is
- quite importantly, before mapping Ctrl-S, we first clear the
autocmdof point 2 above, because we don't want tocunmap <space>on subsequent searches where we don't hit Ctrl-S. - leaving the search
cunmaps Ctrl-S. CmdWinEnteris treated asCmdLineLeaveandCmdWinLeaveasCmdLineEnter, 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
autocmdneeds that you write\?, not?, as explained here.
- 2,194
- 15
- 31
cmap <m-space> \_s\+works well (in nvim). – Toothrot Feb 26 '16 at 15:53