From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Ravi R Newsgroups: gmane.emacs.devel Subject: Terminal or keyboard decoding system? Date: Sat, 18 Sep 2021 22:12:58 -0500 Message-ID: <87tuigck4h.fsf@gmail.com> Mime-Version: 1.0 Content-Type: text/plain Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="13911"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: mu4e 1.6.4; emacs 27.2 To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Sun Sep 19 23:49:05 2021 Return-path: Envelope-to: ged-emacs-devel@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1mS4gK-0003SE-9A for ged-emacs-devel@m.gmane-mx.org; Sun, 19 Sep 2021 23:49:04 +0200 Original-Received: from localhost ([::1]:57738 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mS4gI-00051E-AQ for ged-emacs-devel@m.gmane-mx.org; Sun, 19 Sep 2021 17:49:02 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:57900) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mS4fc-0004Mk-P3 for emacs-devel@gnu.org; Sun, 19 Sep 2021 17:48:20 -0400 Original-Received: from mail-io1-xd33.google.com ([2607:f8b0:4864:20::d33]:45852) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1mS4fa-0001Q5-V9 for emacs-devel@gnu.org; Sun, 19 Sep 2021 17:48:20 -0400 Original-Received: by mail-io1-xd33.google.com with SMTP id a22so19541650iok.12 for ; Sun, 19 Sep 2021 14:48:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=user-agent:from:to:subject:date:message-id:mime-version; bh=M76tEvpZd+FE8XjavbeZIQLXZ5cFJmMGhTsy0LjQkA0=; b=ct/VLJjfmmB3p5bsONWrL1O/F1owB63RJIdizlSCqNQVyZiZHq7WCTzEvMmZmXip8w 5r7HF6/llwbmQqCq1x2OWHwfoLw+0rNL4YbfHgwbCgB8Zg8XgglNtFUVyNvrkoudnda8 PnxZgKKu0xj2uk+ZpoWpTAvme3yocBJLPhSr7JRiLxd6aj1wCOxSKMzj0Mwbc3Mi6U5s 5QSTB5I1tuRV0JsIufeTfxZsRgH2UcyXh9PwAOg9kLbzrCpBY9vlvWgVV+SVxob5UUGF qBdnZZhkHORyO6oVKFVgpcU7OKImHel2DWacWApKGsz9XZh8oTTwD07cyEaepoCVdsSq Tdxg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:user-agent:from:to:subject:date:message-id :mime-version; bh=M76tEvpZd+FE8XjavbeZIQLXZ5cFJmMGhTsy0LjQkA0=; b=LmGsSjRRvuGYiqlatLmV/CLsCAr0hMgRGsjAGNYXA+ql8yWXP7n1WLxkrd19+tw0WY 0IrMVwOlB0rwqSLzgor9rSpp1fKibRl8CiqayI9KBf/VTp3exlo9l4A83ek4lCxOjkVd qP1ptUaL67IQy5md5o2IN98n+ZJZmO628/FR0/TeJTVwpTqdqfbJvho9GVnCyBdfzqp+ VTr4Q2iM8UDBiMP0mg9sj9xXRdoNt6r9g10aXNfDCNtD0NIRmV26OFZPuwDf5z8Wvswj x5AQWkU8HXHHRQb4qfi6sSyPVFKXdrvrAPd44GpBJlmHRz6XfTlwH73JT7nOrCWZrhd+ gv2Q== X-Gm-Message-State: AOAM530HmTo79cC2cPr8N3m+BWgp301WzUyvs4IiFXbFoefolUOMmPiI uiQGwB8IPUDn20kVOQ+GR2xrWh+/qOrXDA== X-Google-Smtp-Source: ABdhPJypIYOBd/kLc1qI07j8Gn9xsk62ypAXQVFhhZW04S3HHgBjakuAljjsnS0pMKN362zBsxd9pg== X-Received: by 2002:a05:6638:304b:: with SMTP id u11mr16768613jak.97.1632088096786; Sun, 19 Sep 2021 14:48:16 -0700 (PDT) Original-Received: from cramer (c-73-8-230-52.hsd1.il.comcast.net. [73.8.230.52]) by smtp.gmail.com with ESMTPSA id a25sm7441276ioq.46.2021.09.19.14.48.15 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 19 Sep 2021 14:48:16 -0700 (PDT) Received-SPF: pass client-ip=2607:f8b0:4864:20::d33; envelope-from=lists.ravi@gmail.com; helo=mail-io1-xd33.google.com X-Spam_score_int: -10 X-Spam_score: -1.1 X-Spam_bar: - X-Spam_report: (-1.1 / 5.0 requ) BAYES_00=-1.9, DATE_IN_PAST_12_24=1.049, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.io gmane.emacs.devel:275086 Archived-At: My attempt to use all the standard emacs modifiers (shift, control, meta, alt, super, hyper) on *terminal* emacs has been fairly successful, but it's not clear to me that my current approach of modifying input-decode-map and key-translation-map is the correct one, as it seems to have some pitfalls I do not understand. Please help me identify the correct way to decode these terminal sequences. My terminal emulator of choice, kitty, now provides an unambiguous mechanism [1] for sending all the modifier keys listed above for any key press. The protocol is straightfoward; every key (without exception) is reported to the application in one of the following forms: CSI number ; modifier u CSI 1 ; modifier suffix where spaces have been added above for clarity, but are not part of the protocol. CSI: "\e[" (as an emacs string) number: decimal number in ASCII, e.g., two byte string "97" for ?a modifier: decimal number in ASCII representing a bit-field (see below) suffix: one character for some specific keys The modifier decimal number minus one represents each modifier in one of its bits, e.g., shift is bit LSB, alt is bit 1, etc. My current approach [2] is to bind the CSI sequence to the following function in input-decode-map: (fset 'xterm-kitty--original-read-char-exclusive (symbol-function 'read-char-exclusive)) (defun xterm-kitty--handle-escape-code (prompt) "Handle keycode using integer math; PROMPT is ignored." (let ((keycode 0) (modifiers 0) (suffix nil) (current-num 0) (e)) (while (not suffix) (setq e (xterm-kitty--original-read-char-exclusive)) (if (<= ?0 e ?9) (setq current-num (+ (* current-num 10) (- e ?0))) (if (eql e ?\;) (setq keycode current-num current-num 0) (setq suffix e) (if (> keycode 0) (setq modifiers (1- current-num)) (setq keycode current-num))))) ;; (message "Code: %d modifiers %d suffix: %s" keycode modifiers suffix) (xterm-kitty-decode-key-stroke keycode modifiers suffix))) where xterm-kitty-decode-key-stroke creates the appropriate emacs key sequence, e.g., "\e[97;51u" goes to it as (97 51 u), which is then mapped to (kbd "H-M-A-a") since 51-1 = 32(meta)+16(hyper)+2(alt). This approach has two major pitfalls: 1. read-char-exclusive can be advised by packages 2. C-DEL has some issues 3. Standard C-, M-, C-M- bindings cannot distinguish between shifted and non-shifted variants for characters: abcdefghjklnopqrstuvwxyz\ I don't understand the "C-DEL" issue at all, and work around the shifted/non-shifted bindings via the following hacks: a. Mapping shifted to non-shifted versions in key-tranlation-map b. Add any non-shifted personal bindings (e.g., to "C-A" rather than "C-a") in local-function-key-map (really ugly) The first issue of read-char-exclusive advise by packages cannot be solved at all, as far as I can tell. Questions: 1. Is modifying input-decode-map and key-translation-map the right approach? Or should this be done using a coding system, e.g., keyboard-coding-system or terminal-coding-system? If so, can CCL or equivalent be used to translate from the keyboard protocol to emacs key representations? As far as I can tell, CCL programs transform a byte sequence to a different byte sequence; how can they be used to produce emacs key representations? I'm happy to write C code to implement this new coding system, if that's the best approach. Or is there a function at a lower level than read-char-exclusive that should be used? 2. Emacs key representations seem to come in two forms: a 28-bit integer (e.g., "H-M-A-a" is (1<<24)+(1<<27)+(1<<22)+97) and a symbol list (e.g., "H-" is 'H-f1), both of which are then stored in a vector. To be able to disambiguate between shifted versions and non-shifted versions, I ended up computing [3] the values directly for the integer representation, since event-convert-list (used internally by define-key) strips off shift modifiers for alphabetic characters in C code, and provides no way to work around it. However, "C-a" and "C-S-a" seem to be work perfectly fine if the integer value is computed explicitly; is this expected, or are there other minefields that I haven't encountered? 3. When allowing mouse focus-in/out and or bracketed paste events, occasionally, they seem to interleave with keyboard input read using read-char-exclusive. This problem has been very hard to reproduce deterministically, but happens once or twice daily. How should one debug such issues? Even with all of these issues, the ability to use all 6 modifier keys on a 24-bit color terminal with multiple real frames (rather than just one frame) over chained SSH connections has been fantastic! For my use cases, font sizes/shapes and image display seem to be the only missing features compared to graphical emacs. Implementing meta/hyper support in kitty (after giving up on a more famous terminal emulator), determining heuristics for detecting modifiers in XKB on Wayland (which does not natively provide a way to query them), and modifying XKB system configuration on Wayland to support all these modifiers without breaking other applications, has been quite a journey to getting a terminal emacs experience on par with graphical emacs. Regards, Ravi [1] https://sw.kovidgoyal.net/kitty/keyboard-protocol/#report-all-keys-as-escape-codes [2] http://cgit.lexarcana.com/cgit.cgi/dotemacs/tree/lisp/term/xterm-kitty.el#n390 [3] http://cgit.lexarcana.com/cgit.cgi/dotemacs/tree/lisp/term/xterm-kitty.el#n351