Skip to content
Browse files

[emacs] update evil

  • Loading branch information...
1 parent 46a7127 commit 64428f6f92a7ce5e6992468d035a5c5ff7ca4193 @guns committed Sep 13, 2013
View
56 etc/%emacs.d/evil/CHANGES.org
@@ -0,0 +1,56 @@
+* Changes and New Features in Evil
+
+** News in 1.0.7
+
+ * Fix #319.
+
+** News in 1.0.6
+
+ * Fix bug induced in emacs trunk due to changed behaviour of
+ `overriding-terminal-local-map` (fixes #309).
+
+** News in 1.0.5
+
+ * Fix bug in `show-paren-mode` due to variable renaming in latest
+ emacs.
+
+ * Fix bug in isearch module due to variable renaming in latest
+ emacs.
+
+** News in 1.0.4
+
+ * Undo one restriction when <c> argument is read in operator state.
+
+** News in 1.0.3
+
+ * Fix `evil-delete-backward-word` at first non-blank in a line.
+
+** News in 1.0.2
+
+ * Fix #290.
+
+** News in 1.0.1
+
+*** Improvements
+
+ * An ELPA package built by =make elpa= contains COPYING file.
+
+ * Bind =[tab]= like =\t= in =evil-ex-completion-map=, so that it
+ cannot be overwritten by a =[tab]= binding in the parent keymap
+ =minibuffer-local-completion-map=.
+
+ * Improve worst case performance of internal functions
+ =evil-in-string-p=, =evil-string-beginning= and
+ =evil-string-end=. This functions are used, e.g., in certain text
+ objects to detect whether point is within a string.
+
+ * Update authors list.
+
+*** Fixes
+
+ * The interactive code =<state>= is fixed and used correctly in
+ =evil-ex-set-initial-state=.
+
+ * =evil-ex-global= always generates a single undo-step.
+
+ * Resolved issues: #249, #250, #253 and #257.
View
417 etc/%emacs.d/evil/evil-commands.el
@@ -30,6 +30,10 @@
(require 'evil-ex)
(require 'evil-types)
+;;; Compatibility for Emacs 23
+(unless (fboundp 'window-body-width)
+ (defalias 'window-body-width 'window-width))
+
;;; Motions
;; Movement commands, or motions, are defined with the macro
@@ -175,6 +179,17 @@ If COUNT is given, move COUNT - 1 screen lines downward first."
(end-of-visual-line count)
(end-of-line count)))
+(evil-define-motion evil-middle-of-visual-line ()
+ "Move the cursor to the middle of the current visual line."
+ :type exclusive
+ (beginning-of-visual-line)
+ (evil-with-restriction
+ nil
+ (save-excursion (end-of-visual-line) (point))
+ (move-to-column (+ (current-column)
+ -1
+ (/ (with-no-warnings (window-body-width)) 2)))))
+
(evil-define-motion evil-beginning-of-line-or-digit-argument ()
"Move the cursor to the beginning of the current line.
This function passes its command to `digit-argument' (usually a 0)
@@ -609,6 +624,17 @@ and jump to the corresponding one."
(char (nth 1 evil-last-find))
(fwd (nth 2 evil-last-find))
evil-last-find)
+ ;; ensure count is non-negative
+ (when (< count 0)
+ (setq count (- count)
+ fwd (not fwd)))
+ ;; skip next character when repeating t or T
+ (and (eq cmd #'evil-find-char-to)
+ evil-repeat-find-to-skip-next
+ (= count 1)
+ (or (and fwd (= (char-after (1+ (point))) char))
+ (and (not fwd) (= (char-before) char)))
+ (setq count (1+ count)))
(funcall cmd (if fwd count (- count)) char)
(unless (nth 2 evil-last-find)
(setq evil-this-type 'exclusive)))
@@ -713,11 +739,7 @@ for specifying the tag."
Calls `evil-lookup-func'."
(funcall evil-lookup-func))
-(evil-define-motion evil-ret (count)
- "Move the cursor COUNT lines down.
-If point is on a widget or a button, click on it.
-In Insert state, insert a newline."
- :type line
+(defun evil-ret-gen (count indent?)
(let* ((field (get-char-property (point) 'field))
(button (get-char-property (point) 'button))
(doc (get-char-property (point) 'widget-doc))
@@ -743,20 +765,37 @@ In Insert state, insert a newline."
((or (evil-emacs-state-p)
(and (evil-insert-state-p)
(not buffer-read-only)))
- (if (not evil-auto-indent)
+ (if (not indent?)
(newline count)
(delete-horizontal-space t)
(newline count)
(indent-according-to-mode)))
(t
(evil-next-line-first-non-blank count)))))
+(evil-define-motion evil-ret (count)
+ "Move the cursor COUNT lines down.
+If point is on a widget or a button, click on it.
+In Insert state, insert a newline."
+ :type line
+ (evil-ret-gen count nil))
+
+(evil-define-motion evil-ret-and-indent (count)
+ "Move the cursor COUNT lines down.
+If point is on a widget or a button, click on it.
+In Insert state, insert a newline and indent."
+ :type line
+ (evil-ret-gen count t))
+
(evil-define-motion evil-window-top (count)
"Move the cursor to line COUNT from the top of the window
on the first non-blank character."
:jump t
:type line
- (move-to-window-line (or count 0))
+ (move-to-window-line (max (or count 0)
+ (if (= (point-min) (window-start))
+ 0
+ scroll-margin)))
(back-to-indentation))
(evil-define-motion evil-window-middle ()
@@ -773,7 +812,7 @@ on the first non-blank character."
on the first non-blank character."
:jump t
:type line
- (move-to-window-line (- (or count 1)))
+ (move-to-window-line (- (max (or count 1) (1+ scroll-margin))))
(back-to-indentation))
;; scrolling
@@ -1113,6 +1152,13 @@ or line COUNT to the top of the window."
:motion evil-line
:move-point nil
(interactive "<R><x>")
+ (when (evil-visual-state-p)
+ (unless (memq type '(line block))
+ (let ((range (evil-expand beg end 'line)))
+ (setq beg (evil-range-beginning range)
+ end (evil-range-end range)
+ type (evil-type range))))
+ (evil-exit-visual-state))
(evil-yank beg end type register))
(evil-define-operator evil-delete (beg end type register yank-handler)
@@ -1190,13 +1236,27 @@ Save in REGISTER or in the kill-ring with YANK-HANDLER."
(interactive "<R><x>")
(evil-delete beg end type register))
+(evil-define-command evil-delete-backward-char-and-join (count)
+ "Delete previous character and join lines.
+If point is at the beginning of a line then the current line will
+be joined with the previous line if and only if
+`evil-backspace-join-lines'."
+ (interactive "p")
+ (if (or evil-backspace-join-lines (not (bolp)))
+ (call-interactively 'delete-backward-char)
+ (error "Beginning of line")))
+
(evil-define-command evil-delete-backward-word ()
"Delete previous word."
(if (and (bolp) (not (bobp)))
- (delete-char -1)
- (evil-delete (save-excursion
- (evil-backward-word-begin)
- (point))
+ (progn
+ (unless evil-backspace-join-lines (error "Beginning of line"))
+ (delete-char -1))
+ (evil-delete (max
+ (save-excursion
+ (evil-backward-word-begin)
+ (point))
+ (line-beginning-position))
(point)
'exclusive
nil)))
@@ -1240,6 +1300,40 @@ of the block."
(interactive "<R><x>")
(evil-change beg end type register yank-handler #'evil-delete-whole-line))
+(evil-define-command evil-copy (beg end address)
+ "Copy lines in BEG END below line given by ADDRESS."
+ :motion evil-line
+ (interactive "<r><addr>")
+ (goto-char (point-min))
+ (forward-line address)
+ (let* ((txt (buffer-substring-no-properties beg end))
+ (len (length txt)))
+ ;; ensure text consists of complete lines
+ (when (or (zerop len) (/= (aref txt (1- len)) ?\n))
+ (setq txt (concat txt "\n")))
+ (when (and (eobp) (not (bolp))) (newline)) ; incomplete last line
+ (insert txt)
+ (forward-line -1)))
+
+(evil-define-command evil-move (beg end address)
+ "Move lines in BEG END below line given by ADDRESS."
+ :motion evil-line
+ (interactive "<r><addr>")
+ (goto-char (point-min))
+ (forward-line address)
+ (let* ((m (set-marker (make-marker) (point)))
+ (txt (buffer-substring-no-properties beg end))
+ (len (length txt)))
+ (delete-region beg end)
+ (goto-char m)
+ (set-marker m nil)
+ ;; ensure text consists of complete lines
+ (when (or (zerop len) (/= (aref txt (1- len)) ?\n))
+ (setq txt (concat txt "\n")))
+ (when (and (eobp) (not (bolp))) (newline)) ; incomplete last line
+ (insert txt)
+ (forward-line -1)))
+
(evil-define-operator evil-substitute (beg end type register)
"Change a character."
:motion evil-forward-char
@@ -1578,39 +1672,49 @@ The return value is the yanked text."
"Paste over Visual selection."
:suppress-operator t
(interactive "P<x>")
+ ;; evil-visual-paste is typically called from evil-paste-before or
+ ;; evil-paste-after, but we have to mark that the paste was from
+ ;; visual state
+ (setq this-command 'evil-visual-paste)
(let* ((text (if register
(evil-get-register register)
(current-kill 0)))
(yank-handler (car-safe (get-text-property
0 'yank-handler text)))
+ new-kill
paste-eob)
(evil-with-undo
- (when (evil-visual-state-p)
- ;; add replaced text to the kill-ring
- (unless register
- ;; if pasting from the kill-ring,
- ;; add replaced text before the current kill
- (setq kill-ring (delete text kill-ring)))
- (setq kill-ring-yank-pointer kill-ring)
- (evil-visual-rotate 'upper-left)
- ;; if we replace the last buffer line that does not end in a
- ;; newline, we use `evil-paste-after' because `evil-delete'
- ;; will move point to the line above
- (when (and (= evil-visual-end (point-max))
- (/= (char-before (point-max)) ?\n))
- (setq paste-eob t))
- (evil-delete evil-visual-beginning evil-visual-end
- (evil-visual-type))
- (unless register
- (kill-new text))
- (when (and (eq yank-handler #'evil-yank-line-handler)
- (not (eq (evil-visual-type) 'line))
- (not (= evil-visual-end (point-max))))
- (insert "\n"))
- (evil-normal-state))
- (if paste-eob
- (evil-paste-after count register)
- (evil-paste-before count register)))))
+ (let* ((kill-ring (list (current-kill 0)))
+ (kill-ring-yank-pointer kill-ring))
+ (when (evil-visual-state-p)
+ (evil-visual-rotate 'upper-left)
+ ;; if we replace the last buffer line that does not end in a
+ ;; newline, we use `evil-paste-after' because `evil-delete'
+ ;; will move point to the line above
+ (when (and (= evil-visual-end (point-max))
+ (/= (char-before (point-max)) ?\n))
+ (setq paste-eob t))
+ (evil-delete evil-visual-beginning evil-visual-end
+ (evil-visual-type))
+ (when (and (eq yank-handler #'evil-yank-line-handler)
+ (not (eq (evil-visual-type) 'line))
+ (not (= evil-visual-end (point-max))))
+ (insert "\n"))
+ (evil-normal-state)
+ (setq new-kill (current-kill 0))
+ (current-kill 1))
+ (if paste-eob
+ (evil-paste-after count register)
+ (evil-paste-before count register)))
+ (kill-new new-kill)
+ ;; mark the last paste as visual-paste
+ (setq evil-last-paste
+ (list (nth 0 evil-last-paste)
+ (nth 1 evil-last-paste)
+ (nth 2 evil-last-paste)
+ (nth 3 evil-last-paste)
+ (nth 4 evil-last-paste)
+ t)))))
(defun evil-paste-from-register (register)
"Paste from REGISTER."
@@ -1685,7 +1789,8 @@ when called interactively."
(unless evil-this-macro
(error "No previous macro"))
(condition-case err
- (execute-kbd-macro macro count)
+ (evil-with-single-undo
+ (execute-kbd-macro macro count))
;; enter Normal state if the macro fails
(error
(evil-normal-state)
@@ -1961,33 +2066,28 @@ next VCOUNT - 1 lines below the current one."
(evil-define-command evil-insert-digraph (count)
"Insert COUNT digraphs."
+ :repeat change
(interactive "p")
(let ((digraph (evil-read-digraph-char 0)))
(insert-char digraph count)))
-(defun evil-ex-show-digraphs ()
+(evil-define-command evil-ex-show-digraphs ()
"Shows a list of all available digraphs."
- (interactive)
- (let ((buf (get-buffer-create "*evil-digraphs*"))
- (inhibit-read-only t))
- (with-current-buffer buf
- (erase-buffer)
- (let ((i 0)
- (digraphs
- (mapcar #'(lambda (digraph)
- (cons (cdr digraph)
- (car digraph)))
- (append evil-digraphs-table
- evil-digraphs-table-user))))
- (dolist (digraph digraphs)
- (insert (nth 0 digraph) "\t"
- (nth 1 digraph) " "
- (nth 2 digraph)
- (if (= i 2) "\n" "\t\t"))
- (setq i (mod (1+ i) 3))))
- (goto-char (point-min))
- (view-buffer buf #'kill-buffer)
- (evil-emacs-state))))
+ :repeat nil
+ (evil-with-view-list "evil-digraphs"
+ (let ((i 0)
+ (digraphs
+ (mapcar #'(lambda (digraph)
+ (cons (cdr digraph)
+ (car digraph)))
+ (append evil-digraphs-table
+ evil-digraphs-table-user))))
+ (dolist (digraph digraphs)
+ (insert (nth 0 digraph) "\t"
+ (nth 1 digraph) " "
+ (nth 2 digraph)
+ (if (= i 2) "\n" "\t\t"))
+ (setq i (mod (1+ i) 3))))))
(defun evil-copy-from-above (arg)
"Copy characters from preceding non-blank line.
@@ -2381,16 +2481,19 @@ If no FILE is specified, reload the current buffer from disk."
(unless (bolp) (insert "\n"))))))
(evil-define-command evil-show-buffers ()
- "Shows the buffer-list."
+ "Shows the buffer-list.
+The same as `list-buffers' but selects the buffer window afterwards."
+ :repeat nil
+ (list-buffers)
+ (select-window (get-buffer-window "*Buffer List*")))
+
+(evil-define-command evil-show-files ()
+ "Shows the file-list.
+The same as `list-buffers', but shows only buffers visiting files
+and selects the list window afterwards."
:repeat nil
- (let (message-truncate-lines message-log-max)
- (display-message-or-buffer
- (mapconcat #'identity
- (sort
- (mapcar #'buffer-name (buffer-list))
- #'string<)
- "\n")
- "*Buffers*")))
+ (list-buffers 1)
+ (select-window (get-buffer-window "*Buffer List*")))
(evil-define-command evil-buffer (buffer)
"Switches to another buffer."
@@ -2525,15 +2628,16 @@ the previous shell command is executed instead."
(evil-define-command evil-show-registers ()
"Shows the contents of all registers."
:repeat nil
- (let (message-truncate-lines message-log-max)
- (message "%s"
- (mapconcat #'(lambda (reg)
- (format "\"%c\t%s"
- (car reg)
- (if (stringp (cdr reg))
- (replace-regexp-in-string "\n" "^J" (cdr reg))
- (cdr reg))))
- (evil-register-list) "\n"))))
+ (evil-with-view-list "evil-registers"
+ (setq truncate-lines t)
+ (dolist (reg (evil-register-list))
+ (when (cdr reg)
+ (insert (format "\"%c\t%s"
+ (car reg)
+ (if (stringp (cdr reg))
+ (replace-regexp-in-string "\n" "^J" (cdr reg))
+ (cdr reg))))
+ (newline)))))
(eval-when-compile (require 'ffap))
(evil-define-command evil-find-file-at-point-with-line ()
@@ -2555,30 +2659,27 @@ the previous shell command is executed instead."
(evil-ex-define-argument-type state
"Defines an argument type which can take state names."
- :completer
- (lambda ()
- (list
- (point-min) (point-max)
- (lambda (arg predicate flag)
- (let ((completions
- (append '("nil")
- (mapcar #'(lambda (state)
- (format "%s" (car state)))
- evil-state-properties))))
- (when arg
- (cond
- ((eq flag nil)
- (try-completion arg completions predicate))
- ((eq flag t)
- (all-completions arg completions predicate))
- ((eq flag 'lambda)
- (test-completion arg completions predicate))
- ((eq (car-safe flag) 'boundaries)
- (cons 'boundaries
- (completion-boundaries arg
- completions
- predicate
- (cdr flag)))))))))))
+ :collection
+ (lambda (arg predicate flag)
+ (let ((completions
+ (append '("nil")
+ (mapcar #'(lambda (state)
+ (format "%s" (car state)))
+ evil-state-properties))))
+ (when arg
+ (cond
+ ((eq flag nil)
+ (try-completion arg completions predicate))
+ ((eq flag t)
+ (all-completions arg completions predicate))
+ ((eq flag 'lambda)
+ (test-completion arg completions predicate))
+ ((eq (car-safe flag) 'boundaries)
+ (cons 'boundaries
+ (completion-boundaries arg
+ completions
+ predicate
+ (cdr flag)))))))))
(evil-define-interactive-code "<state>"
"A valid evil state."
@@ -2722,13 +2823,12 @@ resp. after executing the command."
(evil-ex-nohighlight)
(unless pattern
(error "No pattern given"))
- (unless replacement
- (error "No replacement given"))
+ (setq replacement (or replacement ""))
(setq evil-ex-last-was-search nil)
(let* ((flags (append flags nil))
(confirm (memq ?c flags))
- (case-fold-search (eq (evil-ex-pattern-case-fold pattern)
- 'insensitive))
+ (case-fold-search (evil-ex-pattern-ignore-case pattern))
+ (case-replace case-fold-search)
(evil-ex-substitute-regex (evil-ex-pattern-regex pattern)))
(setq evil-ex-substitute-pattern pattern
evil-ex-substitute-replacement replacement
@@ -2746,12 +2846,16 @@ resp. after executing the command."
(1- end)
end))
(let ((evil-ex-substitute-nreplaced 0)
- (evil-ex-substitute-next-line (line-number-at-pos beg))
- (evil-ex-substitute-last-line
- (if (save-excursion (goto-char end) (bolp))
- (1- (line-number-at-pos end))
- (line-number-at-pos end)))
- (evil-ex-substitute-last-point (point)))
+ (evil-ex-substitute-last-point (point))
+ markers
+ transient-mark-mode)
+ (save-excursion
+ (goto-char beg)
+ (beginning-of-line)
+ (while (< (point) end)
+ (push (move-marker (make-marker) (point)) markers)
+ (forward-line)))
+ (setq markers (nreverse markers))
(if confirm
(let ((evil-ex-substitute-overlay
(make-overlay (point) (point)))
@@ -2791,42 +2895,33 @@ resp. after executing the command."
(evil-ex-hl-get-max
'evil-ex-substitute)))
#'(lambda ()
- (goto-char (point-min))
- (when (and
- (zerop
- (forward-line
- (1- evil-ex-substitute-next-line)))
- (bolp)
- (re-search-forward
- evil-ex-substitute-regex
- nil t nil)
- (<= (line-number-at-pos (match-end 0))
- evil-ex-substitute-last-line))
- (goto-char (match-beginning 0))
- (setq evil-ex-substitute-next-line
- (1+ (line-number-at-pos (point))))
- (match-data)))))
+ (catch 'found
+ (while markers
+ (let ((m (pop markers)))
+ (goto-char m)
+ (move-marker m nil))
+ (when (re-search-forward evil-ex-substitute-regex
+ (line-end-position) t nil)
+ (goto-char (match-beginning 0))
+ (throw 'found (match-data))))))))
(evil-ex-delete-hl 'evil-ex-substitute)
(delete-overlay evil-ex-substitute-overlay)))
;; just replace the first occurrences per line
;; without highlighting and asking
- (goto-char (point-min))
- (let ((num (1- evil-ex-substitute-next-line)))
- (while (and (zerop (forward-line num))
- (bolp)
- (re-search-forward
- evil-ex-substitute-regex nil t nil)
- (<= (line-number-at-pos
- (match-beginning 0))
- evil-ex-substitute-last-line))
+ (while markers
+ (let ((m (pop markers)))
+ (goto-char m)
+ (move-marker m nil))
+ (when (re-search-forward evil-ex-substitute-regex
+ (line-end-position) t nil)
(setq evil-ex-substitute-nreplaced
(1+ evil-ex-substitute-nreplaced))
(evil-replace-match evil-ex-substitute-replacement
(not case-replace))
- (setq evil-ex-substitute-last-point (point))
- (setq num 1))))
+ (setq evil-ex-substitute-last-point (point)))))
+ (while markers (move-marker (pop markers) nil))
(goto-char evil-ex-substitute-last-point)
(message "Replaced %d occurrence%s"
@@ -3193,7 +3288,7 @@ and opens a new buffer or edits a certain FILE."
(let ((buffer (generate-new-buffer "*new*")))
(set-window-buffer (selected-window) buffer)
(with-current-buffer buffer
- (evil-normal-state)))))
+ (funcall (default-value 'major-mode))))))
(evil-define-command evil-window-vnew (count file)
"Splits the current window vertically
@@ -3206,7 +3301,7 @@ and opens a new buffer name or edits a certain FILE."
(let ((buffer (generate-new-buffer "*new*")))
(set-window-buffer (selected-window) buffer)
(with-current-buffer buffer
- (evil-normal-state)))))
+ (funcall (default-value 'major-mode))))))
(evil-define-command evil-window-increase-height (count)
"Increase current window height by COUNT."
@@ -3621,22 +3716,34 @@ if the previous state was Emacs state."
(evil-normal-state)
(evil-echo "Switched to Normal state for the next command ..."))
-(defun evil-execute-in-emacs-state (&optional arg)
- "Execute the next command in Emacs state."
- (interactive "p")
- (cond
- (arg
- (add-hook 'post-command-hook #'evil-execute-in-emacs-state t)
- (setq evil-execute-in-emacs-state-buffer (current-buffer))
- (evil-emacs-state)
- (evil-echo "Switched to Emacs state for the next command ..."))
- ((and (not (eq this-command #'evil-execute-in-emacs-state))
- (not (minibufferp)))
- (remove-hook 'post-command-hook 'evil-execute-in-emacs-state)
+(defun evil-stop-execute-in-emacs-state ()
+ (when (and (not (eq this-command #'evil-execute-in-emacs-state))
+ (not (minibufferp)))
+ (remove-hook 'post-command-hook 'evil-stop-execute-in-emacs-state)
(when (buffer-live-p evil-execute-in-emacs-state-buffer)
(with-current-buffer evil-execute-in-emacs-state-buffer
- (evil-change-to-previous-state)))
- (setq evil-execute-in-emacs-state-buffer))))
+ (if (and (eq evil-previous-state 'visual)
+ (not (use-region-p)))
+ (progn
+ (evil-change-to-previous-state)
+ (evil-exit-visual-state))
+ (evil-change-to-previous-state))))
+ (setq evil-execute-in-emacs-state-buffer nil)))
+
+(evil-define-command evil-execute-in-emacs-state ()
+ "Execute the next command in Emacs state."
+ (add-hook 'post-command-hook #'evil-stop-execute-in-emacs-state t)
+ (setq evil-execute-in-emacs-state-buffer (current-buffer))
+ (cond
+ ((evil-visual-state-p)
+ (let ((mrk (mark))
+ (pnt (point)))
+ (evil-emacs-state)
+ (set-mark mrk)
+ (goto-char pnt)))
+ (t
+ (evil-emacs-state)))
+ (evil-echo "Switched to Emacs state for the next command ..."))
(defun evil-exit-visual-and-repeat (event)
"Exit insert state and repeat event.
View
96 etc/%emacs.d/evil/evil-common.el
@@ -31,6 +31,8 @@
;;; Code:
(declare-function evil-visual-state-p "evil-states")
+(declare-function evil-visual-restore "evil-states")
+(declare-function evil-motion-state "evil-states")
;;; Compatibility for Emacs 23
(unless (fboundp 'deactivate-input-method)
@@ -577,8 +579,9 @@ Both COUNT and CMD may be nil."
Translates it according to the input method."
(let ((old-global-map (current-global-map))
(new-global-map (make-sparse-keymap))
- (overriding-terminal-local-map evil-read-key-map)
- overriding-local-map seq char cmd)
+ (overriding-terminal-local-map nil)
+ (overriding-local-map evil-read-key-map)
+ seq char cmd)
(unwind-protect
(condition-case nil
(progn
@@ -941,8 +944,23 @@ a one-sided restriction."
(declare (indent 2)
(debug t))
`(save-restriction
- (evil-narrow ,beg ,end)
- ,@body))
+ (let ((evil-restriction-stack
+ (cons (cons (point-min) (point-max)) evil-restriction-stack)))
+ (evil-narrow ,beg ,end)
+ ,@body)))
+
+(defmacro evil-without-restriction (&rest body)
+ "Execute BODY with the top-most narrowing removed.
+This works only if the previous narrowing has been generated by
+`evil-with-restriction'."
+ (declare (indent defun)
+ (debug t))
+ `(save-restriction
+ (widen)
+ (narrow-to-region (car (car evil-restriction-stack))
+ (cdr (car evil-restriction-stack)))
+ (let ((evil-restriction-stack (cdr evil-restriction-stack)))
+ ,@body)))
(defmacro evil-narrow-to-field (&rest body)
"Narrow to the current field."
@@ -1517,7 +1535,9 @@ The following special registers are supported.
((eq register ?\")
(current-kill 0))
((and (<= ?0 register) (<= register ?9))
- (current-kill (- register ?0) t))
+ (let ((reg (- register ?0)))
+ (and (< reg (length kill-ring))
+ (current-kill reg t))))
((eq register ?*)
(let ((x-select-enable-primary t))
(current-kill 0)))
@@ -1888,6 +1908,15 @@ disjoin range."
The tracked insertion is set to `evil-last-insertion'."
(setq evil-last-insertion
(and evil-current-insertion
+ ;; Check whether the insertion range is a valid buffer
+ ;; range. If a buffer modification is done from within
+ ;; another change hook or modification-hook (yasnippet
+ ;; does this using overlay modification-hooks), then the
+ ;; insertion information may be invalid. There is no way
+ ;; to detect this situation, but at least we should
+ ;; ensure that no error occurs (see bug #272).
+ (>= (car evil-current-insertion) (point-min))
+ (<= (cdr evil-current-insertion) (point-max))
(buffer-substring-no-properties (car evil-current-insertion)
(cdr evil-current-insertion))))
(remove-hook 'after-change-functions #'evil-track-last-insertion t))
@@ -2070,15 +2099,30 @@ is negative this is a more recent kill."
(interactive "p")
(unless (memq last-command
'(evil-paste-after
- evil-paste-before))
+ evil-paste-before
+ evil-visual-paste))
(error "Previous command was not an evil-paste: %s" last-command))
(unless evil-last-paste
(error "Previous paste command used a register"))
(evil-undo-pop)
(goto-char (nth 2 evil-last-paste))
- (current-kill count)
(setq this-command (nth 0 evil-last-paste))
- (funcall (nth 0 evil-last-paste) (nth 1 evil-last-paste)))
+ ;; use temporary kill-ring, so the paste cannot modify it
+ (let ((kill-ring (list (current-kill
+ (if (and (> count 0) (nth 5 evil-last-paste))
+ ;; if was visual paste then skip the
+ ;; text that has been replaced
+ (1+ count)
+ count))))
+ (kill-ring-yank-pointer kill-ring))
+ (when (eq last-command 'evil-visual-paste)
+ (let ((evil-no-display t))
+ (evil-visual-restore)))
+ (funcall (nth 0 evil-last-paste) (nth 1 evil-last-paste))
+ ;; if this was a visual paste, then mark the last paste as NOT
+ ;; being the first visual paste
+ (when (eq last-command 'evil-visual-paste)
+ (setcdr (nthcdr 4 evil-last-paste) nil))))
(defun evil-paste-pop-next (count)
"Same as `evil-paste-pop' but with negative argument."
@@ -3124,7 +3168,7 @@ considered magic.
(t "[][}{*+?$^]")))
;; TODO: support magic characters in patterns
-(defconst evil-replacement-magic "[eElLuU0-9&#,rnbt]"
+(defconst evil-replacement-magic "[eElLuU0-9&#,rnbt=]"
"All magic characters in a replacement string")
(defun evil-compile-subreplacement (to &optional start)
@@ -3155,8 +3199,17 @@ REST is the unparsed remainder of TO."
(list `(,func
(replace-quote
(evil-match-substitute-replacement
- ,(car result) t)))
+ ,(car result)
+ (not case-replace))))
(cdr result))))
+ ((eq char ?=)
+ (when (or (zerop (length rest))
+ (not (eq (aref rest 0) ?@)))
+ (error "Expected @ after \\="))
+ (when (< (length rest) 2)
+ (error "Expected register after \\=@"))
+ (list (evil-get-register (aref rest 1))
+ (substring rest 2)))
((eq char ?,)
(let* ((obj (read-from-string rest))
(result `(replace-quote ,(car obj)))
@@ -3247,6 +3300,29 @@ should be left-aligned for left justification."
(goto-char (point-min))
(back-to-indentation))))
+;;; View helper
+(defun evil-view-list (name body)
+ "Open new view buffer.
+The view buffer is named *NAME*. After the buffer is created, the
+function BODY is called with the view buffer being the current
+buffer. The new buffer is opened in view-mode with evil come up
+in motion state."
+ (let ((buf (get-buffer-create (concat "*" name "*")))
+ (inhibit-read-only t))
+ (with-current-buffer buf
+ (evil-motion-state)
+ (erase-buffer)
+ (funcall body)
+ (goto-char (point-min))
+ (view-buffer-other-window buf nil #'kill-buffer))))
+
+(defmacro evil-with-view-list (name &rest body)
+ "Execute BODY in new view-mode buffer *NAME*.
+This macro is a small convenience wrapper around
+`evil-view-list'."
+ (declare (indent 1) (debug t))
+ `(evil-view-list ,name #'(lambda () ,@body)))
+
(provide 'evil-common)
;;; evil-common.el ends here
View
39 etc/%emacs.d/evil/evil-core.el
@@ -180,12 +180,14 @@ To enable Evil globally, do (evil-mode 1)."
"Enable Evil in Fundamental mode."
(if evil-mode
(progn
- ;; changed back by `evil-local-mode'
- (setq-default major-mode 'turn-on-evil-mode)
+ (when (eq (default-value 'major-mode) 'fundamental-mode)
+ ;; changed back by `evil-local-mode'
+ (setq-default major-mode 'turn-on-evil-mode))
(ad-enable-regexp "^evil")
(ad-activate-regexp "^evil")
(with-no-warnings (evil-esc-mode 1)))
- (setq-default major-mode 'fundamental-mode)
+ (when (eq (default-value 'major-mode) 'turn-on-evil-mode)
+ (setq-default major-mode 'fundamental-mode))
(ad-disable-regexp "^evil")
(ad-update-regexp "^evil")
(with-no-warnings (evil-esc-mode -1))))
@@ -213,10 +215,13 @@ If STATE is nil, disable all states."
(evil-previous-state-alist (copy-tree evil-previous-state-alist))
(evil-next-state evil-next-state)
(old-state evil-state)
- (inhibit-quit t))
+ (inhibit-quit t)
+ (buf (current-buffer)))
(unwind-protect
(progn ,@body)
- (evil-change-state old-state))))
+ (when (buffer-live-p buf)
+ (with-current-buffer buf
+ (evil-change-state old-state))))))
(defmacro evil-with-state (state &rest body)
"Change to STATE and execute BODY without refreshing the display.
@@ -555,13 +560,11 @@ the ESC prefix map (i.e. the map originally bound to \\e in
(unless evil-esc-mode
(setq evil-esc-mode t)
(add-hook 'after-make-frame-functions #'evil-init-esc)
- (add-hook 'delete-terminal-functions #'evil-deinit-esc)
(mapc #'evil-init-esc (frame-list))))
((< arg 0)
(when evil-esc-mode
(remove-hook 'after-make-frame-functions #'evil-init-esc)
- (remove-hook 'delete-terminal-functions #'evil-deinit-esc)
- (mapc #'evil-deinit-esc (terminal-list))
+ (mapc #'evil-deinit-esc (frame-list))
(setq evil-esc-mode nil)))))
(defun evil-init-esc (frame)
@@ -578,12 +581,15 @@ the ESC prefix map (i.e. the map originally bound to \\e in
(define-key input-decode-map [?\e]
`(menu-item "" ,evil-esc-map :filter ,#'evil-esc)))))))
-(defun evil-deinit-esc (term)
+(defun evil-deinit-esc (frame)
"Restore `input-decode-map' in terminal."
- (when (eq (terminal-live-p term) 't)
- (let ((evil-esc-map (terminal-parameter term 'evil-esc-map)))
- (define-key input-decode-map [?\e] evil-esc-map)
- (set-terminal-parameter term 'evil-esc-map nil))))
+ (with-selected-frame frame
+ (let ((term (frame-terminal frame)))
+ (when (terminal-live-p term)
+ (let ((evil-esc-map (terminal-parameter term 'evil-esc-map)))
+ (when evil-esc-map
+ (define-key input-decode-map [?\e] evil-esc-map)
+ (set-terminal-parameter term 'evil-esc-map nil)))))))
(defun evil-esc (map)
"Translate \\e to 'escape if no further event arrives.
@@ -606,7 +612,12 @@ mapping will always be the ESC prefix map."
(not (evil-emacs-state-p))
(equal (this-single-command-keys) [?\e])
(sit-for evil-esc-delay))
- [escape] map))
+ (prog1 [escape]
+ (when defining-kbd-macro
+ (end-kbd-macro)
+ (setq last-kbd-macro (vconcat last-kbd-macro [escape]))
+ (start-kbd-macro t t)))
+ map))
(defun evil-state-p (sym)
"Whether SYM is the name of a state."
View
378 etc/%emacs.d/evil/evil-ex.el
@@ -62,7 +62,9 @@
((\? space) (\? "\\(?:.\\|\n\\)+") #'$2))
(range
("%" #'(evil-ex-full-range))
- (line (\? "[,;]" line #'$2) #'evil-ex-range))
+ (line (\? "[,;]" line #'$2) #'evil-ex-range)
+ ("`" "[-a-zA-Z_<>']" ",`" "[-a-zA-Z_<>']"
+ #'(evil-ex-char-marker-range $2 $4)))
(line
(base (\? offset) #'evil-ex-line)
((\? base) offset #'evil-ex-line))
@@ -125,6 +127,10 @@ of the syntax.")
:keep-visual t
(interactive
(cond
+ ((and (evil-visual-state-p)
+ evil-ex-visual-char-range
+ (memq (evil-visual-type) '(inclusive exclusive)))
+ '("`<,`>"))
((evil-visual-state-p)
'("'<,'>"))
(current-prefix-arg
@@ -133,26 +139,31 @@ of the syntax.")
((> arg 0) (setq arg (1- arg))))
(if (= arg 0) '(".")
`(,(format ".,.%+d" arg)))))))
- (let ((minibuffer-local-completion-map evil-ex-completion-map)
- (evil-ex-current-buffer (current-buffer))
+ (let ((evil-ex-current-buffer (current-buffer))
(evil-ex-previous-command (unless initial-input
(car-safe evil-ex-history)))
- evil-ex-argument-handler evil-ex-info-string result)
- (add-hook 'minibuffer-setup-hook #'evil-ex-setup)
- (setq result (read-from-minibuffer
- ":"
- (or initial-input
- (and evil-ex-previous-command
- (format "(default: %s) "
- evil-ex-previous-command)))
- evil-ex-completion-map
- nil
- 'evil-ex-history
- evil-ex-previous-command
- t))
+ evil-ex-argument-handler
+ evil-ex-info-string
+ result)
+ (minibuffer-with-setup-hook
+ #'evil-ex-setup
+ (setq result
+ (read-from-minibuffer
+ ":"
+ (or initial-input
+ (and evil-ex-previous-command
+ (format "(default: %s) " evil-ex-previous-command)))
+ evil-ex-completion-map
+ nil
+ 'evil-ex-history
+ evil-ex-previous-command
+ t)))
+ ;; empty input means repeating the previous command
(when (zerop (length result))
(setq result evil-ex-previous-command))
+ ;; parse data
(evil-ex-update nil nil nil result)
+ ;; execute command
(unless (zerop (length result))
(if evil-ex-expression
(eval evil-ex-expression)
@@ -168,7 +179,9 @@ Otherwise behaves like `delete-backward-char'."
#'delete-backward-char)))
(defun evil-ex-setup ()
- "Initialize Ex minibuffer."
+ "Initialize Ex minibuffer.
+This function registers several hooks that are used for the
+interactive actions during ex state."
(add-hook 'after-change-functions #'evil-ex-update nil t)
(add-hook 'minibuffer-exit-hook #'evil-ex-teardown)
(when evil-ex-previous-command
@@ -177,11 +190,13 @@ Otherwise behaves like `delete-backward-char'."
(with-no-warnings
(make-variable-buffer-local 'completion-at-point-functions))
(setq completion-at-point-functions
- '(evil-ex-completion-at-point)))
+ '(evil-ex-command-completion-at-point
+ evil-ex-argument-completion-at-point)))
(put 'evil-ex-setup 'permanent-local-hook t)
(defun evil-ex-teardown ()
- "Deinitialize Ex minibuffer."
+ "Deinitialize Ex minibuffer.
+Clean up everything set up by `evil-ex-setup'."
(remove-hook 'minibuffer-exit-hook #'evil-ex-teardown)
(remove-hook 'after-change-functions #'evil-ex-update t)
(when evil-ex-argument-handler
@@ -192,6 +207,10 @@ Otherwise behaves like `delete-backward-char'."
(put 'evil-ex-teardown 'permanent-local-hook t)
(defun evil-ex-remove-default ()
+ "Remove the default text shown in the ex minibuffer.
+When ex starts, the previous command is shown enclosed in
+parenthesis. This function removes this text when the first key
+is pressed."
(delete-minibuffer-contents)
(remove-hook 'pre-command-hook #'evil-ex-remove-default))
(put 'evil-ex-remove-default 'permanent-local-hook t)
@@ -262,12 +281,12 @@ in case of incomplete or unknown commands."
(evil-ex-argument-handler-runner
evil-ex-argument-handler))))
(when runner (funcall runner 'update evil-ex-argument))))
- ((all-completions cmd evil-ex-commands)
- ;; show error message only when called from `after-change-functions'
- (when beg (evil-ex-echo "Incomplete command")))
- (t
+ (beg
;; show error message only when called from `after-change-functions'
- (when beg (evil-ex-echo "Unknown command")))))))))
+ (let ((n (length (all-completions cmd (evil-ex-completion-table)))))
+ (cond
+ ((> n 1) (evil-ex-echo "Incomplete command"))
+ ((= n 0) (evil-ex-echo "Unknown command")))))))))))
(put 'evil-ex-update 'permanent-local-hook t)
(defun evil-ex-echo (string &rest args)
@@ -281,6 +300,122 @@ in case of incomplete or unknown commands."
(put-text-property 0 (length string) 'face 'evil-ex-info string)
(minibuffer-message string))))))
+(defun evil-ex-completion ()
+ "Completes the current ex command or argument."
+ (interactive)
+ (let (after-change-functions)
+ (evil-ex-update)
+ (completion-at-point)
+ (remove-text-properties (minibuffer-prompt-end) (point-max) '(face nil evil))))
+
+(defun evil-ex-command-completion-at-point ()
+ (let ((context (evil-ex-syntactic-context (1- (point)))))
+ (when (memq 'command context)
+ (let ((beg (or (get-text-property 0 'ex-index evil-ex-command)
+ (point)))
+ (end (1+ (or (get-text-property (1- (length evil-ex-command))
+ 'ex-index
+ evil-ex-command)
+ (1- (point))))))
+ (when evil-ex-bang) (setq end (1+ end))
+ (list beg end (evil-ex-completion-table))))))
+
+(defun evil-ex-completion-table ()
+ (cond
+ ((eq evil-ex-complete-emacs-commands nil)
+ #'evil-ex-command-collection)
+ ((eq evil-ex-complete-emacs-commands 'in-turn)
+ (completion-table-in-turn
+ #'evil-ex-command-collection
+ #'(lambda (str pred flag)
+ (completion-table-with-predicate
+ obarray #'commandp t str pred flag))))
+ (t
+ #'(lambda (str pred flag)
+ (evil-completion-table-concat
+ #'evil-ex-command-collection
+ #'(lambda (str pred flag)
+ (completion-table-with-predicate
+ obarray #'commandp t str pred flag))
+ str pred flag)))))
+
+(defun evil-completion-table-concat (table1 table2 string pred flag)
+ (cond
+ ((eq flag nil)
+ (let ((result1 (try-completion string table1 pred))
+ (result2 (try-completion string table2 pred)))
+ (cond
+ ((null result1) result2)
+ ((null result2) result1)
+ ((and (eq result1 t) (eq result2 t)) t)
+ (t (assert (equal result1 result2))
+ result1))))
+ ((eq flag t)
+ (delete-dups
+ (append (all-completions string table1 pred)
+ (all-completions string table2 pred))))
+ ((eq flag 'lambda)
+ (and (or (eq t (test-completion string table1 pred))
+ (eq t (test-completion string table2 pred)))
+ t))
+ ((eq (car-safe flag) 'boundaries)
+ (or (completion-boundaries string table1 pred (cdr flag))
+ (completion-boundaries string table2 pred (cdr flag))))
+ ((eq flag 'metadata)
+ '(metadata (display-sort-function . evil-ex-sort-completions)))))
+
+(defun evil-ex-sort-completions (completions)
+ (sort completions
+ #'(lambda (str1 str2)
+ (let ((p1 (eq 'evil-ex-commands (get-text-property 0 'face str1)))
+ (p2 (eq 'evil-ex-commands (get-text-property 0 'face str2))))
+ (if (equal p1 p2)
+ (string< str1 str2)
+ p1)))))
+
+(defun evil-ex-command-collection (cmd predicate flag)
+ "Called to complete a command."
+ (let (commands)
+ ;; append ! to all commands that may take a bang argument
+ (dolist (cmd (mapcar #'car evil-ex-commands))
+ (push cmd commands)
+ (if (evil-ex-command-force-p cmd)
+ (push (concat cmd "!") commands)))
+ (when (eq evil-ex-complete-emacs-commands t)
+ (setq commands
+ (mapcar #'(lambda (str) (propertize str 'face 'evil-ex-commands))
+ commands)))
+ (cond
+ ((eq flag nil) (try-completion cmd commands predicate))
+ ((eq flag t) (all-completions cmd commands predicate))
+ ((eq flag 'lambda) (test-completion cmd commands))
+ ((eq (car-safe flag) 'boundaries)
+ `(boundaries 0 . ,(length (cdr flag)))))))
+
+(defun evil-ex-argument-completion-at-point ()
+ (let ((context (evil-ex-syntactic-context (1- (point)))))
+ (when (memq 'argument context)
+ (let* ((beg (or (and evil-ex-argument
+ (get-text-property 0 'ex-index evil-ex-argument))
+ (point)))
+ (end (1+ (or (and evil-ex-argument
+ (get-text-property (1- (length evil-ex-argument))
+ 'ex-index
+ evil-ex-argument))
+ (1- (point)))))
+ (binding (evil-ex-completed-binding evil-ex-command))
+ (arg-type (evil-get-command-property binding :ex-arg))
+ (arg-handler (assoc arg-type evil-ex-argument-types))
+ (completer (and arg-handler
+ (evil-ex-argument-handler-completer
+ (cdr arg-handler)))))
+ (when completer
+ (if (eq (car completer) 'collection)
+ (list beg end (cdr completer))
+ (save-restriction
+ (narrow-to-region beg (point-max))
+ (funcall (cdr completer)))))))))
+
(defun evil-ex-define-cmd (cmd function)
"Binds the function FUNCTION to the command CMD."
(if (string-match "^[^][]*\\(\\[\\(.*\\)\\]\\)[^][]*$" cmd)
@@ -304,28 +439,31 @@ in case of incomplete or unknown commands."
DOC is the documentation string. It is followed by a list of
keywords and function:
-:completer FUNC Function to be called to initialize a
- potential completion. FUNC must match the
- requirements as described for the variable
- `completion-at-point-functions'. When FUNC is
- called the minibuffer content is narrowed to
- exactly match the argument.
-
-:runner FUNC Function to be called when the type of the
- current argument changes or when the content
- of this argument changes. This function
- should take one obligatory argument FLAG
- followed by an optional argument ARG. FLAG is
- one of three symbol 'start, 'stop or
- 'update. When the argument type is recognized
- for the first time and this handler is
- started the FLAG is 'start. If the argument
- type changes to something else or ex state
- finished the handler FLAG is 'stop. If the
- content of the argument has changed FLAG is
- 'update. If FLAG is either 'start or 'update
- then ARG is the current value of this
- argument. If FLAG is 'stop then arg is nil."
+:collection COLLECTION
+
+ A collection for completion as required by `all-completions'.
+
+:completion-at-point FUNC
+
+ Function to be called to initialize a potential
+ completion. FUNC must match the requirements as described for
+ the variable `completion-at-point-functions'. When FUNC is
+ called the minibuffer content is narrowed to exactly match the
+ argument.
+
+:runner FUNC
+
+ Function to be called when the type of the current argument
+ changes or when the content of this argument changes. This
+ function should take one obligatory argument FLAG followed by
+ an optional argument ARG. FLAG is one of three symbol 'start,
+ 'stop or 'update. When the argument type is recognized for the
+ first time and this handler is started the FLAG is 'start. If
+ the argument type changes to something else or ex state
+ finished the handler FLAG is 'stop. If the content of the
+ argument has changed FLAG is 'update. If FLAG is either 'start
+ or 'update then ARG is the current value of this argument. If
+ FLAG is 'stop then arg is nil."
(declare (indent defun)
(debug (&define name
[&optional stringp]
@@ -338,61 +476,23 @@ keywords and function:
(cond
((eq key :runner)
(setq runner func))
- ((eq key :completer)
- (setq completer func)))))
+ ((eq key :collection)
+ (setq completer (cons 'collection func)))
+ ((eq key :completion-at-point)
+ (setq completer (cons 'completion-at-point func))))))
`(eval-and-compile
(evil-add-to-alist
'evil-ex-argument-types
',arg-type
'(,runner ,completer)))))
-(defun evil-ex-filename-completion-at-point ()
- "Completion at point function for file arguments."
- (list
- (point-min) (point-max)
- (lambda (arg predicate flag)
- (if (null arg)
- default-directory
- (let ((dir (or (file-name-directory arg)
- (with-current-buffer evil-ex-current-buffer
- default-directory)))
- (fname (file-name-nondirectory arg)))
- (cond
- ((null dir) (ding))
- ((null flag)
- (let ((result (file-name-completion fname dir)))
- (cond
- ((null result) nil)
- ((eq result t) t)
- (t (concat dir result)))))
-
- ((eq t flag)
- (file-name-all-completions fname dir))
-
- ((eq 'lambda flag)
- (eq (file-name-completion fname dir) t))))))))
-
(evil-ex-define-argument-type file
"Handles a file argument."
- :completer evil-ex-filename-completion-at-point)
+ :collection read-file-name-internal)
(evil-ex-define-argument-type buffer
"Called to complete a buffer name argument."
- :completer (lambda ()
- (list
- (point-min) (point-max)
- (lambda (arg predicate flag)
- (when arg
- (let ((buffers (mapcar #'(lambda (buffer)
- (cons (buffer-name buffer) nil))
- (buffer-list t))))
- (cond
- ((null flag)
- (try-completion arg buffers predicate))
- ((eq t flag)
- (all-completions arg buffers predicate))
- ((eq 'lambda flag)
- (test-completion arg buffers predicate)))))))))
+ :collection internal-complete-buffer)
(declare-function shell-completion-vars "shell" ())
@@ -413,14 +513,15 @@ argument handler that requires shell completion."
(set (make-local-variable 'minibuffer-default-add-function)
'minibuffer-default-add-shell-commands)))
(setq completion-at-point-functions
- '(evil-ex-completion-at-point))))
+ '(evil-ex-command-completion-at-point
+ evil-ex-argument-completion-at-point))))
;; because this variable is used only for Emacs 23 shell completion,
;; we put it here instead of "evil-vars.el"
(defvar evil-ex-shell-argument-range nil
"Internal helper variable for Emacs 23 shell completion.")
-(defun evil-ex-complete-shell-command-at-point ()
+(defun evil-ex-shell-command-completion-at-point ()
"Completion at point function for shell commands."
(cond
;; Emacs 24
@@ -451,21 +552,23 @@ argument handler that requires shell completion."
(evil-ex-define-argument-type shell
"Shell argument type, supports completion."
- :completer evil-ex-complete-shell-command-at-point
+ :completion-at-point evil-ex-shell-command-completion-at-point
:runner evil-ex-init-shell-argument-completion)
+(defun evil-ex-file-or-shell-command-completion-at-point ()
+ (if (and (< (point-min) (point-max))
+ (= (char-after (point-min)) ?!))
+ (save-restriction
+ (narrow-to-region (1+ (point-min)) (point-max))
+ (evil-ex-shell-command-completion-at-point))
+ (list (point-min) (point-max) #'read-file-name-internal)))
+
(evil-ex-define-argument-type file-or-shell
"File or shell argument type.
If the current argument starts with a ! the rest of the argument
is considered a shell command, otherwise a file-name. Completion
works accordingly."
- :completer (lambda ()
- (if (and (< (point-min) (point-max))
- (= (char-after (point-min)) ?!))
- (save-restriction
- (narrow-to-region (1+ (point-min)) (point-max))
- (evil-ex-complete-shell-command-at-point))
- (evil-ex-filename-completion-at-point)))
+ :completion-at-point evil-ex-file-or-shell-command-completion-at-point
:runner evil-ex-init-shell-argument-completion)
(defun evil-ex-binding (command &optional noerror)
@@ -521,67 +624,6 @@ This function interprets special file names like # and %."
(zerop (length evil-ex-argument)))
(evil-ex-replace-special-filenames evil-ex-argument)))
-(defun evil-ex-run-completion-at-point ()
- "Same as `completion-at-point' but disables `evil-ex-update' during call.
-This function calls `evil-ex-update' explicitly when
-`completion-at-point' finished."
- (interactive)
- (let ((after-change-functions
- (remq 'evil-ex-update after-change-functions)))
- (completion-at-point)
- (evil-ex-update t)))
-
-(defun evil-ex-completion-at-point ()
- (let ((string (minibuffer-contents))
- (prompt (minibuffer-prompt-end))
- context start prefix)
- (when (= (point) (+ (length string) prompt))
- (evil-ex-update)
- (setq context (evil-ex-syntactic-context (1- (point))))
- (cond
- ((memq 'command context)
- (setq start (or (get-text-property
- 0 'ex-index evil-ex-command)
- (point))
- prefix (buffer-substring prompt start))
- (list start (point-max) #'evil-ex-complete-command))
- ((memq 'argument context)
- (let ((arg (or evil-ex-argument "")))
- (setq start (or (get-text-property
- 0 'ex-index arg)
- (point))
- prefix (buffer-substring prompt start))
- (let* ((binding (evil-ex-completed-binding evil-ex-command))
- (arg-type (evil-get-command-property binding :ex-arg))
- (arg-handler (assoc arg-type evil-ex-argument-types))
- (completer (and arg-handler
- (evil-ex-argument-handler-completer
- (cdr arg-handler)))))
- (when completer
- (save-restriction
- (narrow-to-region start (point-max))
- (funcall completer))))))))))
-
-(defun evil-ex-complete-command (cmd predicate flag)
- "Called to complete a command."
- (cond
- ((eq flag nil)
- (let ((result (try-completion cmd evil-ex-commands predicate)))
- (if (and (eq result t) (evil-ex-command-force-p cmd))
- cmd
- result)))
- ((eq flag t)
- (let ((result (all-completions cmd evil-ex-commands predicate))
- new-result)
- (mapc #'(lambda (x)
- (push x new-result)
- (when (evil-ex-command-force-p cmd)
- (push (concat x "!") new-result)))
- result)
- new-result))
- ((eq flag 'lambda)
- (test-completion cmd evil-ex-commands predicate))))
-
(defun evil-ex-repeat (count)
"Repeats the last ex command."
(interactive "P")
@@ -606,6 +648,7 @@ This function calls `evil-ex-update' explicitly when
(let* ((count (when (numberp range) range))
(range (when (evil-range-p range) range))
(bang (and (string-match ".!$" command) t))
+ (evil-ex-point (point))
(evil-ex-range
(or range (and count (evil-ex-range count count))))
(evil-ex-command (evil-ex-completed-binding command))
@@ -680,6 +723,19 @@ Signal an error if MARKER is in a different buffer."
(line-number-at-pos marker)
(error "Ex does not support markers in other files")))
+(defun evil-ex-char-marker-range (beg end)
+ (when (stringp beg) (setq beg (aref beg 0)))
+ (when (stringp end) (setq end (aref end 0)))
+ (setq beg (evil-get-marker beg)
+ end (evil-get-marker end))
+ (if (and (numberp beg) (numberp end))
+ (evil-expand-range
+ (evil-range beg end
+ (if (evil-visual-state-p)
+ (evil-visual-type)
+ 'inclusive)))
+ (error "Ex does not support markers in other files")))
+
(defun evil-ex-re-fwd (pattern)
"Search forward for PATTERN.
Returns the line number of the match."
View
169 etc/%emacs.d/evil/evil-integration.el
@@ -27,6 +27,9 @@
(require 'evil-maps)
(require 'evil-core)
+(require 'evil-macros)
+(require 'evil-types)
+(require 'evil-repeat)
;;; Code:
@@ -57,10 +60,14 @@
find-file-at-point
ffap-other-window
recompile
+ redo
save-buffer
split-window
split-window-horizontally
- split-window-vertically))
+ split-window-vertically
+ undo
+ undo-tree-redo
+ undo-tree-undo))
(evil-set-type #'previous-line 'line)
(evil-set-type #'next-line 'line)
@@ -164,10 +171,12 @@
(narrow-to-region narrow (point-max)))
ad-do-it))
;; prevent the preceding pair from being highlighted
- (when (overlayp show-paren-overlay)
- (delete-overlay show-paren-overlay))
- (when (overlayp show-paren-overlay-1)
- (delete-overlay show-paren-overlay-1))))))
+ (dolist (ov '(show-paren--overlay
+ show-paren--overlay-1
+ show-paren-overlay
+ show-paren-overlay-1))
+ (let ((ov (and (boundp ov) (symbol-value ov))))
+ (when (overlayp ov) (delete-overlay ov))))))))
;;; Speedbar
@@ -198,15 +207,29 @@
(when evil-local-mode
(evil-initialize-state)))
-(when (boundp 'undo-tree-visualizer-map)
- (define-key undo-tree-visualizer-map [remap evil-backward-char]
+(when (boundp 'undo-tree-visualizer-mode-map)
+ (define-key undo-tree-visualizer-mode-map [remap evil-backward-char]
'undo-tree-visualize-switch-branch-left)
- (define-key undo-tree-visualizer-map [remap evil-forward-char]
+ (define-key undo-tree-visualizer-mode-map [remap evil-forward-char]
'undo-tree-visualize-switch-branch-right)
- (define-key undo-tree-visualizer-map [remap evil-next-line]
+ (define-key undo-tree-visualizer-mode-map [remap evil-next-line]
'undo-tree-visualize-redo)
- (define-key undo-tree-visualizer-map [remap evil-previous-line]
- 'undo-tree-visualize-undo))
+ (define-key undo-tree-visualizer-mode-map [remap evil-previous-line]
+ 'undo-tree-visualize-undo)
+ (define-key undo-tree-visualizer-mode-map [remap evil-ret]
+ 'undo-tree-visualizer-set))
+
+(when (boundp 'undo-tree-visualizer-selection-mode-map)
+ (define-key undo-tree-visualizer-selection-mode-map [remap evil-backward-char]
+ 'undo-tree-visualizer-select-left)
+ (define-key undo-tree-visualizer-selection-mode-map [remap evil-forward-char]
+ 'undo-tree-visualizer-select-right)
+ (define-key undo-tree-visualizer-selection-mode-map [remap evil-next-line]
+ 'undo-tree-visualizer-select-next)
+ (define-key undo-tree-visualizer-selection-mode-map [remap evil-previous-line]
+ 'undo-tree-visualizer-select-previous)
+ (define-key undo-tree-visualizer-selection-mode-map [remap evil-ret]
+ 'undo-tree-visualizer-set))
;;; Auto-complete
(eval-after-load 'auto-complete
@@ -240,6 +263,26 @@
;; Finish repeation
(evil-repeat-finish-record-changes))))))
+;;; Company
+(eval-after-load 'company
+ '(progn
+ (mapc #'evil-declare-change-repeat
+ '(company-complete-mouse
+ company-complete-selection
+ company-complete-common))
+
+ (mapc #'evil-declare-ignore-repeat
+ '(company-abort
+ company-select-next
+ company-select-previous
+ company-select-next-or-abort
+ company-select-previous-or-abort
+ company-select-mouse
+ company-show-doc-buffer
+ company-show-location
+ company-search-candidates
+ company-filter-candidates))))
+
;; Eval last sexp
(defadvice preceding-sexp (around evil activate)
"In normal-state, last sexp ends at point."
@@ -266,6 +309,110 @@
"Temporarily go to Emacs state"
(evil-with-state emacs ad-do-it))
+;; ace-jump-mode
+(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-ace-jump-active nil)
+
+(defmacro evil-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)))
+ (remove-hook 'pre-command-hook #'evil-visual-pre-command t)
+ (remove-hook 'post-command-hook #'evil-visual-post-command t)
+ (unwind-protect
+ (let ((evil-ace-jump-active 'prepare))
+ (add-hook 'ace-jump-mode-end-hook
+ #'evil-ace-jump-exit-recursive-edit)
+ ,@body
+ (when evil-ace-jump-active
+ (setq evil-ace-jump-active t)
+ (recursive-edit)))
+ (remove-hook 'post-command-hook
+ #'evil-ace-jump-exit-recursive-edit)
+ (remove-hook 'ace-jump-mode-end-hook
+ #'evil-ace-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)))))
+
+(eval-after-load 'ace-jump-mode
+ `(defadvice ace-jump-done (after evil activate)
+ (when evil-ace-jump-active
+ (add-hook 'post-command-hook #'evil-ace-jump-exit-recursive-edit))))
+
+(defun evil-ace-jump-exit-recursive-edit ()
+ "Exit a recursive edit caused by an evil jump."
+ (cond
+ ((eq evil-ace-jump-active 'prepare)
+ (setq evil-ace-jump-active nil))
+ (evil-ace-jump-active
+ (remove-hook 'post-command-hook #'evil-ace-jump-exit-recursive-edit)
+ (exit-recursive-edit))))
+
+(evil-define-motion evil-ace-jump-char-mode (count)
+ "Jump visually directly to a char using ace-jump."
+ :type inclusive
+ (evil-without-repeat
+ (let ((pnt (point))
+ (buf (current-buffer)))
+ (evil-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 'exclusive)))))
+
+(evil-define-motion evil-ace-jump-char-to-mode (count)
+ "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-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 'exclusive))
+ (backward-char)))))
+
+(evil-define-motion evil-ace-jump-line-mode (count)
+ "Jump visually to the beginning of a line using ace-jump."
+ :type line
+ :repeat abort
+ (evil-without-repeat
+ (evil-enclose-ace-jump-for-motion
+ (call-interactively #'ace-jump-line-mode))))
+
+(evil-define-motion evil-ace-jump-word-mode (count)
+ "Jump visually to the beginning of a word using ace-jump."
+ :type exclusive
+ :repeat abort
+ (evil-without-repeat
+ (evil-enclose-ace-jump-for-motion
+ (call-interactively #'ace-jump-word-mode))))
+
+(define-key evil-motion-state-map [remap ace-jump-char-mode] #'evil-ace-jump-char-mode)
+(define-key evil-motion-state-map [remap ace-jump-line-mode] #'evil-ace-jump-line-mode)
+(define-key evil-motion-state-map [remap ace-jump-word-mode] #'evil-ace-jump-word-mode)
+
(provide 'evil-integration)
;;; evil-integration.el ends here
View
25 etc/%emacs.d/evil/evil-maps.el
@@ -99,10 +99,7 @@
;; undo
(define-key evil-normal-state-map "u" 'undo)
-
-(when (fboundp 'undo-tree-undo)
- (define-key evil-normal-state-map "u" 'undo-tree-undo)
- (define-key evil-normal-state-map "\C-r" 'undo-tree-redo))
+(define-key evil-normal-state-map "\C-r" 'redo)
;; window commands
(define-prefix-command 'evil-window-map)
@@ -202,6 +199,7 @@
(define-key evil-motion-state-map "g0" 'evil-beginning-of-visual-line)
(define-key evil-motion-state-map "g_" 'evil-last-non-blank)
(define-key evil-motion-state-map "g^" 'evil-first-non-blank-of-visual-line)
+(define-key evil-motion-state-map "gm" 'evil-middle-of-visual-line)
(define-key evil-motion-state-map "g$" 'evil-end-of-visual-line)
(define-key evil-motion-state-map "g\C-]" 'find-tag)
(define-key evil-motion-state-map "{" 'evil-backward-paragraph)
@@ -346,8 +344,10 @@
(define-key evil-insert-state-map "\C-x\C-p" 'evil-complete-previous-line)
(define-key evil-insert-state-map "\C-t" 'evil-shift-right-line)
(define-key evil-insert-state-map "\C-d" 'evil-shift-left-line)
+(define-key evil-insert-state-map [remap delete-backward-char] 'evil-delete-backward-char-and-join)
+(define-key evil-insert-state-map [delete] 'delete-char)
(define-key evil-insert-state-map [remap newline] 'evil-ret)
-(define-key evil-insert-state-map [remap newline-and-indent] 'evil-ret)
+(define-key evil-insert-state-map [remap newline-and-indent] 'evil-ret-and-indent)
(define-key evil-insert-state-map [escape] 'evil-normal-state)
(define-key evil-insert-state-map
(read-kbd-macro evil-toggle-key) 'evil-emacs-state)
@@ -399,10 +399,13 @@
(evil-ex-define-cmd "sbp[revious]" 'evil-split-prev-buffer)
(evil-ex-define-cmd "sbN[ext]" "sbprevious")
(evil-ex-define-cmd "buffers" 'evil-show-buffers)
-(evil-ex-define-cmd "files" "buffers")
+(evil-ex-define-cmd "files" 'evil-show-files)
(evil-ex-define-cmd "ls" "buffers")
(evil-ex-define-cmd "c[hange]" 'evil-change)
+(evil-ex-define-cmd "co[py]" 'evil-copy)
+(evil-ex-define-cmd "t" "copy")
+(evil-ex-define-cmd "m[ove]" 'evil-move)
(evil-ex-define-cmd "d[elete]" 'evil-delete)
(evil-ex-define-cmd "y[ank]" 'evil-yank)
(evil-ex-define-cmd "go[to]" 'evil-goto-char)
@@ -455,15 +458,15 @@
;; ex command line
(define-key evil-ex-completion-map "\d" #'evil-ex-delete-backward-char)
-(define-key evil-ex-completion-map "\t" #'evil-ex-run-completion-at-point)
-(define-key evil-ex-completion-map [tab] #'evil-ex-run-completion-at-point)
-(define-key evil-ex-completion-map "\C-a" 'evil-ex-run-completion-at-point)
+(define-key evil-ex-completion-map "\t" #'evil-ex-completion)
+(define-key evil-ex-completion-map [tab] #'evil-ex-completion)
+(define-key evil-ex-completion-map "\C-a" 'evil-ex-completion)
(define-key evil-ex-completion-map "\C-b" 'move-beginning-of-line)
(define-key evil-ex-completion-map "\C-c" 'abort-recursive-edit)
-(define-key evil-ex-completion-map "\C-d" 'evil-ex-run-completion-at-point)
+(define-key evil-ex-completion-map "\C-d" 'evil-ex-completion)
(define-key evil-ex-completion-map "\C-g" 'abort-recursive-edit)
(define-key evil-ex-completion-map "\C-k" 'evil-insert-digraph)
-(define-key evil-ex-completion-map "\C-l" 'evil-ex-run-completion-at-point)
+(define-key evil-ex-completion-map "\C-l" 'evil-ex-completion)
(define-key evil-ex-completion-map "\C-p" #'next-complete-history-element)
(define-key evil-ex-completion-map "\C-r" 'evil-paste-from-register)
(define-key evil-ex-completion-map "\C-n" #'next-complete-history-element)
View
4 etc/%emacs.d/evil/evil-pkg.el
@@ -1,5 +1,5 @@
(define-package
"evil"
- "1.0.0"
+ "1.0.6"
"Extensible Vi layer for Emacs."
- '((undo-tree "0.5.1")))
+ '((undo-tree "0.6.3")))
View
8 etc/%emacs.d/evil/evil-repeat.el
@@ -135,6 +135,14 @@
(declare-function evil-visual-line "evil-visual")
(declare-function evil-visual-block "evil-visual")
+(defmacro evil-without-repeat (&rest body)
+ (declare (indent defun)
+ (debug t))
+ `(let ((pre-command-hook (remq 'evil-repeat-pre-hook pre-command-hook))
+ (post-command-hook (remq 'evil-repeat-post-hook post-command-hook)))
+ ,@body
+ (evil-repeat-abort)))
+
(defsubst evil-repeat-recording-p ()
"Returns non-nil iff a recording is in progress."
(eq evil-recording-repeat t))
View
208 etc/%emacs.d/evil/evil-search.el
@@ -220,9 +220,12 @@ one more than the current position."
(setq isearch-string string)
(isearch-update-ring string regexp-p)
;; handle opening and closing of invisible area
- (when (boundp 'isearch-filter-predicate)
- (funcall isearch-filter-predicate
- (match-beginning 0) (match-end 0)))
+ (cond
+ ((boundp 'isearch-filter-predicates)
+ (dolist (pred isearch-filter-predicates)
+ (funcall pred (match-beginning 0) (match-end 0))))
+ ((boundp 'isearch-filter-predicate)
+ (funcall isearch-filter-predicate (match-beginning 0) (match-end 0))))
;; always position point at the beginning of the match
(goto-char (match-beginning 0))
;; determine message for echo area
@@ -310,39 +313,6 @@ Returns nil if nothing is found."
;;; Ex search
-;; a pattern
-(defun evil-ex-make-pattern (regexp casefold whole-line)
- "Create a new search pattern.
-REGEXP is the regular expression to be searched for.
-CASEFOLD is the case-fold property of the search,
-which can be either `sensitive', `insensitive' or `smart'.
-Here `smart' means the pattern is case sensitive if and only if
-it contains a capital character. If WHOLE-LINE is non-nil,
-all occurrences of the pattern on a line will be highlighted,
-otherwise only the first one."
- (let ((re (evil-ex-regex-without-case regexp)))
- (when evil-ex-search-vim-style-regexp
- (setq re (evil-transform-vim-style-regexp re)))
- (setq re (evil-transform-regexp re
- '((?t . "\t")
- (?n . "\n")
- (?r . "\r"))))
- (list re
- (evil-ex-regex-case regexp casefold)
- whole-line)))
-
-(defun evil-ex-pattern-regex (pattern)
- "Return the regular expression of a search PATTERN."
- (car pattern))
-
-(defun evil-ex-pattern-case-fold (pattern)
- "Return the case-fold property of a search PATTERN."
- (cadr pattern))
-
-(defun evil-ex-pattern-whole-line (pattern)
- "Return the whole-line property of a search PATTERN."
- (nth 2 pattern))
-
(defun evil-ex-regex-without-case (re)
"Return the regular expression without all occurrences of \\c and \\C."
(evil-transform-regexp re '((?c . "") (?C . ""))))
@@ -366,6 +336,69 @@ letter, otherwise it will be case-insensitive."
'sensitive))
(t default-case)))
+;; a pattern
+(defun evil-ex-make-substitute-pattern (regexp flags)
+ "Creates a PATTERN for substitution with FLAGS.
+This function respects the values of `evil-ex-substitute-case'
+and `evil-ex-substitute-global'."
+ (evil-ex-make-pattern regexp
+ (cond
+ ((memq ?i flags) 'insensitive)
+ ((memq ?I flags) 'sensitive)
+ ((not evil-ex-substitute-case)
+ evil-ex-search-case)
+ (t evil-ex-substitute-case))
+ (or (and evil-ex-substitute-global
+ (not (memq ?g flags)))
+ (and (not evil-ex-substitute-global)
+ (memq ?g flags)))))
+
+(defun evil-ex-make-search-pattern (regexp)
+ "Creates a PATTERN for search.
+This function respects the values of `evil-ex-search-case'."
+ (evil-ex-make-pattern regexp evil-ex-search-case t))
+
+(defun evil-ex-make-pattern (regexp case whole-line)
+ "Create a new search pattern.
+REGEXP is the regular expression to be searched for. CASE should
+be either 'sensitive, 'insensitive for case-sensitive and
+case-insensitive search, respectively, or anything else. In the
+latter case the pattern is smart-case, i.e. it is automatically
+sensitive of the pattern contains one upper case letter,
+otherwise it is insensitive. The input REGEXP is considered a
+Vim-style regular expression if `evil-ex-search-vim-style-regexp'
+is non-nil, in which case it is transformed to an Emacs style
+regular expression (i.e. certain backslash-codes are
+transformed. Otherwise REGEXP must be an Emacs style regular
+expression and is not transformed."
+ (let ((re (evil-ex-regex-without-case regexp))
+ (ignore-case (eq (evil-ex-regex-case regexp case) 'insensitive)))
+ ;; possibly transform regular expression from vim-style to
+ ;; Emacs-style.
+ (if evil-ex-search-vim-style-regexp
+ (setq re (evil-transform-vim-style-regexp re))
+ ;; Even for Emacs regular expressions we translate certain
+ ;; whitespace sequences
+ (setq re (evil-transform-regexp re
+ '((?t . "\t")
+ (?n . "\n")
+ (?r . "\r")))))
+ (list re ignore-case whole-line)))
+
+(defun evil-ex-pattern-regex (pattern)
+ "Return the regular expression of a search PATTERN."
+ (nth 0 pattern))
+
+(defun evil-ex-pattern-ignore-case (pattern)
+ "Return t if and only if PATTERN should ignore case."
+ (nth 1 pattern))
+
+(defun evil-ex-pattern-whole-line (pattern)
+ "Return t if and only if PATTERN should match all occurences of a line.
+Otherwise PATTERN matches only the first occurence."
+ (nth 2 pattern))
+
+;; Highlight
(defun evil-ex-make-hl (name &rest args)
"Create a new highlight object with name NAME and properties ARGS.
The following properties are supported:
@@ -513,12 +546,14 @@ The following properties are supported:
(defun evil-ex-hl-update-highlights ()
"Update the overlays of all active highlights."
(dolist (hl (mapcar #'cdr evil-ex-active-highlights-alist))
- (let ((old-ovs (evil-ex-hl-overlays hl))
- new-ovs
- (pattern (evil-ex-hl-pattern hl))
- (face (evil-ex-hl-face hl))
- (match-hook (evil-ex-hl-match-hook hl))
- result)
+ (let* ((old-ovs (evil-ex-hl-overlays hl))
+ new-ovs
+ (pattern (evil-ex-hl-pattern hl))
+ (case-fold-search (evil-ex-pattern-ignore-case pattern))
+ (case-replace case-fold-search)
+ (face (evil-ex-hl-face hl))
+ (match-hook (evil-ex-hl-match-hook hl))
+ result)
(if pattern
;; collect all visible ranges
(let (ranges sranges)
@@ -610,8 +645,7 @@ The following properties are supported:
"Look for the next occurrence of PATTERN in a certain DIRECTION.
Note that this function ignores the whole-line property of PATTERN."
(setq direction (or direction 'forward))
- (let ((case-fold-search (eq (evil-ex-pattern-case-fold pattern)
- 'insensitive)))
+ (let ((case-fold-search (evil-ex-pattern-ignore-case pattern)))
(cond
((eq direction 'forward)
(re-search-forward (evil-ex-pattern-regex pattern) nil t))
@@ -633,8 +667,9 @@ Note that this function ignores the whole-line property of PATTERN."
(defun evil-ex-hl-do-update-highlight (&optional buffer)
"Timer function for updating the highlights."
- (with-current-buffer buffer
- (evil-ex-hl-update-highlights))
+ (when (buffer-live-p buffer)
+ (with-current-buffer buffer
+ (evil-ex-hl-update-highlights)))
(setq evil-ex-hl-update-timer nil))
(defun evil-ex-hl-update-highlights-scroll (win beg)
@@ -673,7 +708,7 @@ only searches invisible text if `search-invisible' is t. If
PATTERN is not specified the current global pattern
`evil-ex-search-pattern' and if DIRECTION is not specified the
current global direction `evil-ex-search-direction' is used.
-This function return t if the search was successful, nil if it
+This function returns t if the search was successful, nil if it
was unsuccessful and 'wrapped if the search was successful but
has been wrapped at the buffer boundaries."
(setq pattern (or pattern evil-ex-search-pattern)
@@ -811,9 +846,7 @@ any error conditions."
(next-pat (pop res)))
;; use last pattern of no new pattern has been specified
(if (not (zerop (length pat)))
- (setq pat (evil-ex-make-pattern pat
- evil-ex-search-case
- t))
+ (setq pat (evil-ex-make-search-pattern pat))
(setq pat evil-ex-search-pattern
offset (or offset evil-ex-search-offset)))
(when (zerop (length pat))
@@ -849,36 +882,37 @@ any error conditions."
(defun evil-ex-search-update-pattern (beg end range)
"Update the current search pattern."
- (let ((pattern-string (minibuffer-contents)))
- (with-current-buffer evil-ex-current-buffer
- (with-selected-window (minibuffer-selected-window)
- (goto-char (1+ evil-ex-search-start-point))
- (condition-case err
- (let* ((result (evil-ex-search-full-pattern pattern-string
- (or evil-ex-search-count 1)
- evil-ex-search-direction))
- (success (pop result))
- (pattern (pop result))
- (offset (pop result)))
- (cond
- ((eq success 'wrap)
- (evil-ex-search-update pattern offset
- (match-beginning 0) (match-end 0)
- "Wrapped"))
- ((eq success 'empty-pattern)
- (evil-ex-search-update nil nil nil nil nil))
- (success
- (evil-ex-search-update pattern offset
- (match-beginning 0) (match-end 0)
- nil))
- (t
- (evil-ex-search-update nil nil
- nil nil
- "search failed"))))
- (invalid-regexp
- (evil-ex-search-update nil nil nil nil (cadr err)))
- (error
- (evil-ex-search-update nil nil nil nil (format "%s" err))))))))
+ (save-match-data
+ (let ((pattern-string (minibuffer-contents)))
+ (with-current-buffer evil-ex-current-buffer
+ (with-selected-window (minibuffer-selected-window)
+ (goto-char (1+ evil-ex-search-start-point))
+ (condition-case err
+ (let* ((result (evil-ex-search-full-pattern pattern-string
+ (or evil-ex-search-count 1)
+ evil-ex-search-direction))
+ (success (pop result))
+ (pattern (pop result))
+ (offset (pop result)))
+ (cond
+ ((eq success 'wrap)
+ (evil-ex-search-update pattern offset
+ (match-beginning 0) (match-end 0)
+ "Wrapped"))
+ ((eq success 'empty-pattern)
+ (evil-ex-search-update nil nil nil nil nil))
+ (success
+ (evil-ex-search-update pattern offset
+ (match-beginning 0) (match-end 0)
+ nil))
+ (t
+ (evil-ex-search-update nil nil
+ nil nil
+ "search failed"))))
+ (invalid-regexp
+ (evil-ex-search-update nil nil nil nil (cadr err)))
+ (error
+ (evil-ex-search-update nil nil nil nil (format "%s" err)))))))))
(put 'evil-ex-search-update-pattern 'permanent-local-hook t)
(defun evil-ex-search-exit ()
@@ -985,7 +1019,7 @@ The DIRECTION argument should be either `forward' or
(setq evil-ex-search-count count
evil-ex-search-direction direction
evil-ex-search-pattern
- (evil-ex-make-pattern regex evil-ex-search-case t)
+ (evil-ex-make-search-pattern regex)
evil-ex-search-offset nil
evil-ex-last-was-search t)
;; update search history unless this pattern equals the
@@ -1118,17 +1152,7 @@ a :substitute command with arguments."
flags (remq ?r flags)))
;; generate pattern
(when pattern
- (setq pattern
- (evil-ex-make-pattern
- pattern
- (or (and (memq ?i flags) 'insensitive)
- (and (memq ?I flags) 'sensitive)
- evil-ex-substitute-case
- evil-ex-search-case)
- (or (and (not evil-ex-substitute-global)
- (memq ?g flags))
- (and evil-ex-substitute-global
- (not (memq ?g flags)))))))
+ (setq pattern (evil-ex-make-substitute-pattern pattern flags)))
(list pattern replacement flags)))
(defun evil-ex-nohighlight ()
View
26 etc/%emacs.d/evil/evil-states.el
@@ -268,7 +268,10 @@ the selection is enabled.
Expand the region to the selection unless COMMAND is a motion."
(when (evil-visual-state-p)
(setq command (or command this-command))
+ (when evil-visual-x-select-timer
+ (cancel-timer evil-visual-x-select-timer))
(unless (evil-get-command-property command :keep-visual)
+ (evil-visual-update-x-selection)
(evil-visual-expand-region
;; exclude final newline from linewise selection
;; unless the command has real need of it
@@ -283,8 +286,6 @@ If COMMAND is a motion, refresh the selection;
otherwise exit Visual state."
(when (evil-visual-state-p)
(setq command (or command this-command))
- (when evil-visual-x-select-timer
- (cancel-timer evil-visual-x-select-timer))
(if (or quit-flag
(eq command #'keyboard-quit)
;; Is `mark-active' nil for an unexpanded region?
@@ -307,15 +308,17 @@ otherwise exit Visual state."
(defun evil-visual-update-x-selection (&optional buffer)
"Update the X selection with the current visual region."
- (with-current-buffer (or buffer (current-buffer))
- (when (and (evil-visual-state-p)
- (fboundp 'x-select-text)
- (or (not (boundp 'ns-initialized))
- (with-no-warnings ns-initialized))
- (not (eq evil-visual-selection 'block)))
- (x-select-text (buffer-substring-no-properties
- evil-visual-beginning
- evil-visual-end)))))
+ (let ((buf (or buffer (current-buffer))))
+ (when (buffer-live-p buf)
+ (with-current-buffer buf
+ (when (and (evil-visual-state-p)
+ (fboundp 'x-select-text)
+ (or (not (boundp 'ns-initialized))
+ (with-no-warnings ns-initialized))
+ (not (eq evil-visual-selection 'block)))
+ (x-select-text (buffer-substring-no-properties
+ evil-visual-beginning
+ evil-visual-end)))))))
(defun evil-visual-activate-hook (&optional command)
"Enable Visual state if the region is activated."
@@ -357,7 +360,6 @@ If LATER is non-nil, exit after the current command."
:repeat abort
(with-current-buffer (or buffer (current-buffer))
(when (evil-visual-state-p)
- (evil-visual-update-x-selection)
(if later
(setq deactivate-mark t)
(when evil-visual-region-expanded
View
308 etc/%emacs.d/evil/evil-tests.el
@@ -197,6 +197,7 @@ then the test fails unless an error of type SYMBOL is raised.
;; necessary for keyboard macros to work
(switch-to-buffer-other-window (current-buffer))
(buffer-enable-undo)
+ (undo-tree-mode 1)
;; parse remaining forms
,@(mapcar
#'(lambda (form)
@@ -1720,6 +1721,16 @@ New Tex[t]
((kbd "C-v") "jj$AXXX" [escape])
"line 1line 1line 1XX[X]\nline 2XXX\nline 3line 3XXX\n")))
+(ert-deftest evil-test-repeat-digraph ()
+ "Test repeat of insertion of a digraph."
+ :tags '(evil digraph repeat)
+ (evil-test-buffer
+ "Line with ['] several apostrophes ', yeah."
+ ("s" (kbd "C-k") "'9" [escape])
+ "Line with [’] several apostrophes ', yeah."
+ ("f'.")
+ "Line with ’ several apostrophes [’], yeah."))
+
;;; Operators
(ert-deftest evil-test-keypress-parser ()
@@ -2067,6 +2078,26 @@ ine3 line3 line3 l\n")))
("zm2j3dd")
"line1\n\n[\n]last line\n")))
+(ert-deftest evil-test-delete-backward-word ()
+ "Test `evil-delete-backward-word' in insert state."
+ :tags '(evil)
+ (let ((evil-backspace-join-lines t))
+ (evil-test-buffer
+ "abc def\n ghi j[k]l\n"
+ ("i" (kbd "C-w"))
+ "abc def\n ghi [k]l\n"
+ ((kbd "C-w"))
+ "abc def\n [k]l\n"
+ ((kbd "C-w"))
+ "abc def\n[k]l\n"
+ ((kbd "C-w"))
+ "abc def[k]l\n"))
+ (let (evil-backspace-join-lines)
+ (evil-test-buffer
+ "abc def\n[k]l\n"
+ (should-error (execute-kbd-macro (concat "i" (kbd "C-w"))))
+ "abc def\n[k]l\n")))
+
(ert-deftest evil-test-change ()
"Test `evil-change'"
:tags '(evil operator)
@@ -2645,6 +2676,52 @@ This bufferThis bufferThis buffe[r];; and for Lisp evaluation."))
";; This buffer is for notes you don't want to save.
\[;]; This buffer is for notes you don't want to save."))
+(ert-deftest evil-test-visual-paste-pop ()
+ "Test `evil-paste-pop' after visual paste."
+ :tags '(evil paste)
+ (ert-info ("Visual-char paste, char paste")
+ (evil-test-buffer
+ "[w]ord1a word1b word1c\nword2a word2b\nword3a word3b word3c word3d\n"
+ ("yiwyywyiw^jw")
+ "word1a word1b word1c\nword2a [w]ord2b\nword3a word3b word3c word3d\n"
+ ("viwp")
+ "word1a word1b word1c\nword2a word1[b]\nword3a word3b word3c word3d\n"))
+ (ert-info ("Visual-char paste, char paste, line pop")
+ (evil-test-buffer
+ "[w]ord1a word1b word1c\nword2a word2b\nword3a word3b word3c word3d\n"
+ ("yiwyywyiw^jw")
+ "word1a word1b word1c\nword2a [w]ord2b\nword3a word3b word3c word3d\n"
+ ("viwp\C-p")
+ "word1a word1b word1c\nword2a \n[w]ord1a word1b word1c\n\nword3a word3b word3c word3d\n"))
+ (ert-info ("Visual-char paste, char paste, line pop, char pop")
+ (evil-test-buffer
+ "[w]ord1a word1b word1c\nword2a word2b\nword3a word3b word3c word3d\n"
+ ("yiwyywyiw^jw")
+ "word1a word1b word1c\nword2a [w]ord2b\nword3a word3b word3c word3d\n"
+ ("viwp\C-p\C-p")
+ "word1a word1b word1c\nword2a word1[a]\nword3a word3b word3c word3d\n"))
+ (ert-info ("Visual-line paste, char paste")
+ (evil-test-buffer
+ "[w]ord1a word1b word1c\nword2a word2b\nword3a word3b word3c word3d\n"
+ ("yiwyywyiw^j")
+ "word1a word1b word1c\n[w]ord2a word2b\nword3a word3b word3c word3d\n"
+ ("Vp")
+ "word1a word1b word1c\nword1[b]word3a word3b word3c word3d\n"))
+ (ert-info ("Visual-line paste, char paste, line pop")
+ (evil-test-buffer
+ "[w]ord1a word1b word1c\nword2a word2b\nword3a word3b word3c word3d\n"
+ ("yiwyywyiw^j")
+ "word1a word1b word1c\n[w]ord2a word2b\nword3a word3b word3c word3d\n"
+ ("Vp\C-p")
+ "word1a word1b word1c\n[w]ord1a word1b word1c\nword3a word3b word3c word3d\n"))
+ (ert-info ("Visual-line paste, char paste, line pop, char pop")