Skip to content

Commit

Permalink
Split off terminal support code into separate files
Browse files Browse the repository at this point in the history
  • Loading branch information
CyberShadow committed Nov 10, 2017
1 parent 8f8232c commit 05eacc5
Show file tree
Hide file tree
Showing 6 changed files with 606 additions and 531 deletions.
93 changes: 93 additions & 0 deletions term-keys-konsole.el
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
;;; term-keys-konsole.el --- term-keys support for Konsole

;;; Commentary:

;; This file contains supplementary code for aiding in the
;; configuration of the Konsole terminal emulator to interoperate with
;; the term-keys package.

;; For more information, please see the accompanying README.md file.

;;; Code:


(require 'term-keys)


(define-widget 'term-keys/konsole-modifier 'lazy
"Choice for Konsole key binding modifiers and state flags."
:type '(choice (const "Shift")
(const "Ctrl")
(const "Alt")
(const "Meta")
(const "KeyPad")
(const "AppScreen")
(const "AppCursorKeys")
(const "NewLine")
(const "Ansi")
(const "AnyModifier")
(const "AppKeypad")
(const :tag "(none)" nil)))


(defcustom term-keys/konsole-modifier-map ["Shift" "Ctrl" "Alt" "Meta" nil nil]
"Modifier keys for Konsole key bindings.
This should be a vector of 6 elements, with each element being a
string indicating the name of the Konsole modifier or state flag
corresponding to the Emacs modifiers Shift, Control, Meta, Super,
Hyper and Alt respectively, as they should appear in generated
Konsole .keytab files. nil indicates that there is no mapping
for this modifier."
:type '(vector
(term-keys/konsole-modifier :tag "Shift")
(term-keys/konsole-modifier :tag "Control")
(term-keys/konsole-modifier :tag "Meta")
(term-keys/konsole-modifier :tag "Super")
(term-keys/konsole-modifier :tag "Hyper")
(term-keys/konsole-modifier :tag "Alt"))
:group 'term-keys)


(defun term-keys/konsole-keytab ()
"Construct Konsole key binding configuration as .keytab file syntax.
This function returns, as a string, a Konsole keytab which can be
used to configure Konsole to encode term-keys key sequences,
according to the term-keys configuration.
The returned string is suitable to be pasted as-is to the end of
an existing Konsole .keytab file."
(apply #'concat
(term-keys/iterate-keys
(lambda (index keymap mods)

;; Skip key combinations with unrepresentable modifiers
(unless (cl-reduce (lambda (x y) (or x y)) ; any
(mapcar (lambda (n) ; active modifier mapped to nil
(and (elt mods n)
(not (elt term-keys/konsole-modifier-map n))))
(number-sequence 0 (1- (length mods))))) ; 0..5
(format "key %s%s : \"%s\"\n"
(elt keymap 3) ; key name
(mapconcat
(lambda (n)
(if (elt term-keys/konsole-modifier-map n)
(concat
(if (elt mods n) "+" "-")
(elt term-keys/konsole-modifier-map n))
""))
(number-sequence 0 (1- (length mods)))
"")
(mapconcat ; hex-escaped sequence
(lambda (x) (format "\\x%02X" x))
(append
term-keys/prefix
(term-keys/encode-key index mods)
term-keys/suffix
nil)
"")))))))


(provide 'term-keys-konsole)
;;; term-keys-konsole.el ends here
124 changes: 124 additions & 0 deletions term-keys-linux.el
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
;;; term-keys-linux.el --- term-keys support for the Linux TTY

;;; Commentary:

;; This file contains supplementary code for aiding in the
;; configuration of the Linux TTY to interoperate with the term-keys
;; package.

;; For more information, please see the accompanying README.md file.

;;; Code:


(require 'term-keys)


(define-widget 'term-keys/linux-modifier 'lazy
"Choice for Linux modifiers for keymap files."
:type '(choice (const "Shift")
(const "AltGr")
(const "Control")
(const "Alt")
(const "ShiftL")
(const "ShiftR")
(const "CtrlL")
(const "CtrlR")
(const "CapsShift")
(const :tag "(none)" nil)))


(defcustom term-keys/linux-modifier-map ["Shift" "Control" "Alt" nil nil "AltGr"]
"Modifier keys for Linux TTY keymaps.
This should be a vector of 6 elements, with each element being a
string indicating the name of the modifier key corresponding to
the Emacs modifiers Shift, Control, Meta, Super, Hyper and Alt
respectively, as they should appear in generated .keymap files.
nil indicates that there is no mapping for this modifier."
:type '(vector
(term-keys/linux-modifier :tag "Shift")
(term-keys/linux-modifier :tag "Control")
(term-keys/linux-modifier :tag "Meta")
(term-keys/linux-modifier :tag "Super")
(term-keys/linux-modifier :tag "Hyper")
(term-keys/linux-modifier :tag "Alt"))
:group 'term-keys)


(defcustom term-keys/linux-first-function-key 13
"First Linux TTY keymap function key to use for term-keys bindings.
The Linux TTY allows binding custom character sequences to keys
only by assigning them to a \"function key\" (named thus after
the usual F1, F2 etc. function keys found on a computer
keyboard). Although most PC keyboards today only have 12
function keys, some keyboards/computers had more, and (also for
the purposes of key binding) the Linux kernel allows registering
character sequences for as many as 246 function keys (see output
for 'loadkeys -l' for the exact figure on your machine).
Crucially, these virtual keys provide the means to configure
arbitrary character sequences for any key combination, which is
necessary for term-keys to work.
This variable specifies the first function key entry that's used
by term-keys in the .keymap files it generates (see
`term-keys/linux-keymap'). The default value (13) will make
`term-keys' use F13 and onwards, and is fine for most uses,
unless you happen to use a keyboard with more than 12 F-keys, or
wish to use the F13-F20 keys through the shifted state of the
F1-F8 keys."
:type 'integer
:group 'term-keys)


(defun term-keys/linux-keymap ()
"Construct Linux TTY configuration in the form of a keymap.
This function returns, as a string, a keymap which can be used to
configure the Linux kernel's TTY emulator to encode term-keys key
sequences, according to the term-keys configuration.
The returned string is suitable to be saved as-is in a .keymap
file and loaded by the loadkeys program."
(apply #'concat
(let ((fkey term-keys/linux-first-function-key))
(term-keys/iterate-keys
(lambda (index keymap mods)

;; Skip key combinations with unrepresentable modifiers
(unless (cl-reduce (lambda (x y) (or x y)) ; any
(mapcar (lambda (n) ; active modifier mapped to nil
(and (elt mods n)
(not (elt term-keys/linux-modifier-map n))))
(number-sequence 0 (1- (length mods))))) ; 0..5
(prog1
(format "# %s\n%s\tkeycode %3d = F%d\nstring F%d = \"%s\"\n\n"
;; Emacs key name for comment
(term-keys/format-key (elt keymap 0) mods)

(if (cl-reduce (lambda (x y) (or x y)) mods)
;; tab-separated mod list
(mapconcat
(lambda (n)
(if (elt mods n) (elt term-keys/linux-modifier-map n) ""))
(number-sequence 0 (1- (length mods)))
"\t")
;; "plain" if no mods
(concat "plain" (make-string (1- (length mods)) ?\t)))
(elt keymap 2) ; keynumber
fkey ; F-key number (use)
fkey ; F-key number (declaration)
(mapconcat ; octal-escaped sequence
(lambda (x) (format "\\%03o" x))
(append
term-keys/prefix
(term-keys/encode-key index mods)
term-keys/suffix
nil)
""))
(setq fkey (1+ fkey)))))))))


(provide 'term-keys-linux)
;;; term-keys-linux.el ends here
164 changes: 164 additions & 0 deletions term-keys-st.el
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
;;; term-keys-st.el --- term-keys support for the st terminal emulator

;;; Commentary:

;; This file contains supplementary code for aiding in the
;; configuration of the st terminal emulator to interoperate with the
;; term-keys package.

;; For more information, please see the accompanying README.md file.

;;; Code:


(require 'term-keys)


(define-widget 'term-keys/x11-modifier 'lazy
"Choice for X11 key modifier state flags."
:type '(choice (const "Shift")
(const "Lock")
(const "Control")
(const "Mod1" :tag "Mod1 (usually Alt)")
(const "Mod2" :tag "Mod2 (usually Num Lock)")
(const "Mod3")
(const "Mod4" :tag "Mod4 (usually the Windows Logo key)")
(const "Mod5")
(const :tag "(none)" nil)))


(defcustom term-keys/x11-modifier-map ["Shift" "Control" "Mod1" "Mod4" "Mod3" "Mod5"]
"Map of X11 modifier state flags to Emacs modifiers.
This should be a vector of 6 elements, with each element being a
string indicating the name of the X11 modifier state mask (sans
the -\"Mask\" suffix) corresponding to the Emacs modifiers Shift,
Control, Meta, Super, Hyper and Alt respectively, as they should
appear in the generated st configuration. nil indicates that
there is no mapping for this modifier."
:type '(vector
(term-keys/x11-modifier :tag "Shift")
(term-keys/x11-modifier :tag "Control")
(term-keys/x11-modifier :tag "Meta")
(term-keys/x11-modifier :tag "Super")
(term-keys/x11-modifier :tag "Hyper")
(term-keys/x11-modifier :tag "Alt"))
:group 'term-keys)


(defun term-keys/x11-apply-mod-state (key shift lock control mod1 mod2 mod3 mod4 mod5)
"Apply modifier state flags to an X11 KeySym.
Given a KeySym KEY which would be received by an application with
no modifier flags, return the KeySym that would be received by
the application if SHIFT, LOCK, CONTROL, MOD1, MOD2, MOD3, MOD4
and MOD5 modifier flags are respectively active."
(cond
((and (string-match-p "^[a-z]$" key) shift)
(upcase key))
((string-equal key "Tab")
"ISO_Left_Tab")
(t
key)))


(defun term-keys/x11-apply-mods (key mods)
"Apply Emacs modifiers to X11 KeySym KEY.
Translate Emacs modifiers MODS to X11 modifiers (according to
`term-keys/x11-modifier-map') and invoke
`term-keys/x11-apply-mod-state')."
(let (shift lock control mod1 mod2 mod3 mod4 mod5)
(mapc
(lambda (n)
(when (elt mods n)
(pcase (downcase (elt term-keys/x11-modifier-map n))
("shift"
(setq shift t))
("lock"
(setq lock t))
("control"
(setq control t))
("mod1"
(setq mod1 t))
("mod2"
(setq mod2 t))
("mod3"
(setq mod3 t))
("mod4"
(setq mod4 t))
("mod5"
(setq mod5 t))
('nil)
(_ (error "Unknown modifier: %s" (elt term-keys/x11-modifier-map n))))))
(number-sequence 0 (1- (length mods))))
(term-keys/x11-apply-mod-state key shift lock control mod1 mod2 mod3 mod4 mod5)))


(defun term-keys/st-config-key ()
"Construct st key binding configuration (key array entries).
This function returns, as a string, C code of Key entries of the
config.h 'key' array, which can be used to configure st to encode
term-keys key sequences, according to the term-keys
configuration.
The returned string is suitable to be pasted as-is into the 'key'
array in the st config.h configuration file; however, this is
just one half of the necessary configuration (see
`term-keys/st-config-mappedkeys' for the other half)."
(apply #'concat
(term-keys/iterate-keys
(lambda (index keymap mods)

;; Skip key combinations with unrepresentable modifiers
(unless (cl-reduce (lambda (x y) (or x y)) ; any
(mapcar (lambda (n) ; active modifier mapped to nil
(and (elt mods n)
(not (elt term-keys/x11-modifier-map n))))
(number-sequence 0 (1- (length mods))))) ; 0..5
(format "{ XK_%-16s, %-40s, \"%s\", 0, 0, 0},\n"
(term-keys/x11-apply-mods (elt keymap 1) mods) ; X11 key name
(if (cl-reduce (lambda (x y) (or x y)) mods)
(mapconcat
(lambda (n)
(concat
(elt term-keys/x11-modifier-map n)
"Mask"))
(cl-remove-if-not (lambda (n) (elt mods n))
(number-sequence 0 (1- (length mods))))
"|")
"XK_NO_MOD")
(mapconcat ; hex-escaped sequence
(lambda (x) (format "\\x%02X" x))
(append
term-keys/prefix
(term-keys/encode-key index mods)
term-keys/suffix
nil)
"")))))))


(defun term-keys/st-config-mappedkeys ()
"Construct st key binding configuration (mappedkeys array entries).
This function returns, as a string, C code of KeySym entries of
the config.h 'mappedkeys' array, which can be used to configure
st to encode term-keys key sequences, according to the term-keys
configuration.
The returned string is suitable to be pasted as-is into the
'mappedkeys' array in the st config.h configuration file;
however, this is just one half of the necessary
configuration (see `term-keys/st-config-key' for the other
half)."
(apply #'concat
(delete-dups
(term-keys/iterate-keys
(lambda (index keymap mods)
(format "XK_%s,\n"
(term-keys/x11-apply-mods (elt keymap 1) mods)))))))


(provide 'term-keys-st)
;;; term-keys-st.el ends here
Loading

0 comments on commit 05eacc5

Please sign in to comment.