I usually edit RUBY files in VIM. I want the methods(def...end) to fold. Could you please help me define the fold syntax?
Assuming you've already got Ruby syntax highlighting setup and working, use the syntax mode for folding:
set foldmethod=syntax
This will give you folds on class .. end and def .. end, etc.
I like to have everything fold by default, and this here will let you tweak a whole bunch of things related to folding. I do mostly Perl and C++ coding and I find it works well with that. Folding and unfolding is mapped to space key.
Here's what I have going in my vimrc:
" Folding stuff
hi Folded guibg=red guifg=Red cterm=bold ctermbg=DarkGrey ctermfg=lightblue
hi FoldColumn guibg=grey78 gui=Bold guifg=DarkBlue
set foldcolumn=2
set foldclose=
set foldmethod=indent
set foldnestmax=10
set foldlevel=0
set fillchars=vert:\|,fold:\
set foldminlines=1
" Toggle fold state between closed and opened.
"
" If there is no fold at current line, just moves forward.
" If it is present, reverse it's state.
fu! ToggleFold()
if foldlevel('.') == 0
normal! l
else
if foldclosed('.') < 0
. foldclose
else
. foldopen
endif
endif
echo
endf
" Map this function to Space key.
noremap <space> :call ToggleFold()<CR>
I think you put the cursor on the first line then zfnj where n is the number of lines to fold (so to fold 10 lines you woudl zf10j). I think it will also recognize syntax so like in PHP I do zf} to fold to the closing bracket. I don't code in Ruby, so I don't know if this works in Ruby.
From then on, to toggle, zo will open and zc will close.
Related
Hi ,
I want to fold set of lines after search as follows,
The mouse can also be used to open and close folds by following steps:
Click on a '+' to open the closed fold at this row.
Click on any other non-blank character to close the open fold at this row
I want to search click and collapse all matching lines.
The mouse can also be used to open and close folds by followingsteps:
+--
There is a method to collapse the patterns which are not matching in vim , after searching a pattern we can collapse non matching patterns by "\z" key .
nnoremap \z :setlocal foldexpr=(getline(v:lnum)=~#/)?0:(getline(v:lnum-1)=~#/)\\|\\|(getline(v:lnum+1)=~#/)?1:2 foldmethod=expr foldlevel=0 foldcolumn=2<CR>
Is there any option to do the opposite? Just find a pattern and collapse?
I'm using below configuration with neovim I think should work with regular vim as well:
nnoremap \Z :setlocal foldexpr=(getline(v:lnum)=~#/)?0:1 foldmethod=expr foldlevel=0 foldcolumn=2 foldminlines=0<CR><CR>
nnoremap \z :setlocal foldexpr=(getline(v:lnum)=~#/)?1:0 foldmethod=expr foldlevel=0 foldcolumn=2 foldminlines=0<CR><CR>
\z: Fold matching expression from last search
\Z: Fold anything that's NOT matching from last search
It's quite useful when I want to see all comments or no comments at all,
First do \ and search for ^# (If that's your language's comment start symbol) hit return, then do the folding as above.
Edit: You might want to add below to reset the folding back to manual if you want:
nnoremap \F :setlocal foldmethod=manual<CR><CR>
I got an answer to this question from reddit user on reddit vim forum.
https://www.reddit.com/r/vim/comments/91qz90/search_a_pattern_and_fold_the_matching_lines_in/
function! FoldSearchPattern() abort
if !exists('w:foldpatterns')
let w:foldpatterns=[]
setlocal foldmethod=expr foldlevel=0 foldcolumn=2
endif
if index(w:foldpatterns, #/) == -1
call add(w:foldpatterns, #/)
setlocal foldexpr=SetFolds(v:lnum)
endif
endfunction
function! SetFolds(lnum) abort
for pattern in w:foldpatterns
if getline(a:lnum) =~ pattern
if getline(a:lnum + 1) !~ pattern
return 's1'
else
return 1
endif
endif
endfor
endfunction
nnoremap \z :call FoldSearchPattern()<CR>
Hope it is helpful.
I am using :set textwidth=80 to make the Vim editor do hard wrapping automatically. However, sometimes for certain lines within a file (e.g. tables in LaTeX), I do not want Vim to do any hard wrapping automatically. Is there a way to mark certain lines to disable hard wrapping in Vim? Or automatically :set textwidth=0 just for specified lines?
There's nothing out-of-the-box, but you can build a solution with an :autocmd <buffer> on the CursorMoved,CursorMovedI events. On each move of the cursor, you have to check whether you're currently in one of those "certain lines", and modify the local 'textwidth' option accordingly:
autocmd CursorMoved,CursorMovedI <buffer> if IsSpecialLine() | setlocal textwidth=0 | else | setlocal textwidth=80 | endif
Put this into ~/.vim/after/ftplugin/tex.vim. (This requires that you have :filetype plugin on; use of the after directory allows you to override any default filetype settings done by $VIMRUNTIME/ftplugin/tex.vim.) Alternatively, you could define an :autocmd FileType tex autocmd ... directly in your ~/.vimrc, but this tends to become unwieldy once you have many customizations.
For the IsSpecialLine() function, you probably need to match a regular expression on the current line (getline('.') =~# "..."). If you can identify the "certain lines" through syntax highlighting, my OnSyntaxChange plugin can do all the work for you.
I've tried Ingo Karkat answer. Although it does work very well and does what the OP asks, I find it distracting (if I have long tables with row hundreds of characters long, there are a lot of shifts up and down when passing over tables) and can slow down a lot vim on big files (the textwidth and wrap are changed for the whole file, so running the autocmd for every cursor movement can be costly).
So I propose a static solution based on the idea that hopefully you have to modify a table as few times as possible. I've added the following to my ftplugin/tex.vim file:
" By default the text is
let s:textwidth = 90
let &l:textwidth=s:textwidth
" Toggle between "textwidth and wrap" and "textwidth=0 and nowrap".
" When editing a table, can be useful to have all the '&' aligned (using e.g.
" ':Tabularize /&') but without line brakes and wraps. Besides it's very
" annoying when line brakes "happen" while editing.
" As hopefully tables must be edited only from time to time, one can toggle
" wrap and textwidth by hand.
function! ToggleTwWrap() "{{{
" if textwidth and wrap is used, then disable them
if &textwidth > 0
let &l:textwidth=0
setlocal nowrap
else " otherwise re-enable them
let &l:textwidth=s:textwidth
setlocal wrap
endif
endfunction
So now if I want to edit manually a table I simply do
:call ToggleTwWrap()
to disable wrapping and textwidth and then again when I'm done with the table.
And of course you can create a command or a map
You can certainly set it for specific file types, but I don't think you can change those settings (or any, really) for individual lines.
Ingo Karat's answer works but setting textwidth on every single cursor move is too slow. This adapted version will only call setlocal textwidth= if the text width is actually going to change. This speeds things up considerably:
autocmd CursorMoved,CursorMovedI <buffer> if IsSpecialLine() | if &textwidth != 0 | setlocal textwidth=0 | endif | else | if &textwidth != 80 | setlocal textwidth=80 | endif | endif
What I'd like is to map one key, e.g. F4, so that pressing F4 will toggle the visibility of search highlights, and so that starting a new search enables visibility no matter the current visibility.
What I've tried:
Mapping F4 to :nohlsearch temporarily disables highlight visibility without turning the hlsearch setting off, but it does not toggle visibility back again.
Mapping F4 to :set hlsearch! does toggle on/off, but I don't want to toggle the hlsearch setting off, just the visibility setting. If hlsearch is off then it doesn't come back automatically with a new search.
There doesn't seem to be an opposite form of :nohlsearch and the command itself has problems being called from a function.
I've found similiar questions, but they don't provide an answer.
Update:
The first comment provides exactly what I was asking for, reproduced below:
let hlstate=0
nnoremap <F4> :if (hlstate == 0) \| nohlsearch \| else \| set hlsearch \| endif \| let hlstate=1-hlstate<cr>
(N.B. for anyone using this --- cramming the map onto one line instead of using a function is necessary since you can't effect a change on highlighting from inside a function.)
Related question for slightly different functionality: https://stackoverflow.com/a/16750393/1176650
Note, recent Vims (7.4.79) have the v:hlsearch variable available. This means you can improve your mapping to:
:nnoremap <silent><expr> <Leader>h (&hls && v:hlsearch ? ':nohls' : ':set hls')."\n"
" ctrl+c to toggle highlight.
let hlstate=0
nnoremap <c-c> :if (hlstate%2 == 0) \| nohlsearch \| else \| set hlsearch \| endif \| let hlstate=hlstate+1<cr>
Now just press ctrl+c to toggle highlight. Only quirk is you gotta press it twice after a search to toggle off highlight because searching doesn't increment the counter.
What I'd like is to map one key, e.g. F4, so that pressing F4 will
toggle the visibility of search highlights, and so that starting a new
search enables visibility no matter the current visibility.
Just tried this and seems to do the trick:
" switch higlight no matter the previous state
nmap <F4> :set hls! <cr>
" hit '/' highlights then enter search mode
nnoremap / :set hlsearch<cr>/
You can toggle with :set invhlsearch
From Highlight all search pattern matches, we can map a key to toggle the highlighting states. Unlike trusktr's answer, here we do use a variable to store the state.
"If you want to be able to enable/disable highlighting quickly, you can map a key to toggle the hlsearch option":
" Press F4 to toggle highlighting on/off, and show current value.
:noremap <F4> :set hlsearch! hlsearch?<CR>
"Or, press return to temporarily get out of the highlighted search":
:nnoremap <CR> :nohlsearch<CR><CR>
Other answer need to toggle highlight search, this is not so good.
Actually you only need to
let #/ = ''
I write a little function to implement this feature, and highlight current word (just like * star key), but not jump to next matched word, and not touch jumplist.
function! HLtoggle()
if (#/ == '')
let #/ = expand("<cword>")
else
let #/ = ''
endif
endfunc
it's simple, but i'm not find it in google.
Have fun with vim! :)
Okay, try this:
:map <F12> :set nohls<CR>:let #/ = ""<CR>:set hls<CR>
Then if you hit F12, it turns of the higlighting, then sets the last search string to an empty one (that is: clears it), and turns back on the highlighting.
Or if you want to save the search string, then you can do something like:
:map <F12> :set nohls<CR>:let #s = #/<CR>:let #/ = ""<CR>:set hls<CR>
:map <SHIFT><F12> :let #/=#s<CR>
Now after pressing SHIFTF12 the original searchstring will be set back and highlighted.
If that still not satisfy you, you can still do it like:
:map <F12> :highlight Search term=None ctermfg=None ctermbg=None guifg=None guibg=None<CR>
:map <SHIFT><F12> :highlight Search term=OV1 ctermfg=OV2 ctermbg=OV3 guifg=OV4 guibg=OV5<CR>
Where OVx are the original values which you can write down when you issue a :highlight Search<CR>. This way it can be turned off then set back on, but with two keyboard shortcuts. If you want it with one, you should create a function for that which toggles it, then create a mapping for that function.
Hmm, isn't :set hlsearch the opposite of :nohlsearch?
The first one turns matches highlighting on, the second one turns matches highlighting off temporarilly.
I don't understand what you mean by "I don't want to toggle the 'hlsearch' setting itself, just the visibility setting.": :set hlsearch and its pendant only deal with the visibility ("highlighting") of search matches, nothing else.
If you want to have matches highlighted each time you do a search just add :set hlsearch to your ~/.vimrc.
If you want the ability to turn highlighting off after a search just map F4 to :nohlsearch, highlighting will be back at your next search.
I use this slightly improved version from trusktr. Note that ctrl+c as used in the example from trusktr is already mapped to Escape by default which is very handy.
" Toggle highlight search
let hlstate=0
nnomap <Leader>b :if (hlstate%2 == 0) \| nohlsearch \| else \| set hlsearch \| endif \| let hlstate=hlstate+1<CR>:echo "toggled visibility for hlsearch"<CR>
inomap <Leader>b <ESC>:if (hlstate%2 == 0) \| nohlsearch \| else \| set hlsearch \| endif \| let hlstate=hlstate+1<CR>:echo "toggled visibility for hlsearch"<CR>a
In order to accomplish this, I added this unsophisticated line in my .vimrc:
nmap <LEADER>h /xxxxx<CR>
I use the following:
augroup onsearch
autocmd!
autocmd VimEnter * set hlsearch
augroup END
nnoremap <leader>/ :set hlsearch!<CR>
The autogroup ensure's that highlighting is enabled when entering vim, but not switched on when re-sourcing your vimrc file(s). The mapping toggles it on and off.
If anyone is looking to do this in neovim (in lua) this is a simple command that I wrote:
HLSTATE = vim.opt.hlsearch
function TOGGLE_SEARCH_HIGHLIGTING()
if HLSTATE == true then
vim.opt.hlsearch = false
HLSTATE = false
else
vim.opt.hlsearch = true
HLSTATE = true
end
end
vim.api.nvim_create_user_command('HighlightToggle', 'lua TOGGLE_SEARCH_HIGHLIGTING()', {})
You can then run it with the command :HighlightToggle (and assign in a keymap if you want).
In Vim, is there a way to enable on-the-fly highlighting for all matches when searching?
If I enable incsearch and type "/something" it will highlight the first match only. If I enable hlsearch and type "/something", nothing happens until I press enter (it only highlights the previous search).
In emacs the first match will be highlighted, and (after a slight delay) all other matches on the screen are highlighted in a different color, giving almost instant feedback when scanning for matches in a piece of code.
Doesn't answer your question, but maybe this Wikia post can help?
Quote from that post:
Put the following code in your vimrc, or create file
~/.vim/plugin/autohighlight.vim (Unix) or
$HOME/vimfiles/plugin/autohighlight.vim (Windows) containing the
script below. Then restart Vim.
To automatically highlight the current word, type z/. To turn off,
type z/ again.
" Highlight all instances of word under cursor, when idle.
" Useful when studying strange source code.
" Type z/ to toggle highlighting on/off.
nnoremap z/ :if AutoHighlightToggle()<Bar>set hls<Bar>endif<CR>
function! AutoHighlightToggle()
let #/ = ''
if exists('#auto_highlight')
au! auto_highlight
augroup! auto_highlight
setl updatetime=4000
echo 'Highlight current word: off'
return 0
else
augroup auto_highlight
au!
au CursorHold * let #/ = '\V\<'.escape(expand('<cword>'), '\').'\>'
augroup end
setl updatetime=500
echo 'Highlight current word: ON'
return 1
endif
endfunction
Add this to your .vimrc
hi Search guifg=black guibg=#C6C5FE gui=BOLD ctermfg=black ctermbg=cyan cterm=BOLD
Of course, you might want to change the colors to suit your needs.
I worked in NetBeans and liked this feature: when you place cursor in a variable name all occurences of the variable are highlighted. This is very useful for quick searching all occurences of the variable. Is it possible to add this behavior to Vim?
This autocommand will do what you want:
:autocmd CursorMoved * exe printf('match IncSearch /\V\<%s\>/', escape(expand('<cword>'), '/\'))
Edit: I have used the IncSearch highlight group in my example, but you can find other colours to use by running this command:
:so $VIMRUNTIME/syntax/hitest.vim
If you set
:set hlsearch
to highlight all occurrences of a search pattern, and then use * or # to find occurrences of the word under your cursor, that will get you some way to what you want. However I think a syntax-aware variable highlighting is beyond the scope of VIM.
This statement will allow a variable to enable/disable highlighting all occurences of the word under the cursor:
:autocmd CursorMoved * exe exists("HlUnderCursor")?HlUnderCursor?printf('match IncSearch /\V\<%s\>/', escape(expand('<cword>'), '/\')):'match none':""
One would activate highlighting with:
:let HlUnderCursor=1
And disable it with:
:let HlUnderCursor=0
One could easily define a shortcut key for enabling/disabling highlighting:
:nnoremap <silent> <F3> :exe "let HlUnderCursor=exists(\"HlUnderCursor\")?HlUnderCursor*-1+1:1"<CR>
Deleting the variable would prevent the match statement from executing, and not clear the current highlight:
:unlet HlUnderCursor
If you do not want to highlight language words (statements / preprocs such as if, #define) when your cursor is on these words, you can put this function in your .vimrc based on the #too_much_php answer :
let g:no_highlight_group_for_current_word=["Statement", "Comment", "Type", "PreProc"]
function s:HighlightWordUnderCursor()
let l:syntaxgroup = synIDattr(synIDtrans(synID(line("."), stridx(getline("."), expand('<cword>')) + 1, 1)), "name")
if (index(g:no_highlight_group_for_current_word, l:syntaxgroup) == -1)
exe printf('match IncSearch /\V\<%s\>/', escape(expand('<cword>'), '/\'))
else
exe 'match IncSearch /\V\<\>/'
endif
endfunction
autocmd CursorMoved * call s:HighlightWordUnderCursor()
i think that what you really want is the following plugin by Shuhei Kubota:
http://www.vim.org/scripts/script.php?script_id=4306
According to the description: 'This script highlights words under the cursor like many IDEs.'
Cheers.
vim_current_word works out of the box, is syntax aware, and allows customisable colours.
To map F2 to toggle highlighting:
map <F2> :set hlsearch!<CR> * #
It is certainly not perfect. '* #' jumps around a bit much...
This variant is optimized for speed (uses CursorHold instead of CursorMoved) and compatibility with hlsearch. The current search word highlighting will not be disrupted.
" autosave delay, cursorhold trigger, default: 4000ms
setl updatetime=300
" highlight the word under cursor (CursorMoved is inperformant)
highlight WordUnderCursor cterm=underline gui=underline
autocmd CursorHold * call HighlightCursorWord()
function! HighlightCursorWord()
" if hlsearch is active, don't overwrite it!
let search = getreg('/')
let cword = expand('<cword>')
if match(cword, search) == -1
exe printf('match WordUnderCursor /\V\<%s\>/', escape(cword, '/\'))
endif
endfunction
Similar to the accepted answer, but this way allows you to set a delay time after holding the cursor over a word before the highlighting will appear. The 1000 is in milliseconds and means that it will highlight after 1 second.
set updatetime=1000
autocmd CursorHold * exe
\ printf('match IncSearch /\V\<%s\>/', escape(expand('<cword>'), '/\'))
See :h CursorHold for more info.
vim-illuminate does the trick for me.
match-up does the trick for me.
vim match-up: even better % navigate and highlight matching words modern matchit and matchparen
Features
jump between matching words
jump to open & close words
jump inside (z%)
full set of text objects
highlight (), [], & {}
highlight all matching words
display matches off-screen
show where you are (breadcrumbs)
(neovim) tree-sitter integration