diff options
| author | Ravi R Kiran <aine.marina@gmail.com> | 2021-04-05 00:32:42 (GMT) |
|---|---|---|
| committer | Ravi R Kiran <aine.marina@gmail.com> | 2021-04-05 00:32:42 (GMT) |
| commit | 5a6d046d1e6a4eef168090b09ea09861e3b86b6c (patch) | |
| tree | 285c1d5bfaf2bdd56cb705411e7599d57756f63e | |
| parent | 19a76fb6b4337e466ea9dfc59acaafbe8b6205af (diff) | |
| download | dotemacs-5a6d046d1e6a4eef168090b09ea09861e3b86b6c.zip dotemacs-5a6d046d1e6a4eef168090b09ea09861e3b86b6c.tar.gz dotemacs-5a6d046d1e6a4eef168090b09ea09861e3b86b6c.tar.bz2 | |
Support for kitty
| -rw-r--r-- | init.el | 56 | ||||
| -rw-r--r-- | lisp/ravi-ergodox-mode.el | 16 | ||||
| -rw-r--r-- | lisp/ravi-init-appearance.el | 2 | ||||
| -rw-r--r-- | lisp/ravi-init-helm.el | 9 | ||||
| -rw-r--r-- | lisp/ravi-init-ido.el | 33 | ||||
| -rw-r--r-- | lisp/ravi-init-insertion.el | 3 | ||||
| -rw-r--r-- | lisp/ravi-init-maps.el | 1 | ||||
| -rw-r--r-- | lisp/ravi-init-tex.el | 29 | ||||
| -rw-r--r-- | lisp/ravi-init-vc.el | 5 | ||||
| -rw-r--r-- | lisp/xterm-kitty.el | 390 |
10 files changed, 485 insertions, 59 deletions
@@ -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 |
