Skip to content

Support Ctrl Modifier for Word Navigation and Deletion in Text Areas#5394

Open
iskandergaba wants to merge 3 commits intojesseduffield:masterfrom
iskandergaba:support-ctrl-modifier
Open

Support Ctrl Modifier for Word Navigation and Deletion in Text Areas#5394
iskandergaba wants to merge 3 commits intojesseduffield:masterfrom
iskandergaba:support-ctrl-modifier

Conversation

@iskandergaba
Copy link
Copy Markdown

PR Description

Unlike lazygit, most text editors and TUIs support Ctrl based key bindings for word navigation and deletion. They also support forward word deletion. As a heavy user of these key bindings, I wanted to extend their support to lazygit to switch between tools more easily.

I am sure that I am not the only one who would appreciate this, and in any case, this extension does not break any preexisting key bindings.

Changes:

  • Ctrl+Left / Ctrl+Right: Move cursor one word left/right (alongside existing Alt+Left/Right and Emacs-style Alt+B/Alt+F)
  • Ctrl+Backspace: delete word to the left (alongside existing Alt+Backspace and Ctrl+W)
  • Ctrl+Delete / Alt+D: Delete word to the right (new; no equivalent existed before)

Note:

ModCtrl was previously disabled in gocui with a comment stating it didn't work with keyboard keys. This comment was written 5 years ago and mentions tcell.v1 while the project is currently using tcell.v2, so I suspect it is a bit legacy now, but I would like it if the maintainers double-checked that part. I managed to make ModCtrl work by patching tcell_driver.go to preserve it for right/left and deletion key events while keeping it stripped from all other ones, as before.

Please Check If the PR Fulfills these Requirements

  • Cheatsheets are up-to-date (run go generate ./...)
  • Code has been formatted (see here)
  • Tests have been added/updated (see here for the integration test guide)
  • Text is internationalized (see here)
  • If a new UserConfig entry was added, make sure it can be hot-reloaded (see here)
  • Docs have been updated if necessary
  • You've read through your own file changes for silly mistakes etc.

@stefanhaller
Copy link
Copy Markdown
Collaborator

Thanks for the contribution. I'm not going to merge this because I'm in the process of rewriting the key handling in gocui and lazygit, so all the code you are touching here will be different. I will try to remember to make this change as part of that work.

However:

Unlike lazygit, most text editors and TUIs support Ctrl based key bindings for word navigation and deletion.

Which platform are you on? As far as I am aware, using Alt is standard on Mac. Windows does use Ctrl though; not sure about Linux, I don't have a Linux system to test this on.

I think I would like to avoid offering both variants on all platforms; I'd prefer to only have the one that is standard on each platform. Also, it would be good to make them configurable I guess.

Never seen Ctrl-Delete or Alt-D for forward-delete-word; is this standard? What software supports it?

@iskandergaba
Copy link
Copy Markdown
Author

iskandergaba commented Apr 4, 2026

Thanks for the contribution. I'm not going to merge this because I'm in the process of rewriting the key handling in gocui and lazygit, so all the code you are touching here will be different. I will try to remember to make this change as part of that work.

Fair enough. Thanks for taking the time to consider the PR. I will lay out my case here.

I will start from this point and build back from there.

Never seen Ctrl-Delete or Alt-D for forward-delete-word; is this standard? What software supports it?

These shortcuts are standard on:

  • Windows (on PowerShell, but not on CMD).
  • bash shell:
    • Tested on Debian (Windows Subsystem for Linux)
    • Tested on Ubuntu (Gnome Terminal and Ghostty Terminal)

Here are a couple of sources that support the existence of the action and the key-binding (Alt+D):

Technically, the shortcut is the Emacs key-biding Meta-D, which maps to Alt-D usually. And since the default mode for bash is emacs (It can be switched to vi but who does that I guess?), you end up with that.

Which platform are you on? As far as I am aware, using Alt is standard on Mac. Windows does use Ctrl though; not sure about Linux, I don't have a Linux system to test this on.
Mainly GNU/Linux, bash specifically. Indeed, Windows uses Ctrl as well as almost all modern text editors.

For the sake of more clarity, I did some digging. Listing the key binding on a bash shell session using the bind command, we can find the following:

  • Backward delete word:
$ bind -p | grep -w " backward-kill-word"
"\e\C-h": backward-kill-word
"\e\C-?": backward-kill-word
$ bind -p | grep -w " unix-word-rubout"
"\C-w": unix-word-rubout
  • \e\C-h —> Alt+Backspace (terminals that send 0x08 for Backspace). Exists already.
  • \e\C-? —> Alt+Backspace (terminals that send 0x7F for Backspace). Exists already.
  • \C-w —>Ctrl+W Exists already.

Notes:

  1. backward-kill-word and unix-word-rubout behave slightly differently. While unix-word-rubout stops at whitespaces only, backward-kill-word uses GNU Readline word definition and additionally stops at punctuation like /, . and -. But that's neither here nor there I guess.
  2. The proposed Ctrl+Backspace default binding does not exist for this action, apparently, so this one is on me. It is however standard on PowerShell and most code editors, for what its worth.
  • Forward delete word:
$ bind -p | grep -w " kill-word"
"\e[3;5~": kill-word
"\ed": kill-word
  • \ed —> Alt+D (classic Emacs/Readline binding). Proposed.

  • \e[3;5~ —> Ctrl+Del (the [3~ is the Del key, the 5 modifier means Ctrl). Proposed.

  • Move one word backward:

$ bind -p | grep -w " backward-word"
"\e\e[D": backward-word
"\e[1;3D": backward-word
"\e[1;5D": backward-word
"\e[5D": backward-word
"\eb": backward-word
  • \eb —> Alt+B (classic Emacs/Readline). Exists already.

  • \e[1;3D —> Alt+Left. Exists already.

  • \e[1;5D —> Ctrl+Left. Proposed.

  • \e[5D —> Ctrl+Left (older terminal encoding). Proposed.

  • \e\e[D —> Esc then Left.

  • Move one word forward:

$ bind -p | grep -w " forward-word"
"\e\e[C": forward-word
"\e[1;3C": forward-word
"\e[1;5C": forward-word
"\e[5C": forward-word
"\ef": forward-word
  • \ef —> Alt+F (classic Emacs/Readline). Exists already.
  • \e[1;3C —> Alt+Right. Exists already.
  • \e[1;5C —> Ctrl+Right. Proposed.
  • \e[5C —> Ctrl+Right (older terminal encoding). Proposed.
  • \e\e[C —> Esc then Right.

I think I would like to avoid offering both variants on all platforms; I'd prefer to only have the one that is standard on each platform. Also, it would be good to make them configurable I guess.

Fair point. Ultimately, this has to do more with the shell you use rather than then the OS. The reason you can't find those key bindings on macOS is because it defaults to zsh rather than bash. zsh uses ZLE (Zsh Line Editor), not GNU Readline, leading to some different key bindings, even though the emacs-style ones remain the same (Ctrl+A, Ctrl+E, Alt+B, Alt+F, etc.).

I guess I just wanted less friction switching between my code editors and Lazygit. I think it can be configurable, say bash-style, zsh-style, and PowerShell-style key bindings. An auto setting could select the key binding corresponding to default shell, with a fallback to bash for Linux, zsh for macOS, and powershell for Windows should the shell session not match any style.

Or you could force the law on everyone and dictate the key bindings :)

Either way, I hope this discussion has shed more light on the matter and that it will help your technical choices in the ongoing rewrite. Good luck.

@codacy-production
Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

TIP This summary will be updated as you push new changes. Give us feedback

@stefanhaller
Copy link
Copy Markdown
Collaborator

Thanks for all the information.

Ultimately, this has to do more with the shell you use rather than then the OS.

I disagree, I actually don't care too much about shells, I want to use the keybindings that are the default on the respective platform in text editors or text fields. Like, when typing text into a field like this comment field in github in Firefox. Or TextEdit.app on Mac, or Notepad.exe on Windows. From looking at these, I see that move-word, delete-word, and forward-delete-word all use alt on Mac and ctrl on Windows, so that's what I'll pick as a default on these platforms (and make them configurable like all other keybindings). In addition, I'll keep providing the alternatives that we already have, like alt-b etc., but maybe not make those configurable, as that would require extending the keybinding system to support more than one binding per function.

Can you help me with those defaults on Linux, alt or ctrl? I don't have a Linux system to try this out myself.

the Emacs key-biding Meta-D, which maps to Alt-D usually

I found this bit interesting, and maybe you can help me with that too. I don't really know what a Meta key is, but I see that tcell supports it, and it appears that this maps to Command on Mac. Which is useful, because it allows us to map the <a-enter> binding that we currently have for committing from the commit description field to <m-enter> on Mac, so it's the same as in this field here in the browser. Is that a good use of the Meta modifier? What would it map to on other platforms?

@stefanhaller
Copy link
Copy Markdown
Collaborator

Can you help me with those defaults on Linux, alt or ctrl? I don't have a Linux system to try this out myself.

Ok, found it out myself, it's ctrl like on Windows.

Would still appreciate help with the question about the Meta modifier.

@iskandergaba
Copy link
Copy Markdown
Author

iskandergaba commented Apr 8, 2026

Ok, found it out myself, it's ctrl like on Windows.

Yeah, I confirm. Sorry for the late reply. Life.

Would still appreciate help with the question about the Meta modifier.

From the little digging I did, it depends on the context. Here's a summary table:

Context macOS Windows Linux
Terminal Use Option (⌥) key (Functionally equivalent to Alt). Alt key. Alt key.
System Use Command (⌘) key. Windows (⊞) key. Super key.
Application Use Command (⌘) key. Ctrl key. Ctrl key.

Therefore, it is safe to say that for application shortcuts, Meta would usually point to Ctrl on Windows and Linux.

I don't really know what a Meta key is, but I see that tcell supports it, and it appears that this maps to Command on Mac. Which is useful, because it allows us to map the binding that we currently have for committing from the commit description field to on Mac, so it's the same as in this field here in the browser.

Well, I tested that on Windows and Linux and I can tell you that the equivalent key binding is Ctrl + Enter, which corroborates my summary table above.

My recommendation: If you want to have an equivalent experience to GUI applications across all the platforms, I believe that you should not rely on Meta as it is, probably, reported as on macOS terminal and as Alt on Windows and Linux. I believe you should rely on explicit Alt, Ctrl and shortcuts instead. Here is a summary table applying the Meta + Enter example on this text field:

OS Expected Reality
macOS + Enter + Enter
Windows Ctrl + Enter Alt + Enter
Linux Ctrl + Enter Alt + Enter

@stefanhaller
Copy link
Copy Markdown
Collaborator

I now have a preliminary branch that implements configurable and platform-specific edit bindings; it is called platform-specific-edit-bindings if you feel like testing it. No PR yet, there's a bit more work to do until I'm there.

@iskandergaba
Copy link
Copy Markdown
Author

iskandergaba commented Apr 9, 2026

I now have a preliminary branch that implements configurable and platform-specific edit bindings; it is called platform-specific-edit-bindings if you feel like testing it. No PR yet, there's a bit more work to do until I'm there.

I can't tell that I have checked the code thoroughly on that branch, but as far as testing go, word navigation and deletion feels exactly how I'd expect it on Linux, i.e. via Ctrl modifier instead of Alt. I have also noticed that the word definition is smarter than simply space-separated strings.

I like it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants