Skip to main content

Overview

Visual mode is one of Vim’s most powerful features, allowing you to select text and perform operations on the selection. CodeMirror Vim supports all three types of visual mode: character-wise, line-wise, and block-wise.

Visual Mode Types

CodeMirror Vim implements three visual modes, matching standard Vim behavior:
1

Character-wise Visual Mode (v)

Select characters individually. Press v in normal mode to enter.
// In normal mode, press:
// v - enter visual mode
// motion commands (h, j, k, l, w, e, etc.) to extend selection
// operator (d, y, c, etc.) to act on selection
Use cases:
  • Selecting specific words or characters
  • Precise text manipulation
  • Selecting parts of lines
2

Line-wise Visual Mode (V)

Select entire lines at a time. Press V (Shift+v) in normal mode.
// In normal mode, press:
// V - enter visual line mode
// j/k to select more lines
// operator to act on complete lines
Use cases:
  • Deleting multiple lines
  • Moving blocks of code
  • Indenting sections
3

Block-wise Visual Mode (Ctrl+v)

Select rectangular blocks of text. Press Ctrl+v in normal mode.
// In normal mode, press:
// Ctrl+v (or Ctrl+q) - enter visual block mode
// motion commands to define rectangle
// operator to act on block
Use cases:
  • Editing columns in aligned text
  • Adding/removing prefixes to multiple lines
  • Working with tabular data

Entering Visual Mode

From normal mode, use these keys to enter different visual modes:
  • v - Character-wise visual mode
  • V - Line-wise visual mode
  • <Ctrl-v> - Block-wise visual mode
  • <Ctrl-q> - Alternative for block-wise (useful when Ctrl+v is paste)
  • gv - Reselect the last visual selection
// From the default keymap:
{
  keys: 'v',
  type: 'action',
  action: 'toggleVisualMode'
}

// Usage:
// 1. Press 'v' in normal mode
// 2. Use motions (w, e, $, etc.) to select
// 3. Press operator (d, y, c) to act

Visual Mode Operations

Once in visual mode, you can use operators to manipulate the selection:

Common Operators

  • d - Delete selection
  • y - Yank (copy) selection
  • c - Change selection (delete and enter insert mode)
  • > - Indent selection right
  • < - Indent selection left
  • = - Auto-indent selection
  • ~ - Toggle case
  • u - Make lowercase
  • U - Make uppercase
  • gq - Format/wrap text (if defined)
Most normal mode operators work in visual mode, acting on the selected text.

Selection Behavior

Visual mode selections are tracked in the Vim state:
// From types.ts:
type vimState = {
  visualMode: boolean,     // True when in visual mode
  visualLine: boolean,     // True for line-wise visual
  visualBlock: boolean,    // True for block-wise visual
  lastSelection: {         // Last visual selection
    anchorMark: Marker,
    headMark: Marker,
    visualLine: boolean,
    visualBlock: boolean,
    visualMode: boolean,
    anchor: Pos,
    head: Pos,
  },
  // ... other properties
}

Visual Mode Examples

// Delete 5 lines:
// V      - Enter line-wise visual
// 4j     - Select 5 lines total (current + 4 down)
// d      - Delete selection

// Or use count directly:
// V5j    - Select 6 lines
// d      - Delete

DrawSelection Plugin Requirement

If you are not using basicSetup, you must include the drawSelection plugin to correctly render visual mode selections.
From the README:
import { basicSetup, EditorView } from 'codemirror';
import { vim } from "@replit/codemirror-vim";
import { drawSelection } from "@codemirror/view";

let view = new EditorView({
  doc: "",
  extensions: [
    vim(),
    // If NOT using basicSetup, add drawSelection:
    drawSelection(),
    // ... other extensions
  ],
  parent: document.querySelector('#editor'),
});
The basicSetup bundle already includes drawSelection, so you only need to add it explicitly if you’re building a custom extension setup.

Visual Mode State Tracking

The vim state tracks visual mode information:
import { getCM } from "@replit/codemirror-vim";

// Get the CodeMirror adapter
const cm = getCM(view);

// Check current mode
if (cm.state.vim.visualMode) {
  if (cm.state.vim.visualLine) {
    console.log('In line-wise visual mode');
  } else if (cm.state.vim.visualBlock) {
    console.log('In block-wise visual mode');
  } else {
    console.log('In character-wise visual mode');
  }
}

Mode Change Events

CodeMirror Vim fires events when entering or exiting visual mode:
import { CodeMirror } from "@replit/codemirror-vim";

const cm = getCM(view);

CodeMirror.signal(cm, 'vim-mode-change', function(e) {
  console.log('Mode:', e.mode);      // 'visual', 'normal', 'insert'
  console.log('SubMode:', e.subMode); // 'linewise', 'blockwise', or undefined
});
From the source code (index.ts:75-85):
this.cm.on("vim-mode-change", (e: any) => {
  if (!cm.state.vim) return;
  cm.state.vim.mode = e.mode;
  if (e.subMode) {
    cm.state.vim.mode += e.subMode === "linewise" ? " line" : " block";
  }
  cm.state.vim.status = "";
  this.blockCursor.scheduleRedraw();
  this.updateClass();
  this.updateStatus();
});

Exiting Visual Mode

There are several ways to exit visual mode:
  • <Esc> - Return to normal mode
  • v / V / <Ctrl-v> - Toggle off the current visual mode
  • Execute an operator (automatically exits after operation)
  • <Ctrl-c> - Alternative to Escape

Reselecting Last Selection

Use gv to reselect the last visual selection:
// From defaultKeymap:
{
  keys: 'gv',
  type: 'action',
  action: 'reselectLastSelection'
}

// Usage:
// 1. Make a visual selection and perform operation
// 2. Press 'gv' to reselect the same area

Visual Mode with Custom Operators

Your custom operators automatically work in visual mode:
import { Vim } from "@replit/codemirror-vim";

Vim.defineOperator("uppercase", function(cm, operatorArgs, ranges) {
  for (const range of ranges) {
    const text = cm.getRange(range.anchor, range.head);
    cm.replaceRange(text.toUpperCase(), range.anchor, range.head);
  }
});

// Add to keymap
defaultKeymap.push({
  keys: 'gU',
  type: 'operator',
  operator: 'uppercase'
});

// Now works with visual mode:
// v3w - Select 3 words
// gU  - Make uppercase

Best Practices

1

Use the Right Visual Mode

  • Character-wise (v) for word-level selections
  • Line-wise (V) for line operations
  • Block-wise (Ctrl+v) for column operations
2

Combine with Text Objects

Visual mode works great with text objects:
viw  - Select inner word
vip  - Select inner paragraph
vi{  - Select inside braces
va" - Select around quotes
3

Use gv to Reselect

After performing an operation, use gv to reselect the same area for additional operations.

Build docs developers (and LLMs) love