Shift+Arrow keys insert characters in WSL/Bash; Windows Terminal rewrites explicit selection keybindings to "id": null #23261

Closed
opened 2026-01-31 08:37:05 +00:00 by claunia · 6 comments
Owner

Originally created by @SlintyLinters on GitHub (May 17, 2025).

Windows Terminal version

1.22.11141.0

Windows build number

10.0.26100.0

Other Software

Windows Terminal Preview: Version: 1.23.11132.0

WSL2 Distribution: Ubuntu 24.04.2 LTS (noble)

Steps to reproduce

steps_to_reproduce.txt

  1. Perform a fresh installation of Windows Terminal (issue observed even after a full reinstall and deletion of associated settings files like settings.dat, roaming.lock, and the settings.json containing folder).
  2. Allow Windows Terminal to generate a default settings.json.
  3. Open a WSL/Bash profile (e.g., Ubuntu).
  4. In the Bash prompt, press Shift + Right Arrow (or other Shift + Arrow combinations).
  5. Observation 1: Instead of selecting text, characters like C (or D, A, B) are inserted into the prompt.
  6. Attempt to fix this by explicitly defining selection keybindings in settings.json. Close Windows Terminal, edit settings.json to add the following to the keybindings array (ensuring the actions array is empty or does not contain these):
   // Intended correct keybindings
   { "keys": "shift+left",         "command": { "action": "adjustSelection", "direction": "left" } },
   { "keys": "shift+right",        "command": { "action": "adjustSelection", "direction": "right" } },
   { "keys": "shift+up",           "command": { "action": "adjustSelection", "direction": "up" } },
   { "keys": "shift+down",         "command": { "action": "adjustSelection", "direction": "down" } },
   { "keys": "shift+home",         "command": { "action": "adjustSelectionToStartOfLine" } },
   { "keys": "shift+end",          "command": { "action": "adjustSelectionToEndOfLine" } },
   { "keys": "ctrl+shift+left",    "command": { "action": "adjustSelectionWord", "direction": "left" } },
   { "keys": "ctrl+shift+right",   "command": { "action": "adjustSelectionWord", "direction": "right" } }
  1. Save settings.json.
  2. Reopen Windows Terminal.
  3. Observation 2: Open settings.json again. The explicitly defined selection keybindings from step 6 have been rewritten by Windows Terminal to:
   // What Windows Terminal rewrites them to
   { "id": null, "keys": "shift+left" },
   { "id": null, "keys": "shift+right" },
   // ... and so on for all the selection keybindings that used a command object.
  1. Observation 3: The Shift+Arrow key behavior in WSL/Bash remains broken (inserts characters).

Expected Behavior

expected_behavior.txt

Shift+Arrow key combinations should perform text selection within the WSL/Bash prompt in Windows Terminal, similar to their behavior in PowerShell profiles within Windows Terminal.
Valid, user-defined keybindings in settings.json (using command objects for actions like adjustSelection) should be respected and not automatically rewritten to an unbound state ("id": null).

Actual Behavior

actual_behavior.txt

Actual Behavior:

  • Shift+Arrow keys insert literal characters (A, B, C, D) in the WSL/Bash prompt.
  • Windows Terminal actively rewrites correctly defined selection keybindings in settings.json that use command objects into an unbound state ("id": null) upon startup. This occurs even on a fresh installation.
  • This behavior is consistent in both Windows Terminal Stable and Windows Terminal Preview (which appear to share/migrate the same problematic settings behavior).
  • Ctrl+Arrow for word-wise navigation does work correctly in WSL/Bash (this is handled by /etc/inputrc within WSL).
  • The issue of characters appearing with Shift+Arrow was also observed when WSL/Bash was run in the legacy Windows Console Host (conhost.exe) after uninstalling Windows Terminal, indicating that for selection to work, the terminal emulator must handle it, and Windows Terminal is currently failing to allow itself to be configured to do so for WSL/Bash due to the settings rewrite.
  • Attempts to use the Windows Terminal Settings GUI to define these actions have also been unsuccessful, as the specific granular selection actions are not clearly available for binding or the GUI also fails to apply them correctly.

Diagnostic Information:

  • showkey -a output for Shift+Arrow keys in WSL/Bash:

    • Shift + Right Arrow: ^[[1;2C (\e[1;2C)
    • Shift + Left Arrow: ^[[1;2D (\e[1;2D)
    • Shift + Up Arrow: ^[[1;2A (\e[1;2A)
    • Shift + Down Arrow: ^[[1;2B (\e[1;2B)
  • WSL Readline Configuration:

    • User's ~/.inputrc file does not exist.
    • System /etc/inputrc does not contain bindings for the Shift+Arrow sequences above but does contain working bindings for Ctrl+Arrow sequences (e.g., "\e[1;5C": forward-word).

Impact:
This bug significantly hinders keyboard-based text selection usability for users of WSL/Bash within Windows Terminal, forcing reliance on mouse selection or alternative methods. The aggressive rewriting of settings.json also makes it impossible for users to manually correct the behavior.

Originally created by @SlintyLinters on GitHub (May 17, 2025). ### Windows Terminal version 1.22.11141.0 ### Windows build number 10.0.26100.0 ### Other Software Windows Terminal Preview: Version: 1.23.11132.0 WSL2 Distribution: Ubuntu 24.04.2 LTS (noble) ### Steps to reproduce [steps_to_reproduce.txt](https://github.com/user-attachments/files/20260139/steps_to_reproduce.txt) 1. Perform a fresh installation of Windows Terminal (issue observed even after a full reinstall and deletion of associated settings files like `settings.dat`, `roaming.lock`, and the `settings.json` containing folder). 2. Allow Windows Terminal to generate a default `settings.json`. 3. Open a WSL/Bash profile (e.g., Ubuntu). 4. In the Bash prompt, press Shift + Right Arrow (or other Shift + Arrow combinations). 5. Observation 1: Instead of selecting text, characters like C (or D, A, B) are inserted into the prompt. 6. Attempt to fix this by explicitly defining selection keybindings in `settings.json`. Close Windows Terminal, edit `settings.json` to add the following to the keybindings array (ensuring the actions array is empty or does not contain these): ```json // Intended correct keybindings { "keys": "shift+left", "command": { "action": "adjustSelection", "direction": "left" } }, { "keys": "shift+right", "command": { "action": "adjustSelection", "direction": "right" } }, { "keys": "shift+up", "command": { "action": "adjustSelection", "direction": "up" } }, { "keys": "shift+down", "command": { "action": "adjustSelection", "direction": "down" } }, { "keys": "shift+home", "command": { "action": "adjustSelectionToStartOfLine" } }, { "keys": "shift+end", "command": { "action": "adjustSelectionToEndOfLine" } }, { "keys": "ctrl+shift+left", "command": { "action": "adjustSelectionWord", "direction": "left" } }, { "keys": "ctrl+shift+right", "command": { "action": "adjustSelectionWord", "direction": "right" } } ``` 7. Save settings.json. 8. Reopen Windows Terminal. 9. Observation 2: Open settings.json again. The explicitly defined selection keybindings from step 6 have been rewritten by Windows Terminal to: ```json // What Windows Terminal rewrites them to { "id": null, "keys": "shift+left" }, { "id": null, "keys": "shift+right" }, // ... and so on for all the selection keybindings that used a command object. ``` 10. Observation 3: The Shift+Arrow key behavior in WSL/Bash remains broken (inserts characters). ### Expected Behavior [expected_behavior.txt](https://github.com/user-attachments/files/20260147/expected_behavior.txt) Shift+Arrow key combinations should perform text selection within the WSL/Bash prompt in Windows Terminal, similar to their behavior in PowerShell profiles within Windows Terminal. Valid, user-defined keybindings in settings.json (using command objects for actions like adjustSelection) should be respected and not automatically rewritten to an unbound state ("id": null). ### Actual Behavior [actual_behavior.txt](https://github.com/user-attachments/files/20260170/actual_behavior.txt) Actual Behavior: * Shift+Arrow keys insert literal characters (A, B, C, D) in the WSL/Bash prompt. * Windows Terminal actively rewrites correctly defined selection keybindings in settings.json that use command objects into an unbound state (`"id": null`) upon startup. This occurs even on a fresh installation. * This behavior is consistent in both Windows Terminal Stable and Windows Terminal Preview (which appear to share/migrate the same problematic settings behavior). * Ctrl+Arrow for word-wise navigation does work correctly in WSL/Bash (this is handled by /etc/inputrc within WSL). * The issue of characters appearing with Shift+Arrow was also observed when WSL/Bash was run in the legacy Windows Console Host (conhost.exe) after uninstalling Windows Terminal, indicating that for selection to work, the terminal emulator must handle it, and Windows Terminal is currently failing to allow itself to be configured to do so for WSL/Bash due to the settings rewrite. * Attempts to use the Windows Terminal Settings GUI to define these actions have also been unsuccessful, as the specific granular selection actions are not clearly available for binding or the GUI also fails to apply them correctly. Diagnostic Information: * showkey -a output for Shift+Arrow keys in WSL/Bash: - Shift + Right Arrow: `^[[1;2C (\e[1;2C)` - Shift + Left Arrow: `^[[1;2D (\e[1;2D)` - Shift + Up Arrow: `^[[1;2A (\e[1;2A)` - Shift + Down Arrow: `^[[1;2B (\e[1;2B)` * WSL Readline Configuration: - User's `~/.inputrc` file does not exist. - System `/etc/inputrc` does not contain bindings for the `Shift+Arrow` sequences above but does contain working bindings for `Ctrl+Arrow sequences` (e.g., `"\e[1;5C": forward-word`). Impact: This bug significantly hinders keyboard-based text selection usability for users of WSL/Bash within Windows Terminal, forcing reliance on mouse selection or alternative methods. The aggressive rewriting of settings.json also makes it impossible for users to manually correct the behavior.
claunia added the Needs-TriageIssue-BugNeeds-Attention labels 2026-01-31 08:37:05 +00:00
Author
Owner

@SlintyLinters commented on GitHub (May 17, 2025):

Further testing shows that Shift+Home also inserts an H character, and Shift+End inserts an F character in the WSL/Bash prompt. This is consistent with the Shift+Arrow behavior and suggests the issue affects other Shift-modified navigation/selection keys where the terminal should be handling selection but is instead passing modified escape sequences to Bash, which Readline doesn't recognize.

@SlintyLinters commented on GitHub (May 17, 2025): Further testing shows that Shift+Home also inserts an H character, and Shift+End inserts an F character in the WSL/Bash prompt. This is consistent with the Shift+Arrow behavior and suggests the issue affects other Shift-modified navigation/selection keys where the terminal should be handling selection but is instead passing modified escape sequences to Bash, which Readline doesn't recognize.
Author
Owner

@DHowett commented on GitHub (May 17, 2025):

I expanded your report attachments inline.

As a quick gut check, if you do instead insert all of those bindings into actions... what happens?

@DHowett commented on GitHub (May 17, 2025): I expanded your report attachments inline. As a quick gut check, if you do instead insert all of those bindings into `actions`... what happens?
Author
Owner

@DHowett commented on GitHub (May 17, 2025):

(Thanks for the comprehensive report!)

@DHowett commented on GitHub (May 17, 2025): (Thanks for the comprehensive report!)
Author
Owner

@SlintyLinters commented on GitHub (May 17, 2025):

No problem!

I tried inserting them into actions originally, and Terminal would automatically overwrite the JSON, moving them from actions to keybindings and changing it to the format you see in the file attached.

settings.json

@SlintyLinters commented on GitHub (May 17, 2025): No problem! I tried inserting them into `actions` originally, and Terminal would automatically overwrite the JSON, moving them from `actions` to `keybindings` and changing it to the format you see in the file attached. [settings.json](https://github.com/user-attachments/files/20260426/settings.json)
Author
Owner

@j4james commented on GitHub (May 17, 2025):

Shift+Arrow selection works in PowerShell because it specifically handles those key bindings itself. Bash does not. For information on why that's the case see https://unix.stackexchange.com/questions/444214/bash-shiftarrow-keys-make-a-b-c-d

And mapping the Shift+Arrow keys to terminal actions wouldn't really help, because that would be applying the selection in the terminal and not in the shell. That might be fine if all you want to do is copy the selected text, but it wouldn't work if you wanted to delete the selection, because that's the shell's responsibility, and it would have no knowledge of what you had selected.

I'm also not sure it's even possible to create a key binding in Windows Terminal for selection. What made you think you could use something like "action": "adjustSelection"? I can't see anything like that in the source here: ActionAndArgs.cpp. And I suspect that might be why your key bindings are getting deleted.

@j4james commented on GitHub (May 17, 2025): Shift+Arrow selection works in PowerShell because it specifically handles those key bindings itself. Bash does not. For information on why that's the case see https://unix.stackexchange.com/questions/444214/bash-shiftarrow-keys-make-a-b-c-d And mapping the Shift+Arrow keys to terminal actions wouldn't really help, because that would be applying the selection in the terminal and not in the shell. That might be fine if all you want to do is copy the selected text, but it wouldn't work if you wanted to delete the selection, because that's the shell's responsibility, and it would have no knowledge of what you had selected. I'm also not sure it's even possible to create a key binding in Windows Terminal for selection. What made you think you could use something like `"action": "adjustSelection"`? I can't see anything like that in the source here: [ActionAndArgs.cpp](https://github.com/microsoft/terminal/blob/a093ca3d54ff00d79f00dc4dbd0e4f63ad96aa46/src/cascadia/TerminalSettingsModel/ActionAndArgs.cpp). And I suspect that might be why your key bindings are getting deleted.
Author
Owner

@zero-stroke commented on GitHub (Aug 12, 2025):

I had the exact same annoyances using Windows Terminal with zsh in WSL and asked chatgpt to come up with a solution. As a windows user and someone who found out what zsh is yesterday, I don't really know how most of this works but when added to the end of ~/.zshrc it seems to properly bind most Ctrl Shift Arrow Key combinations:

if [[ -o interactive ]]; then
  zmodload -i zsh/zle

  bindkey -e

  # --- selection helpers ---
  typeset -ga zle_highlight
  zle_highlight+=(region:standout)
  _select_init() { (( REGION_ACTIVE )) || zle set-mark-command }
  _select_left()       { _select_init; zle backward-char; }
  _select_right()      { _select_init; zle forward-char;  }
  _select_word_left()  { _select_init; zle backward-word; }
  _select_word_right() { _select_init; zle forward-word;  }
  zle -N _select_left _select_left
  zle -N _select_right _select_right
  zle -N _select_word_left _select_word_left
  zle -N _select_word_right _select_word_right

  # --- smart editing ---
  _smart_backspace() { (( REGION_ACTIVE )) && zle kill-region || zle backward-delete-char; }
  _smart_delete()    { (( REGION_ACTIVE )) && zle kill-region || zle delete-char; }
  zle -N _smart_backspace _smart_backspace
  zle -N _smart_delete _smart_delete

  # Replace-on-type: use builtin .self-insert to avoid recursion with plugins
  _overwrite_or_insert() {
    (( REGION_ACTIVE )) && zle kill-region
    zle .self-insert        # <<< critical: dot-prefixed builtin
  }
  zle -N _overwrite_or_insert
  zle -N self-insert _overwrite_or_insert  # our widget handles all typed chars

  # Backspace/Delete
  bindkey -M emacs '^?'    _smart_backspace
  bindkey -M emacs '^H'    _smart_backspace
  bindkey -M emacs '^[[3~' _smart_delete

  # Selection with Shift/Ctrl+Shift
  bindkey -M emacs '^[[1;2D' _select_left
  bindkey -M emacs '^[[1;2C' _select_right
  bindkey -M emacs '^[[1;6D' _select_word_left
  bindkey -M emacs '^[[1;6C' _select_word_right

  # Stop selecting when Shift is released
  _clear_selection() { (( REGION_ACTIVE )) && MARK=-1; }
  _unselect_then()   { _clear_selection; zle "$1"; }
  _left_nosel()       { _unselect_then backward-char; }
  _right_nosel()      { _unselect_then forward-char; }
  _word_left_nosel()  { _unselect_then backward-word; }
  _word_right_nosel() { _unselect_then forward-word; }
  _home_nosel()       { _unselect_then beginning-of-line; }
  _end_nosel()        { _unselect_then end-of-line; }
  zle -N _left_nosel _left_nosel
  zle -N _right_nosel _right_nosel
  zle -N _word_left_nosel _word_left_nosel
  zle -N _word_right_nosel _word_right_nosel
  zle -N _home_nosel _home_nosel
  zle -N _end_nosel _end_nosel

  # Plain arrows (CSI + SS3/application)
  bindkey -M emacs '^[[D'  _left_nosel
  bindkey -M emacs '^[OD'  _left_nosel
  bindkey -M emacs '^[[C'  _right_nosel
  bindkey -M emacs '^[OC'  _right_nosel

  # Ctrl+Left/Right (include both forms)
  bindkey -M emacs '^[[1;5D' _word_left_nosel
  bindkey -M emacs '^[[1;5C' _word_right_nosel
  bindkey -M emacs '^[1;5D'  _word_left_nosel
  bindkey -M emacs '^[1;5C'  _word_right_nosel

  # Home/End (CSI + SS3)
  bindkey -M emacs '^[[H'  _home_nosel
  bindkey -M emacs '^[OH'  _home_nosel
  bindkey -M emacs '^[[F'  _end_nosel
  bindkey -M emacs '^[OF'  _end_nosel

  # Optional: select whole line on Ctrl+A
  _select_all() { zle beginning-of-line; zle set-mark-command; zle end-of-line; }
  zle -N _select_all
  bindkey -M emacs '^A' _select_all
fi


# --- end: zle selection + word-delete setup ---

# Widgets for selecting to start/end of line
_select_home() { _select_init; zle beginning-of-line; }
_select_end()  { _select_init; zle end-of-line;      }
zle -N _select_home
zle -N _select_end

# Home/End + Shift variants (Windows Terminal common escapes)
bindkey -M emacs '^[[H'    beginning-of-line
bindkey -M emacs '^[[F'    end-of-line
bindkey -M emacs '^[[1;2H' _select_home
bindkey -M emacs '^[[1;2F' _select_end

# Ctrl+A = select entire line (optional)
_select_all() { zle beginning-of-line; zle set-mark-command; zle end-of-line; }
zle -N _select_all
bindkey -M emacs '^A' _select_all


bindkey -M emacs '^?'    _smart_backspace     # some terms send ^?
bindkey -M emacs '^H'    _smart_backspace     # others (incl. Windows Terminal) send ^H
bindkey -M emacs '^[[3~' _smart_delete        # Delete


_clear_selection() { (( REGION_ACTIVE )) && MARK=-1; }
_unselect_then()   { _clear_selection; zle "$1"; }


_left_nosel()        { _unselect_then backward-char; }
_right_nosel()       { _unselect_then forward-char; }
_word_left_nosel()   { _unselect_then backward-word; }
_word_right_nosel()  { _unselect_then forward-word; }
_home_nosel()        { _unselect_then beginning-of-line; }
_end_nosel()         { _unselect_then end-of-line; }

zle -N _left_nosel
zle -N _right_nosel
zle -N _word_left_nosel
zle -N _word_right_nosel
zle -N _home_nosel
zle -N _end_nosel

# --- keep your Shift bindings as-is; (re)bind the non-Shift ones to the *_nosel widgets ---
# Plain arrows (both CSI and SS3 / application-cursor)
bindkey -M emacs '^[[D'  _left_nosel
bindkey -M emacs '^[OD'  _left_nosel
bindkey -M emacs '^[[C'  _right_nosel
bindkey -M emacs '^[OC'  _right_nosel

# Ctrl+Left/Right (word). Keep your CSI binds, and add these tmux/xterm-ish fallbacks just in case:
bindkey -M emacs '^[[1;5D' _word_left_nosel
bindkey -M emacs '^[[1;5C' _word_right_nosel
bindkey -M emacs '^[1;5D'  _word_left_nosel
bindkey -M emacs '^[1;5C'  _word_right_nosel

# Home/End (both CSI and SS3)
bindkey -M emacs '^[[H'  _home_nosel
bindkey -M emacs '^[OH'  _home_nosel
bindkey -M emacs '^[[F'  _end_nosel
bindkey -M emacs '^[OF'  _end_nosel

# Also handle SS3 / application-cursor mode
bindkey -M emacs '^[OD' _left_nosel
bindkey -M emacs '^[OC' _right_nosel
bindkey -M emacs '^[OH' _home_nosel
bindkey -M emacs '^[OF' _end_nosel

bindkey '^H' backward-kill-word
@zero-stroke commented on GitHub (Aug 12, 2025): I had the exact same annoyances using Windows Terminal with zsh in WSL and asked chatgpt to come up with a solution. As a windows user and someone who found out what zsh is yesterday, I don't really know how most of this works but when added to the end of ~/.zshrc it seems to properly bind most Ctrl Shift Arrow Key combinations: ``` if [[ -o interactive ]]; then zmodload -i zsh/zle bindkey -e # --- selection helpers --- typeset -ga zle_highlight zle_highlight+=(region:standout) _select_init() { (( REGION_ACTIVE )) || zle set-mark-command } _select_left() { _select_init; zle backward-char; } _select_right() { _select_init; zle forward-char; } _select_word_left() { _select_init; zle backward-word; } _select_word_right() { _select_init; zle forward-word; } zle -N _select_left _select_left zle -N _select_right _select_right zle -N _select_word_left _select_word_left zle -N _select_word_right _select_word_right # --- smart editing --- _smart_backspace() { (( REGION_ACTIVE )) && zle kill-region || zle backward-delete-char; } _smart_delete() { (( REGION_ACTIVE )) && zle kill-region || zle delete-char; } zle -N _smart_backspace _smart_backspace zle -N _smart_delete _smart_delete # Replace-on-type: use builtin .self-insert to avoid recursion with plugins _overwrite_or_insert() { (( REGION_ACTIVE )) && zle kill-region zle .self-insert # <<< critical: dot-prefixed builtin } zle -N _overwrite_or_insert zle -N self-insert _overwrite_or_insert # our widget handles all typed chars # Backspace/Delete bindkey -M emacs '^?' _smart_backspace bindkey -M emacs '^H' _smart_backspace bindkey -M emacs '^[[3~' _smart_delete # Selection with Shift/Ctrl+Shift bindkey -M emacs '^[[1;2D' _select_left bindkey -M emacs '^[[1;2C' _select_right bindkey -M emacs '^[[1;6D' _select_word_left bindkey -M emacs '^[[1;6C' _select_word_right # Stop selecting when Shift is released _clear_selection() { (( REGION_ACTIVE )) && MARK=-1; } _unselect_then() { _clear_selection; zle "$1"; } _left_nosel() { _unselect_then backward-char; } _right_nosel() { _unselect_then forward-char; } _word_left_nosel() { _unselect_then backward-word; } _word_right_nosel() { _unselect_then forward-word; } _home_nosel() { _unselect_then beginning-of-line; } _end_nosel() { _unselect_then end-of-line; } zle -N _left_nosel _left_nosel zle -N _right_nosel _right_nosel zle -N _word_left_nosel _word_left_nosel zle -N _word_right_nosel _word_right_nosel zle -N _home_nosel _home_nosel zle -N _end_nosel _end_nosel # Plain arrows (CSI + SS3/application) bindkey -M emacs '^[[D' _left_nosel bindkey -M emacs '^[OD' _left_nosel bindkey -M emacs '^[[C' _right_nosel bindkey -M emacs '^[OC' _right_nosel # Ctrl+Left/Right (include both forms) bindkey -M emacs '^[[1;5D' _word_left_nosel bindkey -M emacs '^[[1;5C' _word_right_nosel bindkey -M emacs '^[1;5D' _word_left_nosel bindkey -M emacs '^[1;5C' _word_right_nosel # Home/End (CSI + SS3) bindkey -M emacs '^[[H' _home_nosel bindkey -M emacs '^[OH' _home_nosel bindkey -M emacs '^[[F' _end_nosel bindkey -M emacs '^[OF' _end_nosel # Optional: select whole line on Ctrl+A _select_all() { zle beginning-of-line; zle set-mark-command; zle end-of-line; } zle -N _select_all bindkey -M emacs '^A' _select_all fi # --- end: zle selection + word-delete setup --- # Widgets for selecting to start/end of line _select_home() { _select_init; zle beginning-of-line; } _select_end() { _select_init; zle end-of-line; } zle -N _select_home zle -N _select_end # Home/End + Shift variants (Windows Terminal common escapes) bindkey -M emacs '^[[H' beginning-of-line bindkey -M emacs '^[[F' end-of-line bindkey -M emacs '^[[1;2H' _select_home bindkey -M emacs '^[[1;2F' _select_end # Ctrl+A = select entire line (optional) _select_all() { zle beginning-of-line; zle set-mark-command; zle end-of-line; } zle -N _select_all bindkey -M emacs '^A' _select_all bindkey -M emacs '^?' _smart_backspace # some terms send ^? bindkey -M emacs '^H' _smart_backspace # others (incl. Windows Terminal) send ^H bindkey -M emacs '^[[3~' _smart_delete # Delete _clear_selection() { (( REGION_ACTIVE )) && MARK=-1; } _unselect_then() { _clear_selection; zle "$1"; } _left_nosel() { _unselect_then backward-char; } _right_nosel() { _unselect_then forward-char; } _word_left_nosel() { _unselect_then backward-word; } _word_right_nosel() { _unselect_then forward-word; } _home_nosel() { _unselect_then beginning-of-line; } _end_nosel() { _unselect_then end-of-line; } zle -N _left_nosel zle -N _right_nosel zle -N _word_left_nosel zle -N _word_right_nosel zle -N _home_nosel zle -N _end_nosel # --- keep your Shift bindings as-is; (re)bind the non-Shift ones to the *_nosel widgets --- # Plain arrows (both CSI and SS3 / application-cursor) bindkey -M emacs '^[[D' _left_nosel bindkey -M emacs '^[OD' _left_nosel bindkey -M emacs '^[[C' _right_nosel bindkey -M emacs '^[OC' _right_nosel # Ctrl+Left/Right (word). Keep your CSI binds, and add these tmux/xterm-ish fallbacks just in case: bindkey -M emacs '^[[1;5D' _word_left_nosel bindkey -M emacs '^[[1;5C' _word_right_nosel bindkey -M emacs '^[1;5D' _word_left_nosel bindkey -M emacs '^[1;5C' _word_right_nosel # Home/End (both CSI and SS3) bindkey -M emacs '^[[H' _home_nosel bindkey -M emacs '^[OH' _home_nosel bindkey -M emacs '^[[F' _end_nosel bindkey -M emacs '^[OF' _end_nosel # Also handle SS3 / application-cursor mode bindkey -M emacs '^[OD' _left_nosel bindkey -M emacs '^[OC' _right_nosel bindkey -M emacs '^[OH' _home_nosel bindkey -M emacs '^[OF' _end_nosel bindkey '^H' backward-kill-word ```
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#23261