Real-World Workflows

Summary: in this tutorial, you will learn put everything together with practical vim workflows for code editing, git integration, multi-file operations, and a comprehensive cheat sheet.

Real-World Workflows

You've learned Vim's individual features — modes, motions, operators, macros, registers, and configuration. Now it's time to put everything together with real-world workflows that show how experienced Vim users actually work day to day.

What you'll learn in this tutorial:

  • Common code editing patterns that make you faster
  • How to use Vim with Git for version control
  • Multi-file editing techniques for project-wide changes
  • How to compile and run code from inside Vim
  • A comprehensive cheat sheet you can reference anytime

Code Editing Patterns

Renaming a Variable

You have a variable called count and want to rename it to total throughout the file:

:%s/\<count\>/total/gc

Breaking it down:

  • % — every line in the file
  • s/old/new/ — substitute command
  • \<count\> — the exact word "count" (word boundaries prevent matching "counter" or "account")
  • g — all occurrences per line
  • c — confirm each replacement (so you don't change "count" in comments by accident)

Duplicating a Function

Want to copy a function and modify it?

" Put cursor anywhere inside the function
V                " Start line selection
ip               " Select the inner paragraph (the whole function block)
y                " Yank (copy)
}                " Move to the blank line after the function
p                " Paste below

Or if the function uses curly braces:

" Put cursor on the opening { of the function
V%               " V starts line selection, % jumps to matching }
y                " Yank the entire function
}p               " Move to the next blank line and paste

Adding a Parameter to a Function

Your function is function process(data) and you want to add a second parameter:

f(               " Find the opening parenthesis
%                " Jump to the closing parenthesis
i, options<Esc>  " Insert before ), type ", options", exit Insert mode

Result: function process(data, options)

Commenting/Uncommenting Code

Without plugins, using block visual mode:

" Comment out lines 10-15 (JavaScript // comments)
10G              " Go to line 10
Ctrl-v           " Block visual mode
5j               " Select 5 more lines (6 total)
I// <Esc>        " Insert "// " at the start of each line
 
" Uncomment them
10G              " Go to line 10
Ctrl-v           " Block visual mode
5j               " Select the same lines
2l               " Select 3 characters ("// ")
d                " Delete the block

With the vim-commentary plugin (if installed):

10G              " Go to line 10
V5j              " Select 6 lines
gc               " Toggle comments on/off

Wrapping Text in a Function Call

You have value and want to change it to parseInt(value):

ciw              " Change the word (deletes "value", enters Insert mode)
parseInt(<C-r>")<Esc>
" Ctrl-r " pastes the deleted word from the unnamed register
" So you type: parseInt( ... paste "value" ... )

Result: parseInt(value)

Aligning Equals Signs

Given this messy code:

const name = "Alice";
const age = 30;
const city = "New York";
const occupation = "Developer";

You can use Visual block mode to align the = signs:

" Select the = column using block visual mode
" Position on the first =, Ctrl-v, extend down, then adjust with spaces
" This is easier with a plugin like vim-easy-align, but doable manually

For frequent alignment tasks, consider the junegunn/vim-easy-align plugin. You can select lines, press ga, then = to align around equals signs. It handles many alignment patterns automatically.

Sorting Imports

If you have a block of import statements:

" Select the import lines
V                " Line visual mode
}                " Select to the next blank line
:sort            " Sort alphabetically

Deleting Inside Matching Pairs

These are incredibly common patterns:

ci(              " Change inside parentheses: foo(old) → foo(|)
ci{              " Change inside braces: {old} → {|}
ci[              " Change inside brackets: [old] → [|]
ci"              " Change inside quotes: "old""|"
ci'              " Change inside single quotes: 'old' → '|'
dit              " Delete inside HTML tags: <div>old</div> → <div></div>

The | shows where your cursor ends up in Insert mode.

Working with Git

Viewing Changes

If you have the vim-gitgutter plugin (from the configuration tutorial), you'll see change indicators in the left margin:

  • + — new lines (added)
  • ~ — modified lines
  • - — deleted lines

Navigate between changes:

]c               " Jump to the next change
[c               " Jump to the previous change

Running Git Commands from Vim

You can run any shell command from Vim using :!:

:!git status              " See which files have changed
:!git diff                " See what lines changed
:!git add %               " Stage the current file (% = current filename)
:!git commit -m "message" " Commit with a message
:!git log --oneline -10   " See the last 10 commits

The % in :!git add % is a special Vim variable that expands to the current file's name. So if you're editing src/app.js, the command becomes git add src/app.js.

Reviewing a Diff

Open two versions of a file side by side:

:vsp                      " Split vertically
:e other-version.js       " Open the other version
:windo diffthis           " Turn on diff mode in both windows

Or from the command line:

vim -d file1.js file2.js  " Open both files in diff mode

In diff mode:

  • Changed sections are highlighted
  • ]c and [c jump between changes
  • do — get the change from the other window ("diff obtain")
  • dp — send the change to the other window ("diff put")

Multi-File Operations

Search Across Files

:vimgrep /TODO/ **/*.js   " Search all JS files recursively
:copen                     " Open the results window

In the results window:

  • Press Enter to jump to a result
  • :cnext (:cn) — go to the next result
  • :cprev (:cp) — go to the previous result
  • :cclose — close the results window

Replace Across Files

To find and replace text across multiple files:

" Step 1: Find all files containing the text
:vimgrep /oldFunction/ **/*.js
 
" Step 2: Run substitute on all results
:cfdo %s/oldFunction/newFunction/gc | update

Breaking it down:

  • :cfdo — run a command on every file in the quickfix list
  • %s/old/new/gc — find and replace with confirmation
  • | update — save the file after replacing
# From the terminal — open all JavaScript files
vim **/*.js
 
# Open all files matching a pattern
vim src/components/*.tsx

Or from inside Vim:

:args **/*.js            " Add all JS files to the argument list
:argdo %s/old/new/ge | update  " Replace in all of them

Be careful with multi-file replacements! Always use the c (confirm) flag the first time, or use Git so you can undo changes with git checkout -- . if something goes wrong.

Compiling and Running Code

Running the Current File

:!python3 %              " Run the current file with Python
:!node %                  " Run with Node.js
:!bash %                  " Run as a shell script
:!gcc % -o output && ./output  " Compile and run C code

Using Vim's :make Command

If your project has a Makefile:

:make                     " Run the Makefile
:copen                    " Open the error list
:cnext                    " Jump to the next error
:cprev                    " Jump to the previous error

Quickfix Window

The quickfix window shows compile errors, search results, and other lists. It's a central feature for navigating errors:

CommandWhat It Does
:copenOpen the quickfix window
:ccloseClose it
:cnext or :cnGo to the next item
:cprev or :cpGo to the previous item
:cfirstJump to the first item
:clastJump to the last item

Productivity Tips

Use Marks for Key Positions

When working on a large file, set marks at important locations:

mf               " Mark the function you're working on
mt               " Mark the test section
mc               " Mark the config/imports section

Then quickly jump between them: 'f, 't, 'c

Use the Alternate File

Ctrl-^ switches between the current file and the last file you viewed. This is incredibly useful when:

  • Switching between a source file and its test file
  • Switching between an HTML file and its CSS
  • Checking a function definition and then going back

Terminal Inside Vim

Vim 8+ has a built-in terminal:

:terminal                 " Open a terminal below
:vert terminal            " Open a terminal on the right

In the terminal window:

  • You're in a real terminal — run any command
  • Press Ctrl-w N (or Ctrl-\ Ctrl-n) to switch to Normal mode (allows copying text)
  • Press i or a to go back to terminal input mode
  • Type exit to close the terminal

Command-Line Window

Vim keeps a history of all your commands and searches. Press q: to open the command-line window — a buffer containing your command history. You can:

  • Navigate with normal motions
  • Edit a previous command
  • Press Enter to execute it

Press q/ for search history instead.

Accidentally opened the command-line window? It's a common slip to press q: when you meant :q (quit). Just press :q to close it.

Vim Cheat Sheet

Here's a comprehensive reference of the most useful Vim commands. Bookmark this page!

Movement

CommandAction
h j k lLeft, Down, Up, Right
w / bNext / Previous word
e / geEnd of word / End of previous word
0 / $Start / End of line
^First non-blank character
gg / GTop / Bottom of file
{number}GGo to line number
Ctrl-d / Ctrl-uHalf page down / up
Ctrl-f / Ctrl-bFull page down / up
f{char} / F{char}Find character forward / backward
%Jump to matching bracket
{ / }Previous / Next paragraph
H / M / LTop / Middle / Bottom of screen

Editing

CommandAction
i / aInsert before / after cursor
I / AInsert at start / end of line
o / ONew line below / above
d{motion}Delete
c{motion}Change (delete + insert)
y{motion}Yank (copy)
dd / cc / yyDelete / Change / Yank entire line
D / CDelete / Change to end of line
x / XDelete character / previous character
r{char}Replace single character
p / PPaste after / before
u / Ctrl-rUndo / Redo
.Repeat last change
JJoin lines

Text Objects

CommandSelects
iw / awInner / around word
is / asInner / around sentence
ip / apInner / around paragraph
i" / a"Inside / around double quotes
i( / a(Inside / around parentheses
i{ / a{Inside / around curly braces
it / atInside / around HTML tags
CommandAction
/patternSearch forward
?patternSearch backward
n / NNext / Previous match
* / #Search word under cursor forward / backward
:%s/old/new/gReplace all in file
:%s/old/new/gcReplace with confirmation
:nohClear search highlights

Windows

CommandAction
:sp / :vspHorizontal / Vertical split
Ctrl-w h/j/k/lMove between windows
Ctrl-w =Equalize window sizes
Ctrl-w oClose all other windows
Ctrl-w qClose current window

Buffers and Files

CommandAction
:e fileOpen file
:lsList buffers
:bn / :bpNext / Previous buffer
:bdClose (delete) buffer
Ctrl-^Toggle last two files
:wSave
:qQuit
:wq or ZZSave and quit
:q!Quit without saving

Visual Mode

CommandAction
vCharacter selection
VLine selection
Ctrl-vBlock (column) selection
gvReselect last selection
oSwap cursor to other end

Macros

CommandAction
q{a-z}Start recording into register
qStop recording
@{a-z}Play macro
@@Repeat last macro
{n}@{a-z}Play macro n times

Marks

CommandAction
m{a-z}Set mark
'{a-z}Jump to mark (line)
`{a-z}Jump to mark (exact position)
Ctrl-oJump back
Ctrl-iJump forward

What's Next?

Congratulations — you've completed the Vim tutorial series! Here's how to keep improving:

  1. Practice daily. The commands will feel slow at first. After a week of consistent use, they become muscle memory.

  2. Learn incrementally. Don't try to memorize everything at once. Pick 2-3 new commands each week and focus on using them until they're automatic.

  3. Use vimtutor. Type vimtutor in your terminal for a built-in interactive tutorial that takes about 30 minutes.

  4. Read :help. Vim has incredibly detailed built-in documentation. Type :help followed by any command or topic (e.g., :help text-objects, :help registers).

  5. Explore plugins when you feel the need — not before. If you find yourself doing something repetitive that Vim can't handle, there's probably a plugin for it.

The key to Vim mastery: Notice when you're doing something the slow way, then find the Vim way to do it faster. Over time, this curiosity compounds into incredible efficiency.

🏋️

Practice: Putting It All Together

Create two practice files and try these real-world workflows:

# Create two files
cat > app.js << 'EOF'
function calculateTotal(items) {
    var total = 0;
    for (var i = 0; i < items.length; i++) {
        total += items[i].price;
    }
    return total;
}
 
function formatPrice(amount) {
    return "$" + amount.toFixed(2);
}
 
// TODO: add tax calculation
// TODO: add discount support
// TODO: add currency formatting
EOF
 
cat > test.js << 'EOF'
const { calculateTotal, formatPrice } = require('./app');
 
test('calculates total', () => {
    const items = [{price: 10}, {price: 20}];
    expect(calculateTotal(items)).toBe(30);
});
 
test('formats price', () => {
    expect(formatPrice(9.99)).toBe("$9.99");
});
EOF

Now try these workflows:

  1. Open both files: vim -O app.js test.js
  2. In app.js, rename var to const: :%s/\<var\>/const/g
  3. Switch to test.js with Ctrl-w l
  4. Switch back with Ctrl-^
  5. In app.js, use * on the word total to see all occurrences
  6. Record a macro to change each TODO: line from a comment to a function stub
  7. Use :vimgrep /function/ % to find all functions, then :copen to see results
  8. Run the file: :!node %
  9. Set a mark at the calculateTotal function: mf
  10. Jump to the end of the file with G, then back to the mark with 'f
Show Solution
" 1. Open both files side by side
" (from terminal: vim -O app.js test.js)
 
" 2. Rename var to const in app.js
" Make sure you're in the app.js window
:%s/\<var\>/const/g
" "var total" → "const total", "var i" → "const i"
 
" 3. Switch to test.js
Ctrl-w l         " Move to the right window
 
" 4. Switch back to app.js
Ctrl-^           " Toggles back to the last file (app.js)
 
" 5. Search for "total"
" Put cursor on the word "total"
*                " Highlights every "total" in the file, jumps to next
n                " Next occurrence
N                " Previous occurrence
 
" 6. Macro: convert TODO comments to function stubs
" Go to the first TODO line
qa               " Start recording
0                " Go to start of line
c$               " Change the entire line
function todo() {}<Esc>  " Type the stub
F}               " Move cursor back to before }
i<CR>    // implement<CR><Esc>  " Add placeholder content
j                " Move to next line
q                " Stop recording
2@a              " Run on the other two TODO lines
 
" 7. Find all functions
:vimgrep /function/ %   " Search current file
:copen                   " Open quickfix window
" Press Enter on any line to jump to that function
:cclose                  " Close quickfix when done
 
" 8. Run the file
:!node %         " Runs app.js with Node.js
" (This won't produce output since there's no main call,
"  but it checks for syntax errors)
 
" 9. Set a mark
" Go to the calculateTotal function
mf               " Set mark 'f' (for "function")
 
" 10. Navigate with marks
G                " Jump to the bottom of the file
'f               " Jump right back to calculateTotal!
 
:qa!             " Quit all files without saving
Was this page helpful?
SR

Written by the ShellRAG Team

The ShellRAG editorial team writes practical, beginner-friendly Vim tutorials with tested code examples and real-world use cases. Every article is technically reviewed for accuracy and updated regularly.

Learn more about us →