about summary refs log tree commit diff
path: root/configs/shared/emacs/.emacs.d/elpa/evil-20180517.1300/evil-common.el
diff options
context:
space:
mode:
Diffstat (limited to 'configs/shared/emacs/.emacs.d/elpa/evil-20180517.1300/evil-common.el')
-rw-r--r--configs/shared/emacs/.emacs.d/elpa/evil-20180517.1300/evil-common.el3883
1 files changed, 3883 insertions, 0 deletions
diff --git a/configs/shared/emacs/.emacs.d/elpa/evil-20180517.1300/evil-common.el b/configs/shared/emacs/.emacs.d/elpa/evil-20180517.1300/evil-common.el
new file mode 100644
index 000000000000..62eda5fffaa4
--- /dev/null
+++ b/configs/shared/emacs/.emacs.d/elpa/evil-20180517.1300/evil-common.el
@@ -0,0 +1,3883 @@
+;;; evil-common.el --- Common functions and utilities
+;; Author: Vegard Øye <vegard_oye at hotmail.com>
+;; Maintainer: Vegard Øye <vegard_oye at hotmail.com>
+
+;; Version: 1.2.13
+
+;;
+;; This file is NOT part of GNU Emacs.
+
+;;; License:
+
+;; This file is part of Evil.
+;;
+;; Evil 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.
+;;
+;; Evil 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 Evil.  If not, see <http://www.gnu.org/licenses/>.
+
+(require 'evil-vars)
+(require 'evil-digraphs)
+(require 'rect)
+(require 'thingatpt)
+
+;;; Code:
+
+(declare-function evil-visual-state-p "evil-states")
+(declare-function evil-visual-restore "evil-states")
+(declare-function evil-motion-state "evil-states")
+(declare-function evil-ex-p "evil-ex")
+(declare-function evil-set-jump "evil-jumps")
+
+(condition-case nil
+    (require 'windmove)
+  (error
+   (message "evil: Could not load `windmove', \
+window commands not available.")
+   nil))
+
+;;; Compatibility with different Emacs versions
+
+;; x-set-selection and x-get-selection have been deprecated since 25.1
+;; by gui-set-selection and gui-get-selection
+(defalias 'evil-get-selection
+  (if (fboundp 'gui-get-selection) 'gui-get-selection 'x-get-selection))
+(defalias 'evil-set-selection
+  (if (fboundp 'gui-set-selection) 'gui-set-selection 'x-set-selection))
+
+(defmacro evil-called-interactively-p ()
+  "Wrapper for `called-interactively-p'.
+In older versions of Emacs, `called-interactively-p' takes
+no arguments.  In Emacs 23.2 and newer, it takes one argument."
+  (called-interactively-p 'any))
+(make-obsolete 'evil-called-interactively-p
+               "please use (called-interactively-p 'any) instead."
+               "Git commit 222b791")
+
+;; macro helper
+(eval-and-compile
+  (defun evil-unquote (exp)
+    "Return EXP unquoted."
+    (while (eq (car-safe exp) 'quote)
+      (setq exp (cadr exp)))
+    exp))
+
+(defun evil-delay (condition form hook &optional append local name)
+  "Execute FORM when CONDITION becomes true, checking with HOOK.
+NAME specifies the name of the entry added to HOOK. If APPEND is
+non-nil, the entry is appended to the hook. If LOCAL is non-nil,
+the buffer-local value of HOOK is modified."
+  (if (and (not (booleanp condition)) (eval condition))
+      (eval form)
+    (let* ((name (or name (format "evil-delay-form-in-%s" hook)))
+           (fun (make-symbol name))
+           (condition (or condition t)))
+      (fset fun `(lambda (&rest args)
+                   (when ,condition
+                     (remove-hook ',hook #',fun ',local)
+                     ,form)))
+      (put fun 'permanent-local-hook t)
+      (add-hook hook fun append local))))
+(put 'evil-delay 'lisp-indent-function 2)
+
+;;; List functions
+
+(defun evil-add-to-alist (list-var key val &rest elements)
+  "Add the assocation of KEY and VAL to the value of LIST-VAR.
+If the list already contains an entry for KEY, update that entry;
+otherwise add at the end of the list."
+  (let ((tail (symbol-value list-var)))
+    (while (and tail (not (equal (car-safe (car-safe tail)) key)))
+      (setq tail (cdr tail)))
+    (if tail
+        (setcar tail (cons key val))
+      (set list-var (append (symbol-value list-var)
+                            (list (cons key val)))))
+    (if elements
+        (apply #'evil-add-to-alist list-var elements)
+      (symbol-value list-var))))
+
+;; custom version of `delete-if'
+(defun evil-filter-list (predicate list &optional pointer)
+  "Delete by side-effect all items satisfying PREDICATE in LIST.
+Stop when reaching POINTER.  If the first item satisfies PREDICATE,
+there is no way to remove it by side-effect; therefore, write
+\(setq foo (evil-filter-list 'predicate foo)) to be sure of
+changing the value of `foo'."
+  (let ((tail list) elt head)
+    (while (and tail (not (eq tail pointer)))
+      (setq elt (car tail))
+      (cond
+       ((funcall predicate elt)
+        (setq tail (cdr tail))
+        (if head
+            (setcdr head tail)
+          (setq list tail)))
+       (t
+        (setq head tail
+              tail (cdr tail)))))
+    list))
+
+(defun evil-member-if (predicate list &optional pointer)
+  "Find the first item satisfying PREDICATE in LIST.
+Stop when reaching POINTER, which should point at a link
+in the list."
+  (let (elt)
+    (catch 'done
+      (while (and (consp list) (not (eq list pointer)))
+        (setq elt (car list))
+        (if (funcall predicate elt)
+            (throw 'done elt)
+          (setq list (cdr list)))))))
+
+(defun evil-member-recursive-if (predicate tree)
+  "Find the first item satisfying PREDICATE in TREE."
+  (cond
+   ((funcall predicate tree)
+    tree)
+   ((listp tree)
+    (catch 'done
+      (dolist (elt tree)
+        (when (setq elt (evil-member-recursive-if predicate elt))
+          (throw 'done elt)))))))
+
+(defun evil-concat-lists (&rest sequences)
+  "Concatenate lists, removing duplicates.
+Elements are compared with `eq'."
+  (let (result)
+    (dolist (sequence sequences)
+      (dolist (elt sequence)
+        (add-to-list 'result elt nil #'eq)))
+    (nreverse result)))
+
+(defun evil-concat-alists (&rest sequences)
+  "Concatenate association lists, removing duplicates.
+An alist is a list of cons cells (KEY . VALUE) where each key
+may occur only once. Later values overwrite earlier values."
+  (let (result)
+    (dolist (sequence sequences)
+      (dolist (elt sequence)
+        (setq result (assq-delete-all (car-safe elt) result))
+        (push elt result)))
+    (nreverse result)))
+
+(defun evil-concat-plists (&rest sequences)
+  "Concatenate property lists, removing duplicates.
+A property list is a list (:KEYWORD1 VALUE1 :KEYWORD2 VALUE2...)
+where each keyword may occur only once. Later values overwrite
+earlier values."
+  (let (result)
+    (dolist (sequence sequences result)
+      (while sequence
+        (setq result
+              (plist-put result (pop sequence) (pop sequence)))))))
+
+(defun evil-concat-keymap-alists (&rest sequences)
+  "Concatenate keymap association lists, removing duplicates.
+A keymap alist is a list of cons cells (VAR . MAP) where each keymap
+may occur only once, but where the variables may be repeated
+\(e.g., (VAR . MAP1) (VAR . MAP2) is allowed). The order matters,
+with the highest priority keymaps being listed first."
+  (let (result)
+    (dolist (sequence sequences)
+      (dolist (elt sequence)
+        (unless (rassq (cdr-safe elt) result)
+          (push elt result))))
+    (nreverse result)))
+
+(defun evil-plist-delete (prop plist)
+  "Delete by side effect the property PROP from PLIST.
+If PROP is the first property in PLIST, there is no way
+to remove it by side-effect; therefore, write
+\(setq foo (evil-plist-delete :prop foo)) to be sure of
+changing the value of `foo'."
+  (let ((tail plist) elt head)
+    (while tail
+      (setq elt (car tail))
+      (cond
+       ((eq elt prop)
+        (setq tail (cdr (cdr tail)))
+        (if head
+            (setcdr (cdr head) tail)
+          (setq plist tail)))
+       (t
+        (setq head tail
+              tail (cdr (cdr tail))))))
+    plist))
+
+(defun evil-get-property (alist key &optional prop)
+  "Return property PROP for KEY in ALIST.
+ALIST is an association list with entries of the form
+\(KEY . PLIST), where PLIST is a property list.
+If PROP is nil, return all properties for KEY.
+If KEY is t, return an association list of keys
+and their PROP values."
+  (cond
+   ((null prop)
+    (cdr (assq key alist)))
+   ((eq key t)
+    (let (result val)
+      (dolist (entry alist result)
+        (setq key (car entry)
+              val (cdr entry))
+        (when (plist-member val prop)
+          (setq val (plist-get val prop))
+          (push (cons key val) result)))))
+   (t
+    (plist-get (cdr (assq key alist)) prop))))
+
+(defun evil-put-property (alist-var key prop val &rest properties)
+  "Set PROP to VAL for KEY in ALIST-VAR.
+ALIST-VAR points to an association list with entries of the form
+\(KEY . PLIST), where PLIST is a property list storing PROP and VAL."
+  (set alist-var
+       (let* ((alist (symbol-value alist-var))
+              (plist (cdr (assq key alist))))
+         (setq plist (plist-put plist prop val))
+         (when properties
+           (setq plist (evil-concat-plists plist properties)
+                 val (car (last properties))))
+         (setq alist (assq-delete-all key alist))
+         (push (cons key plist) alist)))
+  val)
+
+(defun evil-state-property (state prop &optional value)
+  "Return the value of property PROP for STATE.
+PROP is a keyword as used by `evil-define-state'.
+STATE is the state's symbolic name.
+If VALUE is non-nil and the value is a variable,
+return the value of that variable."
+  (let ((val (evil-get-property evil-state-properties state prop)))
+    (if (and value (symbolp val) (boundp val))
+        (symbol-value val)
+      val)))
+
+(defmacro evil-swap (this that &rest vars)
+  "Swap the values of variables THIS and THAT.
+If three or more arguments are given, the values are rotated.
+E.g., (evil-swap A B C) sets A to B, B to C, and C to A."
+  `(progn
+     (setq ,this (prog1 ,that
+                   (setq ,that ,this)))
+     ,@(when vars
+         `((evil-swap ,that ,@vars)))))
+
+(defmacro evil-sort (min max &rest vars)
+  "Place the smallest value in MIN and the largest in MAX.
+If three or more arguments are given, place the smallest
+value in the first argument and the largest in the last,
+sorting in between."
+  (let ((sorted (make-symbol "sortvar")))
+    `(let ((,sorted (sort (list ,min ,max ,@vars) '<)))
+       (setq ,min (pop ,sorted)
+             ,max (pop ,sorted)
+             ,@(apply #'append
+                      (mapcar #'(lambda (var)
+                                  (list var `(pop ,sorted)))
+                              vars))))))
+
+(defun evil-vector-to-string (vector)
+  "Turns vector into a string, changing <escape> to '\\e'"
+  (mapconcat (lambda (c)
+               (if (equal c 'escape)
+                   "\e"
+                 (make-string 1 c)))
+             vector
+             ""))
+
+;;; Command properties
+
+(defmacro evil-define-command (command &rest body)
+  "Define a command COMMAND.
+
+\(fn COMMAND (ARGS...) DOC [[KEY VALUE]...] BODY...)"
+  (declare (indent defun)
+           (debug (&define name
+                           [&optional lambda-list]
+                           [&optional stringp]
+                           [&rest keywordp sexp]
+                           [&optional ("interactive" [&rest form])]
+                           def-body)))
+  (let ((interactive '(interactive))
+        arg args doc doc-form key keys)
+    ;; collect arguments
+    (when (listp (car-safe body))
+      (setq args (pop body)))
+    ;; collect docstring
+    (when (> (length body) 1)
+      (if (eq (car-safe (car-safe body)) 'format)
+          (setq doc-form (pop body))
+        (when (stringp (car-safe body))
+          (setq doc (pop body)))))
+    ;; collect keywords
+    (setq keys (plist-put keys :repeat t))
+    (while (keywordp (car-safe body))
+      (setq key (pop body)
+            arg (pop body))
+      (unless nil ; TODO: add keyword check
+        (setq keys (plist-put keys key arg))))
+    ;; collect `interactive' form
+    (when (and body (consp (car body))
+               (eq (car (car body)) 'interactive))
+      (let* ((iform (pop body))
+             (result (apply #'evil-interactive-form (cdr iform)))
+             (form (car result))
+             (attrs (cdr result)))
+        (setq interactive `(interactive ,form)
+              keys (evil-concat-plists keys attrs))))
+    `(progn
+       ;; the compiler does not recognize `defun' inside `let'
+       ,(when (and command body)
+          `(defun ,command ,args
+             ,@(when doc `(,doc))
+             ,interactive
+             ,@body))
+       ,(when (and command doc-form)
+          `(put ',command 'function-documentation ,doc-form))
+       ;; set command properties for symbol or lambda function
+       (let ((func ',(if (and (null command) body)
+                         `(lambda ,args
+                            ,interactive
+                            ,@body)
+                       command)))
+         (apply #'evil-set-command-properties func ',keys)
+         func))))
+
+;; If no Evil properties are defined for the command, several parts of
+;; Evil apply certain default rules; e.g., the repeat system decides
+;; whether the command is repeatable by monitoring buffer changes.
+(defun evil-has-command-property-p (command property)
+  "Whether COMMAND has Evil PROPERTY.
+See also `evil-has-command-properties-p'."
+  (plist-member (evil-get-command-properties command) property))
+
+(defun evil-has-command-properties-p (command)
+  "Whether Evil properties are defined for COMMAND.
+See also `evil-has-command-property-p'."
+  (and (evil-get-command-properties command) t))
+
+(defun evil-get-command-property (command property &optional default)
+  "Return the value of Evil PROPERTY of COMMAND.
+If the command does not have the property, return DEFAULT.
+See also `evil-get-command-properties'."
+  (if (evil-has-command-property-p command property)
+      (evil-get-property evil-command-properties command property)
+    default))
+
+(defun evil-get-command-properties (command)
+  "Return all Evil properties of COMMAND.
+See also `evil-get-command-property'."
+  (evil-get-property evil-command-properties command))
+
+(defun evil-set-command-property (command property value)
+  "Set PROPERTY to VALUE for COMMAND.
+To set multiple properties at once, see
+`evil-set-command-properties' and `evil-add-command-properties'."
+  (evil-put-property 'evil-command-properties command property value))
+(defalias 'evil-put-command-property 'evil-set-command-property)
+
+(defun evil-add-command-properties (command &rest properties)
+  "Add PROPERTIES to COMMAND.
+PROPERTIES should be a property list.
+To replace all properties at once, use `evil-set-command-properties'."
+  (apply #'evil-put-property
+         'evil-command-properties command properties))
+
+(defun evil-set-command-properties (command &rest properties)
+  "Replace all of COMMAND's properties with PROPERTIES.
+PROPERTIES should be a property list.
+This erases all previous properties; to only add properties,
+use `evil-set-command-property'."
+  (setq evil-command-properties
+        (assq-delete-all command evil-command-properties))
+  (when properties
+    (apply #'evil-add-command-properties command properties)))
+
+(defun evil-remove-command-properties (command &rest properties)
+  "Remove PROPERTIES from COMMAND.
+PROPERTIES should be a list of properties (:PROP1 :PROP2 ...).
+If PROPERTIES is the empty list, all properties are removed."
+  (let (plist)
+    (when properties
+      (setq plist (evil-get-command-properties command))
+      (dolist (property properties)
+        (setq plist (evil-plist-delete property plist))))
+    (apply #'evil-set-command-properties command plist)))
+
+(defun evil-yank-handler (&optional motion)
+  "Return the yank handler for MOTION.
+MOTION defaults to the current motion."
+  (setq motion (or motion evil-this-motion))
+  (evil-get-command-property motion :yank-handler))
+
+(defun evil-declare-motion (command)
+  "Declare COMMAND to be a movement function.
+This ensures that it behaves correctly in Visual state."
+  (evil-add-command-properties command :keep-visual t :repeat 'motion))
+
+(defun evil-declare-repeat (command)
+  "Declare COMMAND to be repeatable."
+  (evil-add-command-properties command :repeat t))
+
+(defun evil-declare-not-repeat (command)
+  "Declare COMMAND to be nonrepeatable."
+  (evil-add-command-properties command :repeat nil))
+
+(defun evil-declare-ignore-repeat (command)
+  "Declare COMMAND to be nonrepeatable."
+  (evil-add-command-properties command :repeat 'ignore))
+
+(defun evil-declare-change-repeat (command)
+  "Declare COMMAND to be repeatable by buffer changes."
+  (evil-add-command-properties command :repeat 'change))
+
+(defun evil-declare-insert-at-point-repeat (command)
+  "Declare COMMAND to be repeatable by buffer changes."
+  (evil-add-command-properties command :repeat 'insert-at-point))
+
+(defun evil-declare-abort-repeat (command)
+  "Declare COMMAND to be nonrepeatable."
+  (evil-add-command-properties command :repeat 'abort))
+
+(defun evil-delimited-arguments (string &optional num)
+  "Parse STRING as a sequence of delimited arguments.
+Returns a list of NUM strings, or as many arguments as
+the string contains. The first non-blank character is
+taken to be the delimiter. If some arguments are missing
+from STRING, the resulting list is padded with nil values.
+Two delimiters following directly after each other gives
+an empty string."
+  (save-match-data
+    (let ((string (or string ""))
+          (count (or num -1)) (idx 0)
+          argument delim match result)
+      (when (string-match "^[[:space:]]*\\([^[:space:]]\\)" string)
+        (setq delim (match-string 1 string)
+              argument (format "%s\\(\\(?:[\\].\\|[^%s]\\)*\\)"
+                               (regexp-quote delim)
+                               delim))
+        (while (and (/= count 0) (string-match argument string idx))
+          (setq match (match-string 1 string)
+                idx (match-end 1)
+                count (1- count))
+          (when (= count 0)
+            (unless (save-match-data
+                      (string-match
+                       (format "%s[[:space:]]*$" delim) string idx))
+              (setq match (substring string (match-beginning 1)))))
+          (unless (and (zerop (length match))
+                       (zerop (length (substring string idx))))
+            (push match result))))
+      (when (and num (< (length result) num))
+        (dotimes (i (- num (length result)))
+          (push nil result)))
+      (nreverse result))))
+
+(defun evil-concat-charsets (&rest sets)
+  "Concatenate character sets.
+A character set is the part between [ and ] in a regular expression.
+If any character set is complemented, the result is also complemented."
+  (let ((bracket "") (complement "") (hyphen "") result)
+    (save-match-data
+      (dolist (set sets)
+        (when (string-match-p "^\\^" set)
+          (setq set (substring set 1)
+                complement "^"))
+        (when (string-match-p "^]" set)
+          (setq set (substring set 1)
+                bracket "]"))
+        (when (string-match-p "^-" set)
+          (setq set (substring set 1)
+                hyphen "-"))
+        (setq result (concat result set)))
+      (format "%s%s%s%s" complement bracket hyphen result))))
+
+;;; Key sequences
+
+(defun evil-keypress-parser (&optional input)
+  "Read from keyboard or INPUT and build a command description.
+Returns (CMD COUNT), where COUNT is the numeric prefix argument.
+Both COUNT and CMD may be nil."
+  (let (count negative)
+    (when input (setq unread-command-events (append input unread-command-events)))
+    (catch 'done
+      (while t
+        (let ((seq (read-key-sequence "")))
+          (when seq
+            (let ((cmd (key-binding seq)))
+              (cond
+               ((null cmd) (throw 'done (list nil nil)))
+               ((arrayp cmd) ; keyboard macro, recursive call
+                (let ((cmd (evil-keypress-parser cmd)))
+                  (throw 'done
+                         (list (car cmd)
+                               (if (or count (cadr cmd))
+                                   (list (car cmd) (* (or count 1)
+                                                      (or (cadr cmd) 1))))))))
+               ((or (eq cmd #'digit-argument)
+                    (and (eq cmd 'evil-digit-argument-or-evil-beginning-of-line)
+                         count))
+                (let* ((event (aref seq (- (length seq) 1)))
+                       (char (or (when (characterp event) event)
+                                 (when (symbolp event)
+                                   (get event 'ascii-character))))
+                       (digit (if (or (characterp char) (integerp char))
+                                  (- (logand char ?\177) ?0))))
+                  (setq count (+ (* 10 (or count 0)) digit))))
+               ((eq cmd #'negative-argument)
+                (setq negative (not negative)))
+               (t
+                (throw 'done (list cmd
+                                   (and count
+                                        (* count
+                                           (if negative -1 1))))))))))))))
+
+(defun evil-read-key (&optional prompt)
+  "Read a key from the keyboard.
+Translates it according to the input method."
+  (let ((old-global-map (current-global-map))
+        (new-global-map (make-sparse-keymap))
+        (overriding-terminal-local-map nil)
+        (overriding-local-map evil-read-key-map)
+        seq char cmd)
+    (unwind-protect
+        (condition-case nil
+            (progn
+              (define-key new-global-map [menu-bar]
+                (lookup-key global-map [menu-bar]))
+              (define-key new-global-map [tool-bar]
+                (lookup-key global-map [tool-bar]))
+              (add-to-list 'new-global-map
+                           (make-char-table 'display-table
+                                            'self-insert-command) t)
+              (use-global-map new-global-map)
+              (setq seq (read-key-sequence prompt nil t)
+                    char (aref seq 0)
+                    cmd (key-binding seq))
+              (while (arrayp cmd)
+                (setq char (aref cmd 0)
+                      cmd (key-binding cmd)))
+              (cond
+               ((eq cmd 'self-insert-command)
+                char)
+               (cmd
+                (call-interactively cmd))
+               (t
+                (user-error "No replacement character typed"))))
+          (quit
+           (when (fboundp 'evil-repeat-abort)
+             (evil-repeat-abort))
+           (signal 'quit nil)))
+      (use-global-map old-global-map))))
+
+(defun evil-read-quoted-char ()
+  "Command that calls `read-quoted-char'.
+This command can be used wherever `read-quoted-char' is required
+as a command. Its main use is in the `evil-read-key-map'."
+  (interactive)
+  (read-quoted-char))
+
+(defun evil-read-digraph-char (&optional hide-chars)
+  "Read two keys from keyboard forming a digraph.
+This function creates an overlay at (point), hiding the next
+HIDE-CHARS characters. HIDE-CHARS defaults to 1."
+  (interactive)
+  (let (char1 char2 string overlay)
+    (unwind-protect
+        (progn
+          (setq overlay (make-overlay (point)
+                                      (min (point-max)
+                                           (+ (or hide-chars 1)
+                                              (point)))))
+          (overlay-put overlay 'invisible t)
+          ;; create overlay prompt
+          (setq string "?")
+          (put-text-property 0 1 'face 'minibuffer-prompt string)
+          ;; put cursor at (i.e., right before) the prompt
+          (put-text-property 0 1 'cursor t string)
+          (overlay-put overlay 'after-string string)
+          (setq char1 (read-key))
+          (setq string (string char1))
+          (put-text-property 0 1 'face 'minibuffer-prompt string)
+          (put-text-property 0 1 'cursor t string)
+          (overlay-put overlay 'after-string string)
+          (setq char2 (read-key)))
+      (delete-overlay overlay))
+    (or (evil-digraph (list char1 char2))
+        ;; use the last character if undefined
+        char2)))
+
+(defun evil-read-motion (&optional motion count type modifier)
+  "Read a MOTION, motion COUNT and motion TYPE from the keyboard.
+The type may be overridden with MODIFIER, which may be a type
+or a Visual selection as defined by `evil-define-visual-selection'.
+Return a list (MOTION COUNT [TYPE])."
+  (let ((modifiers '((evil-visual-char . char)
+                     (evil-visual-line . line)
+                     (evil-visual-block . block)))
+        command prefix)
+    (setq evil-this-type-modified nil)
+    (unless motion
+      (while (progn
+               (setq command (evil-keypress-parser)
+                     motion (pop command)
+                     prefix (pop command))
+               (when prefix
+                 (if count
+                     (setq count (string-to-number
+                                  (concat (number-to-string count)
+                                          (number-to-string prefix))))
+                   (setq count prefix)))
+               ;; if the command is a type modifier, read more
+               (when (rassq motion evil-visual-alist)
+                 (setq modifier
+                       (or modifier
+                           (car (rassq motion evil-visual-alist))))))))
+    (when modifier
+      (setq type (or type (evil-type motion 'exclusive)))
+      (cond
+       ((eq modifier 'char)
+        ;; TODO: this behavior could be less hard-coded
+        (if (eq type 'exclusive)
+            (setq type 'inclusive)
+          (setq type 'exclusive)))
+       (t
+        (setq type modifier)))
+      (setq evil-this-type-modified type))
+    (list motion count type)))
+
+(defun evil-mouse-events-p (keys)
+  "Returns non-nil iff KEYS contains a mouse event."
+  (catch 'done
+    (dotimes (i (length keys))
+      (when (or (and (fboundp 'mouse-event-p)
+                     (mouse-event-p (aref keys i)))
+                (mouse-movement-p (aref keys i)))
+        (throw 'done t)))
+    nil))
+
+(defun evil-extract-count (keys)
+  "Splits the key-sequence KEYS into prefix-argument and the rest.
+Returns the list (PREFIX CMD SEQ REST), where PREFIX is the
+prefix count, CMD the command to be executed, SEQ the subsequence
+calling CMD, and REST is all remaining events in the
+key-sequence. PREFIX and REST may be nil if they do not exist.
+If a command is bound to some keyboard macro, it is expanded
+recursively."
+  (catch 'done
+    (let* ((len (length keys))
+           (beg 0)
+           (end 1)
+           (found-prefix nil))
+      (while (and (<= end len))
+        (let ((cmd (key-binding (substring keys beg end))))
+          (cond
+           ((memq cmd '(undefined nil))
+            (user-error "No command bound to %s" (substring keys beg end)))
+           ((arrayp cmd) ; keyboard macro, replace command with macro
+            (setq keys (vconcat (substring keys 0 beg)
+                                cmd
+                                (substring keys end))
+                  end (1+ beg)
+                  len (length keys)))
+           ((functionp cmd)
+            (if (or (memq cmd '(digit-argument negative-argument))
+                    (and found-prefix
+                         (evil-get-command-property
+                          cmd :digit-argument-redirection)))
+                ;; skip those commands
+                (setq found-prefix t ; found at least one prefix argument
+                      beg end
+                      end (1+ end))
+              ;; a real command, finish
+              (throw 'done
+                     (list (unless (zerop beg)
+                             (string-to-number
+                              (concat (substring keys 0 beg))))
+                           cmd
+                           (substring keys beg end)
+                           (when (< end len)
+                             (substring keys end))))))
+           (t ; append a further event
+            (setq end (1+ end))))))
+      (user-error "Key sequence contains no complete binding"))))
+
+(defmacro evil-redirect-digit-argument (map keys target)
+  "Bind a wrapper function calling TARGET or `digit-argument'.
+MAP is a keymap for binding KEYS to the wrapper for TARGET.
+The wrapper only calls `digit-argument' if a prefix-argument
+has already been started; otherwise TARGET is called."
+  (let* ((target (eval target))
+         (wrapper (intern (format "evil-digit-argument-or-%s"
+                                  target))))
+    `(progn
+       (define-key ,map ,keys ',wrapper)
+       (evil-define-command ,wrapper ()
+         :digit-argument-redirection ,target
+         :keep-visual t
+         :repeat nil
+         (interactive)
+         (cond
+          (current-prefix-arg
+           (setq this-command #'digit-argument)
+           (call-interactively #'digit-argument))
+          (t
+           (let ((target (or (command-remapping #',target)
+                             #',target)))
+             (setq this-command target)
+             (call-interactively target))))))))
+
+(defun evil-extract-append (file-or-append)
+  "Return an (APPEND . FILENAME) pair based on FILE-OR-APPEND.
+FILE-OR-APPEND should either be a filename or a \">> FILE\"
+directive.  APPEND will be t if FILE-OR-APPEND is an append
+directive and nil otherwise.  FILENAME will be the extracted
+filename."
+  (if (and (stringp file-or-append)
+           (string-match "\\(>> *\\)" file-or-append))
+      (cons t (substring file-or-append(match-end 1)))
+    (cons nil file-or-append)))
+
+(defun evil-set-keymap-prompt (map prompt)
+  "Set the prompt-string of MAP to PROMPT."
+  (delq (keymap-prompt map) map)
+  (when prompt
+    (setcdr map (cons prompt (cdr map)))))
+
+(defun evil-lookup-key (map key)
+  "Returns non-nil value if KEY is bound in MAP."
+  (let ((definition (lookup-key map key)))
+    (if (numberp definition) ; in-band error
+        nil
+      definition)))
+
+;;; Display
+
+(defun evil-set-cursor (specs)
+  "Change the cursor's apperance according to SPECS.
+SPECS may be a cursor type as per `cursor-type', a color
+string as passed to `set-cursor-color', a zero-argument
+function for changing the cursor, or a list of the above."
+  (unless (and (listp specs)
+               (null (cdr-safe (last specs))))
+    (setq specs (list specs)))
+  (dolist (spec specs)
+    (cond
+     ((functionp spec)
+      (condition-case nil
+          (funcall spec)
+        (error nil)))
+     ((stringp spec)
+      (evil-set-cursor-color spec))
+     (t
+      (setq cursor-type spec)))))
+
+(defun evil-set-cursor-color (color)
+  "Set the cursor color to COLOR."
+  (unless (equal (frame-parameter nil 'cursor-color) color)
+    ;; `set-cursor-color' forces a redisplay, so only
+    ;; call it when the color actually changes
+    (set-cursor-color color)))
+
+(defun evil-refresh-cursor (&optional state buffer)
+  "Refresh the cursor for STATE in BUFFER.
+BUFFER defaults to the current buffer.  If STATE is nil the
+cursor type is either `evil-force-cursor' or the current state."
+  (when (and (boundp 'evil-local-mode) evil-local-mode)
+    (let* ((state (or state evil-force-cursor evil-state 'normal))
+           (default (or evil-default-cursor t))
+           (cursor (evil-state-property state :cursor t))
+           (color (or (and (stringp cursor) cursor)
+                      (and (listp cursor)
+                           (evil-member-if #'stringp cursor))
+                      (frame-parameter nil 'cursor-color))))
+      (with-current-buffer (or buffer (current-buffer))
+        ;; if both STATE and `evil-default-cursor'
+        ;; specify a color, don't set it twice
+        (when (and color (listp default))
+          (setq default (evil-filter-list #'stringp default)))
+        (evil-set-cursor default)
+        (evil-set-cursor cursor)))))
+
+(defmacro evil-save-cursor (&rest body)
+  "Save the current cursor; execute BODY; restore the cursor."
+  (declare (indent defun)
+           (debug t))
+  `(let ((cursor cursor-type)
+         (color (frame-parameter (selected-frame) 'cursor-color))
+         (inhibit-quit t))
+     (unwind-protect
+         (progn ,@body)
+       (evil-set-cursor cursor)
+       (evil-set-cursor color))))
+
+(defun evil-echo (string &rest args)
+  "Display an unlogged message in the echo area.
+That is, the message is not logged in the *Messages* buffer.
+\(To log the message, just use `message'.)"
+  (unless evil-no-display
+    (let (message-log-max)
+      (apply #'message string args))))
+
+(defun evil-echo-area-save ()
+  "Save the current echo area in `evil-echo-area-message'."
+  (setq evil-echo-area-message (current-message)))
+
+(defun evil-echo-area-restore ()
+  "Restore the echo area from `evil-echo-area-message'.
+Does not restore if `evil-write-echo-area' is non-nil."
+  (unless evil-write-echo-area
+    (if evil-echo-area-message
+        (message "%s" evil-echo-area-message)
+      (message nil)))
+  (setq evil-echo-area-message nil
+        evil-write-echo-area nil))
+
+;; toggleable version of `with-temp-message'
+(defmacro evil-save-echo-area (&rest body)
+  "Save the echo area; execute BODY; restore the echo area.
+Intermittent messages are not logged in the *Messages* buffer."
+  (declare (indent defun)
+           (debug t))
+  `(let ((inhibit-quit t)
+         evil-echo-area-message
+         evil-write-echo-area)
+     (unwind-protect
+         (progn
+           (evil-echo-area-save)
+           ,@body)
+       (evil-echo-area-restore))))
+
+(defmacro evil-without-display (&rest body)
+  "Execute BODY without Evil displays.
+Inhibits echo area messages, mode line updates and cursor changes."
+  (declare (indent defun)
+           (debug t))
+  `(let ((evil-no-display t))
+     ,@body))
+
+(defun evil-num-visible-lines ()
+  "Returns the number of currently visible lines."
+  (- (window-height) 1))
+
+(defun evil-count-lines (beg end)
+  "Return absolute line-number-difference betweeen `beg` and `end`.
+This should give the same results no matter where on the line `beg`
+and `end` are."
+  (if (= beg end)
+      0
+    (let* ((last (max beg end))
+           (end-at-bol (save-excursion (goto-char last)
+                                       (bolp))))
+      (if end-at-bol
+          (count-lines beg end)
+        (1- (count-lines beg end))))))
+
+;;; Movement
+
+(defun evil-normalize-position (pos)
+  "Return POS if it does not exceed the buffer boundaries.
+If POS is less than `point-min', return `point-min'.
+Is POS is more than `point-max', return `point-max'.
+If POS is a marker, return its position."
+  (cond
+   ((not (number-or-marker-p pos))
+    pos)
+   ((< pos (point-min))
+    (point-min))
+   ((> pos (point-max))
+    (point-max))
+   ((markerp pos)
+    (marker-position pos))
+   (t
+    pos)))
+
+(defmacro evil-save-goal-column (&rest body)
+  "Restores the goal column after execution of BODY.
+See also `evil-save-column'."
+  (declare (indent defun)
+           (debug t))
+  `(let ((goal-column goal-column)
+         (temporary-goal-column temporary-goal-column))
+     ,@body))
+
+(defmacro evil-save-column (&rest body)
+  "Restores the column after execution of BODY.
+See also `evil-save-goal-column'."
+  (declare (indent defun)
+           (debug t))
+  `(let ((col (current-column)))
+     (evil-save-goal-column
+       ,@body
+       (move-to-column col))))
+
+(defun evil-narrow (beg end)
+  "Restrict the buffer to BEG and END.
+BEG or END may be nil, specifying a one-sided restriction including
+`point-min' or `point-max'. See also `evil-with-restriction.'"
+  (setq beg (or (evil-normalize-position beg) (point-min)))
+  (setq end (or (evil-normalize-position end) (point-max)))
+  (narrow-to-region beg end))
+
+(defmacro evil-with-restriction (beg end &rest body)
+  "Execute BODY with the buffer narrowed to BEG and END.
+BEG or END may be nil as passed to `evil-narrow'; this creates
+a one-sided restriction."
+  (declare (indent 2)
+           (debug t))
+  `(save-restriction
+     (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."
+  (declare (indent defun)
+           (debug t))
+  `(evil-with-restriction (field-beginning) (field-end)
+     ,@body))
+
+(defun evil-move-beginning-of-line (&optional arg)
+  "Move to the beginning of the line as displayed.
+Like `move-beginning-of-line', but retains the goal column."
+  (evil-save-goal-column
+    (move-beginning-of-line arg)
+    (beginning-of-line)))
+
+(defun evil-move-end-of-line (&optional arg)
+  "Move to the end of the line as displayed.
+Like `move-end-of-line', but retains the goal column."
+  (evil-save-goal-column
+    (move-end-of-line arg)
+    (end-of-line)))
+
+(defun evil-adjust-cursor (&optional force)
+  "Move point one character back if at the end of a non-empty line.
+This behavior is contingent on the variable `evil-move-cursor-back';
+use the FORCE parameter to override it."
+  (when (and (eolp)
+             (not evil-move-beyond-eol)
+             (not (bolp))
+             (= (point)
+                (save-excursion
+                  (evil-move-end-of-line)
+                  (point))))
+    (evil-move-cursor-back force)))
+
+(defun evil-move-cursor-back (&optional force)
+  "Move point one character back within the current line.
+Contingent on the variable `evil-move-cursor-back' or the FORCE
+argument. Honors field boundaries, i.e., constrains the movement
+to the current field as recognized by `line-beginning-position'."
+  (when (or evil-move-cursor-back force)
+    (unless (or (= (point) (line-beginning-position))
+                (and (boundp 'visual-line-mode)
+                     visual-line-mode
+                     (= (point) (save-excursion
+                                  (beginning-of-visual-line)
+                                  (point)))))
+      (backward-char))))
+
+(defun evil-line-position (line &optional column)
+  "Return the position of LINE.
+If COLUMN is specified, return its position on the line.
+A negative number means the end of the line."
+  (save-excursion
+    (when (fboundp 'evil-goto-line)
+      (evil-goto-line line))
+    (if (numberp column)
+        (if (< column 0)
+            (beginning-of-line 2)
+          (move-to-column column))
+      (beginning-of-line))
+    (point)))
+
+(defun evil-column (&optional pos)
+  "Return the horizontal position of POS.
+POS defaults to point."
+  (save-excursion
+    (when pos
+      (goto-char pos))
+    (current-column)))
+
+(defun evil-move-to-column (column &optional dir force)
+  "Move point to column COLUMN in the current line.
+Places point at left of the tab character (at the right if DIR
+is non-nil) and returns point."
+  (interactive "p")
+  (move-to-column column force)
+  (unless force
+    (when (or (not dir) (and (numberp dir) (< dir 1)))
+      (when (> (current-column) column)
+        (evil-move-cursor-back))))
+  (point))
+
+(defmacro evil-loop (spec &rest body)
+  "Loop with countdown variable.
+Evaluate BODY with VAR counting down from COUNT to 0.
+COUNT can be negative, in which case VAR counts up instead.
+The return value is the value of VAR when the loop
+terminates, which is 0 if the loop completes successfully.
+RESULT specifies a variable for storing this value.
+
+\(fn (VAR COUNT [RESULT]) BODY...)"
+  (declare (indent defun)
+           (debug dolist))
+  (let* ((i (make-symbol "loopvar"))
+         (var (pop spec))
+         (count (pop spec))
+         (result (pop spec)))
+    (setq var (or (unless (eq var result) var) i)
+          result (or result var))
+    `(let ((,var ,count))
+       (setq ,result ,var)
+       (while (/= ,var 0)
+         ,@body
+         (if (> ,var 0)
+             (setq ,var (1- ,var))
+           (setq ,var (1+ ,var)))
+         (setq ,result ,var))
+       ,var)))
+
+;;; Motions
+
+(defmacro evil-motion-loop (spec &rest body)
+  "Loop a certain number of times.
+Evaluate BODY repeatedly COUNT times with VAR bound to 1 or -1,
+depending on the sign of COUNT. RESULT, if specified, holds
+the number of unsuccessful iterations, which is 0 if the loop
+completes successfully. This is also the return value.
+
+Each iteration must move point; if point does not change,
+the loop immediately quits. See also `evil-loop'.
+
+\(fn (VAR COUNT [RESULT]) BODY...)"
+  (declare (indent defun)
+           (debug ((symbolp form &optional symbolp) body)))
+  (let* ((var (or (pop spec) (make-symbol "unitvar")))
+         (countval (or (pop spec) 0))
+         (result (pop spec))
+         (i (make-symbol "loopvar"))
+         (count (make-symbol "countvar"))
+         (done (make-symbol "donevar"))
+         (orig (make-symbol "origvar")))
+    `(let* ((,count ,countval)
+            (,var (if (< ,count 0) -1 1)))
+       (catch ',done
+         (evil-loop (,i ,count ,result)
+           (let ((,orig (point)))
+             ,@body
+             (when (= (point) ,orig)
+               (throw ',done ,i))))))))
+
+(defmacro evil-signal-without-movement (&rest body)
+  "Catches errors provided point moves within this scope."
+  (declare (indent defun)
+           (debug t))
+  `(let ((p (point)))
+     (condition-case err
+         (progn ,@body)
+       (error
+        (when (= p (point))
+          (signal (car err) (cdr err)))))))
+
+(defun evil-signal-at-bob-or-eob (&optional count)
+  "Signals error if `point' is at boundaries.
+If `point' is at bob and COUNT is negative this function signal
+'beginning-of-buffer. If `point' is at eob and COUNT is positive
+this function singal 'end-of-buffer. This function should be used
+in motions. COUNT defaults to 1."
+  (setq count (or count 1))
+  (cond
+   ((< count 0) (evil-signal-at-bob))
+   ((> count 0) (evil-signal-at-eob))))
+
+(defun evil-signal-at-bob ()
+  "Signals 'beginning-of-buffer if `point' is at bob.
+This function should be used in backward motions. If `point' is at
+bob so that no further backward motion is possible the error
+'beginning-of-buffer is raised."
+  (when (bobp) (signal 'beginning-of-buffer nil)))
+
+(defun evil-signal-at-eob ()
+  "Signals 'end-of-buffer if `point' is at eob.
+This function should be used in forward motions. If `point' is close
+to eob so that no further forward motion is possible the error
+'end-of-buffer is raised. This is the case if `point' is at
+`point-max' or if is one position before `point-max',
+`evil-move-cursor-back' is non-nil and `point' is not at the end
+of a line. The latter is necessary because `point' cannot be
+moved to `point-max' if `evil-move-cursor-back' is non-nil and
+the last line in the buffer is not empty."
+  (when (or (eobp)
+            (and (not (eolp))
+                 evil-move-cursor-back
+                 (save-excursion (forward-char) (eobp))))
+    (signal 'end-of-buffer nil)))
+
+(defmacro evil-with-hproject-point-on-window (&rest body)
+  "Project point after BODY to current window.
+If point is on a position left or right of the current window
+then it is moved to the left and right boundary of the window,
+respectively. If `auto-hscroll-mode' is non-nil then the left and
+right positions are increased or decreased, respectively, by
+`horizontal-margin' so that no automatic scrolling occurs."
+  (declare (indent defun)
+           (debug t))
+  (let ((diff (make-symbol "diff"))
+        (left (make-symbol "left"))
+        (right (make-symbol "right")))
+    `(let ((,diff (if auto-hscroll-mode (1+ hscroll-margin) 0))
+           auto-hscroll-mode)
+       ,@body
+       (let* ((,left (+ (window-hscroll) ,diff))
+              (,right (+ (window-hscroll) (window-width) (- ,diff) -1)))
+         (move-to-column (min (max (current-column) ,left) ,right))))))
+
+(defun evil-goto-min (&rest positions)
+  "Go to the smallest position in POSITIONS.
+Non-numerical elements are ignored.
+See also `evil-goto-max'."
+  (when (setq positions (evil-filter-list
+                         #'(lambda (elt)
+                             (not (number-or-marker-p elt)))
+                         positions))
+    (goto-char (apply #'min positions))))
+
+(defun evil-goto-max (&rest positions)
+  "Go to the largest position in POSITIONS.
+Non-numerical elements are ignored.
+See also `evil-goto-min'."
+  (when (setq positions (evil-filter-list
+                         #'(lambda (elt)
+                             (not (number-or-marker-p elt)))
+                         positions))
+    (goto-char (apply #'max positions))))
+
+(defun evil-forward-not-thing (thing &optional count)
+  "Move point to the end or beginning of the complement of THING."
+  (evil-motion-loop (dir (or count 1))
+    (let (bnd)
+      (cond
+       ((> dir 0)
+        (while (and (setq bnd (bounds-of-thing-at-point thing))
+                    (< (point) (cdr bnd)))
+          (goto-char (cdr bnd)))
+        ;; no thing at (point)
+        (if (zerop (forward-thing thing))
+            ;; now at the end of the next thing
+            (let ((bnd (bounds-of-thing-at-point thing)))
+              (if (or (< (car bnd) (point))    ; end of a thing
+                      (= (car bnd) (cdr bnd))) ; zero width thing
+                  (goto-char (car bnd))
+                ;; beginning of yet another thing, go back
+                (forward-thing thing -1)))
+          (goto-char (point-max))))
+       (t
+        (while (and (not (bobp))
+                    (or (backward-char) t)
+                    (setq bnd (bounds-of-thing-at-point thing))
+                    (< (point) (cdr bnd)))
+          (goto-char (car bnd)))
+        ;; either bob or no thing at point
+        (goto-char
+         (if (and (not (bobp))
+                  (zerop (forward-thing thing -1))
+                  (setq bnd (bounds-of-thing-at-point thing)))
+             (cdr bnd)
+           (point-min))))))))
+
+(defun evil-bounds-of-not-thing-at-point (thing &optional which)
+  "Returns the bounds of a complement of THING at point.
+If there is a THING at point nil is returned.  Otherwise if WHICH
+is nil or 0 a cons cell (BEG . END) is returned. If WHICH is
+negative the beginning is returned. If WHICH is positive the END
+is returned."
+  (let ((pnt (point)))
+    (let ((beg (save-excursion
+                 (and (zerop (forward-thing thing -1))
+                      (forward-thing thing))
+                 (if (> (point) pnt) (point-min) (point))))
+          (end (save-excursion
+                 (and (zerop (forward-thing thing))
+                      (forward-thing thing -1))
+                 (if (< (point) pnt) (point-max) (point)))))
+      (when (and (<= beg (point)) (<= (point) end) (< beg end))
+        (cond
+         ((or (not which) (zerop which)) (cons beg end))
+         ((< which 0) beg)
+         ((> which 0) end))))))
+
+(defun evil-forward-nearest (count &rest forwards)
+  "Moves point forward to the first of several motions.
+FORWARDS is a list of forward motion functions (i.e. each moves
+point forward to the next end of a text object (if passed a +1)
+or backward to the preceeding beginning of a text object (if
+passed a -1)). This function calls each of these functions once
+and moves point to the nearest of the resulting positions. If
+COUNT is positive point is moved forward COUNT times, if negative
+point is moved backward -COUNT times."
+  (evil-motion-loop (dir (or count 1))
+    (let ((pnt (point))
+          (nxt (if (> dir 0) (point-max) (point-min))))
+      (dolist (fwd forwards)
+        (goto-char pnt)
+        (condition-case nil
+            (evil-with-restriction
+                (and (< dir 0)
+                     (save-excursion
+                       (goto-char nxt)
+                       (line-beginning-position 0)))
+                (and (> dir 0)
+                     (save-excursion
+                       (goto-char nxt)
+                       (line-end-position 2)))
+              (if (and (zerop (funcall fwd dir))
+                       (/= (point) pnt)
+                       (or (and (> dir 0) (< (point) nxt))
+                           (and (< dir 0) (> (point) nxt))))
+                  (setq nxt (point))))
+          (error)))
+      (goto-char nxt))))
+
+(defun bounds-of-evil-string-at-point (&optional state)
+  "Return the bounds of a string at point.
+If STATE is given it used a parsing state at point."
+  (save-excursion
+    (let ((state (or state (syntax-ppss))))
+      (and (nth 3 state)
+           (cons (nth 8 state)
+                 (and (parse-partial-sexp (point)
+                                          (point-max)
+                                          nil
+                                          nil
+                                          state
+                                          'syntax-table)
+                      (point)))))))
+(put 'evil-string 'bounds-of-thing-at-point #'bounds-of-evil-string-at-point)
+
+(defun bounds-of-evil-comment-at-point ()
+  "Return the bounds of a string at point."
+  (save-excursion
+    (let ((state (syntax-ppss)))
+      (and (nth 4 state)
+           (cons (nth 8 state)
+                 (and (parse-partial-sexp (point)
+                                          (point-max)
+                                          nil
+                                          nil
+                                          state
+                                          'syntax-table)
+                      (point)))))))
+(put 'evil-comment 'bounds-of-thing-at-point #'bounds-of-evil-comment-at-point)
+
+;; The purpose of this function is the provide line motions which
+;; preserve the column. This is how `previous-line' and `next-line'
+;; work, but unfortunately the behaviour is hard-coded: if and only if
+;; the last command was `previous-line' or `next-line', the column is
+;; preserved. Furthermore, in contrast to Vim, when we cannot go
+;; further, those motions move point to the beginning resp. the end of
+;; the line (we never want point to leave its column). The code here
+;; comes from simple.el, and I hope it will work in future.
+(defun evil-line-move (count &optional noerror)
+  "A wrapper for line motions which conserves the column.
+Signals an error at buffer boundaries unless NOERROR is non-nil."
+  (cond
+   (noerror
+    (condition-case nil
+        (evil-line-move count)
+      (error nil)))
+   (t
+    (evil-signal-without-movement
+      (setq this-command (if (>= count 0)
+                             #'next-line
+                           #'previous-line))
+      (let ((opoint (point)))
+        (condition-case err
+            (with-no-warnings
+              (funcall this-command (abs count)))
+          ((beginning-of-buffer end-of-buffer)
+           (let ((col (or goal-column
+                          (if (consp temporary-goal-column)
+                              (car temporary-goal-column)
+                            temporary-goal-column))))
+             (if line-move-visual
+                 (vertical-motion (cons col 0))
+               (line-move-finish col opoint (< count 0)))
+             ;; Maybe we should just `ding'?
+             (signal (car err) (cdr err))))))))))
+
+(defun evil-forward-syntax (syntax &optional count)
+  "Move point to the end or beginning of a sequence of characters in
+SYNTAX.
+Stop on reaching a character not in SYNTAX."
+  (let ((notsyntax (if (= (aref syntax 0) ?^)
+                       (substring syntax 1)
+                     (concat "^" syntax))))
+    (evil-motion-loop (dir (or count 1))
+      (cond
+       ((< dir 0)
+        (skip-syntax-backward notsyntax)
+        (skip-syntax-backward syntax))
+       (t
+        (skip-syntax-forward notsyntax)
+        (skip-syntax-forward syntax))))))
+
+(defun evil-forward-chars (chars &optional count)
+  "Move point to the end or beginning of a sequence of CHARS.
+CHARS is a character set as inside [...] in a regular expression."
+  (let ((notchars (if (= (aref chars 0) ?^)
+                      (substring chars 1)
+                    (concat "^" chars))))
+    (evil-motion-loop (dir (or count 1))
+      (cond
+       ((< dir 0)
+        (skip-chars-backward notchars)
+        (skip-chars-backward chars))
+       (t
+        (skip-chars-forward notchars)
+        (skip-chars-forward chars))))))
+
+(defun evil-up-block (beg end &optional count)
+  "Move point to the end or beginning of text enclosed by BEG and END.
+BEG and END should be regular expressions matching the opening
+and closing delimiters, respectively. If COUNT is greater than
+zero point is moved forward otherwise it is moved
+backwards. Whenever an opening delimiter is found the COUNT is
+increased by one, if a closing delimiter is found the COUNT is
+decreased by one. The motion stops when COUNT reaches zero. The
+match-data reflects the last successful match (that caused COUNT
+to reach zero). The behaviour of this functions is similar to
+`up-list'."
+  (let* ((count (or count 1))
+         (forwardp (> count 0))
+         (dir (if forwardp +1 -1)))
+    (catch 'done
+      (while (not (zerop count))
+        (let* ((pnt (point))
+               (cl (save-excursion
+                     (and (re-search-forward (if forwardp end beg) nil t dir)
+                          (or (/= pnt (point))
+                              (progn
+                                ;; zero size match, repeat search from
+                                ;; the next position
+                                (forward-char dir)
+                                (re-search-forward (if forwardp end beg) nil t dir)))
+                          (point))))
+               (match (match-data t))
+               (op (save-excursion
+                     (and (not (equal beg end))
+                          (re-search-forward (if forwardp beg end) cl t dir)
+                          (or (/= pnt (point))
+                              (progn
+                                ;; zero size match, repeat search from
+                                ;; the next position
+                                (forward-char dir)
+                                (re-search-forward (if forwardp beg end) cl t dir)))
+                          (point)))))
+          (cond
+           ((not cl)
+            (goto-char (if forwardp (point-max) (point-min)))
+            (set-match-data nil)
+            (throw 'done count))
+           (t
+            (if op
+                (progn
+                  (setq count (if forwardp (1+ count) (1- count)))
+                  (goto-char op))
+              (setq count (if forwardp (1- count) (1+ count)))
+              (if (zerop count) (set-match-data match))
+              (goto-char cl))))))
+      0)))
+
+(defun evil-up-paren (open close &optional count)
+  "Move point to the end or beginning of balanced parentheses.
+OPEN and CLOSE should be characters identifying the opening and
+closing parenthesis, respectively. If COUNT is greater than zero
+point is moved forward otherwise it is moved backwards. Whenever
+an opening delimiter is found the COUNT is increased by one, if a
+closing delimiter is found the COUNT is decreased by one. The
+motion stops when COUNT reaches zero. The match-data reflects the
+last successful match (that caused COUNT to reach zero)."
+  ;; Always use the default `forward-sexp-function'. This is important
+  ;; for modes that use a custom one like `python-mode'.
+  ;; (addresses #364)
+  (let (forward-sexp-function)
+    (with-syntax-table (copy-syntax-table (syntax-table))
+      (modify-syntax-entry open (format "(%c" close))
+      (modify-syntax-entry close (format ")%c" open))
+      (let ((rest (evil-motion-loop (dir count)
+                    (let ((pnt (point)))
+                      (condition-case nil
+                          (cond
+                           ((> dir 0)
+                            (while (progn
+                                     (up-list dir)
+                                     (/= (char-before) close))))
+                           (t
+                            (while (progn
+                                     (up-list dir)
+                                     (/= (char-after) open)))))
+                        (error (goto-char pnt)))))))
+        (cond
+         ((= rest count) (set-match-data nil))
+         ((> count 0) (set-match-data (list (1- (point)) (point))))
+         (t (set-match-data (list (point) (1+ (point))))))
+        rest))))
+
+(defun evil-up-xml-tag (&optional count)
+  "Move point to the end or beginning of balanced xml tags.
+OPEN and CLOSE should be characters identifying the opening and
+closing parenthesis, respectively. If COUNT is greater than zero
+point is moved forward otherwise it is moved backwards. Whenever
+an opening delimiter is found the COUNT is increased by one, if a
+closing delimiter is found the COUNT is decreased by one. The
+motion stops when COUNT reaches zero. The match-data reflects the
+last successful match (that caused COUNT to reach zero)."
+  (let* ((dir (if (> (or count 1) 0) +1 -1))
+         (count (abs (or count 1)))
+         (match (> count 0))
+         (op (if (> dir 0) 1 2))
+         (cl (if (> dir 0) 2 1))
+         (orig (point))
+         pnt tags match)
+    (catch 'done
+      (while (> count 0)
+        ;; find the previous opening tag
+        (while
+            (and (setq match
+                       (re-search-forward
+                        "<\\([^/ >]+\\)\\(?:[^\"/>]\\|\"[^\"]*\"\\)*?>\\|</\\([^>]+?\\)>"
+                        nil t dir))
+                 (cond
+                  ((match-beginning op)
+                   (push (match-string op) tags))
+                  ((null tags) nil) ; free closing tag
+                  ((and (< dir 0)
+                        (string= (car tags) (match-string cl)))
+                   ;; in backward direction we only accept matching
+                   ;; tags. If the current tag is a free opener
+                   ;; without matching closing tag, the subsequents
+                   ;; test will make us ignore this tag
+                   (pop tags))
+                  ((and (> dir 0))
+                   ;; non matching openers are considered free openers
+                   (while (and tags
+                               (not (string= (car tags)
+                                             (match-string cl))))
+                     (pop tags))
+                   (pop tags)))))
+        (unless (setq match (and match (match-data t)))
+          (setq match nil)
+          (throw 'done count))
+        ;; found closing tag, look for corresponding opening tag
+        (cond
+         ((> dir 0)
+          (setq pnt (match-end 0))
+          (goto-char (match-beginning 0)))
+         (t
+          (setq pnt (match-beginning 0))
+          (goto-char (match-end 0))))
+        (let* ((tag (match-string cl))
+               (refwd (concat "<\\(/\\)?"
+                              (regexp-quote tag)
+                              "\\(?:>\\| \\(?:[^\"/>]\\|\"[^\"]*\"\\)*?>\\)"))
+               (cnt 1))
+          (while (and (> cnt 0) (re-search-backward refwd nil t dir))
+            (setq cnt (+ cnt (if (match-beginning 1) dir (- dir)))))
+          (if (zerop cnt) (setq count (1- count) tags nil))
+          (goto-char pnt)))
+      (if (> count 0)
+          (set-match-data nil)
+        (set-match-data match)
+        (goto-char (if (> dir 0) (match-end 0) (match-beginning 0)))))
+    ;; if not found, set to point-max/point-min
+    (unless (zerop count)
+      (set-match-data nil)
+      (goto-char (if (> dir 0) (point-max) (point-min)))
+      (if (/= (point) orig) (setq count (1- count))))
+    (* dir count)))
+
+(defun evil-forward-quote (quote &optional count)
+  "Move point to the end or beginning of a string.
+QUOTE is the character delimiting the string. If COUNT is greater
+than zero point is moved forward otherwise it is moved
+backwards."
+  (let (reset-parser)
+    (with-syntax-table (copy-syntax-table (syntax-table))
+      (unless (= (char-syntax quote) ?\")
+        (modify-syntax-entry quote "\"")
+        (setq reset-parser t))
+      ;; global parser state is out of state, use local one
+      (let* ((pnt (point))
+             (state (save-excursion
+                      (beginning-of-defun)
+                      (parse-partial-sexp (point) pnt nil nil (syntax-ppss))))
+             (bnd (bounds-of-evil-string-at-point state)))
+        (when (and bnd (< (point) (cdr bnd)))
+          ;; currently within a string
+          (if (> count 0)
+              (progn
+                (goto-char (cdr bnd))
+                (setq count (1- count)))
+            (goto-char (car bnd))
+            (setq count (1+ count))))
+        ;; forward motions work with local parser state
+        (cond
+         ((> count 0)
+          ;; no need to reset global parser state because we only use
+          ;; the local one
+          (setq reset-parser nil)
+          (catch 'done
+            (while (and (> count 0) (not (eobp)))
+              (setq state (parse-partial-sexp (point) (point-max)
+                                              nil
+                                              nil
+                                              state
+                                              'syntax-table))
+              (cond
+               ((nth 3 state)
+                (setq bnd (bounds-of-thing-at-point 'evil-string))
+                (goto-char (cdr bnd))
+                (setq count (1- count)))
+               ((eobp) (goto-char pnt) (throw 'done nil))))))
+         ((< count 0)
+          ;; need to update global cache because of backward motion
+          (setq reset-parser (and reset-parser (point)))
+          (save-excursion
+            (beginning-of-defun)
+            (syntax-ppss-flush-cache (point)))
+          (catch 'done
+            (while (and (< count 0) (not (bobp)))
+              (setq pnt (point))
+              (while (and (not (bobp))
+                          (or (eobp) (/= (char-after) quote)))
+                (backward-char))
+              (cond
+               ((setq bnd (bounds-of-thing-at-point 'evil-string))
+                (goto-char (car bnd))
+                (setq count (1+ count)))
+               ((bobp) (goto-char pnt) (throw 'done nil))
+               (t (backward-char))))))
+         (t (setq reset-parser nil)))))
+    (when reset-parser
+      ;; reset global cache
+      (save-excursion
+        (goto-char reset-parser)
+        (beginning-of-defun)
+        (syntax-ppss-flush-cache (point))))
+    count))
+
+;;; Thing-at-point motion functions for Evil text objects and motions
+(defun forward-evil-empty-line (&optional count)
+  "Move forward COUNT empty lines."
+  (setq count (or count 1))
+  (cond
+   ((> count 0)
+    (while (and (> count 0) (not (eobp)))
+      (when (and (bolp) (eolp))
+        (setq count (1- count)))
+      (forward-line 1)))
+   (t
+    (while (and (< count 0) (not (bobp))
+                (zerop (forward-line -1)))
+      (when (and (bolp) (eolp))
+        (setq count (1+ count))))))
+  count)
+
+(defun forward-evil-space (&optional count)
+  "Move forward COUNT whitespace sequences [[:space:]]+."
+  (evil-forward-chars "[:space:]" count))
+
+(defun forward-evil-word (&optional count)
+  "Move forward COUNT words.
+Moves point COUNT words forward or (- COUNT) words backward if
+COUNT is negative. Point is placed after the end of the word (if
+forward) or at the first character of the word (if backward). A
+word is a sequence of word characters matching
+\[[:word:]] (recognized by `forward-word'), a sequence of
+non-whitespace non-word characters '[^[:word:]\\n\\r\\t\\f ]', or
+an empty line matching ^$."
+  (evil-forward-nearest
+   count
+   #'(lambda (&optional cnt)
+       (let ((word-separating-categories evil-cjk-word-separating-categories)
+             (word-combining-categories evil-cjk-word-combining-categories)
+             (pnt (point)))
+         (forward-word cnt)
+         (if (= pnt (point)) cnt 0)))
+   #'(lambda (&optional cnt)
+       (evil-forward-chars "^[:word:]\n\r\t\f " cnt))
+   #'forward-evil-empty-line))
+
+(defun forward-evil-WORD (&optional count)
+  "Move forward COUNT \"WORDS\".
+Moves point COUNT WORDS forward or (- COUNT) WORDS backward if
+COUNT is negative. Point is placed after the end of the WORD (if
+forward) or at the first character of the WORD (if backward). A
+WORD is a sequence of non-whitespace characters
+'[^\\n\\r\\t\\f ]', or an empty line matching ^$."
+  (evil-forward-nearest count
+                        #'(lambda (&optional cnt)
+                            (evil-forward-chars "^\n\r\t\f " cnt))
+                        #'forward-evil-empty-line))
+
+(defun forward-evil-symbol (&optional count)
+  "Move forward COUNT symbols.
+Moves point COUNT symbols forward or (- COUNT) symbols backward
+if COUNT is negative. Point is placed after the end of the
+symbol (if forward) or at the first character of the symbol (if
+backward). A symbol is either determined by `forward-symbol', or
+is a sequence of characters not in the word, symbol or whitespace
+syntax classes."
+  (evil-forward-nearest
+   count
+   #'(lambda (&optional cnt)
+       (evil-forward-syntax "^w_->" cnt))
+   #'(lambda (&optional cnt)
+       (let ((pnt (point)))
+         (forward-symbol cnt)
+         (if (= pnt (point)) cnt 0)))
+   #'forward-evil-empty-line))
+
+(defun forward-evil-defun (&optional count)
+  "Move forward COUNT defuns.
+Moves point COUNT defuns forward or (- COUNT) defuns backward
+if COUNT is negative.  A defun is defined by
+`beginning-of-defun' and `end-of-defun' functions."
+  (evil-motion-loop (dir (or count 1))
+    (if (> dir 0) (end-of-defun) (beginning-of-defun))))
+
+(defun forward-evil-sentence (&optional count)
+  "Move forward COUNT sentences.
+Moves point COUNT sentences forward or (- COUNT) sentences
+backward if COUNT is negative.  This function is the same as
+`forward-sentence' but returns the number of sentences that could
+NOT be moved over."
+  (evil-motion-loop (dir (or count 1))
+    (condition-case nil
+        (forward-sentence dir)
+      (error))))
+
+(defun forward-evil-paragraph (&optional count)
+  "Move forward COUNT paragraphs.
+Moves point COUNT paragraphs forward or (- COUNT) paragraphs backward
+if COUNT is negative.  A paragraph is defined by
+`start-of-paragraph-text' and `forward-paragraph' functions."
+  (evil-motion-loop (dir (or count 1))
+    (cond
+     ((> dir 0) (forward-paragraph))
+     ((not (bobp)) (start-of-paragraph-text) (beginning-of-line)))))
+
+(defvar evil-forward-quote-char ?\"
+  "The character to be used by `forward-evil-quote'.")
+
+(defun forward-evil-quote (&optional count)
+  "Move forward COUNT strings.
+The quotation character is specified by the global variable
+`evil-forward-quote-char'. This character is passed to
+`evil-forward-quote'."
+  (evil-forward-quote evil-forward-quote-char count))
+
+(defun forward-evil-quote-simple (&optional count)
+  "Move forward COUNT strings.
+The quotation character is specified by the global variable
+`evil-forward-quote-char'. This functions uses Vim's rules
+parsing from the beginning of the current line for quotation
+characters. It should only be used when looking for strings
+within comments and buffer *must* be narrowed to the comment."
+  (let ((dir (if (> (or count 1) 0) 1 -1))
+        (ch evil-forward-quote-char)
+        (pnt (point))
+        (cnt 0))
+    (beginning-of-line)
+    ;; count number of quotes before pnt
+    (while (< (point) pnt)
+      (when (= (char-after) ch)
+        (setq cnt (1+ cnt)))
+      (forward-char))
+    (setq cnt (- (* 2 (abs count)) (mod cnt 2)))
+    (cond
+     ((> dir 0)
+      (while (and (not (eolp)) (not (zerop cnt)))
+        (when (= (char-after) ch) (setq cnt (1- cnt)))
+        (forward-char))
+      (when (not (zerop cnt)) (goto-char (point-max))))
+     (t
+      (while (and (not (bolp)) (not (zerop cnt)))
+        (when (= (char-before) ch) (setq cnt (1- cnt)))
+        (forward-char -1))
+      (when (not (zerop cnt)) (goto-char (point-min)))))
+    (/ cnt 2)))
+
+;;; Motion functions
+(defun evil-forward-beginning (thing &optional count)
+  "Move forward to beginning of THING.
+The motion is repeated COUNT times."
+  (setq count (or count 1))
+  (if (< count 0)
+      (forward-thing thing count)
+    (let ((bnd (bounds-of-thing-at-point thing))
+          rest)
+      (when (and bnd (< (point) (cdr bnd)))
+        (goto-char (cdr bnd)))
+      (condition-case nil
+          (when (zerop (setq rest (forward-thing thing count)))
+            (when (and (bounds-of-thing-at-point thing)
+                       (not (bobp))
+                       ;; handle final empty line
+                       (not (and (bolp) (eobp))))
+              (forward-char -1))
+            (beginning-of-thing thing))
+        (error))
+      rest)))
+
+(defun evil-backward-beginning (thing &optional count)
+  "Move backward to beginning of THING.
+The motion is repeated COUNT times. This is the same as calling
+`evil-backward-beginning' with -COUNT."
+  (evil-forward-beginning thing (- (or count 1))))
+
+(defun evil-forward-end (thing &optional count)
+  "Move forward to end of THING.
+The motion is repeated COUNT times."
+  (setq count (or count 1))
+  (cond
+   ((> count 0)
+    (unless (eobp) (forward-char))
+    (prog1 (forward-thing thing count)
+      (unless (bobp) (forward-char -1))))
+   (t
+    (let ((bnd (bounds-of-thing-at-point thing))
+          rest)
+      (when (and bnd (< (point) (cdr bnd) ))
+        (goto-char (car bnd)))
+      (condition-case nil
+          (when (zerop (setq rest (forward-thing thing count)))
+            (end-of-thing thing)
+            (forward-char -1))
+        (error))
+      rest))))
+
+(defun evil-backward-end (thing &optional count)
+  "Move backward to end of THING.
+The motion is repeated COUNT times. This is the same as calling
+`evil-backward-end' with -COUNT."
+  (evil-forward-end thing (- (or count 1))))
+
+(defun evil-forward-word (&optional count)
+  "Move by words.
+Moves point COUNT words forward or (- COUNT) words backward if
+COUNT is negative. This function is the same as `forward-word'
+but returns the number of words by which point could *not* be
+moved."
+  (setq count (or count 1))
+  (let* ((dir (if (>= count 0) +1 -1))
+         (count (abs count)))
+    (while (and (> count 0)
+                (forward-word dir))
+      (setq count (1- count)))
+    count))
+
+(defun evil-in-comment-p (&optional pos)
+  "Checks if POS is within a comment according to current syntax.
+If POS is nil, (point) is used. The return value is the beginning
+position of the comment."
+  (setq pos (or pos (point)))
+  (let ((chkpos
+         (cond
+          ((eobp) pos)
+          ((= (char-syntax (char-after)) ?<) (1+ pos))
+          ((and (not (zerop (logand (car (syntax-after (point)))
+                                    (lsh 1 16))))
+                (not (zerop (logand (or (car (syntax-after (1+ (point)))) 0)
+                                    (lsh 1 17)))))
+           (+ pos 2))
+          ((and (not (zerop (logand (car (syntax-after (point)))
+                                    (lsh 1 17))))
+                (not (zerop (logand (or (car (syntax-after (1- (point)))) 0)
+                                    (lsh 1 16)))))
+           (1+ pos))
+          (t pos))))
+    (let ((syn (save-excursion (syntax-ppss chkpos))))
+      (and (nth 4 syn) (nth 8 syn)))))
+
+(defun evil-looking-at-start-comment (&optional move)
+  "Returns t if point is at the start of a comment.
+point must be on one of the opening characters of a block comment
+according to the current syntax table. Futhermore these
+characters must been parsed as opening characters, i.e. they
+won't be considered as comment starters inside a string or
+possibly another comment. Point is moved to the first character
+of the comment opener if MOVE is non-nil."
+  (cond
+   ;; one character opener
+   ((= (char-syntax (char-after)) ?<)
+    (equal (point) (evil-in-comment-p (1+ (point)))))
+   ;; two character opener on first char
+   ((and (not (zerop (logand (car (syntax-after (point)))
+                             (lsh 1 16))))
+         (not (zerop (logand (or (car (syntax-after (1+ (point)))) 0)
+                             (lsh 1 17)))))
+    (equal (point) (evil-in-comment-p (+ 2 (point)))))
+   ;; two character opener on second char
+   ((and (not (zerop (logand (car (syntax-after (point)))
+                             (lsh 1 17))))
+         (not (zerop (logand (or (car (syntax-after (1- (point)))) 0)
+                             (lsh 1 16)))))
+    (and (equal (1- (point)) (evil-in-comment-p (1+ (point))))
+         (prog1 t (when move (backward-char)))))))
+
+(defun evil-looking-at-end-comment (&optional move)
+  "Returns t if point is at the end of a comment.
+point must be on one of the opening characters of a block comment
+according to the current syntax table. Futhermore these
+characters must been parsed as opening characters, i.e. they
+won't be considered as comment starters inside a string or
+possibly another comment. Point is moved right after the comment
+closer if MOVE is non-nil."
+  (cond
+   ;; one char closer
+   ((= (char-syntax (char-after)) ?>)
+    (and (evil-in-comment-p) ; in comment
+         (not (evil-in-comment-p (1+ (point))))
+         (prog1 t (when move (forward-char)))))
+   ;; two char closer on first char
+   ((and (not (zerop (logand (car (syntax-after (point)))
+                             (lsh 1 18))))
+         (not (zerop (logand (or (car (syntax-after (1+ (point)))) 0)
+                             (lsh 1 19)))))
+    (and (evil-in-comment-p)
+         (not (evil-in-comment-p (+ (point) 2)))
+         (prog1 t (when move (forward-char 2)))))
+   ;; two char closer on second char
+   ((and (not (zerop (logand (car (syntax-after (point)))
+                             (lsh 1 19))))
+         (not (zerop (logand (or (car (syntax-after (1- (point)))) 0)
+                             (lsh 1 18)))))
+    (and (evil-in-comment-p)
+         (not (evil-in-comment-p (1+ (point))))
+         (prog1 t (when move (forward-char)))))))
+
+(defun evil-insert-newline-above ()
+  "Inserts a new line above point and places point in that line
+with regard to indentation."
+  (evil-narrow-to-field
+    (evil-move-beginning-of-line)
+    (insert (if use-hard-newlines hard-newline "\n"))
+    (forward-line -1)
+    (back-to-indentation)))
+
+(defun evil-insert-newline-below ()
+  "Inserts a new line below point and places point in that line
+with regard to indentation."
+  (evil-narrow-to-field
+    (evil-move-end-of-line)
+    (insert (if use-hard-newlines hard-newline "\n"))
+    (back-to-indentation)))
+
+;;; Markers
+
+(defun evil-global-marker-p (char)
+  "Whether CHAR denotes a global marker."
+  (or (and (>= char ?A) (<= char ?Z))
+      (assq char (default-value 'evil-markers-alist))))
+
+(defun evil-set-marker (char &optional pos advance)
+  "Set the marker denoted by CHAR to position POS.
+POS defaults to the current position of point.
+If ADVANCE is t, the marker advances when inserting text at it;
+otherwise, it stays behind."
+  (interactive (list (read-char)))
+  (catch 'done
+    (let ((marker (evil-get-marker char t)) alist)
+      (unless (markerp marker)
+        (cond
+         ((and marker (symbolp marker) (boundp marker))
+          (set marker (or (symbol-value marker) (make-marker)))
+          (setq marker (symbol-value marker)))
+         ((eq marker 'evil-jump-backward-swap)
+          (evil-set-jump)
+          (throw 'done nil))
+         ((functionp marker)
+          (user-error "Cannot set special marker `%c'" char))
+         ((evil-global-marker-p char)
+          (setq alist (default-value 'evil-markers-alist)
+                marker (make-marker))
+          (evil-add-to-alist 'alist char marker)
+          (setq-default evil-markers-alist alist))
+         (t
+          (setq marker (make-marker))
+          (evil-add-to-alist 'evil-markers-alist char marker))))
+      (add-hook 'kill-buffer-hook #'evil-swap-out-markers nil t)
+      (set-marker-insertion-type marker advance)
+      (set-marker marker (or pos (point))))))
+
+(defun evil-get-marker (char &optional raw)
+  "Return the marker denoted by CHAR.
+This is either a marker object as returned by `make-marker',
+a number, a cons cell (FILE . POS) with FILE being a string
+and POS a number, or nil. If RAW is non-nil, then the
+return value may also be a variable, a movement function,
+or a marker object pointing nowhere."
+  (let ((marker (if (evil-global-marker-p char)
+                    (cdr-safe (assq char (default-value
+                                           'evil-markers-alist)))
+                  (cdr-safe (assq char evil-markers-alist)))))
+    (save-excursion
+      (if raw
+          marker
+        (when (and (symbolp marker) (boundp marker))
+          (setq marker (symbol-value marker)))
+        (when (functionp marker)
+          (funcall marker)
+          (setq marker (point)))
+        (when (markerp marker)
+          (if (eq (marker-buffer marker) (current-buffer))
+              (setq marker (marker-position marker))
+            (setq marker (and (marker-buffer marker) marker))))
+        (when (or (numberp marker)
+                  (markerp marker)
+                  (and (consp marker)
+                       (stringp (car marker))
+                       (numberp (cdr marker))))
+          marker)))))
+
+(defun evil-swap-out-markers ()
+  "Turn markers into file references when the buffer is killed."
+  (and buffer-file-name
+       (dolist (entry evil-markers-alist)
+         (and (markerp (cdr entry))
+              (eq (marker-buffer (cdr entry)) (current-buffer))
+              (setcdr entry (cons buffer-file-name
+                                  (marker-position (cdr entry))))))))
+(put 'evil-swap-out-markers 'permanent-local-hook t)
+
+(defun evil-get-register (register &optional noerror)
+  "Return contents of REGISTER.
+Signal an error if empty, unless NOERROR is non-nil.
+
+The following special registers are supported.
+  \"  the unnamed register
+  *  the clipboard contents
+  +  the clipboard contents
+  <C-w> the word at point (ex mode only)
+  <C-a> the WORD at point (ex mode only)
+  <C-o> the symbol at point (ex mode only)
+  <C-f> the current file at point (ex mode only)
+  %  the current file name (read only)
+  #  the alternate file name (read only)
+  /  the last search pattern (read only)
+  :  the last command line (read only)
+  .  the last inserted text (read only)
+  -  the last small (less than a line) delete
+  _  the black hole register
+  =  the expression register (read only)"
+  (condition-case err
+      (when (characterp register)
+        (or (cond
+             ((eq register ?\")
+              (current-kill 0))
+             ((and (<= ?1 register) (<= register ?9))
+              (let ((reg (- register ?1)))
+                (and (< reg (length kill-ring))
+                     (current-kill reg t))))
+             ((memq register '(?* ?+))
+              ;; the following code is modified from
+              ;; `x-selection-value-internal'
+              (let ((what (if (eq register ?*) 'PRIMARY 'CLIPBOARD))
+                    (request-type (or (and (boundp 'x-select-request-type)
+                                           x-select-request-type)
+                                      '(UTF8_STRING COMPOUNT_TEXT STRING)))
+                    text)
+                (unless (consp request-type)
+                  (setq request-type (list request-type)))
+                (while (and request-type (not text))
+                  (condition-case nil
+                      (setq text (evil-get-selection what (pop request-type)))
+                    (error nil)))
+                (when text
+                  (remove-text-properties 0 (length text) '(foreign-selection nil) text))
+                text))
+             ((eq register ?\C-W)
+              (unless (evil-ex-p)
+                (user-error "Register <C-w> only available in ex state"))
+              (with-current-buffer evil-ex-current-buffer
+                (thing-at-point 'evil-word)))
+             ((eq register ?\C-A)
+              (unless (evil-ex-p)
+                (user-error "Register <C-a> only available in ex state"))
+              (with-current-buffer evil-ex-current-buffer
+                (thing-at-point 'evil-WORD)))
+             ((eq register ?\C-O)
+              (unless (evil-ex-p)
+                (user-error "Register <C-o> only available in ex state"))
+              (with-current-buffer evil-ex-current-buffer
+                (thing-at-point 'evil-symbol)))
+             ((eq register ?\C-F)
+              (unless (evil-ex-p)
+                (user-error "Register <C-f> only available in ex state"))
+              (with-current-buffer evil-ex-current-buffer
+                (thing-at-point 'filename)))
+             ((eq register ?%)
+              (or (buffer-file-name (and (evil-ex-p)
+                                         (minibufferp)
+                                         evil-ex-current-buffer))
+                  (user-error "No file name")))
+             ((= register ?#)
+              (or (with-current-buffer (other-buffer) (buffer-file-name))
+                  (user-error "No file name")))
+             ((eq register ?/)
+              (or (car-safe
+                   (or (and (boundp 'evil-search-module)
+                            (eq evil-search-module 'evil-search)
+                            evil-ex-search-history)
+                       (and isearch-regexp regexp-search-ring)
+                       search-ring))
+                  (user-error "No previous regular expression")))
+             ((eq register ?:)
+              (or (car-safe evil-ex-history)
+                  (user-error "No previous command line")))
+             ((eq register ?.)
+              evil-last-insertion)
+             ((eq register ?-)
+              evil-last-small-deletion)
+             ((eq register ?=)
+              (let* ((enable-recursive-minibuffers t)
+                     (result (eval (car (read-from-string (read-string "="))))))
+                (cond
+                 ((or (stringp result)
+                      (numberp result)
+                      (symbolp result))
+                  (prin1-to-string result))
+                 ((sequencep result)
+                  (mapconcat #'prin1-to-string result "\n"))
+                 (t (user-error "Using %s as a string" (type-of result))))))
+             ((eq register ?_) ; the black hole register
+              "")
+             (t
+              (setq register (downcase register))
+              (get-register register)))
+            (user-error "Register `%c' is empty" register)))
+    (error (unless err (signal (car err) (cdr err))))))
+
+(defun evil-set-register (register text)
+  "Set the contents of register REGISTER to TEXT.
+If REGISTER is an upcase character then text is appended to that
+register instead of replacing its content."
+  (cond
+   ((not (characterp register))
+    (user-error "Invalid register"))
+   ;; don't allow modification of read-only registers
+   ((member register '(?: ?. ?%))
+    (user-error "Can't modify read-only register"))
+   ((eq register ?\")
+    (kill-new text))
+   ((and (<= ?1 register) (<= register ?9))
+    (if (null kill-ring)
+        (kill-new text)
+      (let ((kill-ring-yank-pointer kill-ring-yank-pointer)
+            interprogram-paste-function
+            interprogram-cut-function)
+        (current-kill (- register ?1))
+        (setcar kill-ring-yank-pointer text))))
+   ((eq register ?*)
+    (evil-set-selection 'PRIMARY text))
+   ((eq register ?+)
+    (evil-set-selection 'CLIPBOARD text))
+   ((eq register ?-)
+    (setq evil-last-small-deletion text))
+   ((eq register ?_) ; the black hole register
+    nil)
+   ((and (<= ?A register) (<= register ?Z))
+    (setq register (downcase register))
+    (let ((content (get-register register)))
+      (cond
+       ((not content)
+        (set-register register text))
+       ((or (text-property-not-all 0 (length content)
+                                   'yank-handler nil
+                                   content)
+            (text-property-not-all 0 (length text)
+                                   'yank-handler nil
+                                   text))
+        ;; some non-trivial yank-handler -> always switch to line handler
+        ;; ensure complete lines
+        (when (and (> (length content) 0)
+                   (/= (aref content (1- (length content))) ?\n))
+          (setq content (concat content "\n")))
+        (when (and (> (length text) 0)
+                   (/= (aref text (1- (length text))) ?\n))
+          (setq text (concat text "\n")))
+        (setq text (concat content text))
+        (remove-list-of-text-properties 0 (length text) '(yank-handler) text)
+        (setq text (propertize text 'yank-handler '(evil-yank-line-handler)))
+        (set-register register text))
+       (t
+        (set-register register (concat content text))))))
+   (t
+    (set-register register text))))
+
+(defun evil-register-list ()
+  "Returns an alist of all registers"
+  (sort (append (mapcar #'(lambda (reg)
+                            (cons reg (evil-get-register reg t)))
+                        '(?\" ?* ?+ ?% ?# ?/ ?: ?. ?-
+                              ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9))
+                register-alist nil)
+        #'(lambda (reg1 reg2) (< (car reg1) (car reg2)))))
+
+(defsubst evil-kbd-macro-suppress-motion-error ()
+  "Returns non-nil if a motion error should be suppressed.
+Whether the motion error should be suppressed depends on the
+variable `evil-kbd-macro-suppress-motion-error'."
+  (or (and defining-kbd-macro
+           (memq evil-kbd-macro-suppress-motion-error '(t record)))
+      (and executing-kbd-macro
+           (memq evil-kbd-macro-suppress-motion-error '(t replay)))))
+
+;;; Region
+
+;; `set-mark' does too much at once
+(defun evil-move-mark (pos)
+  "Set buffer's mark to POS.
+If POS is nil, delete the mark."
+  (when pos
+    (setq pos (evil-normalize-position pos)))
+  (set-marker (mark-marker) pos))
+
+(defun evil-save-transient-mark-mode ()
+  "Save Transient Mark mode and make it buffer-local.
+Any changes to Transient Mark mode are now local to the current
+buffer, until `evil-restore-transient-mark-mode' is called.
+
+Variables pertaining to Transient Mark mode are listed in
+`evil-transient-vars', and their values are stored in
+`evil-transient-vals'."
+  (dolist (var evil-transient-vars)
+    (when (and (boundp var)
+               (not (assq var evil-transient-vals)))
+      (push (list var (symbol-value var)
+                  (local-variable-p var))
+            evil-transient-vals)
+      (make-variable-buffer-local var)
+      (put var 'permanent-local t))))
+
+(defun evil-restore-transient-mark-mode ()
+  "Restore Transient Mark mode.
+This presupposes that `evil-save-transient-mark-mode' has been
+called earlier. If Transient Mark mode was disabled before but
+enabled in the meantime, this function disables it; if it was
+enabled before but disabled in the meantime, this function
+enables it.
+
+The earlier settings of Transient Mark mode are stored in
+`evil-transient-vals'."
+  (let (entry local var val)
+    (while (setq entry (pop evil-transient-vals))
+      (setq var (pop entry)
+            val (pop entry)
+            local (pop entry))
+      (unless local
+        (kill-local-variable var))
+      (unless (equal (symbol-value var) val)
+        (if (fboundp var)
+            (funcall var (if val 1 -1))
+          (setq var val))))))
+
+(defun evil-save-mark ()
+  "Save the current mark, including whether it is transient.
+See also `evil-restore-mark'."
+  (unless evil-visual-previous-mark
+    (setq evil-visual-previous-mark (mark t))
+    (evil-save-transient-mark-mode)))
+
+(defun evil-restore-mark ()
+  "Restore the mark, including whether it was transient.
+See also `evil-save-mark'."
+  (when evil-visual-previous-mark
+    (evil-restore-transient-mark-mode)
+    (evil-move-mark evil-visual-previous-mark)
+    (setq evil-visual-previous-mark nil)))
+
+;; In theory, an active region implies Transient Mark mode, and
+;; disabling Transient Mark mode implies deactivating the region.
+;; In practice, Emacs never clears `mark-active' except in Transient
+;; Mark mode, so we define our own toggle functions to make things
+;; more predictable.
+(defun evil-transient-mark (&optional arg)
+  "Toggle Transient Mark mode.
+Ensure that the region is properly deactivated.
+Enable with positive ARG, disable with negative ARG."
+  (unless (numberp arg)
+    (setq arg (if transient-mark-mode -1 1)))
+  (cond
+   ((< arg 1)
+    (evil-active-region -1)
+    ;; Transient Mark mode cannot be disabled
+    ;; while CUA mode is enabled
+    (when (fboundp 'cua-mode)
+      (cua-mode -1))
+    (when transient-mark-mode
+      (transient-mark-mode -1)))
+   (t
+    (unless transient-mark-mode
+      (evil-active-region -1)
+      (transient-mark-mode 1)))))
+
+(defun evil-active-region (&optional arg)
+  "Toggle active region.
+Ensure that Transient Mark mode is properly enabled.
+Enable with positive ARG, disable with negative ARG."
+  (unless (numberp arg)
+    (setq arg (if (region-active-p) -1 1)))
+  (cond
+   ((and (< arg 1))
+    (when (or transient-mark-mode mark-active)
+      (setq mark-active nil
+            deactivate-mark nil)
+      (when (boundp 'cua--explicit-region-start)
+        (setq cua--explicit-region-start nil))
+      (run-hooks 'deactivate-mark-hook)))
+   (t
+    (evil-transient-mark 1)
+    (when deactivate-mark
+      (setq deactivate-mark nil))
+    (unless (mark t)
+      (evil-move-mark (point)))
+    (unless (region-active-p)
+      (set-mark (mark t)))
+    (when (boundp 'cua--explicit-region-start)
+      (setq cua--explicit-region-start t)))))
+
+(defmacro evil-with-transient-mark-mode (&rest body)
+  "Execute BODY with Transient Mark mode.
+Then restore Transient Mark mode to its previous setting."
+  (declare (indent defun)
+           (debug t))
+  `(let ((inhibit-quit t)
+         evil-transient-vals)
+     (unwind-protect
+         (progn
+           (evil-save-transient-mark-mode)
+           (evil-transient-mark 1)
+           ,@body)
+       (evil-restore-transient-mark-mode))))
+
+(defmacro evil-with-active-region (beg end &rest body)
+  "Execute BODY with an active region from BEG to END."
+  (declare (indent 2)
+           (debug t))
+  `(let ((beg ,beg) (end ,end)
+         evil-transient-vals)
+     (evil-with-transient-mark-mode
+       (save-excursion
+         (evil-active-region 1)
+         (evil-move-mark beg)
+         (goto-char end)
+         ,@body))))
+
+(defun evil-exchange-point-and-mark ()
+  "Exchange point and mark without activating the region."
+  (let* ((point (point))
+         (mark  (or (mark t) point)))
+    (set-marker (mark-marker) point)
+    (goto-char mark)))
+
+(defun evil-apply-on-block (func beg end pass-columns &rest args)
+  "Call FUNC for each line of a block selection.
+The selection is specified by the region BEG and END.  FUNC must
+take at least two arguments, the beginning and end of each
+line. If PASS-COLUMNS is non-nil, these values are the columns,
+otherwise tey are buffer positions. Extra arguments to FUNC may
+be passed via ARGS."
+  (let ((eol-col (and (memq last-command '(next-line previous-line))
+                      (numberp temporary-goal-column)
+                      temporary-goal-column))
+        startcol startpt endcol endpt)
+    (save-excursion
+      (goto-char beg)
+      (setq startcol (current-column))
+      (beginning-of-line)
+      (setq startpt (point))
+      (goto-char end)
+      (setq endcol (current-column))
+      (forward-line 1)
+      (setq endpt (point-marker))
+      ;; ensure the start column is the left one.
+      (evil-sort startcol endcol)
+      ;; maybe find maximal column
+      (when eol-col
+        (setq eol-col 0)
+        (goto-char startpt)
+        (while (< (point) endpt)
+          (setq eol-col (max eol-col
+                             (evil-column (line-end-position))))
+          (forward-line 1))
+        (setq endcol (max endcol
+                          (min eol-col
+                               (1+ (min (1- most-positive-fixnum)
+                                        (truncate temporary-goal-column)))))))
+      ;; start looping over lines
+      (goto-char startpt)
+      (while (< (point) endpt)
+        (if pass-columns
+            (apply func startcol endcol args)
+          (apply func
+                 (save-excursion (evil-move-to-column startcol))
+                 (save-excursion (evil-move-to-column endcol t))
+                 args))
+        (forward-line 1)))))
+
+(defun evil-apply-on-rectangle (function start end &rest args)
+  "Like `apply-on-rectangle' but maybe extends to eol.
+If `temporary-goal-column' is set to a big number, then the
+region of each line is extended to the end of each line. The end
+column is set to the maximal column in all covered lines."
+  (apply #'evil-apply-on-block function start end t args))
+
+;;; Insertion
+
+(defun evil-concat-ranges (ranges)
+  "Concatenate RANGES.
+RANGES must be a list of ranges.  They must be ordered so that
+successive ranges share their boundaries.  The return value is a
+single range of disjoint union of the ranges or nil if the
+disjoint union is not a single range."
+  (let ((range (car-safe ranges)) (ranges (cdr ranges)) r)
+    (while (and range (setq r (car-safe ranges)))
+      (setq range
+            (cond ((and (= (cdr r) (car range))) (cons (car r) (cdr range)))
+                  ((and (= (cdr range) (car r))) (cons (car range) (cdr r)))))
+      (setq ranges (cdr ranges)))
+    range))
+
+(defun evil-track-last-insertion (beg end len)
+  "Track the last insertion range and its text.
+The insertion range is stored as a pair of buffer positions in
+`evil-current-insertion'. If a subsequent change is compatible,
+then the current range is modified, otherwise it is replaced by a
+new range. Compatible changes are changes that do not create a
+disjoin range."
+  ;; deletion
+  (when (> len 0)
+    (if (and evil-current-insertion
+             (>= beg (car evil-current-insertion))
+             (<= (+ beg len) (cdr evil-current-insertion)))
+        (setcdr evil-current-insertion
+                (- (cdr evil-current-insertion) len))
+      (setq evil-current-insertion nil)))
+  ;; insertion
+  (if (and evil-current-insertion
+           (>= beg (car evil-current-insertion))
+           (<= beg (cdr evil-current-insertion)))
+      (setcdr evil-current-insertion
+              (+ (- end beg)
+                 (cdr evil-current-insertion)))
+    (setq evil-current-insertion (cons beg end))))
+(put 'evil-track-last-insertion 'permanent-local-hook t)
+
+(defun evil-start-track-last-insertion ()
+  "Start tracking the last insertion."
+  (setq evil-current-insertion nil)
+  (add-hook 'after-change-functions #'evil-track-last-insertion nil t))
+
+(defun evil-stop-track-last-insertion ()
+  "Stop tracking the last insertion.
+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))
+
+;;; Paste
+
+(defun evil-yank-characters (beg end &optional register yank-handler)
+  "Saves the characters defined by the region BEG and END in the kill-ring."
+  (let ((text (filter-buffer-substring beg end)))
+    (when yank-handler
+      (setq text (propertize text 'yank-handler (list yank-handler))))
+    (when register
+      (evil-set-register register text))
+    (when evil-was-yanked-without-register
+      (evil-set-register ?0 text)) ; "0 register contains last yanked text
+    (unless (eq register ?_)
+      (kill-new text))))
+
+(defun evil-yank-lines (beg end &optional register yank-handler)
+  "Saves the lines in the region BEG and END into the kill-ring."
+  (let* ((text (filter-buffer-substring beg end))
+         (yank-handler (list (or yank-handler
+                                 #'evil-yank-line-handler)
+                             nil
+                             t)))
+    ;; Ensure the text ends with a newline. This is required
+    ;; if the deleted lines were the last lines in the buffer.
+    (when (or (zerop (length text))
+              (/= (aref text (1- (length text))) ?\n))
+      (setq text (concat text "\n")))
+    (setq text (propertize text 'yank-handler yank-handler))
+    (when register
+      (evil-set-register register text))
+    (when evil-was-yanked-without-register
+      (evil-set-register ?0 text)) ; "0 register contains last yanked text
+    (unless (eq register ?_)
+      (kill-new text))))
+
+(defun evil-yank-rectangle (beg end &optional register yank-handler)
+  "Saves the rectangle defined by region BEG and END into the kill-ring."
+  (let ((lines (list nil)))
+    (evil-apply-on-rectangle #'extract-rectangle-line beg end lines)
+    ;; We remove spaces from the beginning and the end of the next.
+    ;; Spaces are inserted explicitly in the yank-handler in order to
+    ;; NOT insert lines full of spaces.
+    (setq lines (nreverse (cdr lines)))
+    ;; `text' is used as default insert text when pasting this rectangle
+    ;; in another program, e.g., using the X clipboard.
+    (let* ((yank-handler (list (or yank-handler
+                                   #'evil-yank-block-handler)
+                               lines
+                               t
+                               'evil-delete-yanked-rectangle))
+           (text (propertize (mapconcat #'identity lines "\n")
+                             'yank-handler yank-handler)))
+      (when register
+        (evil-set-register register text))
+      (when evil-was-yanked-without-register
+        (evil-set-register ?0 text)) ; "0 register contains last yanked text
+      (unless (eq register ?_)
+        (kill-new text)))))
+
+(defun evil-remove-yank-excluded-properties (text)
+  "Removes `yank-excluded-properties' from TEXT."
+  (if (eq yank-excluded-properties t)
+      (set-text-properties 0 (length text) nil text)
+    (remove-list-of-text-properties 0 (length text)
+                                    yank-excluded-properties text)))
+
+(defun evil-yank-line-handler (text)
+  "Inserts the current text linewise."
+  (let ((text (apply #'concat (make-list (or evil-paste-count 1) text)))
+        (opoint (point)))
+    (evil-remove-yank-excluded-properties text)
+    (cond
+     ((eq this-command 'evil-paste-before)
+      (evil-move-beginning-of-line)
+      (evil-move-mark (point))
+      (insert text)
+      (setq evil-last-paste
+            (list 'evil-paste-before
+                  evil-paste-count
+                  opoint
+                  (mark t)
+                  (point)))
+      (evil-set-marker ?\[ (mark))
+      (evil-set-marker ?\] (1- (point)))
+      (evil-exchange-point-and-mark)
+      (back-to-indentation))
+     ((eq this-command 'evil-paste-after)
+      (evil-move-end-of-line)
+      (evil-move-mark (point))
+      (insert "\n")
+      (insert text)
+      (evil-set-marker ?\[ (1+ (mark)))
+      (evil-set-marker ?\] (1- (point)))
+      (delete-char -1) ; delete the last newline
+      (setq evil-last-paste
+            (list 'evil-paste-after
+                  evil-paste-count
+                  opoint
+                  (mark t)
+                  (point)))
+      (evil-move-mark (1+ (mark t)))
+      (evil-exchange-point-and-mark)
+      (back-to-indentation))
+     (t
+      (insert text)))))
+
+(defun evil-yank-block-handler (lines)
+  "Inserts the current text as block."
+  (let ((count (or evil-paste-count 1))
+        (col (if (eq this-command 'evil-paste-after)
+                 (1+ (current-column))
+               (current-column)))
+        (current-line (line-number-at-pos (point)))
+        (opoint (point))
+        epoint)
+    (dolist (line lines)
+      ;; concat multiple copies according to count
+      (setq line (apply #'concat (make-list count line)))
+      ;; strip whitespaces at beginning and end
+      (string-match "^ *\\(.*?\\) *$" line)
+      (let ((text (match-string 1 line))
+            (begextra (match-beginning 1))
+            (endextra (- (match-end 0) (match-end 1))))
+        ;; maybe we have to insert a new line at eob
+        (while (< (line-number-at-pos (point))
+                  current-line)
+          (goto-char (point-max))
+          (insert "\n"))
+        (setq current-line (1+ current-line))
+        ;; insert text unless we insert an empty line behind eol
+        (unless (and (< (evil-column (line-end-position)) col)
+                     (zerop (length text)))
+          ;; if we paste behind eol, it may be sufficient to insert tabs
+          (if (< (evil-column (line-end-position)) col)
+              (move-to-column (+ col begextra) t)
+            (move-to-column col t)
+            (insert (make-string begextra ?\s)))
+          (evil-remove-yank-excluded-properties text)
+          (insert text)
+          (unless (eolp)
+            ;; text follows, so we have to insert spaces
+            (insert (make-string endextra ?\s)))
+          (setq epoint (point)))
+        (forward-line 1)))
+    (setq evil-last-paste
+          (list this-command
+                evil-paste-count
+                opoint
+                (length lines)                   ; number of rows
+                (* count (length (car lines))))) ; number of colums
+    (evil-set-marker ?\[ opoint)
+    (evil-set-marker ?\] (1- epoint))
+    (goto-char opoint)
+    (when (and (eq this-command 'evil-paste-after)
+               (not (eolp)))
+      (forward-char))))
+
+(defun evil-delete-yanked-rectangle (nrows ncols)
+  "Special function to delete the block yanked by a previous paste command."
+  (let ((opoint (point))
+        (col (if (eq last-command 'evil-paste-after)
+                 (1+ (current-column))
+               (current-column))))
+    (dotimes (i nrows)
+      (delete-region (save-excursion
+                       (move-to-column col)
+                       (point))
+                     (save-excursion
+                       (move-to-column (+ col ncols))
+                       (point)))
+      (unless (eobp) (forward-line)))
+    (goto-char opoint)))
+
+;; TODO: if undoing is disabled in the current buffer, paste-pop won't
+;; work. Although this is probably not a big problem, because usually
+;; buffers where `evil-paste-pop' may be useful have undoing enabled.
+;; A solution would be to temporarily enable undo when pasting and
+;; store the undo information in a special variable that does not
+;; interfere with `buffer-undo-list'.
+(defun evil-paste-pop (count)
+  "Replace the just-yanked stretch of killed text with a different stretch.
+This command is allowed only immediatly after a `yank',
+`evil-paste-before', `evil-paste-after' or `evil-paste-pop'.
+This command uses the same paste command as before, i.e., when
+used after `evil-paste-after' the new text is also yanked using
+`evil-paste-after', used with the same paste-count argument.
+
+The COUNT argument inserts the COUNTth previous kill.  If COUNT
+is negative this is a more recent kill."
+  (interactive "p")
+  (unless (memq last-command
+                '(evil-paste-after
+                  evil-paste-before
+                  evil-visual-paste))
+    (user-error "Previous command was not an evil-paste: %s" last-command))
+  (unless evil-last-paste
+    (user-error "Previous paste command used a register"))
+  (evil-undo-pop)
+  (goto-char (nth 2 evil-last-paste))
+  (setq this-command (nth 0 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."
+  (interactive "p")
+  (evil-paste-pop (- count)))
+
+;;; Interactive forms
+
+(defun evil-match-interactive-code (interactive &optional pos)
+  "Match an interactive code at position POS in string INTERACTIVE.
+Returns the first matching entry in `evil-interactive-alist', or nil."
+  (let ((length (length interactive))
+        (pos (or pos 0)))
+    (catch 'done
+      (dolist (entry evil-interactive-alist)
+        (let* ((string (car entry))
+               (end (+ (length string) pos)))
+          (when (and (<= end length)
+                     (string= string
+                              (substring interactive pos end)))
+            (throw 'done entry)))))))
+
+(defun evil-concatenate-interactive-forms (&rest forms)
+  "Concatenate interactive list expressions FORMS.
+Returns a single expression where successive expressions
+are joined, if possible."
+  (let (result)
+    (when forms
+      (while (cdr forms)
+        (cond
+         ((null (car forms))
+          (pop forms))
+         ((and (eq (car (car forms)) 'list)
+               (eq (car (cadr forms)) 'list))
+          (setq forms (cons (append (car forms)
+                                    (cdr (cadr forms)))
+                            (cdr (cdr forms)))))
+         (t
+          (push (pop forms) result))))
+      (when (car forms)
+        (push (pop forms) result))
+      (setq result (nreverse result))
+      (cond
+       ((null result))
+       ((null (cdr result))
+        (car result))
+       (t
+        `(append ,@result))))))
+
+(defun evil-interactive-string (string)
+  "Evaluate the interactive string STRING.
+The string may contain extended interactive syntax.
+The return value is a cons cell (FORM . PROPERTIES),
+where FORM is a single list-expression to be passed to
+a standard `interactive' statement, and PROPERTIES is a
+list of command properties as passed to `evil-define-command'."
+  (let ((length (length string))
+        (pos 0)
+        code expr forms match plist prompt properties)
+    (while (< pos length)
+      (if (eq (aref string pos) ?\n)
+          (setq pos (1+ pos))
+        (setq match (evil-match-interactive-code string pos))
+        (if (null match)
+            (user-error "Unknown interactive code: `%s'"
+                        (substring string pos))
+          (setq code (car match)
+                expr (car (cdr match))
+                plist (cdr (cdr match))
+                pos (+ pos (length code)))
+          (when (functionp expr)
+            (setq prompt
+                  (substring string pos
+                             (or (string-match "\n" string pos)
+                                 length))
+                  pos (+ pos (length prompt))
+                  expr `(funcall ,expr ,prompt)))
+          (setq forms (append forms (list expr))
+                properties (append properties plist)))))
+    (cons `(append ,@forms) properties)))
+
+(defun evil-interactive-form (&rest args)
+  "Evaluate interactive forms ARGS.
+The return value is a cons cell (FORM . PROPERTIES),
+where FORM is a single list-expression to be passed to
+a standard `interactive' statement, and PROPERTIES is a
+list of command properties as passed to `evil-define-command'."
+  (let (forms properties)
+    (dolist (arg args)
+      (if (not (stringp arg))
+          (setq forms (append forms (list arg)))
+        (setq arg (evil-interactive-string arg)
+              forms (append forms (cdr (car arg)))
+              properties (append properties (cdr arg)))))
+    (cons (apply #'evil-concatenate-interactive-forms forms)
+          properties)))
+
+;;; Types
+
+(defun evil-type (object &optional default)
+  "Return the type of OBJECT, or DEFAULT if none."
+  (let (type)
+    (cond
+     ((overlayp object)
+      (setq type (overlay-get object :type)))
+     ((evil-range-p object)
+      (setq type (nth 2 object)))
+     ((listp object)
+      (setq type (plist-get object :type)))
+     ((commandp object)
+      (setq type (evil-get-command-property object :type)))
+     ((symbolp object)
+      (setq type (get object 'type))))
+    (setq type (or type default))
+    (and (evil-type-p type) type)))
+
+(defun evil-set-type (object type)
+  "Set the type of OBJECT to TYPE.
+For example, (evil-set-type 'next-line 'line)
+will make `line' the type of the `next-line' command."
+  (cond
+   ((overlayp object)
+    (overlay-put object :type type))
+   ((evil-range-p object)
+    (evil-set-range-type object type))
+   ((listp object)
+    (plist-put object :type type))
+   ((commandp object)
+    (evil-set-command-property object :type type))
+   ((symbolp object)
+    (put object 'type type)))
+  object)
+
+(defun evil-type-property (type prop)
+  "Return property PROP for TYPE."
+  (evil-get-property evil-type-properties type prop))
+
+(defun evil-type-p (sym)
+  "Whether SYM is the name of a type."
+  (assq sym evil-type-properties))
+
+(defun evil-expand (beg end type &rest properties)
+  "Expand BEG and END as TYPE with PROPERTIES.
+Returns a list (BEG END TYPE PROPERTIES ...), where the tail
+may contain a property list."
+  (apply #'evil-transform
+         ;; don't expand if already expanded
+         (unless (plist-get properties :expanded) :expand)
+         beg end type properties))
+
+(defun evil-contract (beg end type &rest properties)
+  "Contract BEG and END as TYPE with PROPERTIES.
+Returns a list (BEG END TYPE PROPERTIES ...), where the tail
+may contain a property list."
+  (apply #'evil-transform :contract beg end type properties))
+
+(defun evil-normalize (beg end type &rest properties)
+  "Normalize BEG and END as TYPE with PROPERTIES.
+Returns a list (BEG END TYPE PROPERTIES ...), where the tail
+may contain a property list."
+  (apply #'evil-transform :normalize beg end type properties))
+
+(defun evil-transform (transform beg end type &rest properties)
+  "Apply TRANSFORM on BEG and END with PROPERTIES.
+Returns a list (BEG END TYPE PROPERTIES ...), where the tail
+may contain a property list. If TRANSFORM is undefined,
+return positions unchanged."
+  (let* ((type (or type (evil-type properties)))
+         (transform (when (and type transform)
+                      (evil-type-property type transform))))
+    (if transform
+        (apply transform beg end properties)
+      (apply #'evil-range beg end type properties))))
+
+(defun evil-describe (beg end type &rest properties)
+  "Return description of BEG and END with PROPERTIES.
+If no description is available, return the empty string."
+  (let* ((type (or type (evil-type properties)))
+         (properties (plist-put properties :type type))
+         (describe (evil-type-property type :string)))
+    (or (when describe
+          (apply describe beg end properties))
+        "")))
+
+;;; Ranges
+
+(defun evil-range (beg end &optional type &rest properties)
+  "Return a list (BEG END [TYPE] PROPERTIES...).
+BEG and END are buffer positions (numbers or markers),
+TYPE is a type as per `evil-type-p', and PROPERTIES is
+a property list."
+  (let ((beg (evil-normalize-position beg))
+        (end (evil-normalize-position end)))
+    (when (and (numberp beg) (numberp end))
+      (append (list (min beg end) (max beg end))
+              (when (evil-type-p type)
+                (list type))
+              properties))))
+
+(defun evil-range-p (object)
+  "Whether OBJECT is a range."
+  (and (listp object)
+       (>= (length object) 2)
+       (numberp (nth 0 object))
+       (numberp (nth 1 object))))
+
+(defun evil-range-beginning (range)
+  "Return beginning of RANGE."
+  (when (evil-range-p range)
+    (let ((beg (evil-normalize-position (nth 0 range)))
+          (end (evil-normalize-position (nth 1 range))))
+      (min beg end))))
+
+(defun evil-range-end (range)
+  "Return end of RANGE."
+  (when (evil-range-p range)
+    (let ((beg (evil-normalize-position (nth 0 range)))
+          (end (evil-normalize-position (nth 1 range))))
+      (max beg end))))
+
+(defun evil-range-properties (range)
+  "Return properties of RANGE."
+  (when (evil-range-p range)
+    (if (evil-type range)
+        (nthcdr 3 range)
+      (nthcdr 2 range))))
+
+(defun evil-copy-range (range)
+  "Return a copy of RANGE."
+  (copy-sequence range))
+
+(defun evil-set-range (range &optional beg end type &rest properties)
+  "Set RANGE to have beginning BEG and end END.
+The TYPE and additional PROPERTIES may also be specified.
+If an argument is nil, it's not used; the previous value is retained.
+See also `evil-set-range-beginning', `evil-set-range-end',
+`evil-set-range-type' and `evil-set-range-properties'."
+  (when (evil-range-p range)
+    (let ((beg (or (evil-normalize-position beg)
+                   (evil-range-beginning range)))
+          (end (or (evil-normalize-position end)
+                   (evil-range-end range)))
+          (type (or type (evil-type range)))
+          (plist (evil-range-properties range)))
+      (evil-sort beg end)
+      (setq plist (evil-concat-plists plist properties))
+      (evil-set-range-beginning range beg)
+      (evil-set-range-end range end)
+      (evil-set-range-type range type)
+      (evil-set-range-properties range plist)
+      range)))
+
+(defun evil-set-range-beginning (range beg &optional copy)
+  "Set RANGE's beginning to BEG.
+If COPY is non-nil, return a copy of RANGE."
+  (when copy
+    (setq range (evil-copy-range range)))
+  (setcar range beg)
+  range)
+
+(defun evil-set-range-end (range end &optional copy)
+  "Set RANGE's end to END.
+If COPY is non-nil, return a copy of RANGE."
+  (when copy
+    (setq range (evil-copy-range range)))
+  (setcar (cdr range) end)
+  range)
+
+(defun evil-set-range-type (range type &optional copy)
+  "Set RANGE's type to TYPE.
+If COPY is non-nil, return a copy of RANGE."
+  (when copy
+    (setq range (evil-copy-range range)))
+  (if type
+      (setcdr (cdr range)
+              (cons type (evil-range-properties range)))
+    (setcdr (cdr range) (evil-range-properties range)))
+  range)
+
+(defun evil-set-range-properties (range properties &optional copy)
+  "Set RANGE's properties to PROPERTIES.
+If COPY is non-nil, return a copy of RANGE."
+  (when copy
+    (setq range (evil-copy-range range)))
+  (if (evil-type range)
+      (setcdr (cdr (cdr range)) properties)
+    (setcdr (cdr range) properties))
+  range)
+
+(defun evil-range-union (range1 range2 &optional type)
+  "Return the union of the ranges RANGE1 and RANGE2.
+If the ranges have conflicting types, use RANGE1's type.
+This can be overridden with TYPE."
+  (when (and (evil-range-p range1)
+             (evil-range-p range2))
+    (evil-range (min (evil-range-beginning range1)
+                     (evil-range-beginning range2))
+                (max (evil-range-end range1)
+                     (evil-range-end range2))
+                (or type
+                    (evil-type range1)
+                    (evil-type range2)))))
+
+(defun evil-subrange-p (range1 range2)
+  "Whether RANGE1 is contained within RANGE2."
+  (and (evil-range-p range1)
+       (evil-range-p range2)
+       (<= (evil-range-beginning range2)
+           (evil-range-beginning range1))
+       (>= (evil-range-end range2)
+           (evil-range-end range1))))
+
+(defun evil-select-inner-object (thing beg end type &optional count line)
+  "Return an inner text object range of COUNT objects.
+If COUNT is positive, return objects following point; if COUNT is
+negative, return objects preceding point.  If one is unspecified,
+the other is used with a negative argument.  THING is a symbol
+understood by thing-at-point.  BEG, END and TYPE specify the
+current selection.  If LINE is non-nil, the text object should be
+linewise, otherwise it is character wise."
+  (let* ((count (or count 1))
+         (bnd (or (let ((b (bounds-of-thing-at-point thing)))
+                    (and b (< (point) (cdr b)) b))
+                  (evil-bounds-of-not-thing-at-point thing))))
+    ;; check if current object is selected
+    (when (or (not beg) (not end)
+              (> beg (car bnd))
+              (< end (cdr bnd))
+              (and (eq type 'inclusive)
+                   (= (1+ beg) end))) ; empty region does not count
+      (when (or (not beg) (< (car bnd) beg)) (setq beg (car bnd)))
+      (when (or (not end) (> (cdr bnd) end)) (setq end (cdr bnd)))
+      (setq count (if (> count 0) (1- count) (1+ count))))
+    (goto-char (if (< count 0) beg end))
+    (evil-forward-nearest count
+                          #'(lambda (cnt) (forward-thing thing cnt))
+                          #'(lambda (cnt) (evil-forward-not-thing thing cnt)))
+    (evil-range (if (>= count 0) beg (point))
+                (if (< count 0) end (point))
+                (if line 'line type)
+                :expanded t)))
+
+(defun evil-select-an-object (thing beg end type count &optional line)
+  "Return an outer text object range of COUNT objects.
+If COUNT is positive, return objects following point; if COUNT is
+negative, return objects preceding point.  If one is unspecified,
+the other is used with a negative argument.  THING is a symbol
+understood by thing-at-point.  BEG, END and TYPE specify the
+current selection.  If LINE is non-nil, the text object should be
+linewise, otherwise it is character wise."
+  (let* ((dir (if (> (or count 1) 0) +1 -1))
+         (count (abs (or count 1)))
+         (objbnd (let ((b (bounds-of-thing-at-point thing)))
+                   (and b (< (point) (cdr b)) b)))
+         (bnd (or objbnd (evil-bounds-of-not-thing-at-point thing)))
+         addcurrent other)
+    ;; check if current object is not selected
+    (when (or (not beg) (not end)
+              (> beg (car bnd))
+              (< end (cdr bnd))
+              (and (eq type 'inclusive)
+                   (= (1+ beg) end))) ; empty region does not count
+      ;; if not, enlarge selection
+      (when (or (not beg) (< (car bnd) beg)) (setq beg (car bnd)))
+      (when (or (not end) (> (cdr bnd) end)) (setq end (cdr bnd)))
+      (if objbnd (setq addcurrent t)))
+    ;; make other and (point) reflect the selection
+    (cond
+     ((> dir 0) (goto-char end) (setq other beg))
+     (t (goto-char beg) (setq other end)))
+    (cond
+     ;; do nothing more than only current is selected
+     ((not (and (= beg (car bnd)) (= end (cdr bnd)))))
+     ;; current match is thing, add whitespace
+     (objbnd
+      (let ((wsend (evil-with-restriction
+                       ;; restrict to current line if we do non-line selection
+                       (and (not line) (line-beginning-position))
+                       (and (not line) (line-end-position))
+                     (evil-bounds-of-not-thing-at-point thing dir))))
+        (cond
+         (wsend
+          ;; add whitespace at end
+          (goto-char wsend)
+          (setq addcurrent t))
+         (t
+          ;; no whitespace at end, try beginning
+          (save-excursion
+            (goto-char other)
+            (setq wsend
+                  (evil-with-restriction
+                      ;; restrict to current line if we do non-line selection
+                      (and (not line) (line-beginning-position))
+                      (and (not line) (line-end-position))
+                    (evil-bounds-of-not-thing-at-point thing (- dir))))
+            (when wsend (setq other wsend addcurrent t)))))))
+     ;; current match is whitespace, add thing
+     (t
+      (forward-thing thing dir)
+      (setq addcurrent t)))
+    ;; possibly count current object as selection
+    (if addcurrent (setq count (1- count)))
+    ;; move
+    (dotimes (var count)
+      (let ((wsend (evil-bounds-of-not-thing-at-point thing dir)))
+        (if (and wsend (/= wsend (point)))
+            ;; start with whitespace
+            (forward-thing thing dir)
+          ;; start with thing
+          (forward-thing thing dir)
+          (setq wsend (evil-bounds-of-not-thing-at-point thing dir))
+          (when wsend (goto-char wsend)))))
+    ;; return range
+    (evil-range (if (> dir 0) other (point))
+                (if (< dir 0) other (point))
+                (if line 'line type)
+                :expanded t)))
+
+(defun evil--get-block-range (op cl selection-type)
+  "Return the exclusive range of a visual selection.
+OP and CL are pairs of buffer positions for the opening and
+closing delimiter of a range. SELECTION-TYPE is the desired type
+of selection.  It is a symbol that determines which parts of the
+block are selected.  If it is 'inclusive or t the returned range
+is \(cons (car OP) (cdr CL)). If it is 'exclusive or nil the
+returned range is (cons (cdr OP) (car CL)).  If it is
+'exclusive-line the returned range will skip whitespace at the
+end of the line of OP and at the beginning of the line of CL."
+  (cond
+   ((memq selection-type '(inclusive t)) (cons (car op) (cdr cl)))
+   ((memq selection-type '(exclusive nil)) (cons (cdr op) (car cl)))
+   ((eq selection-type 'exclusive-line)
+    (let ((beg (cdr op))
+          (end (car cl)))
+      (save-excursion
+        (goto-char beg)
+        (when (and (eolp) (not (eobp)))
+          (setq beg (line-beginning-position 2)))
+        (goto-char end)
+        (skip-chars-backward " \t")
+        (when (bolp)
+          (setq end (point))
+          (goto-char beg)
+          (when (and (not (bolp)) (< beg end))
+            (setq end (1- end)))))
+      (cons beg end)))
+   (t
+    (user-error "Unknown selection-type %s" selection-type))))
+
+(defun evil-select-block (thing beg end type count
+                                &optional
+                                selection-type
+                                countcurrent
+                                fixedscan)
+  "Return a range (BEG END) of COUNT delimited text objects.
+BEG END TYPE are the currently selected (visual) range.  The
+delimited object must be given by THING-up function (see
+`evil-up-block').
+
+SELECTION-TYPE is symbol that determines which parts of the block
+are selected.  If it is 'inclusive or t OPEN and CLOSE are
+included in the range. If it is 'exclusive or nil the delimiters
+are not contained. If it is 'exclusive-line the delimiters are
+not included as well as adjacent whitespace until the beginning
+of the next line or the end of the previous line. If the
+resulting selection consists of complete lines only and visual
+state is not active, the returned selection is linewise.
+
+If COUNTCURRENT is non-nil an objected is counted if the current
+selection matches that object exactly.
+
+Usually scanning for the surrounding block starts at (1+ beg)
+and (1- end). If this might fail due to the behavior of THING
+then FIXEDSCAN can be set to t. In this case the scan starts at
+BEG and END. One example where this might fail is if BEG and END
+are the delimiters of a string or comment."
+  (save-excursion
+    (save-match-data
+      (let* ((orig-beg beg)
+             (orig-end end)
+             (beg (or beg (point)))
+             (end (or end (point)))
+             (count (abs (or count 1)))
+             op cl op-end cl-end)
+        ;; We always assume at least one selected character.
+        (if (= beg end) (setq end (1+ end)))
+        ;; We scan twice: starting at (1+ beg) forward and at (1- end)
+        ;; backward. The resulting selection is the smaller one.
+        (goto-char (if fixedscan beg (1+ beg)))
+        (when (and (zerop (funcall thing +1)) (match-beginning 0))
+          (setq cl (cons (match-beginning 0) (match-end 0)))
+          (goto-char (car cl))
+          (when (and (zerop (funcall thing -1)) (match-beginning 0))
+            (setq op (cons (match-beginning 0) (match-end 0)))))
+        ;; start scanning from end
+        (goto-char (if fixedscan end (1- end)))
+        (when (and (zerop (funcall thing -1)) (match-beginning 0))
+          (setq op-end (cons (match-beginning 0) (match-end 0)))
+          (goto-char (cdr op-end))
+          (when (and (zerop (funcall thing +1)) (match-beginning 0))
+            (setq cl-end (cons (match-beginning 0) (match-end 0)))))
+        ;; Bug #607: use the tightest selection that contains the
+        ;; original selection. If non selection contains the original,
+        ;; use the larger one.
+        (cond
+         ((and (not op) (not cl-end))
+          (error "No surrounding delimiters found"))
+         ((or (not op) ; first not found
+              (and cl-end ; second found
+                   (>= (car op-end) (car op)) ; second smaller
+                   (<= (cdr cl-end) (cdr cl))
+                   (<= (car op-end) beg)      ; second contains orig
+                   (>= (cdr cl-end) end)))
+          (setq op op-end cl cl-end)))
+        (setq op-end op cl-end cl) ; store copy
+        ;; if the current selection contains the surrounding
+        ;; delimiters, they do not count as new selection
+        (let ((cnt (if (and orig-beg orig-end (not countcurrent))
+                       (let ((sel (evil--get-block-range op cl selection-type)))
+                         (if (and (<= orig-beg (car sel))
+                                  (>= orig-end (cdr sel)))
+                             count
+                           (1- count)))
+                     (1- count))))
+          ;; starting from the innermost surrounding delimiters
+          ;; increase selection
+          (when (> cnt 0)
+            (setq op (progn
+                       (goto-char (car op-end))
+                       (funcall thing (- cnt))
+                       (if (match-beginning 0)
+                           (cons (match-beginning 0) (match-end 0))
+                         op))
+                  cl (progn
+                       (goto-char (cdr cl-end))
+                       (funcall thing cnt)
+                       (if (match-beginning 0)
+                           (cons (match-beginning 0) (match-end 0))
+                         cl)))))
+        (let ((sel (evil--get-block-range op cl selection-type)))
+          (setq op (car sel)
+                cl (cdr sel)))
+        (cond
+         ((and (equal op orig-beg) (equal cl orig-end)
+               (or (not countcurrent)
+                   (and countcurrent (/= count 1))))
+          (error "No surrounding delimiters found"))
+         ((save-excursion
+            (and (not (evil-visual-state-p))
+                 (eq type 'inclusive)
+                 (progn (goto-char op) (bolp))
+                 (progn (goto-char cl) (bolp))))
+          (evil-range op cl 'line :expanded t))
+         (t
+          (evil-range op cl type :expanded t)))))))
+
+(defun evil-select-paren (open close beg end type count &optional inclusive)
+  "Return a range (BEG END) of COUNT delimited text objects.
+OPEN and CLOSE specify the opening and closing delimiter,
+respectively. BEG END TYPE are the currently selected (visual)
+range.  If INCLUSIVE is non-nil, OPEN and CLOSE are included in
+the range; otherwise they are excluded.
+
+The types of OPEN and CLOSE specify which kind of THING is used
+for parsing with `evil-select-block'. If OPEN and CLOSE are
+characters `evil-up-paren' is used. Otherwise OPEN and CLOSE
+must be regular expressions and `evil-up-block' is used.
+
+If the selection is exclusive, whitespace at the end or at the
+beginning of the selection until the end-of-line or beginning-of-line
+is ignored."
+  ;; we need special linewise exclusive selection
+  (unless inclusive (setq inclusive 'exclusive-line))
+  (cond
+   ((and (characterp open) (characterp close))
+    (let ((thing #'(lambda (&optional cnt)
+                     (evil-up-paren open close cnt)))
+          (bnd (or (bounds-of-thing-at-point 'evil-string)
+                   (bounds-of-thing-at-point 'evil-comment)
+                   ;; If point is at the opening quote of a string,
+                   ;; this must be handled as if point is within the
+                   ;; string, i.e. the selection must be extended
+                   ;; around the string. Otherwise
+                   ;; `evil-select-block' might do the wrong thing
+                   ;; because it accidentally moves point inside the
+                   ;; string (for inclusive selection) when looking
+                   ;; for the current surrounding block. (re #364)
+                   (and (= (point) (or beg (point)))
+                        (save-excursion
+                          (goto-char (1+ (or beg (point))))
+                          (or (bounds-of-thing-at-point 'evil-string)
+                              (bounds-of-thing-at-point 'evil-comment)))))))
+      (if (not bnd)
+          (evil-select-block thing beg end type count inclusive)
+        (or (evil-with-restriction (car bnd) (cdr bnd)
+              (condition-case nil
+                  (evil-select-block thing beg end type count inclusive)
+                (error nil)))
+            (save-excursion
+              (setq beg (or beg (point))
+                    end (or end (point)))
+              (goto-char (car bnd))
+              (let ((extbeg (min beg (car bnd)))
+                    (extend (max end (cdr bnd))))
+                (evil-select-block thing
+                                   extbeg extend
+                                   type
+                                   count
+                                   inclusive
+                                   (or (< extbeg beg) (> extend end))
+                                   t)))))))
+   (t
+    (evil-select-block #'(lambda (&optional cnt)
+                           (evil-up-block open close cnt))
+                       beg end type count inclusive))))
+
+(defun evil-select-quote-thing (thing beg end type count &optional inclusive)
+  "Selection THING as if it described a quoted object.
+THING is typically either 'evil-quote or 'evil-chars. This
+function is called from `evil-select-quote'."
+  (save-excursion
+    (let* ((count (or count 1))
+           (dir (if (> count 0) 1 -1))
+           (bnd (let ((b (bounds-of-thing-at-point thing)))
+                  (and b (< (point) (cdr b)) b)))
+           contains-string
+           addcurrent
+           wsboth)
+      (if inclusive (setq inclusive t)
+        (when (= (abs count) 2)
+          (setq count dir)
+          (setq inclusive 'quote-only))
+        ;; never extend with exclusive selection
+        (setq beg nil end nil))
+      ;; check if the previously selected range does not contain a
+      ;; string
+      (unless (and beg end
+                   (save-excursion
+                     (goto-char (if (> dir 0) beg end))
+                     (forward-thing thing dir)
+                     (and (<= beg (point)) (< (point) end))))
+        ;; if so forget the range
+        (setq beg nil end nil))
+      ;; check if there is a current object, if not fetch one
+      (when (not bnd)
+        (unless (and (zerop (forward-thing thing dir))
+                     (setq bnd (bounds-of-thing-at-point thing)))
+          (error "No quoted string found"))
+        (if (> dir 0)
+            (setq end (point))
+          (setq beg (point)))
+        (setq addcurrent t))
+      ;; check if current object is not selected
+      (when (or (not beg) (not end) (> beg (car bnd)) (< end (cdr bnd)))
+        ;; if not, enlarge selection
+        (when (or (not beg) (< (car bnd) beg)) (setq beg (car bnd)))
+        (when (or (not end) (> (cdr bnd) end)) (setq end (cdr bnd)))
+        (setq addcurrent t wsboth t))
+      ;; maybe count current element
+      (when addcurrent
+        (setq count (if (> dir 0) (1- count) (1+ count))))
+      ;; enlarge selection
+      (goto-char (if (> dir 0) end beg))
+      (when (and (not addcurrent)
+                 (= count (forward-thing thing count)))
+        (error "No quoted string found"))
+      (if (> dir 0) (setq end (point)) (setq beg (point)))
+      ;; add whitespace
+      (cond
+       ((not inclusive) (setq beg (1+ beg) end (1- end)))
+       ((not (eq inclusive 'quote-only))
+        ;; try to add whitespace in forward direction
+        (goto-char (if (> dir 0) end beg))
+        (if (setq bnd (bounds-of-thing-at-point 'evil-space))
+            (if (> dir 0) (setq end (cdr bnd)) (setq beg (car bnd)))
+          ;; if not found try backward direction
+          (goto-char (if (> dir 0) beg end))
+          (if (and wsboth (setq bnd (bounds-of-thing-at-point 'evil-space)))
+              (if (> dir 0) (setq beg (car bnd)) (setq end (cdr bnd)))))))
+      (evil-range beg end
+                  ;; HACK: fixes #583
+                  ;; When not in visual state, an empty range is
+                  ;; possible. However, this cannot be achieved with
+                  ;; inclusive ranges, hence we use exclusive ranges
+                  ;; in this case. In visual state the range must be
+                  ;; inclusive because otherwise the selection would
+                  ;; be wrong.
+                  (if (evil-visual-state-p) 'inclusive 'exclusive)
+                  :expanded t))))
+
+(defun evil-select-quote (quote beg end type count &optional inclusive)
+  "Return a range (BEG END) of COUNT quoted text objects.
+QUOTE specifies the quotation delimiter. BEG END TYPE are the
+currently selected (visual) range.
+
+If INCLUSIVE is nil the previous selection is ignore. If there is
+quoted string at point this object will be selected, otherwise
+the following (if (> COUNT 0)) or preceeding object (if (< COUNT
+0)) is selected. If (/= (abs COUNT) 2) the delimiting quotes are not
+contained in the range, otherwise they are contained in the range.
+
+If INCLUSIVE is non-nil the selection depends on the previous
+selection. If the currently selection contains at least one
+character that is contained in a quoted string then the selection
+is extended, otherwise it is thrown away. If there is a
+non-selected object at point then this object is added to the
+selection. Otherwise the selection is extended to the
+following (if (> COUNT 0)) or preceeding object (if (< COUNT
+0)). Any whitespace following (or preceeding if (< COUNT 0)) the
+new selection is added to the selection. If no such whitespace
+exists and the selection contains only one quoted string then the
+preceeding (or following) whitespace is added to the range. "
+  (let ((evil-forward-quote-char quote))
+    (or (let ((bnd (or (bounds-of-thing-at-point 'evil-comment)
+                       (bounds-of-thing-at-point 'evil-string))))
+          (when (and bnd (< (point) (cdr bnd))
+                     (/= (char-after (car bnd)) quote)
+                     (/= (char-before (cdr bnd)) quote))
+            (evil-with-restriction (car bnd) (cdr bnd)
+              (condition-case nil
+                  (evil-select-quote-thing 'evil-quote-simple
+                                           beg end type
+                                           count
+                                           inclusive)
+                (error nil)))))
+        (let ((evil-forward-quote-char quote))
+          (evil-select-quote-thing 'evil-quote
+                                   beg end type
+                                   count
+                                   inclusive)))))
+
+(defun evil-select-xml-tag (beg end type &optional count inclusive)
+  "Return a range (BEG END) of COUNT matching XML tags.
+If INCLUSIVE is non-nil, the tags themselves are included
+from the range."
+  (cond
+   ((and (not inclusive) (= (abs (or count 1)) 1))
+    (let ((rng (evil-select-block #'evil-up-xml-tag beg end type count nil t)))
+      (if (or (and beg (= beg (evil-range-beginning rng))
+                   end (= end (evil-range-end rng)))
+              (= (evil-range-beginning rng) (evil-range-end rng)))
+          (evil-select-block #'evil-up-xml-tag beg end type count t)
+        rng)))
+   (t
+    (evil-select-block #'evil-up-xml-tag beg end type count inclusive))))
+
+(defun evil-expand-range (range &optional copy)
+  "Expand RANGE according to its type.
+Return a new range if COPY is non-nil."
+  (when copy
+    (setq range (evil-copy-range range)))
+  (unless (plist-get (evil-range-properties range) :expanded)
+    (setq range (evil-transform-range :expand range)))
+  range)
+
+(defun evil-contract-range (range &optional copy)
+  "Contract RANGE according to its type.
+Return a new range if COPY is non-nil."
+  (evil-transform-range :contract range copy))
+
+(defun evil-normalize-range (range &optional copy)
+  "Normalize RANGE according to its type.
+Return a new range if COPY is non-nil."
+  (evil-transform-range :normalize range copy))
+
+(defun evil-transform-range (transform range &optional copy)
+  "Apply TRANSFORM to RANGE according to its type.
+Return a new range if COPY is non-nil."
+  (when copy
+    (setq range (evil-copy-range range)))
+  (when (evil-type range)
+    (apply #'evil-set-range range
+           (apply #'evil-transform transform range)))
+  range)
+
+(defun evil-describe-range (range)
+  "Return description of RANGE.
+If no description is available, return the empty string."
+  (apply #'evil-describe range))
+
+;;; Undo
+
+(defun evil-start-undo-step (&optional continue)
+  "Start a undo step.
+All following buffer modifications are grouped together as a
+single action. If CONTINUE is non-nil, preceding modifications
+are included. The step is terminated with `evil-end-undo-step'."
+  (when (and (listp buffer-undo-list)
+             (not evil-in-single-undo))
+    (if evil-undo-list-pointer
+        (evil-refresh-undo-step)
+      (unless (or continue (null (car-safe buffer-undo-list)))
+        (undo-boundary))
+      (setq evil-undo-list-pointer (or buffer-undo-list t)))))
+
+(defun evil-end-undo-step (&optional continue)
+  "End a undo step started with `evil-start-undo-step'.
+Adds an undo boundary unless CONTINUE is specified."
+  (when (and (listp buffer-undo-list)
+             evil-undo-list-pointer
+             (not evil-in-single-undo))
+    (evil-refresh-undo-step)
+    (unless (or continue (null (car-safe buffer-undo-list)))
+      (undo-boundary))
+    (setq evil-undo-list-pointer nil)))
+
+(defun evil-refresh-undo-step ()
+  "Refresh `buffer-undo-list' entries for current undo step.
+Undo boundaries until `evil-undo-list-pointer' are removed to
+make the entries undoable as a single action. See
+`evil-start-undo-step'."
+  (when evil-undo-list-pointer
+    (setq buffer-undo-list
+          (evil-filter-list #'null buffer-undo-list evil-undo-list-pointer))
+    (setq evil-undo-list-pointer (or buffer-undo-list t))))
+
+(defmacro evil-with-undo (&rest body)
+  "Execute BODY with enabled undo.
+If undo is disabled in the current buffer, the undo information
+is stored in `evil-temporary-undo' instead of `buffer-undo-list'."
+  (declare (indent defun)
+           (debug t))
+  `(unwind-protect
+       (let (buffer-undo-list)
+         (unwind-protect
+             (progn ,@body)
+           (setq evil-temporary-undo buffer-undo-list)
+           ;; ensure evil-temporary-undo starts with exactly one undo
+           ;; boundary marker, i.e. nil
+           (unless (null (car-safe evil-temporary-undo))
+             (push nil evil-temporary-undo))))
+     (unless (eq buffer-undo-list t)
+       ;; undo is enabled, so update the global buffer undo list
+       (setq buffer-undo-list
+             ;; prepend new undos (if there are any)
+             (if (cdr evil-temporary-undo)
+                 (nconc evil-temporary-undo buffer-undo-list)
+               buffer-undo-list)
+             evil-temporary-undo nil))))
+
+(defmacro evil-with-single-undo (&rest body)
+  "Execute BODY as a single undo step."
+  (declare (indent defun)
+           (debug t))
+  `(let (evil-undo-list-pointer)
+     (evil-with-undo
+       (unwind-protect
+           (progn
+             (evil-start-undo-step)
+             (let ((evil-in-single-undo t))
+               ,@body))
+         (evil-end-undo-step)))))
+
+(defun evil-undo-pop ()
+  "Undo the last buffer change.
+Removes the last undo information from `buffer-undo-list'.
+If undo is disabled in the current buffer, use the information
+in `evil-temporary-undo' instead."
+  (let ((paste-undo (list nil)))
+    (let ((undo-list (if (eq buffer-undo-list t)
+                         evil-temporary-undo
+                       buffer-undo-list)))
+      (when (or (not undo-list) (car undo-list))
+        (user-error "Can't undo previous change"))
+      (while (and undo-list (null (car undo-list)))
+        (pop undo-list)) ; remove nil
+      (while (and undo-list (car undo-list))
+        (push (pop undo-list) paste-undo))
+      (let ((buffer-undo-list (nreverse paste-undo)))
+        (evil-save-echo-area
+          (undo)))
+      (if (eq buffer-undo-list t)
+          (setq evil-temporary-undo nil)
+        (setq buffer-undo-list undo-list)))))
+
+;;; Search
+(defun evil-transform-regexp (regexp replacements-alist)
+  (let ((pos 0) result)
+    (replace-regexp-in-string
+     "\\\\+[^\\\\]"
+     #'(lambda (txt)
+         (let* ((b (match-beginning 0))
+                (e (match-end 0))
+                (ch (aref txt (1- e)))
+                (repl (assoc ch replacements-alist)))
+           (if (and repl (zerop (mod (length txt) 2)))
+               (concat (substring txt b (- e 2))
+                       (cdr repl))
+             txt)))
+     regexp nil t)))
+
+(defun evil-transform-magic (str magic quote transform &optional start)
+  "Transforms STR with magic characters.
+MAGIC is a regexp that matches all potential magic
+characters. Each occurence of CHAR as magic character within str
+is replaced by the result of calling the associated TRANSFORM
+function. TRANSFORM is a function taking two arguments, the
+character to be transformed and the rest of string after the
+character. The function should return a triple (REPLACEMENT REST
+. STOP) where REPLACEMENT is the replacement and REST is the rest
+of the string that has not been transformed. If STOP is non-nil
+then the substitution stops immediately.  The replacement starts
+at position START, everything before that position is returned
+literally.  The result is a pair (RESULT . REST). RESULT is a
+list containing the transformed parts in order. If two
+subsequents parts are both strings, they are concatenated. REST
+is the untransformed rest string (usually \"\" but may be more if
+TRANSFORM stopped the substitution). Which characters are
+considered as magic characters (i.e. the transformation happens
+if the character is NOT preceeded by a backslash) is determined
+by `evil-magic'. The special tokens \\v, \\V, \\m and \\M have
+always a special meaning (like in Vim) and should not be
+contained in TRANSFORMS, otherwise their meaning is overwritten.
+
+The parameter QUOTE is a quoting function applied to literal
+transformations, usually `regexp-quote' or `replace-quote'."
+  (save-match-data
+    (let ((regexp (concat "\\(?:\\`\\|[^\\]\\)\\(\\\\\\(?:\\(" magic "\\)\\|\\(.\\)\\)\\|\\(" magic "\\)\\)"))
+          (magic-chars (evil-get-magic evil-magic))
+          (evil-magic evil-magic)
+          (quote (or quote #'identity))
+          result stop)
+      (while (and (not stop) str (string-match regexp str))
+        (unless (zerop (match-beginning 1))
+          (push (substring str 0 (match-beginning 1)) result))
+        (let ((char (or (match-string 2 str)
+                        (match-string 3 str)
+                        (match-string 4 str)))
+              (rest (substring str (match-end 0))))
+          (cond
+           ((match-beginning 4)
+            ;; magic character without backslash
+            (if (string-match magic-chars char)
+                ;; magic, do transform
+                (let ((trans (funcall transform (aref char 0) rest)))
+                  (push (car trans) result)
+                  (setq str (cadr trans) stop (nthcdr 2 trans)))
+              ;; non-magic, literal transformation
+              (push (funcall quote char) result)
+              (setq str rest)))
+           ((match-beginning 2)
+            ;; magic character with backslash
+            (if (not (string-match magic-chars char))
+                ;; non-magic, do transform
+                (let ((trans (funcall transform (aref char 0) rest)))
+                  (push (car trans) result)
+                  (setq str (cadr trans) stop (nthcdr 2 trans)))
+              ;; magic, literal transformation
+              (push (funcall quote char) result)
+              (setq str rest)))
+           ((memq (aref char 0) '(?m ?M ?v ?V))
+            (setq evil-magic (cdr (assq (aref char 0)
+                                        '((?m . t)
+                                          (?M . nil)
+                                          (?v . very-magic)
+                                          (?V . very-nomagic)))))
+            (setq magic-chars (evil-get-magic evil-magic))
+            (setq str rest))
+           (t
+            ;; non-magic char with backslash, literal transformation
+            (push (funcall quote char) result)
+            (setq str rest)))))
+      (cond
+       ((and str (not stop))
+        (push str result)
+        (setq str ""))
+       ((not str)
+        (setq str "")))
+      ;; concatenate subsequent strings
+      ;; note that result is in reverse order
+      (let (repl)
+        (while result
+          (cond
+           ((and (stringp (car result))
+                 (zerop (length (car result))))
+            (pop result))
+           ((and (stringp (car result))
+                 (stringp (cadr result)))
+            (setq result (cons (concat (cadr result)
+                                       (car result))
+                               (nthcdr 2 result))))
+           (t
+            (push (pop result) repl))))
+        (cons repl str)))))
+
+(defconst evil-vim-regexp-replacements
+  '((?n  . "\n")           (?r  . "\r")
+    (?t  . "\t")           (?b  . "\b")
+    (?s  . "[[:space:]]")  (?S  . "[^[:space:]]")
+    (?d  . "[[:digit:]]")  (?D  . "[^[:digit:]]")
+    (?x  . "[[:xdigit:]]") (?X  . "[^[:xdigit:]]")
+    (?o  . "[0-7]")        (?O  . "[^0-7]")
+    (?a  . "[[:alpha:]]")  (?A  . "[^[:alpha:]]")
+    (?l  . "[a-z]")        (?L  . "[^a-z]")
+    (?u  . "[A-Z]")        (?U  . "[^A-Z]")
+    (?y  . "\\s")          (?Y  . "\\S")
+    (?\( . "\\(")          (?\) . "\\)")
+    (?{  . "\\{")          (?}  . "\\}")
+    (?\[ . "[")            (?\] . "]")
+    (?<  . "\\<")          (?>  . "\\>")
+    (?_  . "\\_")
+    (?*  . "*")            (?+  . "+")
+    (??  . "?")            (?=  . "?")
+    (?.  . ".")
+    (?`  . "`")            (?^  . "^")
+    (?$  . "$")            (?|  . "\\|")))
+
+(defconst evil-regexp-magic "[][(){}<>_dDsSxXoOaAlLuUwWyY.*+?=^$`|nrtb]")
+
+(defun evil-transform-vim-style-regexp (regexp)
+  "Transforms vim-style backslash codes to Emacs regexp.
+This includes the backslash codes \\d, \\D, \\s, \\S, \\x, \\X,
+\\o, \\O, \\a, \\A, \\l, \\L, \\u, \\U and \\w, \\W. The new
+codes \\y and \\Y can be used instead of the Emacs code \\s and
+\\S which have a different meaning in Vim-style."
+  (car
+   (car
+    (evil-transform-magic
+     regexp evil-regexp-magic #'regexp-quote
+     #'(lambda (char rest)
+         (let ((repl (assoc char evil-vim-regexp-replacements)))
+           (if repl
+               (list (cdr repl) rest)
+             (list (concat "\\" (char-to-string char)) rest))))))))
+
+;;; Substitute
+
+(defun evil-downcase-first (str)
+  "Return STR with the first letter downcased."
+  (if (zerop (length str))
+      str
+    (concat (downcase (substring str 0 1))
+            (substring str 1))))
+
+(defun evil-upcase-first (str)
+  "Return STR with the first letter upcased."
+  (if (zerop (length str))
+      str
+    (concat (upcase (substring str 0 1))
+            (substring str 1))))
+
+(defun evil-get-magic (magic)
+  "Returns a regexp matching the magic characters according to MAGIC.
+Depending on the value of MAGIC the following characters are
+considered magic.
+  t             [][{}*+?.&~$^
+  nil           [][{}*+?$^
+  'very-magic   not 0-9A-Za-z_
+  'very-nomagic empty."
+  (cond
+   ((eq magic t) "[][}{*+?.&~$^]")
+   ((eq magic 'very-magic) "[^0-9A-Za-z_]")
+   ((eq magic 'very-nomagic) "\\\\")
+   (t "[][}{*+?$^]")))
+
+;; TODO: support magic characters in patterns
+(defconst evil-replacement-magic "[eElLuU0-9&#,rnbt=]"
+  "All magic characters in a replacement string")
+
+(defun evil-compile-subreplacement (to &optional start)
+  "Convert a regexp replacement TO to Lisp from START until \\e or \\E.
+Returns a pair (RESULT . REST). RESULT is a list suitable for
+`perform-replace' if necessary, the original string if not.
+REST is the unparsed remainder of TO."
+  (let ((result
+         (evil-transform-magic
+          to evil-replacement-magic #'replace-quote
+          #'(lambda (char rest)
+              (cond
+               ((eq char ?#)
+                (list '(number-to-string replace-count) rest))
+               ((eq char ?r) (list "\r" rest))
+               ((eq char ?n) (list "\n" rest))
+               ((eq char ?b) (list "\b" rest))
+               ((eq char ?t) (list "\t" rest))
+               ((memq char '(?e ?E))
+                `("" ,rest . t))
+               ((memq char '(?l ?L ?u ?U))
+                (let ((result (evil-compile-subreplacement rest))
+                      (func (cdr (assoc char
+                                        '((?l . evil-downcase-first)
+                                          (?L . downcase)
+                                          (?u . evil-upcase-first)
+                                          (?U . upcase))))))
+                  (list `(,func
+                          (replace-quote
+                           (evil-match-substitute-replacement
+                            ,(car result)
+                            (not case-replace))))
+                        (cdr result))))
+               ((eq char ?=)
+                (when (or (zerop (length rest))
+                          (not (eq (aref rest 0) ?@)))
+                  (user-error "Expected @ after \\="))
+                (when (< (length rest) 2)
+                  (user-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)))
+                       (end
+                        ;; swallow a space after a symbol
+                        (if (and (or (symbolp (car obj))
+                                     ;; swallow a space after 'foo,
+                                     ;; but not after (quote foo)
+                                     (and (eq (car-safe (car obj)) 'quote)
+                                          (not (= ?\( (aref rest 0)))))
+                                 (eq (string-match " " rest (cdr obj))
+                                     (cdr obj)))
+                            (1+ (cdr obj))
+                          (cdr obj))))
+                  (list result (substring rest end))))
+               ((eq char ?0)
+                (list "\\&" rest))
+               (t
+                (list (concat "\\" (char-to-string char)) rest))))
+          start)))
+    (let ((rest (cdr result))
+          (result (car result)))
+      (replace-match-string-symbols result)
+      (cons (if (cdr result)
+                (cons 'concat result)
+              (or (car result) ""))
+            rest))))
+
+(defun evil-compile-replacement (to)
+  "Maybe convert a regexp replacement TO to Lisp.
+Returns a list suitable for `perform-replace' if necessary, the
+original string if not. Currently the following magic characters
+in replacements are supported: 0-9&#lLuUrnbt,
+The magic character , (comma) start an Emacs-lisp expression."
+  (when (stringp to)
+    (save-match-data
+      (cons 'replace-eval-replacement
+            (car (evil-compile-subreplacement to))))))
+
+(defun evil-replace-match (replacement &optional fixedcase string)
+  "Replace text match by last search with REPLACEMENT.
+If REPLACEMENT is an expression it will be evaluated to compute
+the replacement text, otherwise the function behaves as
+`replace-match'."
+  (if (stringp replacement)
+      (replace-match replacement fixedcase nil string)
+    (replace-match (funcall (car replacement)
+                            (cdr replacement)
+                            0)
+                   fixedcase nil string)))
+
+(defun evil-match-substitute-replacement (replacement &optional fixedcase string)
+  "Return REPLACEMENT as it will be inserted by `evil-replace-match'."
+  (if (stringp replacement)
+      (match-substitute-replacement replacement fixedcase nil string)
+    (match-substitute-replacement (funcall (car replacement)
+                                           (cdr replacement)
+                                           0)
+                                  fixedcase nil string)))
+
+;;; Alignment
+
+(defun evil-justify-lines (beg end justify position)
+  "Justifes all lines in a range.
+BEG and END specify the range of those lines to be
+justified. JUSTIFY is either 'left, 'right or 'center according
+to the justification type. POSITION is the maximal text width for
+right and center justification or the column at which the lines
+should be left-aligned for left justification."
+  (let ((fill-column position)
+        adaptive-fill-mode fill-prefix)
+    (evil-with-restriction
+        (save-excursion
+          (goto-char beg)
+          (line-beginning-position))
+        (save-excursion
+          (goto-char end)
+          (if (bolp)
+              (line-end-position 0)
+            (line-end-position)))
+      (goto-char (point-min))
+      (while (progn
+               (if (eq justify 'left)
+                   (indent-line-to position)
+                 (when (re-search-forward "^[[:space:]]*" nil t)
+                   (delete-region (match-beginning 0)
+                                  (match-end 0)))
+                 (justify-current-line justify nil t))
+               (and (zerop (forward-line)) (bolp))))
+      (goto-char (point-min))
+      (back-to-indentation))))
+
+;;; View helper
+
+(defvar-local evil-list-view-select-action nil)
+(put 'evil-list-view-select-action 'permanent-local t)
+
+(define-derived-mode evil-list-view-mode tabulated-list-mode
+  "Evil List View"
+  (tabulated-list-init-header)
+  (tabulated-list-print))
+
+(defun evil-list-view-goto-entry ()
+  (interactive)
+  (when (and evil-list-view-select-action
+             (not (eobp)))
+    (let* ((line (line-number-at-pos (point)))
+           (entry (elt tabulated-list-entries (1- line))))
+      (funcall evil-list-view-select-action (nth 1 entry)))))
+
+(define-key evil-list-view-mode-map (kbd "q") #'kill-this-buffer)
+(define-key evil-list-view-mode-map [follow-link] nil) ;; allows mouse-1 to be activated
+(define-key evil-list-view-mode-map [mouse-1] #'evil-list-view-goto-entry)
+(define-key evil-list-view-mode-map [return] #'evil-list-view-goto-entry)
+
+(defmacro evil-with-view-list (&rest properties)
+  "Opens new list view buffer.
+
+PROPERTIES is a property-list which supports the following properties:
+
+:name           (required)   The name of the buffer.
+:mode-name      (required)   The name for the mode line.
+:format         (required)   The value for `tabulated-list-format'.
+:entries        (required)   The value for `tabulated-list-entries'.
+:select-action  (optional)   A function for row selection.
+                             It takes in a single parameter, which is the selected row's
+                             vector value that is passed into `:entries'.
+"
+  (declare (indent defun) (debug t))
+  `(let ((bufname (concat "*" ,(plist-get properties :name) "*"))
+         (inhibit-read-only t))
+     (and (get-buffer bufname)
+          (kill-buffer bufname))
+     (let ((buf (get-buffer-create bufname)))
+       (with-current-buffer buf
+         (setq tabulated-list-format ,(plist-get properties :format))
+         (setq tabulated-list-entries ,(plist-get properties :entries))
+         (setq evil-list-view-select-action ,(plist-get properties :select-action))
+         (evil-list-view-mode)
+         (setq mode-name ,(plist-get properties :mode-name))
+         (evil-motion-state))
+       (switch-to-buffer-other-window buf))))
+
+(provide 'evil-common)
+
+;;; evil-common.el ends here