summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRavi R Kiran <aine.marina@gmail.com>2021-04-05 00:32:42 (GMT)
committerRavi R Kiran <aine.marina@gmail.com>2021-04-05 00:32:42 (GMT)
commit5a6d046d1e6a4eef168090b09ea09861e3b86b6c (patch)
tree285c1d5bfaf2bdd56cb705411e7599d57756f63e
parent19a76fb6b4337e466ea9dfc59acaafbe8b6205af (diff)
downloaddotemacs-5a6d046d1e6a4eef168090b09ea09861e3b86b6c.zip
dotemacs-5a6d046d1e6a4eef168090b09ea09861e3b86b6c.tar.gz
dotemacs-5a6d046d1e6a4eef168090b09ea09861e3b86b6c.tar.bz2
Support for kitty
-rw-r--r--init.el56
-rw-r--r--lisp/ravi-ergodox-mode.el16
-rw-r--r--lisp/ravi-init-appearance.el2
-rw-r--r--lisp/ravi-init-helm.el9
-rw-r--r--lisp/ravi-init-ido.el33
-rw-r--r--lisp/ravi-init-insertion.el3
-rw-r--r--lisp/ravi-init-maps.el1
-rw-r--r--lisp/ravi-init-tex.el29
-rw-r--r--lisp/ravi-init-vc.el5
-rw-r--r--lisp/xterm-kitty.el390
10 files changed, 485 insertions, 59 deletions
diff --git a/init.el b/init.el
index 19edbd6..77975b1 100644
--- a/init.el
+++ b/init.el
@@ -9,25 +9,26 @@
;; Initialize some customizations early on to avoid flicker
(when window-system
(tooltip-mode -1)
- (tool-bar-mode -1))
-;; Open in full-screen of possible
-(when (fboundp 'toggle-frame-maximized)
- (setq frame-resize-pixelwise t)
- (toggle-frame-maximized))
+ (tool-bar-mode -1)
+ ;; Open in full-screen of possible
+ (when (fboundp 'toggle-frame-maximized)
+ (setq frame-resize-pixelwise t)
+ (toggle-frame-maximized)))
(menu-bar-mode -1)
(setq warning-suppress-types nil)
(set-face-background 'default "black")
(set-face-foreground 'default "white")
(add-to-list 'default-frame-alist '(background-mode . dark))
(require 'cl)
-(defun font-candidate (&rest fonts)
- "Return existing font which first match."
- (find-if (lambda (f) (find-font (font-spec :name f))) fonts))
-(let ((fontval (font-candidate "Source Code Pro")))
- (when fontval (set-face-attribute 'default nil :font fontval :height 110)))
-(when (find-font (font-spec :name "Symbola"))
- (set-fontset-font "fontset-default" nil
- (font-spec :size 20 :name "Symbola")))
+(when window-system
+ (defun font-candidate (&rest fonts)
+ "Return existing font which first match."
+ (find-if (lambda (f) (find-font (font-spec :name f))) fonts))
+ (let ((fontval (font-candidate "Source Code Pro")))
+ (when fontval (set-face-attribute 'default nil :font fontval :height 110)))
+ (when (find-font (font-spec :name "Symbola"))
+ (set-fontset-font "fontset-default" nil
+ (font-spec :size 20 :name "Symbola"))))
(setq custom-file (concat ravi/init-dir "custom.el"))
;; Initialize package handling: currently using only the official repository and MELPA
@@ -68,14 +69,31 @@
(use-package s)
(use-package dash)
+
+(use-package xterm-kitty
+ :init
+ (setq xterm-kitty-modifiers-alist '((1 . shift) (2 . alt) (4 . control) (32 . super) (16 . hyper) (8 . meta)))
+ :config
+ (xterm-kitty-add)
+ (when xterm-kitty-in-use
+ (defun ravi/get-rid-of-xterm-key-translations ()
+ (mapcar (lambda (k) (unbind-key (vector k) local-function-key-map))
+ '(tab delete return escape)))
+ (add-hook 'terminal-init-xterm-hook 'ravi/get-rid-of-xterm-key-translations))
+ :ensure nil
+ :load-path (lambda () (ravi/emacs-file "lisp")))
+
(require 's)
(require 'ravi-ergodox-mode)
-(let* ((xinput-string (shell-command-to-string "xinput"))
- (xorg-ergodox (s-contains? "Ergodox" xinput-string))
- (under-xming (or xorg-ergodox
- (s-contains? "vendor string: Colin Harrison"
- (shell-command-to-string "xdpyinfo")))))
- (if (or xorg-ergodox under-xming)
+(let* ((xinput-string (and window-system (shell-command-to-string "xinput")))
+ (xorg-ergodox (and window-system (s-contains? "Ergodox" xinput-string)))
+ (under-xming (and window-system
+ (or xorg-ergodox
+ (s-contains? "vendor string: Colin Harrison"
+ (shell-command-to-string "xdpyinfo")))))
+ (using-kitty (and (not window-system)
+ (string-match "^xterm-kitty" (getenv-internal "TERM" initial-environment)))))
+ (if (or xorg-ergodox under-xming using-kitty)
(progn
(ravi-ergodox-mode)
(diminish 'ravi-ergodox-mode)
diff --git a/lisp/ravi-ergodox-mode.el b/lisp/ravi-ergodox-mode.el
index c8be98f..852285e 100644
--- a/lisp/ravi-ergodox-mode.el
+++ b/lisp/ravi-ergodox-mode.el
@@ -46,15 +46,15 @@ Each function in the list receive no argument."
:lighter " RE" :group 'convenience
:keymap ravi-ergodox-mode-map
:global t
- (if ravi-ergodox-mode
+ (when window-system
+ (if ravi-ergodox-mode
+ (progn
+ (setq x-meta-keysym 'super)
+ (setq x-super-keysym 'meta))
(progn
- (setq x-meta-keysym 'super)
- (setq x-super-keysym 'meta))
- (progn
- (setq x-meta-keysym nil)
- (setq x-super-keysym nil))
- )
- )
+ (setq x-meta-keysym nil)
+ (setq x-super-keysym nil))
+ )))
(define-key ravi-ergodox-mode-map (kbd "H-m") 'magit-status)
(if (and (boundp 'ravi/use-helm-instead-of-ido) ravi/use-helm-instead-of-ido)
diff --git a/lisp/ravi-init-appearance.el b/lisp/ravi-init-appearance.el
index b0dcc9d..e36e70e 100644
--- a/lisp/ravi-init-appearance.el
+++ b/lisp/ravi-init-appearance.el
@@ -266,6 +266,7 @@ Delete all whitespace on a successive key press."
:diminish which-key-mode)
(use-package which-key-posframe
:after which-key
+ :if window-system
:config
(which-key-posframe-mode)
(setq which-key-posframe-poshandler #'posframe-poshandler-frame-bottom-center))
@@ -373,6 +374,7 @@ Delete all whitespace on a successive key press."
(use-package pdf-tools
;; Install this locally; no update from MELPA needed.
;; :mode (("\\.pdf\\'" . pdf-view-mode)) ;; errors first use; to do.
+ :if window-system
:config
(progn
(setq-default pdf-view-display-size 'fit-page)
diff --git a/lisp/ravi-init-helm.el b/lisp/ravi-init-helm.el
index 9ea83db..1d78359 100644
--- a/lisp/ravi-init-helm.el
+++ b/lisp/ravi-init-helm.el
@@ -26,16 +26,18 @@
;;; Code:
(use-package helm
- :bind (("<escape>" . helm-command-prefix)
+ :bind (("H-h" . helm-command-prefix)
("M-x" . helm-M-x)
("<f1>" . helm-multi-files)
("<f2>" . helm-find-files)
("M-y" . helm-show-kill-ring)
("H-`" . helm-all-mark-rings))
+ :commands helm-command-prefix
:init
(progn
(require 'helm-config)
(setq helm-candidate-number-limit 100)
+ ;; (bind-key (xterm-kitty-make-binding-sequence "<escape>" 'escape))
;; From https://gist.github.com/antifuchs/9238468
(setq helm-idle-delay 0.0 ; update fast sources immediately (doesn't).
@@ -50,10 +52,11 @@
:config
(progn
(unbind-key "C-x c") ; default helm prefix key
- (bind-key "<tab>" 'helm-execute-persistent-action helm-map)
- (bind-key "H-<tab>" 'helm-select-action helm-map)
+ (bind-key (xterm-kitty-make-binding-sequence "<tab>" ?\t) 'helm-execute-persistent-action helm-map)
+ (bind-key (xterm-kitty-make-binding-sequence "H-<tab>" ?\t 'hyper) 'helm-select-action helm-map)
(use-package helm-posframe
+ :if window-system
:config
(helm-posframe-enable)
(setq helm-posframe-parameters '((left-fringe . 10)
diff --git a/lisp/ravi-init-ido.el b/lisp/ravi-init-ido.el
index 61f9e50..9e15aba 100644
--- a/lisp/ravi-init-ido.el
+++ b/lisp/ravi-init-ido.el
@@ -138,22 +138,23 @@
(bind-key "<return>" 'ido-smart-select-text
ido-file-completion-map)))
- (defun ido-switch-buffer-tiny-frame (buffer)
- (interactive (list (ido-read-buffer "Buffer: " nil t)))
- (with-selected-frame
- (make-frame '((width . 80)
- (height . 22)
- (left-fringe . 0)
- (right-fringe . 0)
- (vertical-scroll-bars . nil)
- (unsplittable . t)
- (has-modeline-p . nil)
- ;;(background-color . "grey80")
- (minibuffer . nil)))
- (switch-to-buffer buffer)
- (set (make-local-variable 'mode-line-format) nil)))
-
- (bind-key "C-x 5 t" 'ido-switch-buffer-tiny-frame)))
+ (if window-system
+ (defun ido-switch-buffer-tiny-frame (buffer)
+ (interactive (list (ido-read-buffer "Buffer: " nil t)))
+ (with-selected-frame
+ (make-frame '((width . 80)
+ (height . 22)
+ (left-fringe . 0)
+ (right-fringe . 0)
+ (vertical-scroll-bars . nil)
+ (unsplittable . t)
+ (has-modeline-p . nil)
+ ;;(background-color . "grey80")
+ (minibuffer . nil)))
+ (switch-to-buffer buffer)
+ (set (make-local-variable 'mode-line-format) nil)))
+
+ (bind-key "C-x 5 t" 'ido-switch-buffer-tiny-frame))))
(use-package smex
:init
diff --git a/lisp/ravi-init-insertion.el b/lisp/ravi-init-insertion.el
index 8088273..8564e1d 100644
--- a/lisp/ravi-init-insertion.el
+++ b/lisp/ravi-init-insertion.el
@@ -132,6 +132,7 @@
(progn
(use-package all-the-icons)
(use-package company-box
+ :if window-system
:hook (company-mode . company-box-mode)
:config
(setq company-box-icons-unknown (all-the-icons-faicon "question-circle" :height 0.8))
@@ -174,6 +175,7 @@
))
(progn
(use-package company-posframe
+ :if window-system
:config
(company-posframe-mode 1)
:diminish company-posframe-mode))
@@ -181,6 +183,7 @@
(unless ravi/use-company-box
(use-package company-quickhelp
:disabled t
+ :if window-system
:config
(progn
(company-quickhelp-mode 1)
diff --git a/lisp/ravi-init-maps.el b/lisp/ravi-init-maps.el
index a8de0a1..1a148ca 100644
--- a/lisp/ravi-init-maps.el
+++ b/lisp/ravi-init-maps.el
@@ -27,6 +27,7 @@
(use-package hydra-posframe
:load-path (lambda () (ravi/emacs-file "site-lisp/hydra-posframe"))
:after hydra
+ :if window-system
:config
(hydra-posframe-mode)
(setq hydra-posframe-poshandler #'posframe-poshandler-frame-bottom-center)
diff --git a/lisp/ravi-init-tex.el b/lisp/ravi-init-tex.el
index 95df08f..7af212a 100644
--- a/lisp/ravi-init-tex.el
+++ b/lisp/ravi-init-tex.el
@@ -48,8 +48,23 @@
(sp-local-pair 'latex-mode "\\begin" "\\end")
(sp-local-tag 'latex-mode "\\ba" "\\begin{align*}" "\\end{align*}")
- (use-package preview :ensure nil)
- (use-package font-latex :ensure nil)
+ (use-package preview
+ :ensure nil
+ :if window-system
+ :config
+ (defun my-LaTeX-preview-math ()
+ (interactive)
+ (let ((b (save-excursion (while (texmathp) (backward-char 1)) (1- (point))))
+ (e (save-excursion (while (texmathp) (forward-char 1)) (point))))
+ (preview-region b e)))
+ (bind-key "C-<m-key>" 'my-LaTeX-preview-math preview-map))
+
+ (use-package font-latex
+ :ensure nil
+ :if window-system
+ :config
+ ;; fix italian quote highlight
+ (push '("\"<" "\">") font-latex-quote-list))
(fset 'tex-font-lock-subscript 'ignore)
(sp-with-modes '(tex-mode plain-tex-mode latex-mode)
@@ -114,9 +129,6 @@
(add-hook 'TeX-after-TeX-LaTeX-command-finished-hook
#'th/pdf-view-revert-buffer-maybe)
- ;; fix italian quote highlight
- (push '("\"<" "\">") font-latex-quote-list)
-
(defun my-latex-remove-command ()
"Unwrap the expression that point is in or before, also
removing the command name. By command we understand a symbol
@@ -156,13 +168,6 @@ starting with \\ and followed by a block of text enclosed in {}."
:hook (LaTex-mode . latex-extra-mode)
:diminish latex-extra-mode)
- (defun my-LaTeX-preview-math ()
- (interactive)
- (let ((b (save-excursion (while (texmathp) (backward-char 1)) (1- (point))))
- (e (save-excursion (while (texmathp) (forward-char 1)) (point))))
- (preview-region b e)))
- (bind-key "C-<m-key>" 'my-LaTeX-preview-math preview-map)
-
(defun my-LaTeX-mode-init ()
(setq TeX-auto-save t)
(setq TeX-parse-self t)
diff --git a/lisp/ravi-init-vc.el b/lisp/ravi-init-vc.el
index 1b9e9bb..fc7a93c 100644
--- a/lisp/ravi-init-vc.el
+++ b/lisp/ravi-init-vc.el
@@ -83,6 +83,7 @@
(use-package gitignore-mode)
(use-package gitconfig-mode)
(use-package git-messenger
+ :if window-system
:bind ("C-x v p" . git-messenger:popup-message))
(use-package git-timemachine
:bind ("C-x v t" . git-timemachine))
@@ -92,7 +93,9 @@
(use-package diff-hl
:config
- (global-diff-hl-mode))
+ (global-diff-hl-mode)
+ (unless window-system
+ (diff-hl-margin-mode)))
;; Stolen almost entirely from Fuco (Matus Goljer)
(use-package ediff
diff --git a/lisp/xterm-kitty.el b/lisp/xterm-kitty.el
new file mode 100644
index 0000000..16e388f
--- /dev/null
+++ b/lisp/xterm-kitty.el
@@ -0,0 +1,390 @@
+;;; xterm-kitty.el --- kitty terminal support
+
+;; Copyright (C) 2021 Ravi Kiran
+
+;; Author: Ravi Kiran <aine.marina@gmail.com>
+;; Keywords:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Work-in-progress to support kitty terminal with all modifiers
+;; - not ready yet to be moved into term/xterm-kitty.el
+;; - still need to
+;; + ensure proper 24-bit color support
+;; + reduce/formalize dependencies on xterm.el
+;; + provide init-terminal-xterm-kitty
+
+;;; Code:
+
+(defvar xterm-kitty-in-use
+ (and (string-match "^xterm-kitty" (getenv-internal "TERM" initial-environment)) t)
+ "Currently running under xterm-kitty.")
+
+(defvar xterm-kitty-modifiers-alist
+ '((1 . shift) (2 . alt) (4 . control) (8 . super) (16 . hyper) (32 . meta))
+ "Modifier mapping; SHIFT must always be present as first element with value 1.
+
+Changing the values allows for swapping modifiers. For example
+ (1 . shift) (2 . alt) (4 . control) (8 . meta) (16 . hyper) (32 . super)
+would swap meta and super.")
+
+(defvar xterm-kitty-escape-prefix "\e["
+ "CSI escape sequence generated by kitty.")
+
+(defvar xterm-kitty--prefix-alist
+ '((shift . "S-") (alt . "A-") (control . "C-") (super . "s-") (hyper . "H-") (meta . "M-"))
+ "Modifier prefixes.")
+(defvar xterm-kitty--bitset-alist
+ `((shift . ,(ash 1 25)) (alt . ,(ash 1 22)) (control . ,(ash 1 26)) (super . ,(ash 1 23)) (hyper . ,(ash 1 24)) (meta . ,(ash 1 27)))
+ "Modifier bits set.")
+
+(defvar xterm-kitty-shift-alist
+ `(,@(mapcar (lambda (p) (cons (aref p 0) (aref p 1)))
+ (split-string "`~ 1! 2@ 3# 4$ 5% 6^ 7& 8* 9( 0) -_ =+ [{ ]} \\| ;: '\" ,< .> /?"))
+ ,@(mapcar (lambda (c) (cons c (- c (- ?a ?A))))
+ (number-sequence ?a ?z)))
+ "Characters produced by shifted keys; used to convert shifted keybindings.")
+
+(defun xterm-kitty--make-modifiers-from-num (num &rest others)
+ "Make a list of modifiers from NUM along with additional modifiers OTHERS."
+ (let* ((bits (mapcar (lambda (idx) (logand num (ash 1 idx))) (number-sequence 0 (1- (length xterm-kitty-modifiers-alist)))))
+ (found-mods (flatten-list (list (mapcar (lambda (b) (alist-get b xterm-kitty-modifiers-alist)) bits) others))))
+ found-mods))
+
+(defun xterm-kitty--from-numeric-modifer (num list-map folder)
+ (apply folder (mapcar (lambda (mod) (alist-get mod list-map))
+ (xterm-kitty--make-modifiers-from-num num))))
+
+(defvar xterm-kitty--numeric-modifiers
+ (apply #'vector (mapcar (lambda (num) (xterm-kitty--from-numeric-modifer num xterm-kitty--bitset-alist #'logior))
+ (number-sequence 0 (1- (ash 1 (length xterm-kitty-modifiers-alist))))))
+ "Numeric modifiers to apply to each printable character for kitty modifier.")
+
+(defvar xterm-kitty--prefix-modifiers
+ (apply #'vector (mapcar (lambda (num) (if (> num 0)
+ (xterm-kitty--from-numeric-modifer num xterm-kitty--prefix-alist #'concat)
+ ""))
+ (number-sequence 0 (1- (ash 1 (length xterm-kitty-modifiers-alist))))))
+ "Symbolic prefix to apply to each printable character for kitty modifier.")
+
+;; (message (apply #'concat (mapcar (lambda (p) (format "%x " (ash p -22))) (sort xterm-kitty--numeric-modifiers '<))))
+;; (message (apply #'concat (mapcar (lambda (p) (format "%s " p)) xterm-kitty--prefix-modifiers)))
+
+(defun xterm-kitty--add-event-modifier-to-symbol (mod-string e)
+ (let ((symbol (if (symbolp e) e (car e))))
+ (setq symbol (intern (concat mod-string (symbol-name symbol))))
+ (if (symbolp e)
+ symbol
+ (cons symbol (cdr e)))))
+
+(defun xterm-kitty--precompute-with-modifiers (sym)
+ (apply #'vector
+ (and sym
+ (mapcar (lambda (mod) (vector (xterm-kitty--add-event-modifier-to-symbol mod sym)))
+ xterm-kitty--prefix-modifiers))))
+
+(defvar xterm-kitty--suffix-tilde-map
+ '((2 . insert)
+ (3 . delete)
+ (5 . prior)
+ (6 . next)
+ (7 . home)
+ (8 . end)
+ (11 . f1)
+ (12 . f2)
+ (13 . f3)
+ (14 . f4)
+ (15 . f5)
+ (17 . f6)
+ (18 . f7)
+ (19 . f8)
+ (20 . f9)
+ (21 . f10)
+ (23 . f11)
+ (24 . f12))
+ "Entries with ~ suffix.")
+(defvar xterm-kitty--suffix-tilde-precomputed
+ (apply #'vector (mapcar (lambda (n) (xterm-kitty--precompute-with-modifiers (alist-get n xterm-kitty--suffix-tilde-map)))
+ (number-sequence 0 (car (car (last xterm-kitty--suffix-tilde-map))))))
+ "Precomputed vectors for ~ suffix.")
+
+(defvar xterm-kitty--suffix-alpha-map
+ '((?A . up)
+ (?B . down)
+ (?C . right)
+ (?D . left)
+ (?F . end)
+ (?H . home)
+ (?P . f1)
+ (?Q . f2)
+ (?R . f3)
+ (?S . f4))
+ "Entries with alphabetic suffix.")
+(defvar xterm-kitty--suffix-alpha-precomputed
+ (apply #'vector (mapcar (lambda (n) (xterm-kitty--precompute-with-modifiers (alist-get n xterm-kitty--suffix-alpha-map)))
+ (number-sequence ?A (caar (last xterm-kitty--suffix-alpha-map)))))
+ "Precomputed vectors for alphabetic suffix.")
+
+(defvar xterm-kitty--suffix-u-non-private
+ `(?\x8 ?\x9 ?\xd ?\x1b ?\x7f ?\s ; BS, TAB, RET, ESC, DEL, SPC
+ ,@(mapcar #'car xterm-kitty-shift-alist))
+ "All characters in non-private unicode space")
+
+(defconst xterm-kitty--shift-modifier (car (rassoc 'shift xterm-kitty-modifiers-alist))
+ "Value of the shift modifier.")
+
+(defun xterm-kitty--make-suffix (mod)
+ (if (zerop mod) "" (format ";%d" (1+ mod))))
+
+(defun xterm-kitty--insert-decode-table (keymap)
+ "Insert decoding table into KEYMAP"
+ (let* ((all-modifiers (number-sequence 0 (1- (ash 1 (length xterm-kitty-modifiers-alist)))))
+ (all-mod-suffixes (apply #'vector (mapcar #'xterm-kitty--make-suffix all-modifiers))))
+ (mapc
+ (lambda (key)
+ (let ((keystr (format "%d" key)))
+ (mapc
+ (lambda (mod)
+ (unless (zerop mod)
+ (define-key keymap
+ (concat xterm-kitty-escape-prefix keystr (aref all-mod-suffixes mod) "u")
+ (xterm-kitty-decode-key-stroke key mod ?u))))
+ all-modifiers)))
+ xterm-kitty--suffix-u-non-private)
+ (mapc
+ (lambda (key)
+ (let ((keystr (format "%d" key)))
+ (mapc
+ (lambda (mod)
+ (define-key keymap
+ (concat xterm-kitty-escape-prefix keystr (aref all-mod-suffixes mod) "~")
+ (xterm-kitty-decode-key-stroke key mod ?~)))
+ all-modifiers)))
+ (mapcar #'car xterm-kitty--suffix-tilde-map))
+ (mapc
+ (lambda (suffix)
+ (let ((keystr (format "%d" suffix)))
+ (mapc
+ (lambda (mod)
+ (define-key keymap
+ (concat xterm-kitty-escape-prefix
+ (if (zerop mod) "" "1")
+ (aref all-mod-suffixes mod)
+ (string suffix))
+ (xterm-kitty-decode-key-stroke 0 mod suffix)))
+ all-modifiers)))
+ (mapcar #'car xterm-kitty--suffix-alpha-map))))
+
+;; (setq dum2 (let ((map (make-sparse-keymap)))
+;; (xterm-kitty--insert-decode-table map)))
+;; (lookup-key dum2 (concat xterm-kitty-escape-prefix "97;5u"))
+;; (xterm-kitty--add-modifier-list '(control) ?i)
+
+(defun xterm-kitty-decode-key-stroke (keycode modifiers suffix)
+ "Take KEYCODE MODIFIERS SUFFIX of the form 105;5u and construct key."
+ (if (eql suffix ?u)
+ (when (< keycode 57344)
+ ;; To do: support remaining keycodes in unicode private use area
+ ;; (send-string-to-terminal (format "%s" (logior code (aref xterm-kitty--numeric-modifiers modifiers))))
+ (let* ((shifted-key (and (eql (logand modifiers xterm-kitty--shift-modifier)
+ xterm-kitty--shift-modifier)
+ (alist-get keycode xterm-kitty-shift-alist)))
+ ;; The following is equivalent to modifiers & ~shift
+ (new-modifiers (and shifted-key (- modifiers xterm-kitty--shift-modifier))))
+ (vector (logior (or shifted-key keycode)
+ (aref xterm-kitty--numeric-modifiers (if shifted-key new-modifiers modifiers))))))
+ (if (eql suffix ?~)
+ (if (eql keycode 200)
+ (xterm-translate-bracketed-paste nil)
+ (aref (aref xterm-kitty--suffix-tilde-precomputed keycode) modifiers))
+ (when (<= ?A suffix ?S)
+ (if (and (or (eql suffix ?I) (eql suffix ?O))
+ (eql keycode 0)
+ (eql modifiers 0))
+ ;; xterm focus in/out; perhaps there's a better way to do this
+ (if (eql suffix ?I) (xterm-translate-focus-in nil) (xterm-translate-focus-out nil))
+ (aref (aref xterm-kitty--suffix-alpha-precomputed (- suffix ?A)) modifiers))))))
+
+(defun xterm-kitty-handle-non-printable (keystr)
+ (let* ((suffix (aref keystr (1- (length keystr))))
+ (parts (split-string keystr ";"))
+ (num-parts (length parts))
+ (code (string-to-number keystr)) ; will be zero for alpha suffix without modifiers
+ (modifiers (if (>= num-parts 2) (1- (string-to-number (cadr parts))) 0)))
+ ;; (send-string-to-terminal (format "%s %s %s" keystr code modifiers))
+ (xterm-kitty-decode-key-stroke code modifiers suffix)))
+
+(defun xterm-kitty--handle-escape-code1 (prompt)
+ "Handle escape code by reading rest of keycode as string; PROMPT is ignored."
+ (let* ((e (read-char))
+ (complete-string (string e))
+ (count 0))
+ ;; There must be a faster way to create this string one character at a time
+ (while (and (or (<= ?0 e ?9)
+ (eql e ?\;))
+ (< count 25))
+ (setq count (1+ count)) ; safety
+ (setq e (read-char))
+ (setq complete-string (concat complete-string (string e))))
+ ;; (send-string-to-terminal complete-string)
+ (xterm-kitty-handle-non-printable complete-string)))
+
+(defun xterm-kitty--handle-escape-code (prompt)
+ "Try to optimize handling keycode using integer math; PROMPT is ignored."
+ (let ((keycode 0)
+ (modifiers 0)
+ (suffix nil)
+ (current-num 0)
+ (e))
+ (while (not suffix)
+ (setq e (read-char))
+ (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)))
+
+(defvar xterm-kitty-legacy-control-map
+ '(;(?\@ . 0)
+ (?a . 1)
+ (?b . 2)
+ (?c . 3)
+ (?d . 4)
+ (?e . 5)
+ (?f . 6)
+ (?g . 7)
+ (?h . 8)
+ ;; (?i . 9)
+ (?j . 10)
+ (?k . 11)
+ (?l . 12)
+ ;; (?m . 13)
+ (?n . 14)
+ (?o . 15)
+ (?p . 16)
+ (?q . 17)
+ (?r . 18)
+ (?s . 19)
+ (?t . 20)
+ (?u . 21)
+ (?v . 22)
+ (?w . 23)
+ (?x . 24)
+ (?y . 25)
+ (?z . 26)
+ ;; (?\[ . 27)
+ (?\\ . 28)
+ ;; (?\] . 29)
+ ;; (?^ . 30)
+ ;; (?~ . 30)
+ ;; (?/ . 31)
+ ;; (?_ . 31)
+ ;; (?? . 127)
+ ;; (?0 . 48)
+ ;; (?1 . 49)
+ ;; (?2 . 0)
+ ;; (?3 . 27)
+ ;; (?4 . 28)
+ ;; (?5 . 29)
+ ;; (?6 . 30)
+ ;; (?7 . 31)
+ ;; (?8 . 127)
+ ;; (?9 . 57)
+ )
+ "Map C- and C-M- combinations to legacy values.")
+
+(defun xterm-kitty--add-modifier-list (mod-list e)
+ (let ((modifier-list (flatten-list mod-list)))
+ (if (numberp e)
+ (progn
+ ;; (message "%d" (logior e (apply #'logior (mapcar (lambda (m) (alist-get m xterm-kitty--bitset-alist)) modifier-list))))
+ (logior e (apply #'logior (mapcar (lambda (m) (alist-get m xterm-kitty--bitset-alist)) modifier-list))))
+ (and e
+ (if modifier-list
+ (xterm-kitty--add-event-modifier-to-symbol
+ (apply 'concat (mapcar (lambda (m) (alist-get m xterm-kitty--prefix-alist)) modifier-list))
+ e)
+ e)))))
+(defun xterm-kitty--setup-legacy-control-maps (keymap)
+ (mapc
+ (lambda (bind)
+ ;; Redirect C- and C-M- combinations because they are part of base bindings
+ (define-key keymap (vector (xterm-kitty--add-modifier-list '(control) (car bind))) (vector (cdr bind)))
+ (define-key keymap
+ (vector (xterm-kitty--add-modifier-list '(control meta) (car bind)))
+ (vector (xterm-kitty--add-modifier-list '(meta) (cdr bind)))))
+ xterm-kitty-legacy-control-map))
+
+(defun xterm-kitty-make-binding-sequence (default key &rest modifiers)
+ "Make a key vector for KEY with VECTORS suitable for binding with 'define-key' if xterm-kitty is active.
+
+DEFAULT is the value to be returned if xterm-kitty is not active.
+KEY is the key to be used. MODIFIERS is a list of modifiers, or
+modifiers specified explicitly.
+
+'define-key' uses 'event-convert-list' internally, which strips
+off shift modifiers for alphabetic characters. The only way to
+avoid it is to provide the key vector itself to 'define-key',
+which this function explicitly creates. In that sense, this
+function is almost equivalent to 'event-convert-list'."
+ (if xterm-kitty-in-use
+ (vector (xterm-kitty--add-modifier-list modifiers key))
+ default))
+
+(defun xterm-kitty-remove-keyboard ()
+ "Reset keyboard to prior status, if modified by kitty-escape-codes."
+ (send-string-to-terminal "\e[<u"))
+
+;; To do: debug the reason that the table method does not work
+;; - the table does not seem to be reflected in input-decode-map
+;; - the table method is needed for those packages which advice
+;; low-level functions such as read-char, e.g., multiple-cursors
+(defvar xterm-kitty-use-table-method nil
+ "Use table method to handle character map")
+
+(defun xterm-kitty-apply-keyboard (&optional keymap alternate-keymap)
+ "Apply keyboard defintion; optionally to KEYMAP and ALTERNATE-KEYMAP."
+ (let* ((kmap (or keymap
+ (and xterm-kitty-in-use input-decode-map)))
+ (alternate-kmap (or alternate-keymap
+ (and kmap
+ (not keymap)
+ key-translation-map))))
+ (when kmap
+ (unless keymap ; default keymap was used
+ (message "Applying xterm-kitty changes")
+ (send-string-to-terminal "\e[>1;u")
+ (add-hook 'kill-emacs-hook 'xterm-kitty-remove-keyboard))
+ (if xterm-kitty-use-table-method
+ (xterm-kitty--insert-decode-table kmap)
+ (define-key kmap xterm-kitty-escape-prefix #'xterm-kitty--handle-escape-code)))
+ (when (and alternate-kmap)
+ (xterm-kitty--setup-legacy-control-maps alternate-kmap))))
+
+(defun xterm-kitty-add ()
+ "This one should be replaced by init-terminal-xterm-kitty; just a hack for now."
+ (when xterm-kitty-in-use
+ (setq xterm-extra-capabilities '(reportBackground getSelection setSelection))
+ (add-hook 'terminal-init-xterm-hook 'xterm-kitty-apply-keyboard)))
+
+(provide 'xterm-kitty)
+;;; xterm-kitty.el ends here