about summary refs log blame commit diff
path: root/emacs/.emacs.d/wpc/keyboard.el
blob: f8d37280c88088f45517f3695e05926a101c4589 (plain) (tree)
1
2
3
4
5
6
                                                                                       
 
                                              


                                                 




















                                                                                
                                  

                                                      
                                    

                                                         

                                                                           
 

                                                                            
 
                                          

                                          
                                     





                                                                                
                           
                                  
                                                 
 


                                                                 
                                                  
                        
                                  
                                                            







                                                                                                                                  
                                            

                                                      
                                                                               
                 
                                                                                 
                                           
                                                                                 
                                              
 

                                     
               



                                                               
 

                                     
               



                                                               
 

                                      
               



                                                                 
 

                                      
               



                                                                 
 
                                   

                                                  
                   
                                       

                                          
 
                                  



                                                                         


                                                        

                                                                            
                                                 
 
                                   

                                                     


                                                             
 

                                   

                                    
                            





                                                                              




                                        


                         
;;; keyboard.el --- Managing keyboard preferences with Elisp -*- lexical-binding: t -*-

;; Author: William Carroll <wpcarro@gmail.com>
;; Version: 0.0.1
;; URL: https://git.wpcarro.dev/wpcarro/briefcase
;; Package-Requires: ((emacs "24.3"))

;;; 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