Skip to content

Instantly share code, notes, and snippets.

@Falconiere
Last active August 3, 2026 14:23
Show Gist options
  • Select an option

  • Save Falconiere/98ff1afe1897147c39d71cf9825ba58d to your computer and use it in GitHub Desktop.

Select an option

Save Falconiere/98ff1afe1897147c39d71cf9825ba58d to your computer and use it in GitHub Desktop.
fish selection keybindings — Shift/Ctrl/Option/Cmd text selection for the fish command line (requires fish >= 4)

fish selection keybindings

Shift / Ctrl / Option / Cmd text selection for the fish command line — select by character, word or line, and delete the selection with Backspace or Delete.

Requirements

fish 4.0 or newer. These bindings use fish 4's named keys (ctrl-shift-right) instead of raw escape sequences. On fish 3.x they silently misbehave — there, bind backspace ... binds the literal letters b,a,c,k,s,p,a,c,e rather than the Backspace key, so the selection is never deleted (and typing the word "backspace" triggers the binding instead). Check with fish --version.

Install

File Goes in
selection.fish ~/.config/fish/conf.d/
__select_extend.fish ~/.config/fish/functions/
__select_clear.fish ~/.config/fish/functions/
__select_delete.fish ~/.config/fish/functions/

Then exec fish.

Bindings

Chord Action
Shift + Left/Right extend selection by character
Shift + Up/Down extend selection by line
Ctrl + Shift + Left/Right extend selection by word
Option/Alt + Shift + Left/Right extend selection by word
Shift + Home/End extend selection to line bounds
Cmd + Shift + Left/Right extend selection to line bounds (macOS)
Left/Right, Home/End move, clearing the selection
Ctrl + Arrow, Option + Arrow move by word, clearing the selection
Backspace / Delete delete the selection, else delete one character

Not every terminal emits every chord. Run fish_key_reader and press a chord to see what yours actually reports.

Notes

  • Up/Down are deliberately not rebound. fish's own handling of them is history recall, and it is not reproducible from a user binding — there is no up-or-search input function, and up-line alone does not recall history. Rebinding them silently breaks the up-arrow.
  • Typing over a selection does not replace it. The highlight goes stale rather than the text being overwritten. This is fish behaviour in 4.x as well as 3.x. Press Backspace first, or any arrow key to clear the selection.
  • Selection state is read from fish itself via commandline --selection-start rather than tracked in a shell variable, so it cannot fall out of sync with what the editor actually has selected.
function __select_clear --description 'Drop any selection, then run the given cursor motions'
commandline -f end-selection $argv
end
function __select_delete --description 'Delete the selection if there is one, else run the fallback motion'
set -l start (commandline --selection-start)
if test -n "$start"
# Only the selection goes. The fallback must NOT also run, or backspace
# would eat one extra character beyond the highlighted text.
commandline -f kill-selection end-selection
else
commandline -f $argv
end
end
function __select_extend --description 'Start or extend the selection across the given cursor motions'
# fish's own selection state is the source of truth. `--selection-start`
# prints nothing when no selection is active, so there is no shadow
# variable to fall out of sync with what the editor actually has selected.
set -l start (commandline --selection-start)
if test -z "$start"
commandline -f begin-selection
end
commandline -f $argv
end
# Shift/Ctrl/Option/Cmd text selection keybindings (fish >= 4).
#
# Pairs with __select_extend / __select_clear / __select_delete.
#
# fish 4 decodes the terminal's escape sequences into named keys, so chords are
# written as `ctrl-shift-right` rather than `\e\[1\;6C`. Where the terminal
# supports the kitty keyboard protocol or xterm's modifyOtherKeys, fish can also
# tell apart combinations that legacy encodings collapsed together.
# To see what your terminal reports for a chord, run `fish_key_reader`.
if status is-interactive
# ---- Motions that clear the selection --------------------------------
bind right '__select_clear forward-char'
bind left '__select_clear backward-char'
# Up/Down are deliberately NOT rebound: fish's preset handling of them is
# history recall, and it is not reproducible from a user binding. There is
# still no `up-or-search` input function in fish 4, and `up-line` alone does
# not recall history. Rebinding them silently breaks the up-arrow.
# History recall replaces the whole buffer, dropping any selection with it.
# Word motion: Ctrl+Arrow, and Option/Alt+Arrow for the macOS habit
bind ctrl-right '__select_clear forward-word'
bind ctrl-left '__select_clear backward-word'
bind alt-right '__select_clear forward-word'
bind alt-left '__select_clear backward-word'
# Line motion
bind home '__select_clear beginning-of-line'
bind end '__select_clear end-of-line'
bind super-right '__select_clear end-of-line'
bind super-left '__select_clear beginning-of-line'
# ---- Motions that extend the selection -------------------------------
bind shift-right '__select_extend forward-char'
bind shift-left '__select_extend backward-char'
bind shift-up '__select_extend up-line'
bind shift-down '__select_extend down-line'
bind ctrl-shift-right '__select_extend forward-word'
bind ctrl-shift-left '__select_extend backward-word'
bind alt-shift-right '__select_extend forward-word'
bind alt-shift-left '__select_extend backward-word'
bind shift-home '__select_extend beginning-of-line'
bind shift-end '__select_extend end-of-line'
bind super-shift-right '__select_extend end-of-line'
bind super-shift-left '__select_extend beginning-of-line'
# ---- Delete the selection --------------------------------------------
bind backspace '__select_delete backward-delete-char'
bind delete '__select_delete delete-char'
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment