This repository has been archived on 2024-10-22. You can view files and clone it, but cannot push or open issues or pull requests.
spacemacs/layers/+intl/keyboard-layout/funcs.el

221 lines
8.4 KiB
EmacsLisp
Raw Normal View History

2016-04-04 20:35:01 +00:00
;;; funcs.el --- keyboard-layout Layer functions File for Spacemacs
;;
2021-03-22 20:11:29 +00:00
;; Copyright (c) 2012-2021 Sylvain Benner & Contributors
;;
;; Author: Fabien Dubosson <fabien.dubosson@gmail.com>
;; URL: https://github.com/syl20bnr/spacemacs
;;
;; This file is not part of GNU Emacs.
;;
;; 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 <http://www.gnu.org/licenses/>.
;; Map multiple states at once. Courtesy of Michael Markert;
;; http://permalink.gmane.org/gmane.emacs.vim-emulation/1674
2015-10-19 22:41:53 +00:00
;;------------------------------------------------------------------------------
2016-04-04 20:35:01 +00:00
;; PRIVATE FUNCTIONS
2015-10-19 22:41:53 +00:00
;;------------------------------------------------------------------------------
2016-04-04 20:35:01 +00:00
(defun kl//generate-full-rebinding-map (basemap)
"Generate the full rebinding map from a base map."
(mapcan (lambda (binding)
(let ((key1 (car binding))
(key2 (cdr binding)))
(append
(list (cons (upcase key1) (upcase key2))
(cons key1 key2))
(mapcar
(lambda (modifier)
(cons (concat modifier key1) (concat modifier key2)))
'("C-" "M-" "C-S-")))))
2016-04-04 20:35:01 +00:00
basemap))
(defun kl//define-key (maps key def bindings)
2015-10-19 22:41:53 +00:00
"Define a list of KEYS to their associated DEFINITIONS in all
the given MAPS."
(declare (indent 1))
(while key
2015-10-19 22:41:53 +00:00
;; Define the key
(dolist (map maps)
2015-10-19 22:41:53 +00:00
(define-key map (kbd key) def))
;; Get next keybinding
(setq key (pop bindings)
def (pop bindings))))
2016-04-04 20:35:01 +00:00
(defun kl//remap-key-as (map bindings)
2015-10-19 22:41:53 +00:00
"Define keys to the associated definitions of other ones. All
remapping are done atomically, i.e. if `a' -> `b' and `c' -> `a',
then `c' will be defined to the old `a' function, not to `b'."
(if (keymapp map)
(progn
(declare (indent 1))
(let ((map-original (copy-tree map)))
(dolist (binding bindings)
(let ((key1 (kbd (car binding)))
(key2 (kbd (cdr binding))))
(define-key map key1 (lookup-key map-original key2))))))))
2015-10-19 22:41:53 +00:00
2016-04-04 20:35:01 +00:00
(defun kl//replace-in-list-rec (lst elem repl)
2015-10-19 22:41:53 +00:00
"Replace recursively all occurrences of `elem' by `repl' in the
list `lst'."
(declare (indent 0))
(if (cl-typep lst 'list)
2015-10-19 22:41:53 +00:00
(let* ((body-position (cl-position elem lst)))
(if body-position
;; The element is in the list, replace it
(progn
(setf (nth body-position lst) repl)
lst)
;; The element is not in the list, recurse
(dolist (l lst)
2016-04-04 20:35:01 +00:00
(kl//replace-in-list-rec l elem repl))))))
2015-10-19 22:41:53 +00:00
2016-04-04 20:35:01 +00:00
(defun kl//guess-rebindings (key)
2015-10-19 22:41:53 +00:00
"Tries to guess the rebindings needed to correct the given
key."
(let* ((key1 key)
2016-04-04 20:35:01 +00:00
(prefix nil)
(rebinding-map (cdr (assoc kl-layout kl--rebinding-maps))))
;; If key not existing as-is in the kl--rebinding-maps, try on last letter.
(unless (assoc key1 rebinding-map)
2015-10-19 22:41:53 +00:00
(setq key1 (substring key -1))
(setq prefix (substring key 0 -1)))
2016-04-04 20:35:01 +00:00
(let* ((key2 (cdr (assoc key1 rebinding-map)))
(bind1 (assoc key1 rebinding-map))
(bind2 (assoc key2 rebinding-map)))
(when (and prefix
(not (string-empty-p prefix)))
2016-04-04 20:35:01 +00:00
(defun kl//guess-prefixit (bind)
2015-10-19 22:41:53 +00:00
`(,(concat prefix (car bind)) . ,(concat prefix (cdr bind))))
2016-04-04 20:35:01 +00:00
(setq bind1 (kl//guess-prefixit bind1))
(setq bind2 (kl//guess-prefixit bind2)))
2015-10-19 22:41:53 +00:00
`(,bind1 ,bind2))))
;;------------------------------------------------------------------------------
;; HELPER FUNCTIONS
;;------------------------------------------------------------------------------
2016-04-04 20:35:01 +00:00
(defun kl/set-in-state (map key def &rest bindings)
2015-10-19 22:41:53 +00:00
"Define a list of keys with their associated functions in a
given state map."
(declare (indent 1))
2016-04-04 20:35:01 +00:00
(kl//define-key (list map) key def bindings))
2016-04-04 20:35:01 +00:00
(defun kl/set-in-states (maps key def &rest bindings)
2015-10-19 22:41:53 +00:00
"Define a list of keys with their associated functions in all
given state maps."
(declare (indent 1))
2016-04-04 20:35:01 +00:00
(kl//define-key maps key def bindings))
2016-04-04 20:35:01 +00:00
(defun kl/set-in-all-evil-states (key def &rest bindings)
2015-10-19 22:41:53 +00:00
"Define a list of keys with their associated functions in all
evil states."
(declare (indent 0))
2016-04-04 20:35:01 +00:00
(kl//define-key kl--all-evil-states key def bindings))
2016-04-04 20:35:01 +00:00
(defun kl/set-in-all-evil-states-but-insert (key def &rest bindings)
2015-10-19 22:41:53 +00:00
"Define a list of keys with their associated functions in all
evil states, except insert."
(declare (indent 0))
2016-04-04 20:35:01 +00:00
(kl//define-key kl--all-evil-states-but-insert key def bindings))
2016-04-04 20:35:01 +00:00
(defun kl/leader-alias-of (key1 key2)
"Define a leader key as an alias of another one."
(spacemacs/set-leader-keys key1 (lookup-key spacemacs-default-map key2)))
2016-04-04 20:35:01 +00:00
(defun kl/leader-swap-keys (key1 key2)
"Invert the behaviour of two leader keys."
2015-10-19 22:41:53 +00:00
(let ((map1 (lookup-key spacemacs-default-map key1))
(map2 (lookup-key spacemacs-default-map key2)))
(spacemacs/set-leader-keys key1 map2 key2 map1)))
2015-10-19 22:41:53 +00:00
;;------------------------------------------------------------------------------
;; CORRECTION FUNCTIONS
;;------------------------------------------------------------------------------
2016-04-04 20:35:01 +00:00
(defun kl/correct-keys (map &rest keys)
(declare (indent 1))
2016-04-04 20:35:01 +00:00
(let ((bindings (mapcan #'kl//guess-rebindings keys)))
(kl//remap-key-as map (cl-remove-if #'null bindings))))
2015-10-19 22:41:53 +00:00
2016-04-04 20:35:01 +00:00
(defun kl/evil-correct-keys (state map &rest keys)
2015-10-19 22:41:53 +00:00
(declare (indent 2))
2016-04-04 20:35:01 +00:00
(apply #'kl/correct-keys (evil-get-auxiliary-keymap map state) keys))
2015-10-19 22:41:53 +00:00
2016-04-04 20:35:01 +00:00
(defun kl/leader-correct-keys (&rest keys)
2015-10-19 22:41:53 +00:00
(declare (indent 0))
2016-04-04 20:35:01 +00:00
(apply #'kl/correct-keys spacemacs-default-map keys))
2015-10-19 22:41:53 +00:00
;;------------------------------------------------------------------------------
;; MAIN MACRO
;;------------------------------------------------------------------------------
2016-04-04 20:35:01 +00:00
(defmacro kl|config (name &rest props)
"Macro used for structuring `keyboard-layout' configuration changes.
2015-10-19 22:41:53 +00:00
Usage:
2016-04-04 20:35:01 +00:00
(kl|config configuration-name
2015-10-19 22:41:53 +00:00
[:keyword option]...)
:disable Boolean, whether the configuration is disabled or not.
:description String, documents what the configuration does.
:functions Code, functions definitions.
:loader Code, used to load the configuration. Must contains `BODY'
where the real configuration must be placed.
:config Code, the configuration code.
:special Code executed as-is at the end, without being wrapped inside
the `:loader'.
All keywords are optional, except for `:config'.
These configurations can be overridden by the user using a
2016-04-04 20:35:01 +00:00
`kl/pre-config-<name>' or `kl/post-config-<name>'
2015-10-19 22:41:53 +00:00
function (taking no argument). These functions will be called just
2016-04-04 20:35:01 +00:00
before or after the keyboard-layout's configurations."
(declare (indent 1))
2015-10-19 22:41:53 +00:00
(let* ((disable (plist-get props :disable))
(description (plist-get props :description))
(functions (plist-get props :functions))
(loader (plist-get props :loader))
2016-04-04 20:35:01 +00:00
(common (plist-get props :common))
(specific (plist-get props (intern (format ":%s" kl-layout))))
(special (plist-get props :special))
2016-04-04 20:35:01 +00:00
(preconf (intern (format "kl/pre-config-%s" name)))
(postconf (intern (format "kl/post-config-%s" name)))
2015-10-19 22:41:53 +00:00
(body `(progn
(when (fboundp ',preconf) (funcall ',preconf))
2016-04-04 20:35:01 +00:00
,common
,specific
(when (fboundp ',postconf) (funcall ',postconf)))))
;; Use loader if defined
2015-10-19 22:41:53 +00:00
(when loader
2016-04-04 20:35:01 +00:00
(kl//replace-in-list-rec loader 'BODY body)
2015-10-19 22:41:53 +00:00
(setq body loader))
;; If the configuration is not disabled
(unless disable
2015-10-19 22:41:53 +00:00
;; If the configuration is not in disabled-list
(unless (member name kl-disabled-configurations)
2015-10-19 22:41:53 +00:00
;; If the package is in enabled-list, if any.
2016-04-04 20:35:01 +00:00
(when (or (not kl-enabled-configurations) (member name kl-enabled-configurations))
(when init-file-debug
2016-04-04 20:35:01 +00:00
(message (format "[kl] Configuration enabled: '%s'" name)))
2015-10-19 22:41:53 +00:00
`(progn
,functions
,body
,special
,description))))))