;;; core-keybindings.el --- Spacemacs Core File -*- lexical-binding: t -*- ;; ;; Copyright (c) 2012-2022 Sylvain Benner & Contributors ;; ;; Author: Sylvain Benner ;; 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 . (require 'core-funcs) (defvar spacemacs/prefix-titles nil "alist for mapping command prefixes to long names.") (defvar spacemacs-default-map (make-sparse-keymap) "Base keymap for all spacemacs leader key commands.") (defun spacemacs/translate-C-i (_) "If `dotspacemacs-distinguish-gui-tab' is non nil, the raw key sequence does not include or , and we are in the gui, translate to [C-i]. Otherwise, [9] (TAB)." (interactive) (if (and (not (cl-position 'tab (this-single-command-raw-keys))) (not (cl-position 'kp-tab (this-single-command-raw-keys))) dotspacemacs-distinguish-gui-tab (display-graphic-p)) [C-i] [?\C-i])) (define-key key-translation-map [?\C-i] 'spacemacs/translate-C-i) ;; (defun spacemacs/translate-C-m (_) ;; "If `dotspacemacs-distinguish-gui-ret' is non nil, the raw key ;; sequence does not include , and we are in the gui, translate ;; to [C-m]. Otherwise, [9] (TAB)." ;; (interactive) ;; (if (and ;; (not (cl-position 'return (this-single-command-raw-keys))) ;; (not (cl-position 'kp-enter (this-single-command-raw-keys))) ;; dotspacemacs-distinguish-gui-ret ;; (display-graphic-p)) ;; [C-m] [?\C-m])) ;; (define-key key-translation-map [?\C-m] 'spacemacs/translate-C-m) (defun spacemacs/declare-prefix (prefix name &rest more) "Declare a prefix PREFIX. PREFIX is a string describing a key sequence. NAME is a string used as the prefix command." (declare (indent defun)) (apply #'which-key-add-keymap-based-replacements spacemacs-default-map prefix name more)) (defun spacemacs/declare-prefix-for-mode (mode prefix name &optional _) "Declare a prefix PREFIX. MODE is the mode in which this prefix command should be added. PREFIX is a string describing a key sequence. NAME is a symbol name used as the prefix command." (let* ((is-major-mode-prefix (string-prefix-p "m" prefix)) (is-minor-mode-prefix (not is-major-mode-prefix)) (smap (intern (format "spacemacs-%s-map" mode)))) (when (spacemacs//init-leader-mode-map mode smap is-minor-mode-prefix) (which-key-add-keymap-based-replacements (symbol-value smap) (if is-major-mode-prefix (substring prefix 1) prefix) name)))) (put 'spacemacs/declare-prefix-for-mode 'lisp-indent-function 'defun) (defun spacemacs/set-leader-keys (key def &rest bindings) "Add KEY and DEF as key bindings under `dotspacemacs-leader-key' and `dotspacemacs-emacs-leader-key'. KEY should be a string suitable for passing to `kbd', and it should not include the leaders. DEF is most likely a quoted command. See `define-key' for more information about the possible choices for DEF. This function simply uses `define-key' to add the bindings. For convenience, this function will accept additional KEY DEF pairs. For example, \(spacemacs/set-leader-keys \"a\" 'command1 \"C-c\" 'command2 \"bb\" 'command3\)" (while key (define-key spacemacs-default-map (kbd key) def) (setq key (pop bindings) def (pop bindings)))) (put 'spacemacs/set-leader-keys 'lisp-indent-function 'defun) (defalias 'evil-leader/set-key 'spacemacs/set-leader-keys) (defun spacemacs//acceptable-leader-p (key) "Return t if key is a string and non-empty." (and (stringp key) (not (string= key "")))) (defun spacemacs//init-leader-mode-map (mode map &optional minor) "Check for MAP-prefix. If it doesn't exist yet, use `bind-map' to create it and bind it to `dotspacemacs-major-mode-leader-key' and `dotspacemacs-major-mode-emacs-leader-key'. If MODE is a minor-mode, the third argument should be non nil." (let* ((prefix (intern (format "%s-prefix" map))) (leader1 (when (spacemacs//acceptable-leader-p dotspacemacs-major-mode-leader-key) dotspacemacs-major-mode-leader-key)) (leader2 (when (spacemacs//acceptable-leader-p dotspacemacs-leader-key) (concat dotspacemacs-leader-key " m"))) (emacs-leader1 (when (spacemacs//acceptable-leader-p dotspacemacs-major-mode-emacs-leader-key) dotspacemacs-major-mode-emacs-leader-key)) (emacs-leader2 (when (spacemacs//acceptable-leader-p dotspacemacs-emacs-leader-key) (concat dotspacemacs-emacs-leader-key " m"))) (leaders (delq nil (list leader1 leader2))) (emacs-leaders (delq nil (list emacs-leader1 emacs-leader2)))) (or (boundp prefix) (progn (eval `(bind-map ,map :prefix-cmd ,prefix ,(if minor :minor-modes :major-modes) (,mode) :keys ,emacs-leaders :evil-keys ,leaders :evil-states (normal motion visual evilified))) (boundp prefix))))) (defun spacemacs/inherit-leader-keys-from-parent-mode (mode &optional parent-mode) "Make derived mode MODE inherit leader key bindings from PARENT-MODE. If omitted, PARENT-MODE defaults to the parent mode of MODE. Signal an error if MODE is not a derived mode (for example if the package defining the mode has not yet been loaded)." (unless parent-mode (setq parent-mode (or (get mode 'derived-mode-parent) (error "Mode %s has no parent" mode)))) (let ((map (intern (format "spacemacs-%s-map" mode))) (parent-map (intern (format "spacemacs-%s-map" parent-mode)))) (when (and (spacemacs//init-leader-mode-map mode map) (spacemacs//init-leader-mode-map parent-mode parent-map)) (set-keymap-parent (symbol-value map) (symbol-value parent-map))))) (defun spacemacs/set-leader-keys-for-major-mode (mode key def &rest bindings) "Add KEY and DEF as key bindings under `dotspacemacs-major-mode-leader-key' and `dotspacemacs-major-mode-emacs-leader-key' for the major-mode MODE. MODE should be a quoted symbol corresponding to a valid major mode. The rest of the arguments are treated exactly like they are in `spacemacs/set-leader-keys'." (let* ((map (intern (format "spacemacs-%s-map" mode)))) (when (spacemacs//init-leader-mode-map mode map) (while key (define-key (symbol-value map) (kbd key) def) (setq key (pop bindings) def (pop bindings)))))) (put 'spacemacs/set-leader-keys-for-major-mode 'lisp-indent-function 'defun) (defalias 'evil-leader/set-key-for-mode 'spacemacs/set-leader-keys-for-major-mode) (defun spacemacs/set-leader-keys-for-minor-mode (mode key def &rest bindings) "Add KEY and DEF as key bindings under `dotspacemacs-major-mode-leader-key' and `dotspacemacs-major-mode-emacs-leader-key' for the minor-mode MODE. MODE should be a quoted symbol corresponding to a valid minor mode. The rest of the arguments are treated exactly like they are in `spacemacs/set-leader-keys'. If DEF is string, then it is treated as a prefix not a command." (let* ((map (intern (format "spacemacs-%s-map" mode)))) (when (spacemacs//init-leader-mode-map mode map t) (let ((map-value (symbol-value map))) (while key (if (stringp def) (which-key-add-keymap-based-replacements map-value key def) (define-key map-value (kbd key) def)) (setq key (pop bindings) def (pop bindings))))))) (put 'spacemacs/set-leader-keys-for-minor-mode 'lisp-indent-function 'defun) (defun spacemacs/declare-prefix-for-minor-mode (mode prefix name) "Declare a prefix PREFIX. MODE is the mode in which this prefix command should be added. PREFIX is a string describing a key sequence. NAME is a symbol name used as the prefix command. Example: \(spacemacs/declare-prefix-for-minor-mode 'tide-mode \"E\" \"errors\"\)" (let* ((map (intern (format "spacemacs-%s-map" mode)))) (when (spacemacs//init-leader-mode-map mode map t) (which-key-add-keymap-based-replacements (symbol-value map) prefix name)))) (provide 'core-keybindings)