What Folds Actually Are
In Vim, folds are collapsible and expandable regions in a text document. You can use them to collapse entire paragraphs, functions, or code blocks so that only the first line remains visible. This makes navigating large files considerably easier.
The mnemonic for the command is simple. All fold commands begin with z, because the z looks like a folded piece of paper viewed from the side.
The Six Fold Methods
Vim offers six different methods for how folds are created. You set them with :set foldmethod=METHOD or enter them permanently in your ~/.vimrc.
- manual - You create folds yourself with
zf, for unstructured text - indent - Indentation determines the fold depth, ideal for program code
- expr - Folds are defined by an expression, for log files or special filters
- syntax - Syntax highlighting defines the folds, ideal for program code
- diff - Unchanged text is folded
- marker - Markers in the text such as
{{{and}}}define folds
For everyday use, indent for code and manual for everything else are the most practical methods.
foldlevel - Controlling the Fold Depth
The foldlevel option determines how many levels of folds are open or closed at the same time. It is the central control for the fold depth in the current window.
The Typical Values
- foldlevel=0 - All folds are closed. You only see the outermost structure, for example chapter headings or top-level functions
- foldlevel=1 - Only the top level is expanded, folds beneath it remain closed. Good for an overview of the main blocks
- foldlevel=2 - Two levels are visible, deeper folds remain closed. Practical for nested code structures
- foldlevel=99 - Practically everything is open. Only explicitly closed folds remain closed
foldlevel vs. foldlevelstart
An important difference: foldlevel applies to the current window and takes effect immediately. foldlevelstart determines the fold depth with which a file is opened.
So if you want a file to be completely expanded when opened, you set foldlevelstart=99 in your ~/.vimrc.
Important Commands
:set foldlevel?shows the current value:setlocal foldlevel=1sets the depth only for the current window2zMcloses all folds up to level 2, leaving level 1 open
Saving Folds Permanently
An important point that many people do not know. When you close a file, manually created folds are lost. Vim does not remember the state automatically.
For this there are the commands :mkview and :loadview. With :mkview you save the current state including the folds. When you open the file again later, you load everything back with :loadview. You can save up to ten different views per file.
Storage Location of Folds
Vim saves the views in the directory defined in the viewdir option.
The default value depends on your operating system:
- Linux and Unix (including macOS):
~/.vim/view - Windows:
$VIM/vimfiles/view
In this folder, Vim creates a separate view file for each file. The file name is generated from the path of the original file, with special characters replaced by equals signs (=).
Finding Out the Current Storage Location
You can display the path directly in Vim:
:set viewdir?
The output shows you where Vim currently searches or saves.
Changing the Storage Location
If you want to change the default path (for example, to keep your home directory tidy), you can adjust the option in your ~/.vimrc:
set viewdir=~/.vim/my-views
In newer Vim versions, the default value now also respects the XDG_CONFIG_HOME environment variable and then uses ~/.config/vim/view.
Deleting View Files
Since there is no built-in command for deleting, you have to remove the files manually. Simply navigate to the folder mentioned above and delete the corresponding files.
The Most Important Commands for Everyday Use
You should know the basic commands, then you will already get very far.
Opening and Closing
zoopens a fold under the cursor (open)zccloses a fold under the cursor (close)zatoggles the fold, opens if closed, closes if open (alternate)zRopens all folds in the document (Reset)zMcloses all folds in the document (Minimize)
Navigation Between Folds
Combination with the classic navigation commands:
zjjumps to the next foldzkjumps to the previous fold[zjumps to the beginning of the current fold]zjumps to the end of the current fold
Creating and Deleting
zffollowed by a motion creates a fold, for examplezfapfor a whole paragraph (fold)zddeletes the fold under the cursor, the text is preserved (delete)zEdeletes all folds in the window (Eliminate)
Practical Examples - Fold Methods
Vim offers six different methods for creating folds. Which one you choose depends on what you are editing and how much control you want.
manual - Manual Folding with zf
The most direct method. You mark a region and fold it with zf. This works visually, with motions, or with brackets.
Visually mark and fold
Mark the region with
v(character-wise),V(line-wise), orCtrl-v(block-wise)Press
zf
Vim creates a fold from it. The text is preserved, only hidden.
Folding with motions
zfapfolds a whole paragraph (a paragraph)zfGfolds from the cursor to the end of the file (Go to end)zfggfolds from the beginning of the file to the cursor (go all the way up)
Folding Between Brackets
The most elegant way for code. Place the cursor on an opening bracket such as { or [ and press zf%. Vim jumps to the matching closing bracket and folds everything in between.
An example in a JavaScript file:
function calculateSum(a, b) {
const result = a + b;
console.log(result);
return result;
}
With the cursor on the opening { and zf%, it then looks like this:
+-- 4 lines: function calculateSum(a, b) {
indent - Folding by Indentation
The most practical method for code. Vim automatically creates folds based on the indentation depth.
:set foldmethod=indent
Each level of indentation becomes a fold level. When opening a file with foldlevel=1, all functions are collapsed and you see only the structure at a glance.
marker - Folding by Markers
You place special markers in the text that Vim recognizes as fold boundaries. The default markers are {{{ and }}}.
:set foldmethod=marker
An example:
<!-- {{{ -->
<div class="container">
<p>First line</p>
<p>Second line</p>
</div>
<!-- }}} -->
The text between the markers becomes a fold. The advantage: The fold is preserved when the file is opened again. The disadvantage: You are modifying the file itself.
syntax - Folding by Syntax
Vim uses the existing syntax rules to create folds. For most programming languages, these rules are already present.
:set foldmethod=syntax
For Ruby code, for example, all methods are automatically folded. You do not need to configure anything further.
expr - Folding by Expression
The most flexible method. You define an expression that decides for each line whether it is folded.
:set foldmethod=expr
:set foldexpr=getline(v:lnum)=~'ERROR'
This example folds all lines that do not contain the word ERROR. Ideal for log files, to leave only the errors visible.
diff - Folding by diff
When you compare two versions of a file, unchanged regions are automatically folded. This method is usually activated automatically when you use vimdiff or :diffthis.
Practical Application
For code files, I usually use foldmethod=indent in combination with foldlevel=1. Then, when opening a file, all functions are collapsed and I see only the structure at a glance. With za I then expand the function.
For longer text documents, foldmethod=manual is often better. Then I can decide for myself which paragraphs I collapse.
And if the folds ever become too much, zR or zn helps to open everything again.
Sources
Vim is available as open-source software.
- Website: https://www.vim.org/
- Vim Documentation Folding: https://vimhelp.org/fold.txt.html
- Vim User Manual Folding: https://vimhelp.org/usr_28.txt.html
- Vim Folding Wiki: https://vim.fandom.com/wiki/Folding
Deleting Old Views - Vimscript
Here is a Vimscript that finds and deletes orphaned view files, along with instructions for integrating it.
The script uses the functions readdir() to list the view folder and delete() to delete the files. The reversal of the naming convention (=+ to /) is the core of the check.
The Reversal of the Naming Convention
This is the crucial point. Vim does not save view files under the original name, but encodes the complete path into the file name. Every slash (/) is replaced by the string =+.
An example. The original file /home/user/test.txt becomes a view file with the name =+home=+user=+test.txt in the view folder.
" Function to clean up orphaned view files
function! s:CleanOrphanedViews()
" Determine the view directory (default: ~/.vim/view)
let view_dir = expand(&viewdir)
" Check whether the view directory exists
if !isdirectory(view_dir)
echohl WarningMsg
echo "View directory not found: " . view_dir
echohl None
return
endif
let orphaned_count = 0
" List all files in the view directory
for view_file in readdir(view_dir)
let view_path = view_dir . '/' . view_file
" Only process files (no subfolders)
if !filereadable(view_path)
continue
endif
" Convert the file name back into a path
" Vim replaces '/' with '=+' in the file name
let original_path = substitute(view_file, '=+', '/', 'g')
" Check whether the original file still exists
" filereadable() is more robust than glob() with permission problems
if !filereadable(original_path)
" File no longer exists -> delete view
if delete(view_path) == 0
let orphaned_count += 1
echom "Orphaned view deleted: " . view_file
else
echohl WarningMsg
echom "Error deleting: " . view_file
echohl None
endif
endif
endfor
" Output summary
if orphaned_count > 0
echom "Cleanup complete: " . orphaned_count . " orphaned view(s) deleted."
else
echom "No orphaned view files found."
endif
endfunction
" Define command to call the function
command! CleanViews call s:CleanOrphanedViews()
How the Script Works
- Determine directory: The script reads the global option
&viewdir, which by default points to~/.vim/view(Unix) or$VIM/vimfiles/view(Windows). - List files: With
readdir(), all entries in the view folder are read. - Reconstruct path: The crucial step. Vim encodes the original path in the view file name by replacing every slash (
/) with the string=+. Thesubstitute()function reverses this replacement. - Existence check:
filereadable()checks whether the original file reconstructed in this way still exists and is readable. This is more robust than a pureglob()check if permissions are involved. - Deleting: If the original file is missing, the view file is removed with the built-in
delete()function.
Integrating into the Vim Configuration
You have two options for using the script permanently.
Option 1: Insert directly into .vimrc
Copy the entire code block into your ~/.vimrc (or ~/.config/nvim/init.vim). After saving and restarting Vim, you can use the command :CleanViews.
Option 2: As a separate plugin (recommended for tidiness)
- Create a file named
cleanviews.vimin the directory~/.vim/plugin/. - Insert the code there.
- Vim automatically loads files in
~/.vim/plugin/at startup.
In both cases, the command :CleanViews is available. After running, it outputs a message stating how many orphaned view files were deleted.