;;; evil-leader.el --- let there be ;; Copyright (C) 2011-2013 by Michael Markert ;; Author: Michael Markert ;; URL: http://github.com/cofi/evil-leader ;; Git-Repository: git://github.com/cofi/evil-leader.git ;; Created: 2011-09-13 ;; Version: 0.4.3 ;; Keywords: evil vim-emulation leader ;; Package-Requires: ((evil "0")) ;; 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 . ;;; Commentary: ;; ;; Known Bugs: ;; See http://github.com/cofi/evil-leader/issues ;; Install: ;; (require 'evil-leader) ;; Usage: ;; ;; (global-evil-leader-mode) ;; ;; to enable `evil-leader' in every buffer where `evil' is enabled. ;; ;; Note: You should enable `global-evil-leader-mode' before you enable ;; `evil-mode', otherwise `evil-leader' won't be enabled in initial ;; buffers (*scratch*, *Messages*, ...). ;; ;; Use `evil-leader/set-key' to bind keys in the leader map. ;; For example: ;; ;; (evil-leader/set-key "e" 'find-file) ;; ;; You can also bind several keys at once: ;; ;; (evil-leader/set-key ;; "e" 'find-file ;; "b" 'switch-to-buffer ;; "k" 'kill-buffer) ;; ;; The key map can of course be filled in several places. ;; ;; After you set up the key map you can access the bindings by pressing == ;; (default: \) and the key(s). E.g. \ e would call `find-file' to open a file. ;; ;; If you wish to change so you can customize =evil-leader/leader= or call ;; `evil-leader/set-leader', e.g. (evil-leader/set-leader ",") to change it to ;; ",". ;; The leader has to be readable by `read-kbd-macro', so using Space as a ;; prefix key would be (evil-leader/set-leader ""). ;; ;; Beginning with version 0.3 evil-leader has support for mode-local bindings: ;; ;; (evil-leader/set-key-for-mode 'emacs-lisp-mode "b" 'byte-compile-file) ;; ;; Again, you can bind several keys at once. ;; ;; A mode-local binding shadows a normal mode-independent binding. ;;; Code: (require 'evil) (defvar evil-leader--default-map (make-sparse-keymap) "Keymap used for mode-independent leader bindings.") (defvar evil-leader--mode-maps nil "Alist of mode-local leader bindings, shadows mode-independent bindings.") ;;; customization (defgroup evil-leader nil " support for evil." :group 'evil :prefix 'evil-leader/) (defcustom evil-leader/leader "\\" "The key, used to access keys defined by `evil-leader/set-key' in normal and visual state. Must be readable by `read-kbd-macro'. For example: \",\"." :type 'string :group 'evil-leader) (defcustom evil-leader/non-normal-prefix "C-" "Prefix for leader-map in insert- and emacs-state. `evil-leader/in-all-states' has to be non-nil for this to be set. The combination has to be readable by `read-kbd-macro'." :type 'string :group 'evil-leader) (defcustom evil-leader/no-prefix-mode-rx nil "List of regular expressions for mode names where `evil-leader/leader' is used regardless of the state. If the current major mode is matched by one of the regular expressions `evil-leader/leader' is installed in emacs/insert state without the prefix additionally to the prefixed key. `evil-leader/in-all-states' has to be non-nil for this setting to have any effect." :type 'list :group 'evil-leader) (defcustom evil-leader/in-all-states nil "If is non-nil leader-map is accessible by in emacs/insert state. is `evil-leader/non-normal-prefix' + `evil-leader/leader'" :type 'boolean :group 'evil-leader) ;;;###autoload (define-minor-mode global-evil-leader-mode "Global minor mode for support." nil nil nil (if global-evil-leader-mode (add-hook 'evil-local-mode-hook #'evil-leader-mode t) (remove-hook 'evil-local-mode-hook #'evil-leader-mode t))) ;;;###autoload (define-minor-mode evil-leader-mode "Minor mode to enable support." :init-value nil :keymap nil (let* ((prefixed (read-kbd-macro (concat evil-leader/non-normal-prefix evil-leader/leader))) (no-prefix (read-kbd-macro evil-leader/leader)) (mode-map (cdr (assoc major-mode evil-leader--mode-maps))) (map (or mode-map evil-leader--default-map)) (no-prefix-rx (if evil-leader/no-prefix-mode-rx (mapconcat #'identity evil-leader/no-prefix-mode-rx "\\|") nil))) (if evil-leader-mode (progn (evil-normalize-keymaps) (define-key evil-motion-state-local-map no-prefix map) (define-key evil-normal-state-local-map no-prefix map) (when evil-leader/in-all-states (define-key evil-emacs-state-local-map prefixed map) (define-key evil-insert-state-local-map prefixed map)) (when (and no-prefix-rx (string-match-p no-prefix-rx (symbol-name major-mode))) (define-key evil-emacs-state-local-map no-prefix map) (define-key evil-insert-state-local-map no-prefix map))) (define-key evil-motion-state-local-map no-prefix nil) (define-key evil-normal-state-local-map no-prefix nil) (when evil-leader/in-all-states (define-key evil-emacs-state-local-map prefixed nil) (define-key evil-insert-state-local-map prefixed nil) (when (and no-prefix-rx (string-match-p no-prefix-rx (symbol-name major-mode))) (define-key evil-emacs-state-local-map no-prefix nil) (define-key evil-insert-state-local-map no-prefix nil)))))) (defun evil-leader/set-leader (key &optional prefix) "Set leader key to `key' and non-normal-prefix to `prefix' and remove old bindings. Passing `nil' as `prefix' leaves prefix unchanged." (let ((global-on global-evil-leader-mode) (local-on evil-leader-mode)) (when local-on (evil-leader-mode -1)) (when global-on (global-evil-leader-mode -1)) (setq evil-leader/leader key) (when prefix (setq evil-leader/non-normal-prefix prefix)) (if global-on (global-evil-leader-mode 1) (when local-on (evil-leader-mode 1))))) ;;;###autoload (defun evil-leader/set-key (key def &rest bindings) "Bind `key' to command `def' in `evil-leader/default-map'. Key has to be readable by `read-kbd-macro' and `def' a command. Accepts further `key' `def' pairs." (interactive "kKey: \naCommand: ") (evil-leader--def-keys evil-leader--default-map key def bindings)) (put 'evil-leader/set-key 'lisp-indent-function 'defun) ;;;###autoload (defun evil-leader/set-key-for-mode (mode key def &rest bindings) "Create keybindings for major-mode `mode' with `key' bound to command `def'. See `evil-leader/set-key'." (interactive "SMode: \nkKey: \naCommand: ") (let ((mode-map (cdr (assoc mode evil-leader--mode-maps)))) (unless mode-map (setq mode-map (make-sparse-keymap)) (set-keymap-parent mode-map evil-leader--default-map) (push (cons mode mode-map) evil-leader--mode-maps)) (evil-leader--def-keys mode-map key def bindings))) (put 'evil-leader/set-key-for-mode 'lisp-indent-function 'defun) (defun evil-leader--def-keys (map key def bindings) (while key (define-key map (read-kbd-macro key) def) (setq key (pop bindings) def (pop bindings)))) (provide 'evil-leader) ;;; evil-leader.el ends here