diff options
Diffstat (limited to 'emacs/.emacs.d/wpc/keyboard.el')
-rw-r--r-- | emacs/.emacs.d/wpc/keyboard.el | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/emacs/.emacs.d/wpc/keyboard.el b/emacs/.emacs.d/wpc/keyboard.el new file mode 100644 index 000000000000..ec50cabd2719 --- /dev/null +++ b/emacs/.emacs.d/wpc/keyboard.el @@ -0,0 +1,152 @@ +;;; keyboard.el --- Managing keyboard preferences with Elisp -*- lexical-binding: t -*- +;; Author: William Carroll <wpcarro@gmail.com> + +;;; Commentary: +;; Setting key repeat and other values. +;; +;; Be wary of suspiciously round numbers. Especially those divisible by ten! + +;;; Code: + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Dependencies +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(require 'string) +(require 'number) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Constants +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; TODO: Support clamping functions for repeat-{rate,delay} to ensure only valid +;; values are sent to xset. +(defcustom keyboard/repeat-rate 80 + "The number of key repeat signals sent per second.") + +(defcustom keyboard/repeat-delay 170 + "The number of milliseconds before autorepeat starts.") + +(defconst keyboard/repeat-rate-copy keyboard/repeat-rate + "Copy of `keyboard/repeat-rate' to support `keyboard/reset-key-repeat'.") + +(defconst keyboard/repeat-delay-copy keyboard/repeat-delay + "Copy of `keyboard/repeat-delay' to support `keyboard/reset-key-repeat'.") + +(defcustom keyboard/install-preferences? t + "When t, install keyboard preferences.") + +(defcustom keyboard/install-kbds? nil + "When t, install keybindings.") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Functions +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defun keyboard/message (x) + "Message X in a structured way." + (message (string/format "[keyboard.el] %s" x))) + +(cl-defun keyboard/set-key-repeat (&key + (rate keyboard/repeat-rate) + (delay keyboard/repeat-delay)) + "Use xset to set the key-repeat RATE and DELAY." + (prelude/start-process + :name "keyboard/set-key-repeat" + :command (string/format "xset r rate %s %s" delay rate))) + +;; NOTE: Settings like this are machine-dependent. For instance I only need to +;; do this on my laptop and other devices where I don't have access to my split +;; keyboard. +;; NOTE: Running keysym Caps_Lock is not idempotent. If this is called more +;; than once, xmodmap will start to error about non-existent Caps_Lock symbol. +;; For more information see here: +;; https://unix.stackexchange.com/questions/108207/how-to-map-caps-lock-as-the-compose-key-using-xmodmap-portably-and-idempotently +(defun keyboard/swap-caps-lock-and-escape () + "Swaps the caps lock and escape keys using xmodmap." + (interactive) + ;; TODO: Ensure these work once the tokenizing in prelude/start-process works + ;; as expected. + (start-process "keyboard/swap-caps-lock-and-escape" nil "/usr/bin/xmodmap" "-e" + "remove Lock = Caps_Lock") + (start-process "keyboard/swap-caps-lock-and-escape" nil "/usr/bin/xmodmap" "-e" + "keysym Caps_Lock = Escape")) + +(defun keyboard/inc-repeat-rate () + "Increment `keyboard/repeat-rate'." + (interactive) + (setq keyboard/repeat-rate (number/inc keyboard/repeat-rate)) + (keyboard/set-key-repeat :rate keyboard/repeat-rate) + (keyboard/message + (string/format "Rate: %s" keyboard/repeat-rate))) + +(defun keyboard/dec-repeat-rate () + "Decrement `keyboard/repeat-rate'." + (interactive) + (setq keyboard/repeat-rate (number/dec keyboard/repeat-rate)) + (keyboard/set-key-repeat :rate keyboard/repeat-rate) + (keyboard/message + (string/format "Rate: %s" keyboard/repeat-rate))) + +(defun keyboard/inc-repeat-delay () + "Increment `keyboard/repeat-delay'." + (interactive) + (setq keyboard/repeat-delay (number/inc keyboard/repeat-delay)) + (keyboard/set-key-repeat :delay keyboard/repeat-delay) + (keyboard/message + (string/format "Delay: %s" keyboard/repeat-delay))) + +(defun keyboard/dec-repeat-delay () + "Decrement `keyboard/repeat-delay'." + (interactive) + (setq keyboard/repeat-delay (number/dec keyboard/repeat-delay)) + (keyboard/set-key-repeat :delay keyboard/repeat-delay) + (keyboard/message + (string/format "Delay: %s" keyboard/repeat-delay))) + +(defun keyboard/print-key-repeat () + "Print the currently set values for key repeat." + (interactive) + (keyboard/message + (string/format "Rate: %s. Delay: %s" + keyboard/repeat-rate + keyboard/repeat-delay))) + +(defun keyboard/set-preferences () + "Reset the keyboard preferences to their default values. +NOTE: This function exists because occasionally I unplug and re-plug in a + keyboard and all of the preferences that I set using xset disappear." + (interactive) + (keyboard/swap-caps-lock-and-escape) + (keyboard/set-key-repeat :rate keyboard/repeat-rate + :delay keyboard/repeat-delay) + ;; TODO: Implement this message function as a macro that pulls the current + ;; file name. + (keyboard/message "Keyboard preferences set!")) + +(defun keyboard/reset-key-repeat () + "Set key repeat rate and delay to original values." + (interactive) + (keyboard/set-key-repeat :rate keyboard/repeat-rate-copy + :delay keyboard/repeat-delay-copy) + (keyboard/message "Key repeat preferences reset.")) + +(when keyboard/install-preferences? + (keyboard/set-preferences)) + +;; TODO: Define minor-mode for this. +(when keyboard/install-kbds? + (general-unbind 'motion "C-i" "C-y") + (general-define-key + ;; TODO: Choose better KBDs for these that don't interfere with useful evil + ;; ones. + ;; Use C-y when you accidentally send the key-repeat too high or too low to + ;; be meaningful. + "C-y" #'keyboard/reset-key-repeat + "C-i" #'keyboard/inc-repeat-rate + "C-u" #'keyboard/dec-repeat-rate + "C-S-i" #'keyboard/inc-repeat-delay + "C-S-u" #'keyboard/dec-repeat-delay)) + +(provide 'keyboard) +;;; keyboard.el ends here |