(define-module (gri3 bindings) #:use-module (gri3 wm) #:use-module (gri3 hooks) #:use-module (srfi srfi-1) #:use-module (ice-9 match) #:export (define-mode-map add-key-binding kbd key-press-hook clear-bindings)) (define *bindings* '()) (define *mode-map* '()) (define *mode* "default") (define (sym->name sym) (or (assoc-ref '(("\r" . "Return") (" " . "space")) sym) sym)) (define (key-press-hook param) (let ((param (list (list-ref param 0) (list-ref param 1) (sym->name (list-ref param 2))))) (apply format #t "~A ~A ~s\n" param) ;; (display *bindings*) ;; (newline) (let ((binding (assoc-ref *bindings* (list *mode* param)))) ;; (display binding) ;; (newline) (if binding (begin (binding) #t) #f)))) (define (notify-exceptions exc) (system (format #f "notify-send exception ~A" exc))) (define (key-press-hook param) (with-exception-handler notify-exceptions key-press-hook-real #:unwind? #t)) (define (clear-bindings) (set! *bindings* '())) (define (add-key-binding key func) (match-let (((mode (press mod keysym)) key)) ;; (format #t "Binding key ~A\n" keysym) ;; get notified for key with all mods (for-each (lambda (mod) (bind-key keysym mod)) (list #x8 #x10 #x26 #x40)) ;; Store the key+func couple in the list of hooks (set! *bindings* (assoc-set! *bindings* `("default" (,press ,mod ,keysym)) func)))) (define (special->keysym name) (or (assoc-ref '( ;; ("NUL") ;; ("REM") ("RET" . "Return") ("TAB" . "Tab") ("LFD" . "Linefeed") ("ESC" . "Escape") ("SPC" . "space") ("DEL" . "Delete")) name) name)) (define (define-mode-map map mode) (set! *mode-map* (append *mode-map* `((,map . ,mode))))) ;; modifiers ;; ("A" "C" "M" "H" "s" "S") (define *modifiers* ;; Where's H? '(("S" . #b00000001) ("L" . #b00000010) ("C" . #b00000100) ("M" . #b00001000) ("mod2" . #b00010000) ("mod3" . #b00100000) ("s" . #b01000000) ("mod5" . #b10000000))) (define (mod->int mod) (assoc-ref *modifiers* mod)) (define *key-press* 2) ;; TODO: Support multiple modifiers! Sum their int value (define (kbd keys) "Convert keys in our own representation. KEYS should be a string compatible with the emacs format such as `C-h k'." (match (let ((keys (string-split keys #\space))) (map (lambda (key) (string-split key #\-)) keys)) (((M1 mode) (M2 key)) `((,M1 ,mode) (,*key-press* ,(mod->int M2) ,(special->keysym key)))) (((M mode) (key)) `((,M ,mode) (,*key-press* 0 ,(special->keysym key)))) (((M1 M2 key)) `(("") (,*key-press* ,(+ (mod->int M1) (mod->int M2)) ,(special->keysym key)))) (((M key)) `(("") (,*key-press* ,(mod->int M) ,(special->keysym key)))) (((key)) `(("") (,*key-press* 0 ,(special->keysym key)))) (else (display "Cannot parse kdb")))) ;; (kbd "C-RET C-k") ;; (kbd "C-RET C-k") ;; (kbd "C-RET k") ;; (kbd "C-S-1") ;; (kbd "C-h") ;; (kbd "C")