Skip to main content

Editing Cells

VisiData's cell editor lets you modify values directly in any sheet. Edits are held in memory — nothing reaches disk until you explicitly save with Ctrl+S.

Think of it like this: VisiData is always working on a live copy in RAM. Your original file is untouched until you consciously press Save.

Learning Focus

Understand the edit lifecycle: enter edit mode (e), modify, accept or cancel, then optionally save (Ctrl+S). Nothing is written to disk unless you explicitly save. To copy a cell value to another cell, use zy → zp (see Copying and Pasting Rows). For bulk column editing commands, see Column Editing.

warning

Your source file is unchanged until you press Ctrl+S and confirm overwrite or provide a new filename.

Sample Data Used in This Lesson​

cat > ~/github/practice-folder/visidata/04-cleaning/01-dirty_orders.csv << 'EOF'
order_id,customer,status,amount,region
1001,Alice,active,250,sg
1002,Bob,pending,150,kl
1003,Carol,actve,400,sg
1004,Dave,error,0,
1005,Eve,pending,320,kl
EOF

vd ~/github/practice-folder/visidata/04-cleaning/01-dirty_orders.csv

Inside VisiData:

order_id customer status amount region
1001 Alice active 250 sg
1002 Bob pending 150 kl
1003 Carol actve 400 sg ← typo: "actve"
1004 Dave error 0 ← missing region
1005 Eve pending 320 kl

Fix a Typo in a Cell​

Carol's status has a typo: actve instead of active.

# Move cursor to Carol's 'status' cell (row 3, status column)
e
# Edit field opens — shows current value: actve
# Use Backspace to delete, type: active
Enter

Result:

order_id customer status amount region
1001 Alice active 250 sg
1002 Bob pending 150 kl
1003 Carol active 400 sg ← fixed
1004 Dave error 0
1005 Eve pending 320 kl

Inside Edit Mode — Keyboard Shortcuts​

KeyAction
EnterAccept the edit
Ctrl+CCancel and discard the edit
Ctrl+AMove cursor to beginning of field
Ctrl+EMove cursor to end of field
Ctrl+KClear from cursor to end of line
Ctrl+UClear from cursor to beginning of line
Ctrl+OOpen this cell value in external $EDITOR
TabAccept edit and move cursor right
Shift+TabAccept edit and move cursor left
Up / DownAccept edit and use previous/next input history

Bulk Set Column Value for Selected Rows (ge)​

Instead of editing each cell one by one, use ge to set the same value for all selected rows in the current column.

# Select all 'pending' rows
|
# Enter: pending

# Bulk-set their status to 'PENDING' (uppercase)
ge
# Enter: PENDING

Before:

order_id customer status amount region
1002 Bob pending 150 kl
1005 Eve pending 320 kl

After ge → PENDING:

order_id customer status amount region
1002 Bob PENDING 150 kl
1005 Eve PENDING 320 kl

Fill Null Cells Downward (f)​

If a column has blank/null cells, press f to fill each null with the non-null value from the row above.

Before (region column has a blank for Dave):

order_id customer status amount region
1001 Alice active 250 sg
1002 Bob pending 150 kl
1003 Carol active 400 sg
1004 Dave error 0 ← blank
1005 Eve pending 320 kl
# Move cursor to 'region' column
f

After — Dave's region is filled from Carol's row above:

order_id customer status amount region
1001 Alice active 250 sg
1002 Bob pending 150 kl
1003 Carol active 400 sg
1004 Dave error 0 sg ← filled from above
1005 Eve pending 320 kl
note

f fills from the nearest non-null value above. It's perfect for spreadsheets where a category label only appears in the first row of a group.


Undo and Redo​

# After making a change:
U # undo the last change
R # redo (reapply the undone change)

To enable undo, add this to ~/.visidatarc:

options.undo = True

Edit a Single Cell in an External Editor (e, then Ctrl+O)​

For long text, descriptions, or JSON content that is hard to edit inline, hand one cell value to your system $EDITOR. No row selection is needed.

# 1. Move the cursor onto the cell (do NOT select any rows)
# 2. Enter edit mode
e # or i
# 3. With the input line open, launch the external editor
Ctrl+O # opens just this one value in $EDITOR (vim, nvim, nano, ...)
# 4. Edit the value, save, and quit the editor
# → the text returns to the input line and is applied to the cell
Caret notation

^O in VisiData help and cheat sheets means Ctrl+O — the ^ is the standard caret notation for the Ctrl key. A lowercase g before it is a separate keypress, so g^O = press g, then Ctrl+O.

o is not Ctrl+O

Plain o runs open-file (it prompts for a path and opens a new sheet). That is not the external editor. Only Ctrl+O — pressed while a cell's input line is open — launches $EDITOR.

$EDITOR must be set and exported in the shell that launched VisiData:

export EDITOR=nvim # put in ~/.bashrc to make it permanent

Local Common-Config Shortcuts (zn, zq)​

The shared local VisiData config adds two shortcuts that are not built-in VisiData defaults:

KeyAction
zn (z, then n)Open the current cell directly in Neovim, without first entering VisiData's inline editor. Use :wq in Neovim to apply the edited value and return.
zq (z, then q)Force-save the current sheet to its default save path without a filename or overwrite prompt, then quit after saving succeeds.
zq overwrites without asking

zq may replace the original source file. It bypasses the overwrite confirmation and does not ask for another filename. Use Ctrl+S instead when you want VisiData's normal save-path and overwrite prompts. If the forced save fails, zq leaves the sheet open.

These bindings are specific to the local common-config setup and require its .visidatarc.d configuration to be loaded.


Bulk Edit Rows with an External Editor (g^O)​

g^O (press g, then Ctrl+O) opens all currently visible columns of the selected rows in $EDITOR as a single temporary TSV file — one row per line, one column per tab. When you save and quit, VisiData writes the edited values back into the selected rows.

It edits whole rows, not a single column. To edit just one column, hide the other columns first so the target is the only visible one.

# 1. Select the rows you want to edit
s # select current row
gs # or select ALL rows
t / gt # or toggle current / all rows

# 2. (optional) hide the columns you do NOT want to edit
- # hide the current column

# 3. Launch the editor on the selected rows
g Ctrl+O # g, then Ctrl+O
# VisiData prompts: "edit N rows as filetype:" → Enter to accept 'tsv'

# 4. In the temp TSV: edit the values, then save and quit

Example — fix only the status column:

# Move to the 'status' column, then hide every other column with '-'
# (there is no single-column mode for g^O; hiding is how you scope it)
gs # select all rows
g Ctrl+O # Enter to accept the 'tsv' filetype
# edit each status value in the editor, save, quit
U # undo if needed (requires options.undo = True)
Requires selected rows

With nothing selected, g^O stops with a status message such as no rows selected. Select rows with s or gs first.

Keep the TSV structure intact

In the editor, do not delete or add lines, and leave the header row in place. VisiData maps the file back to the rows by position, so changing the number of lines or the header can misalign the values.

note

External-editor changes live in memory like any other edit. Press Ctrl+S to write the sheet to disk.


Renaming Columns​

^ rename current column (opens input prompt)
g^ rename all unnamed columns to content of selected rows
z^ rename current column to content of current cell
# Move cursor to 'order_id' column
^
# Enter: id
# Column header changes from 'order_id' to 'id'

Saving Changes​

Ctrl+S save current sheet to file (prompts for filename)
g Ctrl+S save all open sheets to files
z Ctrl+S save current column only
info

If you save back to the original file, VisiData will prompt for confirmation. Always use a new filename first if you are unsure about overwriting.

# Save changes to a new file
Ctrl+S
# Enter: /tmp/orders_cleaned.csv
# Original file is untouched

# Save to original (with confirmation)
Ctrl+S
# Enter: ~/github/practice-folder/visidata/04-cleaning/01-dirty_orders.csv
# VisiData prompts: "overwrite?" → yes

Complete Edit Commands Reference​

KeyAction
eEnter edit mode on current cell
zn (custom)Open current cell directly in Neovim
geSet current column for all selected rows
Ctrl+OWhile editing a cell, open that cell value in external $EDITOR
g Ctrl+OEdit all visible columns of selected rows in external $EDITOR (temp TSV)
fFill null cells with value from above
^Rename current column
zmCopy cell to tmux buffer (custom)
UUndo most recent modification
RRedo most recent undo
Ctrl+SSave current sheet
zq (custom)Force-save to default path without prompts, then quit

Copy Cell to Tmux Buffer (Custom)​

The zm keybinding copies the current cell value to the tmux paste buffer, enabling cross-pane pasting.

zm # copy current cell to tmux buffer
# Switch to another tmux pane
Ctrl+b ] # cell value is pasted

This uses cursorDisplay (same as zY for system clipboard) and pipes to tmux load-buffer. Requires tmux to be running. See Plugins for details.

Hands-On Practice​

vd ~/github/practice-folder/visidata/04-cleaning/01-dirty_orders.csv

# 1. Move to Carol's 'status' cell (row with 'actve'), press e → fix to 'active'
# 2. Press U → undo the change (confirm it reverts)
# 3. Select rows where status = 'pending': | → Enter: pending
# 4. Bulk-set status: ge → Enter: PENDING
# 5. Press U → undo
# 6. Move to 'region' column where Dave has no region → press f (fill from above)
# 7. Press Ctrl+S → save as /tmp/orders_edited.csv

What's Next​