spacemacs/layers/+distribution/spacemacs-base/local/hybrid-mode/hybrid-mode.el
justbur 18874c9a3e hybrid-mode: Simplify implementation
Make use of new evil variable evil-disable-insert-state-bindings. This
is better because we are not copying evil code to get hybrid state to
work. We should not need to worry about tracking upstream evil changes
with this version of hybrid mode.

The only effect I can think of with this change is that there is no
longer a distinct hybrid-map, since there is no longer a distinct hybrid
state. This means that, for example, (evil-define-key 'hybrid ...)
will throw an error. You can either use (evil-define-key 'insert ...) or
the preferred (global-set-key ...). The latter is preferred because the
purpose of hybrid mode is to not interfere with Emacs bindings in insert
state.

Use post-init-evil function to load
It's a bit safer than with-eval-after-load, in case evil gets loaded
before its init function is called.

Add entry and exit hooks

Add temporary wrapper to evil-define-key
This is so that calls like (evil-define-key 'hybrid ...) do not fail
after switching over. Instead issue a warning for all such instances and
bind using define-key instead.
Also define evil-hybrid-state-map and make it the parent of
evil-insert-state-map this will prevent calls like (define-key
evil-hybrid-state-map ...) from failing.
These are both temporary and are only intended to smooth the transition
to the new version of hybrid-mode.
2016-02-01 00:20:58 -05:00

105 lines
4.1 KiB
EmacsLisp

;;; hybrid-mode.el --- Put one foot in the church of Emacs
;; Copyright (C) 2012-2016 Sylvain Benner & Contributors
;;
;; Authors: Justin Burkett <justin@burkett.cc>
;; Chris Ewald <chrisewald@gmail.com>
;; Keywords: convenience editing
;; Created: 12 Aug 2015
;; Version: 1.00
;; Package-Requires: ((emacs "24") (evil "1.0.9"))
;; 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/>.
;;; Commentary:
;;; Code:
(require 'evil)
(defvar hybrid-mode-default-state-backup evil-default-state
"Backup of `evil-default-state'.")
(defcustom hybrid-mode-default-state 'normal
"Value of `evil-default-state' for hybrid-mode. Set to hybrid
to start in hybrid state (emacs bindings) by default."
:group 'spacemacs
:type 'symbol)
(defvar hybrid-mode-insert-cursor evil-hybrid-state-cursor)
(defvar hybrid-mode-insert-cursor-backup evil-insert-state-cursor)
(defvar hybrid-mode-insert-state-entry-hook)
(defvar hybrid-mode-insert-state-exit-hook)
(defun hybrid-mode-insert-state-entry-hook ()
"Run hooks in `hybrid-mode-insert-state-entry-hook'."
(run-hooks 'hybrid-mode-insert-state-entry-hook))
(defun hybrid-mode-insert-state-exit-hook ()
"Run hooks in `hybrid-mode-insert-state-exit-hook'."
(run-hooks 'hybrid-mode-insert-state-exit-hook))
;;;###autoload
(define-minor-mode hybrid-mode
"Global minor mode to allow emacs bindings in `evil-insert-state'."
:global t
:lighter " hybrid"
:group 'spacemacs
(if hybrid-mode
(progn
(setq hybrid-mode-default-state-backup evil-default-state
evil-default-state hybrid-mode-default-state
evil-insert-state-cursor hybrid-mode-insert-cursor)
(put 'spacemacs-insert-face 'face-alias 'spacemacs-hybrid-face)
;; using this function to set the variable triggers the defcustom :set
;; property which actually does the work of removing the bindings.
(customize-set-variable 'evil-disable-insert-state-bindings t)
(add-hook 'evil-insert-state-entry-hook 'hybrid-mode-insert-state-entry-hook)
(add-hook 'evil-insert-state-exit-hook 'hybrid-mode-insert-state-exit-hook))
(setq evil-default-state hybrid-mode-default-state-backup
evil-insert-state-cursor hybrid-mode-insert-cursor-backup)
(put 'spacemacs-insert-face 'face-alias nil)
(customize-set-variable 'evil-disable-insert-state-bindings nil)
(remove-hook 'evil-insert-state-entry-hook 'hybrid-mode-insert-state-entry-hook)
(remove-hook 'evil-insert-state-exit-hook 'hybrid-mode-insert-state-exit-hook)))
;;; Temporary to support old method of defining bindings. Should be removed
;;; eventually.
(when (fboundp 'advice-add)
(defun hybrid-mode-evil-define-key (old-func &rest args)
(if (equal (car args) ''hybrid)
(let ((map (nth 1 args))
(key (nth 2 args))
(def (nth 3 args))
(bindings (nthcdr 4 args)))
(message "warning: evil-define-key no longer supports \
hybrid as a state please convert to (define-key map key def)")
(while key
(when (keymapp (symbol-value map))
(define-key (symbol-value map) key def)
(setq key (pop bindings)
def (pop bindings)))))
(apply old-func args)))
(advice-add 'evil-define-key :around #'hybrid-mode-evil-define-key))
(defvar evil-hybrid-state-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent evil-insert-state-map map)
map))
(provide 'hybrid-mode)