about summary refs log tree commit diff
path: root/configs/shared/emacs/.emacs.d/elpa/evil-collection-20180720.526/evil-collection-ace-jump-mode.el
blob: f141b17c034a5a6aca17970f660c5b450cf11f88 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
;;; evil-collection-ace-jump-mode.el --- Bindings for `ace-jump-mode' -*- lexical-binding: t -*-

;; Copyright (C) 2017 James Nguyen

;; Author: James Nguyen <james@jojojames.com>
;; Maintainer: James Nguyen <james@jojojames.com>
;; Pierre Neidhardt <ambrevar@gmail.com>
;; URL: https://github.com/emacs-evil/evil-collection
;; Version: 0.0.1
;; Package-Requires: ((emacs "25.1"))
;; Keywords: evil, emacs, tools

;; 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:
;;; Bindings for `ace-jump-mode'

;;; Code:
(require 'evil-collection)
(require 'ace-jump-mode nil t)

(declare-function 'ace-jump-char-mode "ace-jump-mode")
(declare-function 'ace-jump-word-mode "ace-jump-mode")
(declare-function 'ace-jump-line-mode "ace-jump-mode")

(defvar evil-collection-ace-jump-mode-jump-active nil)

(defmacro evil-collection-ace-jump-mode-enclose-ace-jump-for-motion (&rest body)
  "Enclose ace-jump to make it suitable for motions.
This includes restricting `ace-jump-mode' to the current window
in visual and operator state, deactivating visual updates, saving
the mark and entering `recursive-edit'."
  (declare (indent defun)
           (debug t))
  `(let ((old-mark (mark))
         (ace-jump-mode-scope
          (if (and (not (memq evil-state '(visual operator)))
                   (boundp 'ace-jump-mode-scope))
              ace-jump-mode-scope
            'window)))
     (ignore ace-jump-mode-scope) ;; Make byte compiler happy.
     (remove-hook 'pre-command-hook #'evil-visual-pre-command t)
     (remove-hook 'post-command-hook #'evil-visual-post-command t)
     (unwind-protect
         (let ((evil-collection-ace-jump-mode-jump-active 'prepare))
           (add-hook 'ace-jump-mode-end-hook
                     #'evil-collection-ace-jump-mode-jump-exit-recursive-edit)
           ,@body
           (when evil-collection-ace-jump-mode-jump-active
             (setq evil-collection-ace-jump-mode-jump-active t)
             (recursive-edit)))
       (remove-hook 'post-command-hook
                    #'evil-collection-ace-jump-mode-jump-exit-recursive-edit)
       (remove-hook 'ace-jump-mode-end-hook
                    #'evil-collection-ace-jump-mode-jump-exit-recursive-edit)
       (if (evil-visual-state-p)
           (progn
             (add-hook 'pre-command-hook #'evil-visual-pre-command nil t)
             (add-hook 'post-command-hook #'evil-visual-post-command nil t)
             (set-mark old-mark))
         (push-mark old-mark)))))

(defun evil-collection-ace-jump-mode-jump-exit-recursive-edit ()
  "Exit a recursive edit caused by an evil jump."
  (cond
   ((eq evil-collection-ace-jump-mode-jump-active 'prepare)
    (setq evil-collection-ace-jump-mode-jump-active nil))
   (evil-collection-ace-jump-mode-jump-active
    (remove-hook 'post-command-hook
                 #'evil-collection-ace-jump-mode-jump-exit-recursive-edit)
    (exit-recursive-edit))))

(evil-define-motion evil-ace-jump-char-mode (_)
  "Jump visually directly to a char using ace-jump."
  :type inclusive
  (evil-without-repeat
    (let ((pnt (point))
          (buf (current-buffer)))
      (evil-collection-ace-jump-mode-enclose-ace-jump-for-motion
       (call-interactively 'ace-jump-char-mode))
      ;; if we jump backwards, motion type is exclusive, analogously
      ;; to `evil-find-char-backward'
      (when (and (equal buf (current-buffer))
                 (< (point) pnt))
        (setq evil-this-type
              (cond
               ((eq evil-this-type 'exclusive) 'inclusive)
               ((eq evil-this-type 'inclusive) 'exclusive)))))))

(evil-define-motion evil-ace-jump-char-to-mode (_)
  "Jump visually to the char in front of a char using ace-jump."
  :type inclusive
  (evil-without-repeat
    (let ((pnt (point))
          (buf (current-buffer)))
      (evil-collection-ace-jump-mode-enclose-ace-jump-for-motion
       (call-interactively 'ace-jump-char-mode))
      (if (and (equal buf (current-buffer))
               (< (point) pnt))
          (progn
            (or (eobp) (forward-char))
            (setq evil-this-type
                  (cond
                   ((eq evil-this-type 'exclusive) 'inclusive)
                   ((eq evil-this-type 'inclusive) 'exclusive))))
        (backward-char)))))

(evil-define-motion evil-ace-jump-line-mode (_)
  "Jump visually to the beginning of a line using ace-jump."
  :type line
  :repeat abort
  (evil-without-repeat
    (evil-collection-ace-jump-mode-enclose-ace-jump-for-motion
     (call-interactively 'ace-jump-line-mode))))

(evil-define-motion evil-ace-jump-word-mode (_)
  "Jump visually to the beginning of a word using ace-jump."
  :type exclusive
  :repeat abort
  (evil-without-repeat
    (evil-collection-ace-jump-mode-enclose-ace-jump-for-motion
     (call-interactively 'ace-jump-word-mode))))

(defun evil-collection-ace-jump-mode-setup ()
  "Set up `evil' bindings for `ace-jump-mode'."

  (defadvice ace-jump-done (after evil activate)
    (when evil-collection-ace-jump-mode-jump-active
      (add-hook 'post-command-hook #'evil-collection-ace-jump-mode-jump-exit-recursive-edit)))

  (evil-collection-define-key nil 'evil-motion-state-map
    [remap ace-jump-char-mode] #'evil-ace-jump-char-mode
    [remap ace-jump-line-mode] #'evil-ace-jump-line-mode
    [remap ace-jump-word-mode] #'evil-ace-jump-word-mode))

(provide 'evil-collection-ace-jump-mode)
;;; evil-collection-ace-jump-mode.el ends here