Hacker News new | past | comments | ask | show | jobs | submit login
Comprehensive Keyboard Handling in Terminals (kovidgoyal.net)
166 points by g0xA52A2A on April 2, 2023 | hide | past | favorite | 72 comments



It is briefly mentioned in this post, but this work is based on a proposal by Paul Evans [1] (creator of libtickit and libvterm, among others).

Kovid deserves credit for addressing some of the issues in the original proposal, and for documenting it well. But Evans deserves credit as well for formulating the original idea.

Note also that this is not the only solution to this problem. Xterm has had its own solution for a long time called modifyOtherKeys [2] which has been supported by Vim and iTerm2 for quite some time (I believe foot supports it as well, perhaps others). Of course people have different opinions on which approach is “better”, though empirically it seems like the CSIu/“fixterms”/kitty approach has a lot more momentum at present.

[1]: http://www.leonerd.org.uk/hacks/fixterms/

[2]: https://invisible-island.net/xterm/modified-keys.html


I know mlterm is one that supports modifyOtherKeys.

Fragmentation is unfortunate, especially since there's no termcap/terminfo property that indicates which form(s) a terminal supports, and so many terminals already identify themselves as ‘xterm’ without being remotely close to xterm-compatible.


Kovid is one of those 10x engineers for me. I love kitty and use it every day, calibre does it job too.

Great, that he tries to make progress in terminal area, that, as for me, is quite archaic as of now.


I have never quite understood what the benefit of using kitty is. My default terminal emulator just isn’t using that many resources and I don’t get why I would even want GPU rendering for text.

What problem does it solve for you?


Terminals have some infuriating limitations, like imagine not being able to tell the difference between Esc + A or Alt + A as an application. Or that tab and Ctrl + I produce identical input.

Kitty has a new keyboard handling protocol, and Neovim supports it. So if you use kitty, you can use key mappings in neovim in a more predicatable and flexible way.


But xterm and xterm-compatibles have been able to do this for over a decade (CSI > 4 ; 2 m).


While that sounds like a good thing is Esc+<key> really that useful of a bind when you already have Ctrl/Alt + <key> and you can get twice the keys if you add shift in the mix.

Of course your workflow is yours.


When Alt+a looks the same as Esc+a, then the program has to wait biefly after it sees you press Esc - the continuation could mean it's really Alt+a you want to send.

That latency interferes just with a plain Esc key press. There's no weird use case in this.


Either my terminal does some magic or this is not true. Most of my vim & tmux commands are alt+something and these execute as soon as I press the bind.

Or does tmux make them work automagically?


Maybe https://neovim.io/doc/user/options.html#'ttimeout' could be evidence that it's not a problem that I've made up, it exists in some terminals. My comment was about that latency of pressing a single Esc.


I also can't say I've noticed such latency


Joining in questioning… kitty dev seems to hate tmux since kitty can perform many of it's behaviors. The thing that's most interesting to me is tmux for detaching and persisting a session on a remote host. Does kitty cover this functionality too? Is there like kittyd?


If persisting sessions is the only thing you use tmux or screen for (as it was for me), try `dtach`. Session management is all it does; terminal I/O is passed through just like a plain ssh session.


I use tmux for remote and i3 for local use, so I don’t use kittys window management functions. I know author stance on tmux and do not share it


its* behaviors


I’ve tried many terminal emulators, probably all available on Linux, and kitty is the best in my experience. Performance is excellent: keyboard latency, catting files. It’s sometimes convenient to use some of its tricks, such as viewing an image right in the terminal through ssh.


Have you tried wezterm as well?


I don’t think so. Maybe I shouldn’t have said “all”.


kitty is the most feature complete terminal emulator out there. It’s the only one that properly supports ligatures and variable width characters for instance. If you want faithful terminal reproduction with built in native tmux like functionality (including non broken mouse support), kitty is about the only option.


No it isn't, I have version 0.27.1 installed and it reports itself as a VT220 rather than VT420 (like xterm), or VT520 (like Zutty). And even despite purporting to be a VT220 it still fails on LineFeed Mode, DSR, and SRM; which the developer of Zutty called out back in 2020: https://tomscii.sig7.se/2020/12/A-totally-biased-comparison-...


Wezterm is feature parity with kitty. But can be configured in lua instead of a long custom text file with vim tag support


>It’s the only one that properly supports ligatures and variable width characters for instance.

Are these like "powerline fonts" or what? Where are these used?


Are you saying that because you've found something missing from wezterm, or because you're not considering wezterm at all?


> variable width characters

Do you mean such things as wide Unicode glyphs? Because it doesn’t seem to support variable-width fonts.


It's _really_ responsive, whether you're in an editor or accidentally grepped a minified JavaScript file.

I would be capable of working entirely in any modern terminal emulator, but Kitty makes it a pleasure.


Aren't these more about the tools you are using instead of the terminal emulator? Or does kitty use its own grep command?

I use vim as my main editor and while I usually stick with default terminal I have tried others in the past and at least I cant tell a difference in normal usage.


It's not the grep that's slow, it's the printing of a hundred thousand character minified line of JavaScript. Unintentional, but every dev's done it or similar. I used to have to kill urxvt, which I used for nearly 15 years.


>printing of a hundred thousand character minified line of JavaScript.

Yeah... Terminal is not the issue, rather why you have 100000 line js file in the first place.


This really started to bother me. How does terminal emulator speed up grepping a large file?

I made a random file with 100 000 lines and using 3 different terminals (Default Terminal, iTerm2, and Kitty) and using two different grep tools (grep and rip-grep) with and without tmux I can not see any meaningful performance difference.

Do I just not understand what terminal emulators do? How does choice of text printing matter when you run a script?

I could see a tiny performance improvement with kitty when I ran just cat on the file in a loop, but the difference was so tiny that if you want to argue that this is the performance benefit worth using kitty for I have bad news for you since the worst case with kitty was then noticeably worse than in competition.



Yes? Why do you need 100000 characters of JS? Maybe de-bloat your shit. Also grepping through that is even easier than 100_000 lines (which I assumed you meant since grepping over one line of 1_000_000 characters takes so little time that is not any kind of argument)


It's not the grepping that takes the time, it's the printing the highlighted output to the terminal. Keep up.


Being able to display inline images in the terminal


How often do you need this? Feels a pretty niche need. Also not the only terminal emulator capable of this.


You can configure a key combination to run a pager on the last command output, color and everything. You can also configure it so that it pipes the output of a command to a pager automatically whenever it is more than a screen long.


Also support displaying picture (try chafa with any jpg/png file inside kitty). That makes browsing with offpunk a completely different experience.


Kitty renders more cases correctly, more stable, mainly I appreciate it's overall high quality. I don't use it's tmux-like features.


Kitty is fast, configurable and support ligatures.


In addition to what others have said, it is also freely licensed and open source, with ports to my daily drivers macOS and xorg/Linux. I wonder if a Windows port is in the works too?


FWIW Wezterm supports Windows.


I didn't know he also made calibre. That's awesome.


Calibre user. I was like, that’s weird. There’s another Kovid Goyal?


There's an even richer protocol, `?9001h`, developed by the Microsoft Terminal team, designed to maintain the fidelity of INPUT_RECORD events. These are the events seen by console programs in Win32. It's quite nice.

https://github.com/microsoft/terminal/blob/main/doc/specs/%2...


In what way is it richer? I've skimmed through the linked doc, saw the mention that it is richer, but didn't see an explanation of the extra functionality is available


Events include key scan codes for one. The end of the doc contains a pros & cons section of the alternative approaches.

https://github.com/microsoft/terminal/blob/main/doc/specs/%2...


I'm not sure I agree that terminal applications should get access to the whole range of modifiers. It's nice having a certain key dedicated to the WM or macros and know there will be no conflicts.


Which certain key? It's different per user, so no way to have a common list to exclude.

Anyway, there are other better mechanisms to resolve the conflict instead of crippling the app


On Mac, the "Super"/"Command" key controls the terminal app. On Linux, I sometimes wish I had a Command key instead of the Control key being used by both the terminal and programs in the terminal. On X11, "Super" is often mapped to the window manager/the desktop environment, likewise on MS-Windows where it is the Windows key.

BTW. "Hyper" is available also on Mac, by default mapped to Shift+Control+Alt+Command but it can be remapped to another key. That key combination is emitted by the "Office key" on some Microsoft keyboards, and is used in MS-Windows for launching a component in their Office pack, or the Emoji picker.

So, there are lots of opportunities for configuration, and conflicts. IMHO, It would be a "nice thing to have" if users could configure their text-mode programs to use more modifiers, sure ... but as long as they are the only users of that config. I don't think a text-mode program should map Super or Hyper by default.


The command key being different from the control key in macOS is really one of its biggest out-of-the-box strengths fro people who use the terminal a lot. It's really quite helpful to have different modifier keys for different "system layers".

In addition to the Hyper key, there's also the "Meh" key, which is Shift+Control+Command and basically not used by any application. I use it as my default macro hotkey.


> On Linux, I sometimes wish I had a Command key instead of the Control key being used by both the terminal and programs in the terminal.

This is precisely why I prefer KDE — it's feasible to move GUI shortcuts off Control. (It could and should be easier, since there's a global setting deep in Qt somewhere, but it's only exposed on MacOS.)


> BTW. "Hyper" is available also on Mac, by default mapped to Shift+Control+Alt+Command but it can be remapped to another key.

I dedicate "Super" to my WM and Hyper to quite a few things but... Hyper is a hack for the USB specs do not have the concept of the Hyper key. So Hyper support is always a kludge.


In a development that will surely confuse nobody, the terminal emulator linked in this thread (kitty) is completely separate from another terminal named KiTTY. I assume there's some drama behind this. Anyway, this one is for Linux/MacOS only while KiTTY is a PuTTY fork for Windows only.


At some point one might consider if it would be simpler and better to just have some way to pass wayland-compatible events instead of inventing yet another protocol. So much stuff has now been thrown into terminal layer in a way that is not particularly elegant and what we already have perfectly good protocols for.


How would that traverse ssh, tmux, etc?


And what about mac and windows? And X11 for that matter.


It's very nice to see some progress in this moldy part of a technology junkyard


If this were widely adopted, it would do wonders for Emacs. Right now Emacs is unusable in remote terminal connections for many of us, because there is no way to get key combinations like Super-Shift-G to work.


In Emacs, local-function-key-map has this entry:

    C-x @ s                   event-apply-super-modifier
So to get s-g to work, you'd configure the terminal emulator to convert the Command+G key press to the C-x @ s g sequence.

    # Hex code (iTerm)
    0x18 0x40 0x73 0x67

    # kitty (without Emacs doing the integration)
    map cmd+g send_text all \x18@sg
Konsole somehow seems to have this done for the whole English alphabet, so it just works out of the box there.

For 2-modifier bindings, I guess you can add a creative entry to local-function-key-map. (If the other modifier is Shift, you can just use uppercase letters.)


I agree that Emacs would greatly benefit from this feature but "unusable" a overly dramatic. It's an inconvenience. I use Super on the desktop as much as anybody but I manage with remote tty sessions (including termux from phone) just fine. I just make sure that I also have a terminal-friendly binding for anything critical that I have on Super.


> "unusable" a overly dramatic

Disagree. I used to use Emacs with evil-mode, but I gave up because of this issue.

If I entered `ESC` then `k` (i.e. return to normal mode and move up a line) too quickly on an SSH connection, there was a good chance the `read` syscall on the PTTY file descriptor would return two characters (determined via `strace`) instead of two subsequent calls returning a single character each.

This makes it literally impossible for Emacs to distinguish it from `M-k` (i.e. `kill-line`), so I’d “randomly” see lines deleted before I figured out what was going on.

The effect is a lot more pronounced over SSH where a spike in network latency can cause two subsequent TCP segments to reach the host essentially back-to-back (or even be retransmitted as a single segment), leading to this behaviour of `read` returning two characters.


I see. I don't use the vi modes so it never occurred to me that ESC vs meta would be timing sensitive.


I guess it depends on how many Super shortcuts you use, and for how many years you have been using them. In my case, both numbers are into double digits, so.


I count 36 Super bindings and I started using them for Emacs in 2016. I was using them for StumpWM before that.

Some of it is EXWM specific but about half also apply on a tty frame too. My fingers just automatically type the alternate version when needed.

Sorry if it came off too argumentative. I've been on the other side of this plenty, one person's annoyance is another's show stopper.


Glad to see this page featured again.

Is there any advance on that front?

Previous submission was 2 years ago.

https://news.ycombinator.com/item?id=27193661


The progress is that this protocol has been implemented in many widely used programs, such as vim, neovim, helix, kakoune as well as at least two more terminal emulators, wezterm and foot in addition to kitty.


It seems like the protocol has not been implemented yet in neovim.

https://github.com/neovim/neovim/issues/14400


It has, just not fully. See the very first checkbox in the link you posted. Indeed this protocol is designed so applications can pick and choose what parts they want to use.


It has been implemented to a degree that it is useful for most users. For instance, you can now map Control-I and Tab separately, as well as keys like Control-1, Control-2, Control-;, etc.


Thank you for your work on neovim :)

I noticed the difference by playing with kitty. It makes me consider switching to a compatible terminal emulator.


It is also supported by iTerm2, Wezterm, and foot. Alacritty does not (yet) support dynamically modifying the key encoding per-application, but you can hardcode the encodings in your config file (there is an issue in the Alacritty repo that explains how to do this).

You may not have to switch at all if you are already using one of these terminal emulators.


Shoutout to Alacritty for having Windows support. Would have adopted kitty at the time for the reasons mentioned in the article (much more mature) but Alacritty does the trick. Not sure how it deals with modifiers etc. in the plumbing, but the configuration is plenty straightforward to access everything from terminal applications that can use lots of bindings.


Does kitty lets you remap modifiers like iterm2? https://i.stack.imgur.com/hd5Yi.png




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: