Add evil-lisp-state to navigate and edit sexp trees

This commit is contained in:
syl20bnr 2014-10-10 00:38:24 -04:00
parent f245f20fa0
commit b2245bfb3b
5 changed files with 157 additions and 140 deletions

View File

@ -65,9 +65,6 @@
- [Erlang](#erlang)
- [Ledger](#ledger)
- [Lisp](#lisp)
- [Evaluation commands](#evaluation-commands)
- [Other commands](#other-commands)
- [Lisp micro-state](#lisp-micro-state)
- [Magit](#magit)
- [Org](#org)
- [Perforce](#perforce)
@ -802,46 +799,45 @@ the current `major mode`.
#### Lisp
##### Evaluation commands
Lisp navigation and edition is performed with a custom evil `lisp state`.
Key Binding | Description
------------------|------------------------------------------------------------
`<SPC> m e` | evaluate last sexp (sexp just behind point)
`<SPC> m f` | evaluate the current function
`<SPC> m l` | evaluate the current line (go to end of line and evaluate last sexp)
While in `lisp state`, the following key binding map is available:
##### Other commands
Key Binding | Description
------------------|------------------------------------------------------------
`<SPC> m D` | display the documentation for symbol under point
`<SPC> m g` | go to the definition for the symbol under point
##### Lisp micro-state
Key Binding | Description
Key Binding | Function
--------------|------------------------------------------------------------
`<SPC> m m` | initiate lisp micro-state
`a` | go to beginning of sexp
`bb` | backward barf sexp
`bs` | backward slurp sexp
`c` | convolute sexp
`d` | kill sexp
`e` | go to end of sexp
`fb` | forward barf sexp
`fs` | forward slurp sexp
`h` | go forward by symbol or by sexp when point is at the beginning or end of an sexp
`j` | go down the sexp hierarchy
`J` | go down the sexp hierarchy backward
`k` | go up the sexp hierarchy
`K` | go up the sexp hierarchy backward
`l` | go backward by symbol or by sexp when point is at the beginning or end of an sexp
`r` | raise sexp one level
`sa` | remove sexp parentheses and kill the sexp around the current symbol
`sb` | remove sexp parentheses and kill the sexp part before point
`sf` | remove sexp parentheses and kill the sexp part after point
`ss` | remove sexp parentheses
`H` | toggle the help listing all the key bindings
`$` | sp-end-of-sexp
`0` | sp-beginning-of-sexp
`bh` | sp-backward-barf-sexp
`bl` | sp-forward-barf-sexp
`c` | sp-convolute-sexp
`d` | sp-kill-sexp
`e$` | evil-lisp-state-eval-sexp-end-of-line
`ef` | eval-defun
`el` | eval-last-sexp
`es` | eval-sexp
`h` | sp-backward-sexp
`i` | evil-insert-state
`j` | sp-down-sexp
`J` | sp-backward-down-sexp
`k` | sp-up-sexp
`K` | sp-backward-up-sexp
`l` | sp-forward-sexp
`r` | sp-raise-sexp
`C-r` | undo-tree-redo
`sa` | sp-splice-sexp-killing-around
`sb` | sp-splice-sexp-killing-backward
`sf` | sp-splice-sexp-killing-forward
`sh` | sp-backward-slurp-sexp
`sl` | sp-forward-slurp-sexp
`ss` | sp-splice-sexp
`u` | undo-tree-undo
`ESC` | evil-normal-state
**Important Note:**
Pressing `fd` while in `lisp state` will return to `normal state`,
*but* pressing `fd` while in `insert state` will return to `lisp state`.
`ESC` will always return to `normal state`.
#### Magit

View File

@ -14,6 +14,7 @@
centered-cursor
dos
emoji-cheat-sheet
evil-lisp-state
evil-org-mode
evil-plugins
helm-rcirc
@ -127,6 +128,17 @@
(use-package emoji-cheat-sheet
:commands emoji-cheat-sheet))
(defun spacemacs/init-evil-lisp-state ()
(use-package evil-lisp-state
:init
(progn
(evil-leader/set-key-for-mode 'emacs-lisp-mode "ml" 'evil-lisp-state)
(let ((seq spacemacs-normal-state-sequence)
(key (char-to-string (car spacemacs-normal-state-sequence))))
(define-key evil-lisp-state-map key
`(lambda () (interactive)
(spacemacs/switch-to-normal-mode ',seq 'evil-normal-state)))))))
(defun spacemacs/init-evil-org-mode ()
(use-package evil-org
:commands evil-org-mode

View File

@ -0,0 +1,96 @@
;;; evil-lisp-state.el --- Add an evil state to navigate Lisp code and edit the sexp tree with mnemonic key bindings using smartparens.
;; Copyright (C) 2014 syl20bnr
;; Author: Sylvain Benner <sylvain.benner@gmail.com>
;; Keywords: convenience editing evil smartparens lisp mnemonic
;; Created: 9 Oct 2014
;; Version: 1.0
;; Package-Requires: ((evil "1.0.9") (smartparens "1.6.1"))
;; URL: https://github.com/syl20bnr/evil-lisp-state
;; 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:
;; Adds a new Evil state called --LISP-- (<L>) with mnemonics key bindings
;; to navigate Lisp code and edit the sexp tree.
;; Configuration example:
;; (add-hook)
;; More information on the Github repository:
;; https://github.com/syl20bnr/evil-lisp-state
;;; Code:
(require 'evil)
(require 'smartparens)
(evil-define-state lisp
"Lisp state.
Used to navigate lisp code and manipulate the sexp tree."
:tag " <L> "
:cursor (bar . 2)
;; force smartparens mode
(if (evil-lisp-state-p) (smartparens-mode)))
;; key bindings
(define-key evil-lisp-state-map "1" 'digit-argument)
(define-key evil-lisp-state-map "2" 'digit-argument)
(define-key evil-lisp-state-map "3" 'digit-argument)
(define-key evil-lisp-state-map "4" 'digit-argument)
(define-key evil-lisp-state-map "5" 'digit-argument)
(define-key evil-lisp-state-map "6" 'digit-argument)
(define-key evil-lisp-state-map "7" 'digit-argument)
(define-key evil-lisp-state-map "8" 'digit-argument)
(define-key evil-lisp-state-map "9" 'digit-argument)
(define-key evil-lisp-state-map "$" 'sp-end-of-sexp)
(define-key evil-lisp-state-map "0" 'sp-beginning-of-sexp)
(define-key evil-lisp-state-map "bh" 'sp-backward-barf-sexp)
(define-key evil-lisp-state-map "bl" 'sp-forward-barf-sexp)
(define-key evil-lisp-state-map "c" 'sp-convolute-sexp)
(define-key evil-lisp-state-map "d" 'sp-kill-sexp)
(define-key evil-lisp-state-map "e$" 'evil-lisp-state-eval-sexp-end-of-line)
(define-key evil-lisp-state-map "ef" 'eval-defun)
(define-key evil-lisp-state-map "el" 'eval-last-sexp)
(define-key evil-lisp-state-map "es" 'eval-sexp)
(define-key evil-lisp-state-map "h" 'sp-backward-sexp)
(define-key evil-lisp-state-map "i" 'evil-insert-state)
(define-key evil-lisp-state-map "j" 'sp-down-sexp)
(define-key evil-lisp-state-map "J" 'sp-backward-down-sexp)
(define-key evil-lisp-state-map "k" 'sp-up-sexp)
(define-key evil-lisp-state-map "K" 'sp-backward-up-sexp)
(define-key evil-lisp-state-map "l" 'sp-forward-sexp)
(define-key evil-lisp-state-map "r" 'sp-raise-sexp)
(define-key evil-lisp-state-map "C-r" 'undo-tree-redo)
(define-key evil-lisp-state-map "sa" 'sp-splice-sexp-killing-around)
(define-key evil-lisp-state-map "sb" 'sp-splice-sexp-killing-backward)
(define-key evil-lisp-state-map "sf" 'sp-splice-sexp-killing-forward)
(define-key evil-lisp-state-map "sh" 'sp-backward-slurp-sexp)
(define-key evil-lisp-state-map "sl" 'sp-forward-slurp-sexp)
(define-key evil-lisp-state-map "ss" 'sp-splice-sexp)
(define-key evil-lisp-state-map "u" 'undo-tree-undo)
(define-key evil-lisp-state-map [escape] 'evil-normal-state)
(defun evil-lisp-state-eval-sexp-end-of-line ()
"Evaluate the last sexp at the end of the current line."
(interactive)
(save-excursion
(evil-end-of-line)
(eval-last-sexp nil)))
(provide 'evil-lisp-state)

View File

@ -17,7 +17,10 @@
;; thanks to Bin Chen for the idea (http://blog.binchen.org/?p=735)
(global-set-key key `(lambda () (interactive) (spacemacs/switch-to-normal-mode ',seq 'keyboard-quit)))
(define-key minibuffer-local-map key `(lambda () (interactive) (spacemacs/switch-to-normal-mode ',seq 'abort-recursive-edit)))
(define-key evil-insert-state-map key `(lambda () (interactive) (spacemacs/switch-to-normal-mode ',seq 'evil-normal-state)))
(define-key evil-insert-state-map key `(lambda () (interactive)
(if (eq major-mode 'emacs-lisp-mode)
(spacemacs/switch-to-normal-mode ',seq 'evil-lisp-state)
(spacemacs/switch-to-normal-mode ',seq 'evil-normal-state))))
(define-key evil-visual-state-map key `(lambda () (interactive) (spacemacs/switch-to-normal-mode ',seq 'evil-exit-visual-state)))
(define-key evil-emacs-state-map key `(lambda () (interactive) (spacemacs/switch-to-normal-mode ',seq 'evil-normal-state)))
(define-key evil-motion-state-map key `(lambda () (interactive) (spacemacs/switch-to-normal-mode ',seq 'evil-normal-state))))
@ -190,20 +193,10 @@
;; google translate -----------------------------------------------------------
(evil-leader/set-key
"xgl" 'set-google-translate-languages)
;; ---------------------------------------------------------------------------
;; evil-leader modes specific key bindings
;; ---------------------------------------------------------------------------
;; Lisps ----------------------------------------------------------------------
(evil-leader/set-key-for-mode 'emacs-lisp-mode
"mD" 'elisp-slime-nav-describe-elisp-thing-at-point
"me" 'eval-last-sexp
"mf" 'eval-defun
"mg" 'elisp-slime-nav-find-elisp-thing-at-point
"mhv" 'describe-variable
;; Eval the current line
"ml" (lambda () (interactive) (save-excursion (evil-end-of-line)
(eval-last-sexp nil)))
"mta" (lambda () (interactive) (ert t))
"mtf" 'ert)

View File

@ -138,6 +138,8 @@ which require an initialization must be listed explicitly in the list.")
(setq evil-visual-state-cursor '("black" (hbar . 2))))
(defun set-default-evil-motion-state-cursor ()
(setq evil-motion-state-cursor '("purple" box)))
(defun set-default-evil-lisp-state-cursor ()
(setq evil-lisp-state-cursor '("DeepSkyBlue" (bar . 2))))
(defun evil-insert-state-cursor-hide ()
(setq evil-insert-state-cursor '("green3" (hbar . 0))))
(set-default-evil-emacs-state-cursor)
@ -145,6 +147,7 @@ which require an initialization must be listed explicitly in the list.")
(set-default-evil-insert-state-cursor)
(set-default-evil-visual-state-cursor)
(set-default-evil-motion-state-cursor)
(set-default-evil-lisp-state-cursor)
(evil-mode 1))
:config
(progn
@ -225,6 +228,7 @@ cons cell of 2 characters."
((evil-motion-state-p) '(:background "purple"))
((evil-visual-state-p) '(:background "gray"))
((evil-normal-state-p) '(:background "orange"))
((evil-lisp-state-p) '(:background "DeepSkyBlue"))
(t '()))))
(defpowerline powerline-window-number
@ -1356,97 +1360,13 @@ cons cell of 2 characters."
(use-package smartparens-config
:commands smartparens-mode
:init
(add-to-hooks 'smartparens-mode '(erlang-mode-hook
markdown-mode-hook
prog-mode-hook))
(progn
(add-to-hooks 'smartparens-mode '(erlang-mode-hook
markdown-mode-hook
prog-mode-hook)))
:config
(progn
(spacemacs//diminish smartparens-mode" (Ⓢ)")
(evil-leader/set-key-for-mode 'emacs-lisp-mode
"mm" (lambda () (interactive)
(evil-insert-state) (spacemacs/smartparens-overlay-map)))
;; micro-state to easily navigate lisp code
(dolist (sym '(sp-beginning-of-sexp
sp-backward-barf-sexp
sp-backward-slurp-sexp
sp-convolute-sexp
sp-kill-sexp
sp-end-of-sexp
sp-forward-barf-sexp
sp-forward-slurp-sexp
sp-backward-sexp
sp-down-sexp
sp-backward-down-sexp
sp-up-sexp
sp-backward-up-sexp
sp-forward-sexp
sp-raise-sexp
sp-splice-sexp-killing-around
sp-splice-sexp-killing-backward
sp-splice-sexp-killing-forward
sp-splice-sexp
spacemacs/smartparens-overlay-map-toggle-help))
(let* ((advice (intern (format "spacemacs/%s" (symbol-name sym)))))
(eval `(defadvice ,sym (after ,advice activate)
(spacemacs/smartparens-overlay-map)))))
(defvar spacemacs-smartparens-overlay-map-help nil
"If not nil, a comprehensive help is displayed in the minibuffer
when the smartparens micro-state is active.")
(defconst spacemacs-smartparens-overlay-map-prefix
(propertize " <LISP> " 'face `(:foreground "#ffffff"
:background ,(face-attribute
'sp-show-pair-match-face
:foreground)))
"A propertied micro-state name.")
(defun spacemacs/smartparens-overlay-map-toggle-help ()
"Toggle help for smartparens micro-state."
(interactive)
(setq spacemacs-smartparens-overlay-map-help
(if spacemacs-smartparens-overlay-map-help nil t)))
(defun spacemacs/smartparens-overlay-map ()
"Set a temporary overlay map to easily navigate lisp code with
smartparens."
(interactive)
(set-temporary-overlay-map
(let ((map (make-sparse-keymap)))
(define-key map (kbd "a") 'sp-beginning-of-sexp)
(define-key map (kbd "bb") 'sp-backward-barf-sexp)
(define-key map (kbd "bs") 'sp-backward-slurp-sexp)
(define-key map (kbd "c") 'sp-convolute-sexp)
(define-key map (kbd "d") 'sp-kill-sexp)
(define-key map (kbd "e") 'sp-end-of-sexp)
(define-key map (kbd "fb") 'sp-forward-barf-sexp)
(define-key map (kbd "fs") 'sp-forward-slurp-sexp)
(define-key map (kbd "h") 'sp-backward-sexp)
(define-key map (kbd "j") 'sp-down-sexp)
(define-key map (kbd "J") 'sp-backward-down-sexp)
(define-key map (kbd "k") 'sp-up-sexp)
(define-key map (kbd "K") 'sp-backward-up-sexp)
(define-key map (kbd "l") 'sp-forward-sexp)
(define-key map (kbd "r") 'sp-raise-sexp)
(define-key map (kbd "sa") 'sp-splice-sexp-killing-around)
(define-key map (kbd "sb") 'sp-splice-sexp-killing-backward)
(define-key map (kbd "sf") 'sp-splice-sexp-killing-forward)
(define-key map (kbd "ss") 'sp-splice-sexp)
(define-key map (kbd "H")
'spacemacs/smartparens-overlay-map-toggle-help)
map) nil)
(if spacemacs-smartparens-overlay-map-help
; (;) execute last command
(message "%s Help:
(a) beginning of sexp (j) down sexp
(bb) backward barf (J) backward down sexp
(bs) backward slurp (k) up sexp
(c) convolute sexp (K) backward up sexp
(d) kill sexp (l) forward sexp
(e) end of sexp (r) raise sexp
(fb) forward barf (sa) splice sexp and kill around
(fs) forward slurp (sb) splice sexp and kill backward
(h) backward sexp (sf) splice sexp and kill forward
(H) exit help (ss) splice sexp
Press any other key to exit. " spacemacs-smartparens-overlay-map-prefix)
(message "%s (H) to display help"
spacemacs-smartparens-overlay-map-prefix))))))
(spacemacs//diminish smartparens-mode" (Ⓢ)"))))
(defun spacemacs/init-smeargle ()
(use-package smeargle