summaryrefslogtreecommitdiff
path: root/elpa/evil-20220510.2302/evil-commands.el
diff options
context:
space:
mode:
Diffstat (limited to 'elpa/evil-20220510.2302/evil-commands.el')
-rw-r--r--elpa/evil-20220510.2302/evil-commands.el4908
1 files changed, 0 insertions, 4908 deletions
diff --git a/elpa/evil-20220510.2302/evil-commands.el b/elpa/evil-20220510.2302/evil-commands.el
deleted file mode 100644
index d6b2e62..0000000
--- a/elpa/evil-20220510.2302/evil-commands.el
+++ /dev/null
@@ -1,4908 +0,0 @@
-;;; evil-commands.el --- Evil commands and operators -*- lexical-binding: t -*-
-;; Author: Vegard Øye <vegard_oye at hotmail.com>
-;; Maintainer: Vegard Øye <vegard_oye at hotmail.com>
-
-;; Version: 1.15.0
-
-;;
-;; 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-common)
-(require 'evil-digraphs)
-(require 'evil-search)
-(require 'evil-states)
-(require 'evil-ex)
-(require 'evil-types)
-(require 'evil-command-window)
-(require 'evil-jumps)
-(require 'evil-vars)
-(require 'flyspell)
-(require 'cl-lib)
-(require 'reveal)
-
-(declare-function imenu--in-alist "imenu")
-
-;;; Motions
-
-;; Movement commands, or motions, are defined with the macro
-;; `evil-define-motion'. A motion is a command with an optional
-;; argument COUNT (interactively accessed by the code "<c>").
-;; It may specify the :type command property (e.g., :type line),
-;; which determines how it is handled by an operator command.
-;; Furthermore, the command must have the command properties
-;; :keep-visual t and :repeat motion; these are automatically
-;; set by the `evil-define-motion' macro.
-
-;;; Code:
-
-(evil-define-motion evil-forward-char (count &optional crosslines noerror)
- "Move cursor to the right by COUNT characters.
-Movement is restricted to the current line unless CROSSLINES is non-nil.
-If NOERROR is non-nil, don't signal an error upon reaching the end
-of the line or the buffer; just return nil."
- :type exclusive
- (interactive "<c>" (list evil-cross-lines
- (evil-kbd-macro-suppress-motion-error)))
- (cond
- (noerror
- (condition-case nil
- (evil-forward-char count crosslines nil)
- (error nil)))
- ((not crosslines)
- ;; for efficiency, narrow the buffer to the projected
- ;; movement before determining the current line
- (evil-with-restriction
- (point)
- (save-excursion
- (evil-forward-char (1+ (or count 1)) t t)
- (point))
- (condition-case err
- (evil-narrow-to-line
- (evil-forward-char count t noerror))
- (error
- ;; Restore the previous command (this one never happend).
- ;; Actually, this preserves the current column if the
- ;; previous command was `evil-next-line' or
- ;; `evil-previous-line'.
- (setq this-command last-command)
- (signal (car err) (cdr err))))))
- (t
- (evil-motion-loop (nil (or count 1))
- (forward-char)
- ;; don't put the cursor on a newline
- (when (and (not evil-move-beyond-eol)
- (not (evil-visual-state-p))
- (not (evil-operator-state-p))
- (eolp) (not (eobp)) (not (bolp)))
- (forward-char))))))
-
-(evil-define-motion evil-backward-char (count &optional crosslines noerror)
- "Move cursor to the left by COUNT characters.
-Movement is restricted to the current line unless CROSSLINES is non-nil.
-If NOERROR is non-nil, don't signal an error upon reaching the beginning
-of the line or the buffer; just return nil."
- :type exclusive
- (interactive "<c>" (list evil-cross-lines
- (evil-kbd-macro-suppress-motion-error)))
- (cond
- (noerror
- (condition-case nil
- (evil-backward-char count crosslines nil)
- (error nil)))
- ((not crosslines)
- ;; restrict movement to the current line
- (evil-with-restriction
- (save-excursion
- (evil-backward-char (1+ (or count 1)) t t)
- (point))
- (1+ (point))
- (condition-case err
- (evil-narrow-to-line
- (evil-backward-char count t noerror))
- (error
- ;; Restore the previous command (this one never happened).
- ;; Actually, this preserves the current column if the
- ;; previous command was `evil-next-line' or
- ;; `evil-previous-line'.
- (setq this-command last-command)
- (signal (car err) (cdr err))))))
- (t
- (evil-motion-loop (nil (or count 1))
- (backward-char)
- ;; don't put the cursor on a newline
- (unless (or (evil-visual-state-p) (evil-operator-state-p))
- (evil-adjust-cursor))))))
-
-(evil-define-motion evil-next-line (count)
- "Move the cursor COUNT lines down."
- :type line
- (let (line-move-visual)
- (evil-line-move (or count 1))))
-
-(evil-define-motion evil-previous-line (count)
- "Move the cursor COUNT lines up."
- :type line
- (let (line-move-visual)
- (evil-line-move (- (or count 1)))))
-
-(evil-define-motion evil-next-visual-line (count)
- "Move the cursor COUNT screen lines down."
- :type exclusive
- (let ((line-move-visual t))
- (evil-line-move (or count 1))))
-
-(evil-define-motion evil-previous-visual-line (count)
- "Move the cursor COUNT screen lines up."
- :type exclusive
- (let ((line-move-visual t))
- (evil-line-move (- (or count 1)))))
-
-;; used for repeated commands like "dd"
-(evil-define-motion evil-line (count)
- "Move COUNT - 1 lines down."
- :type line
- (let (line-move-visual)
- ;; Catch bob and eob errors. These are caused when not moving
- ;; point starting in the first or last line, respectively. In this
- ;; case the current line should be selected.
- (condition-case _err
- (evil-line-move (1- (or count 1)))
- ((beginning-of-buffer end-of-buffer)))))
-
-(evil-define-motion evil-line-or-visual-line (count)
- "Move COUNT - 1 lines down."
- :type screen-line
- (let ((line-move-visual (and evil-respect-visual-line-mode
- visual-line-mode)))
- ;; Catch bob and eob errors. These are caused when not moving
- ;; point starting in the first or last line, respectively. In this
- ;; case the current line should be selected.
- (condition-case _err
- (evil-line-move (1- (or count 1)))
- ((beginning-of-buffer end-of-buffer)))))
-
-(evil-define-motion evil-beginning-of-line ()
- "Move the cursor to the beginning of the current line."
- :type exclusive
- (move-beginning-of-line nil))
-
-(evil-define-motion evil-end-of-line (count)
- "Move the cursor to the end of the current line.
-If COUNT is given, move COUNT - 1 lines downward first."
- :type inclusive
- (move-end-of-line count)
- (when evil-track-eol
- (setq temporary-goal-column most-positive-fixnum
- this-command 'next-line))
- (if (evil-visual-state-p)
- (when evil-v$-excludes-newline
- (let ((evil-move-beyond-eol nil))
- (evil-adjust-cursor)))
- (evil-adjust-cursor)
- (when (eolp)
- ;; prevent "c$" and "d$" from deleting blank lines
- (setq evil-this-type 'exclusive))))
-
-(evil-define-motion evil-beginning-of-visual-line ()
- "Move the cursor to the first character of the current screen line."
- :type exclusive
- (if (fboundp 'beginning-of-visual-line)
- (beginning-of-visual-line)
- (beginning-of-line)))
-
-(evil-define-motion evil-end-of-visual-line (count)
- "Move the cursor to the last character of the current screen line.
-If COUNT is given, move COUNT - 1 screen lines downward first."
- :type inclusive
- (if (fboundp 'end-of-visual-line)
- (end-of-visual-line count)
- (end-of-line count)))
-
-(evil-define-motion evil-end-of-line-or-visual-line (count)
- "Move the cursor to the last character of the current screen
-line if `visual-line-mode' is active and
-`evil-respect-visual-line-mode' is non-nil. If COUNT is given,
-move COUNT - 1 screen lines downward first."
- :type inclusive
- (if (and (fboundp 'end-of-visual-line)
- evil-respect-visual-line-mode
- visual-line-mode)
- (end-of-visual-line count)
- (evil-end-of-line count)))
-
-(evil-define-motion evil-middle-of-visual-line ()
- "Move the cursor to the middle of the current visual line."
- :type exclusive
- (beginning-of-visual-line)
- (evil-with-restriction
- nil
- (save-excursion (end-of-visual-line) (point))
- (move-to-column (+ (current-column)
- -1
- (/ (with-no-warnings (window-body-width)) 2)))))
-
-(evil-define-motion evil-percentage-of-line (count)
- "Move the cursor to COUNT % of the width of the current line.
-If no COUNT is given, default to 50%."
- :type exclusive
- (let ((line-length (- (line-end-position)
- (line-beginning-position)
- (if evil-move-beyond-eol -1 0))))
- (move-to-column (truncate (* line-length (/ (or count 50) 100.0))))))
-
-(evil-define-motion evil-first-non-blank ()
- "Move the cursor to the first non-blank character of the current line."
- :type exclusive
- (evil-narrow-to-line (back-to-indentation)))
-
-(evil-define-motion evil-last-non-blank (count)
- "Move the cursor to the last non-blank character of the current line.
-If COUNT is given, move COUNT - 1 lines downward first."
- :type inclusive
- (goto-char
- (save-excursion
- (evil-move-beginning-of-line count)
- (if (re-search-forward "[ \t]*$")
- (max (line-beginning-position)
- (1- (match-beginning 0)))
- (line-beginning-position)))))
-
-(evil-define-motion evil-first-non-blank-of-visual-line ()
- "Move the cursor to the first non blank character
-of the current screen line."
- :type exclusive
- (evil-beginning-of-visual-line)
- (skip-chars-forward " \t\r"))
-
-(evil-define-motion evil-next-line-first-non-blank (count)
- "Move the cursor COUNT lines down on the first non-blank character."
- :type line
- (let ((this-command this-command))
- (evil-next-line (or count 1)))
- (evil-first-non-blank))
-
-(evil-define-motion evil-next-line-1-first-non-blank (count)
- "Move the cursor COUNT-1 lines down on the first non-blank character."
- :type line
- (let ((this-command this-command))
- (evil-next-line (1- (or count 1))))
- (evil-first-non-blank))
-
-(evil-define-motion evil-previous-line-first-non-blank (count)
- "Move the cursor COUNT lines up on the first non-blank character."
- :type line
- (let ((this-command this-command))
- (evil-previous-line (or count 1)))
- (evil-first-non-blank))
-
-(evil-define-motion evil-goto-line (count)
- "Go to line COUNT. By default the last line."
- :jump t
- :type line
- (evil-ensure-column
- (if (null count)
- (goto-char (point-max))
- (goto-char (point-min))
- (forward-line (1- count)))))
-
-(evil-define-motion evil-goto-first-line (count)
- "Go to line COUNT. By default the first line."
- :jump t
- :type line
- (evil-goto-line (or count 1)))
-
-(evil-define-motion evil-forward-word-begin (count &optional bigword)
- "Move the cursor to the beginning of the COUNT-th next word.
-If BIGWORD is non-nil, move by WORDS.
-
-If this command is called in operator-pending state it behaves
-differently. If point reaches the beginning of a word on a new
-line point is moved back to the end of the previous line.
-
-If called after a change operator, i.e. cw or cW,
-`evil-want-change-word-to-end' is non-nil and point is on a word,
-then both behave like ce or cE.
-
-If point is at the end of the buffer and cannot be moved signal
-'end-of-buffer is raised.
-"
- :type exclusive
- (let ((thing (if bigword 'evil-WORD 'evil-word))
- (orig (point))
- (count (or count 1)))
- (evil-signal-at-bob-or-eob count)
- (cond
- ;; default motion, beginning of next word
- ((not (evil-operator-state-p))
- (evil-forward-beginning thing count))
- ;; the evil-change operator, maybe behave like ce or cE
- ((and evil-want-change-word-to-end
- (memq evil-this-operator evil-change-commands)
- (< orig (or (cdr-safe (bounds-of-thing-at-point thing)) orig)))
- ;; forward-thing moves point to the correct position because
- ;; this is an exclusive motion
- (forward-thing thing count))
- ;; operator state
- (t
- (prog1 (evil-forward-beginning thing count)
- ;; if we reached the beginning of a word on a new line in
- ;; Operator-Pending state, go back to the end of the previous
- ;; line
- (when (and (> (line-beginning-position) orig)
- (looking-back "^[[:space:]]*" (line-beginning-position)))
- ;; move cursor back as long as the line contains only
- ;; whitespaces and is non-empty
- (evil-move-end-of-line 0)
- ;; skip non-empty lines containing only spaces
- (while (and (looking-back "^[[:space:]]+$" (line-beginning-position))
- (not (<= (line-beginning-position) orig)))
- (evil-move-end-of-line 0))
- ;; but if the previous line is empty, delete this line
- (when (bolp) (forward-char))))))))
-
-(evil-define-motion evil-forward-word-end (count &optional bigword)
- "Move the cursor to the end of the COUNT-th next word.
-If BIGWORD is non-nil, move by WORDS."
- :type inclusive
- (let ((thing (if bigword 'evil-WORD 'evil-word))
- (count (or count 1)))
- (evil-signal-at-bob-or-eob count)
- ;; Evil special behaviour: e or E on a one-character word in
- ;; operator state does not move point
- (unless (and (evil-operator-state-p)
- (= 1 count)
- (let ((bnd (bounds-of-thing-at-point thing)))
- (and bnd
- (= (car bnd) (point))
- (= (cdr bnd) (1+ (point)))))
- (looking-at "[[:word:]]"))
- (evil-forward-end thing count))))
-
-(evil-define-motion evil-backward-word-begin (count &optional bigword)
- "Move the cursor to the beginning of the COUNT-th previous word.
-If BIGWORD is non-nil, move by WORDS."
- :type exclusive
- (let ((thing (if bigword 'evil-WORD 'evil-word)))
- (evil-signal-at-bob-or-eob (- (or count 1)))
- (evil-backward-beginning thing count)))
-
-(evil-define-motion evil-backward-word-end (count &optional bigword)
- "Move the cursor to the end of the COUNT-th previous word.
-If BIGWORD is non-nil, move by WORDS."
- :type inclusive
- (let ((thing (if bigword 'evil-WORD 'evil-word)))
- (evil-signal-at-bob-or-eob (- (or count 1)))
- (evil-backward-end thing count)))
-
-(evil-define-motion evil-forward-WORD-begin (count)
- "Move the cursor to the beginning of the COUNT-th next WORD."
- :type exclusive
- (evil-forward-word-begin count t))
-
-(evil-define-motion evil-forward-WORD-end (count)
- "Move the cursor to the end of the COUNT-th next WORD."
- :type inclusive
- (evil-forward-word-end count t))
-
-(evil-define-motion evil-backward-WORD-begin (count)
- "Move the cursor to the beginning of the COUNT-th previous WORD."
- :type exclusive
- (evil-backward-word-begin count t))
-
-(evil-define-motion evil-backward-WORD-end (count)
- "Move the cursor to the end of the COUNT-th previous WORD."
- :type inclusive
- (evil-backward-word-end count t))
-
-;; section movement
-(evil-define-motion evil-forward-section-begin (count)
- "Move the cursor to the beginning of the COUNT-th next section."
- :jump t
- :type exclusive
- (evil-signal-at-bob-or-eob count)
- (evil-forward-beginning 'evil-defun count))
-
-(evil-define-motion evil-forward-section-end (count)
- "Move the cursor to the end of the COUNT-th next section."
- :jump t
- :type inclusive
- (evil-signal-at-bob-or-eob count)
- (evil-forward-end 'evil-defun count)
- (unless (eobp) (forward-line)))
-
-(evil-define-motion evil-backward-section-begin (count)
- "Move the cursor to the beginning of the COUNT-th previous section."
- :jump t
- :type exclusive
- (evil-signal-at-bob-or-eob (- (or count 1)))
- (evil-backward-beginning 'evil-defun count))
-
-(evil-define-motion evil-backward-section-end (count)
- "Move the cursor to the end of the COUNT-th previous section."
- :jump t
- :type inclusive
- (evil-signal-at-bob-or-eob (- (or count 1)))
- (end-of-line -1)
- (evil-backward-end 'evil-defun count)
- (unless (eobp) (forward-line)))
-
-(evil-define-motion evil-forward-sentence-begin (count)
- "Move to the next COUNT-th beginning of a sentence or end of a paragraph."
- :jump t
- :type exclusive
- (evil-signal-at-bob-or-eob count)
- (evil-forward-nearest count
- #'(lambda (_cnt)
- (evil-forward-beginning 'evil-sentence))
- #'evil-forward-paragraph))
-
-(evil-define-motion evil-backward-sentence-begin (count)
- "Move to the previous COUNT-th beginning of a sentence or paragraph."
- :jump t
- :type exclusive
- (evil-signal-at-bob-or-eob (- (or count 1)))
- (evil-forward-nearest (- (or count 1))
- #'(lambda (_cnt)
- (evil-backward-beginning 'evil-sentence))
- #'(lambda (_cnt)
- (evil-backward-paragraph))))
-
-(evil-define-motion evil-forward-paragraph (count)
- "Move to the end of the COUNT-th next paragraph."
- :jump t
- :type exclusive
- (evil-signal-at-bob-or-eob count)
- (evil-forward-end 'evil-paragraph count)
- (unless (eobp) (forward-line)))
-
-(evil-define-motion evil-backward-paragraph (count)
- "Move to the beginning of the COUNT-th previous paragraph."
- :jump t
- :type exclusive
- (evil-signal-at-bob-or-eob (- (or count 1)))
- (unless (eobp) (forward-line))
- (evil-backward-beginning 'evil-paragraph count)
- (unless (bobp) (forward-line -1)))
-
-(defvar hif-ifx-else-endif-regexp)
-(evil-define-motion evil-jump-item (count)
- "Find the next item in this line after or under the cursor
-and jump to the corresponding one."
- :jump t
- :type inclusive
- (cond
- ;; COUNT% jumps to a line COUNT percentage down the file
- (count
- (evil-ensure-column
- (goto-char
- (evil-normalize-position
- (let ((size (- (point-max) (point-min))))
- (+ (point-min)
- (if (> size 80000)
- (* count (/ size 100))
- (/ (* count size) 100)))))))
- (setq evil-this-type 'line))
- ((and (evil-looking-at-start-comment t)
- (let ((pnt (point)))
- (forward-comment 1)
- (or (not (bolp))
- (prog1 nil (goto-char pnt)))))
- (backward-char))
- ((and (not (eolp)) (evil-looking-at-end-comment t))
- (forward-comment -1))
- ((and
- (memq major-mode '(c-mode c++-mode))
- (require 'hideif nil t)
- (with-no-warnings
- (let* ((hif-else-regexp (concat hif-cpp-prefix "\\(?:else\\|elif[ \t]+\\)"))
- (hif-ifx-else-endif-regexp
- (concat hif-ifx-regexp "\\|" hif-else-regexp "\\|" hif-endif-regexp)))
- (cond
- ((save-excursion (beginning-of-line) (or (hif-looking-at-ifX) (hif-looking-at-else)))
- (hif-find-next-relevant)
- (while (hif-looking-at-ifX)
- (hif-ifdef-to-endif)
- (hif-find-next-relevant))
- t)
- ((save-excursion (beginning-of-line) (hif-looking-at-endif))
- (hif-endif-to-ifdef)
- t))))))
- (t
- (let* ((open (point-max))
- (close (point-max))
- (open-pair (condition-case nil
- (save-excursion
- ;; consider the character right before eol given that
- ;; point may be placed there, e.g. in visual state
- (when (and (eolp) (not (bolp)))
- (backward-char))
- (setq open (1- (scan-lists (point) 1 -1)))
- (when (< open (line-end-position))
- (goto-char open)
- (forward-list)
- (1- (point))))
- (error nil)))
- (close-pair (condition-case nil
- (save-excursion
- ;; consider the character right before eol given that
- ;; point may be placed there, e.g. in visual state
- (when (and (eolp) (not (bolp)))
- (backward-char))
- (setq close (1- (scan-lists (point) 1 1)))
- (when (< close (line-end-position))
- (goto-char (1+ close))
- (backward-list)
- (point)))
- (error nil))))
- (cond
- ((not (or open-pair close-pair))
- ;; nothing found, check if we are inside a string
- (let ((pnt (point))
- (bnd (bounds-of-thing-at-point 'evil-string)))
- (if (not (and bnd (< (point) (cdr bnd))))
- ;; no, then we really failed
- (user-error "No matching item found on the current line")
- ;; yes, go to the end of the string and try again
- (let ((endstr (cdr bnd)))
- (when (or (save-excursion
- (goto-char endstr)
- (let ((b (bounds-of-thing-at-point 'evil-string)))
- (and b (< (point) (cdr b))))) ; not at end of string
- (condition-case nil
- (progn
- (goto-char endstr)
- (evil-jump-item)
- nil)
- (error t)))
- ;; failed again, go back to original point
- (goto-char pnt)
- (user-error "No matching item found on the current line"))))))
- ((< open close) (goto-char open-pair))
- (t (goto-char close-pair)))))))
-
-(defun evil--flyspell-overlays-in-p (beg end)
- (let ((ovs (overlays-in beg end))
- done)
- (while (and ovs (not done))
- (when (flyspell-overlay-p (car ovs))
- (setq done t))
- (setq ovs (cdr ovs)))
- done))
-
-(defun evil--flyspell-overlay-at (pos forwardp)
- (when (not forwardp)
- (setq pos (max (1- pos) (point-min))))
- (let ((ovs (overlays-at pos))
- done)
- (while (and ovs (not done))
- (if (flyspell-overlay-p (car ovs))
- (setq done t)
- (setq ovs (cdr ovs))))
- (when done
- (car ovs))))
-
-(defun evil--flyspell-overlay-after (pos limit forwardp)
- (let (done)
- (while (and (if forwardp
- (< pos limit)
- (> pos limit))
- (not done))
- (let ((ov (evil--flyspell-overlay-at pos forwardp)))
- (when ov
- (setq done ov)))
- (setq pos (if forwardp
- (next-overlay-change pos)
- (previous-overlay-change pos))))
- done))
-
-(defun evil--next-flyspell-error (forwardp)
- (when (evil--flyspell-overlays-in-p (point-min) (point-max))
- (let ((pos (point))
- limit
- ov)
- (when (evil--flyspell-overlay-at pos forwardp)
- (if (/= pos (point-min))
- (setq pos (save-excursion (goto-char pos)
- (forward-word (if forwardp 1 -1))
- (point)))
- (setq pos (point-max))))
- (setq limit (if forwardp (point-max) (point-min))
- ov (evil--flyspell-overlay-after pos limit forwardp))
- (if ov
- (goto-char (overlay-start ov))
- (when evil-search-wrap
- (setq limit pos
- pos (if forwardp (point-min) (point-max))
- ov (evil--flyspell-overlay-after pos limit forwardp))
- (when ov
- (goto-char (overlay-start ov))))))))
-
-(evil-define-motion evil-next-flyspell-error (count)
- "Go to the COUNT'th spelling mistake after point."
- (interactive "p")
- (dotimes (_ count)
- (evil--next-flyspell-error t)))
-
-(evil-define-motion evil-prev-flyspell-error (count)
- "Go to the COUNT'th spelling mistake preceding point."
- (interactive "p")
- (dotimes (_ count)
- (evil--next-flyspell-error nil)))
-
-(evil-define-motion evil-previous-open-paren (count)
- "Go to [count] previous unmatched '('."
- :type exclusive
- (evil-up-paren ?\( ?\) (- (or count 1))))
-
-(evil-define-motion evil-next-close-paren (count)
- "Go to [count] next unmatched ')'."
- :type exclusive
- (forward-char)
- (evil-up-paren ?\( ?\) (or count 1))
- (backward-char))
-
-(evil-define-motion evil-previous-open-brace (count)
- "Go to [count] previous unmatched '{'."
- :type exclusive
- (evil-up-paren ?{ ?} (- (or count 1))))
-
-(evil-define-motion evil-next-close-brace (count)
- "Go to [count] next unmatched '}'."
- :type exclusive
- (forward-char)
- (evil-up-paren ?{ ?} (or count 1))
- (backward-char))
-
-(defun evil--lowercase-markers ()
- "Get all lowercase markers."
- (cl-remove-if-not (lambda (x) (and (markerp (cdr x))
- (<= ?a (car x) ?z)))
- evil-markers-alist))
-
-(defun evil--next-mark (forwardp)
- "Move to next lowercase mark.
-Move forward if FORWARDP is truthy or backward if falsey.
-Loop back to the top of buffer if the end is reached."
- (let ((pos (point))
- (sorted-markers (sort (evil--lowercase-markers)
- (lambda (a b) (< (cdr a) (cdr b))))))
- (cond
- ((null sorted-markers)
- (user-error "No marks in this buffer"))
- (forwardp
- (let ((next-marker (cl-some (lambda (x) (and (< pos (cdr x)) (cdr x)))
- sorted-markers)))
- (if next-marker
- (goto-char (marker-position next-marker))
- (goto-char (marker-position (cdar sorted-markers))))))
- (t
- (let* ((descending-markers (reverse sorted-markers))
- (prev-marker (cl-some (lambda (x) (and (> pos (cdr x)) (cdr x)))
- descending-markers)))
- (if prev-marker
- (goto-char (marker-position prev-marker))
- (goto-char (marker-position (cdar descending-markers)))))))))
-
-(evil-define-motion evil-next-mark (count)
- "Go to [count] next lowercase mark."
- :keep-visual t
- :repeat nil
- :type exclusive
- :jump t
- (dotimes (_ (or count 1))
- (evil--next-mark t)))
-
-(evil-define-motion evil-next-mark-line (count)
- "Go to [count] line of next lowercase mark after current line."
- :keep-visual t
- :repeat nil
- :type exclusive
- :jump t
- (if (evil--lowercase-markers)
- (dotimes (_ (or count 1))
- (evil-end-of-line)
- (evil--next-mark t)
- (evil-first-non-blank))
- (user-error "No marks in this buffer")))
-
-(evil-define-motion evil-previous-mark (count)
- "Go to [count] previous lowercase mark."
- :keep-visual t
- :repeat nil
- :type exclusive
- :jump t
- (dotimes (_ (or count 1))
- (evil--next-mark nil)))
-
-(evil-define-motion evil-previous-mark-line (count)
- "Go to [count] line of previous lowercase mark before current line."
- :keep-visual t
- :repeat nil
- :type exclusive
- :jump t
- (if (evil--lowercase-markers)
- (dotimes (_ (or count 1))
- (evil-beginning-of-line)
- (evil--next-mark nil)
- (evil-first-non-blank))
- (user-error "No marks in this buffer")))
-
-(evil-define-command evil-set-col-0-mark (beg end mark)
- "Set MARK at column 0 of line of END. Default is cursor line."
- (interactive "<r><a>")
- (if (< 1 (length mark))
- (user-error "Trailing characters")
- (save-excursion
- (goto-char (if (eobp) end (1- end)))
- (evil-beginning-of-line)
- (evil-set-marker (string-to-char mark)))))
-
-(evil-define-motion evil-find-char (count char)
- "Move to the next COUNT'th occurrence of CHAR.
-Movement is restricted to the current line unless `evil-cross-lines' is non-nil."
- :type inclusive
- (interactive "<c><C>")
- (setq count (or count 1))
- (let ((fwd (> count 0))
- (visual (and evil-respect-visual-line-mode
- visual-line-mode)))
- (setq evil-last-find (list #'evil-find-char char fwd))
- (when fwd (evil-forward-char 1 evil-cross-lines))
- (let ((case-fold-search nil))
- (unless (prog1
- (search-forward (char-to-string char)
- (cond (evil-cross-lines
- nil)
- ((and fwd visual)
- (save-excursion
- (end-of-visual-line)
- (point)))
- (fwd
- (line-end-position))
- (visual
- (save-excursion
- (beginning-of-visual-line)
- (point)))
- (t
- (line-beginning-position)))
- t count)
- (when fwd (backward-char)))
- (user-error "Can't find %c" char)))))
-
-(evil-define-motion evil-find-char-backward (count char)
- "Move to the previous COUNT'th occurrence of CHAR."
- :type exclusive
- (interactive "<c><C>")
- (evil-find-char (- (or count 1)) char))
-
-(evil-define-motion evil-find-char-to (count char)
- "Move before the next COUNT'th occurrence of CHAR."
- :type inclusive
- (interactive "<c><C>")
- (unwind-protect
- (progn
- (evil-find-char count char)
- (if (> (or count 1) 0)
- (backward-char)
- (forward-char)))
- (setcar evil-last-find #'evil-find-char-to)))
-
-(evil-define-motion evil-find-char-to-backward (count char)
- "Move before the previous COUNT'th occurrence of CHAR."
- :type exclusive
- (interactive "<c><C>")
- (evil-find-char-to (- (or count 1)) char))
-
-(evil-define-motion evil-repeat-find-char (count)
- "Repeat the last find COUNT times."
- :type inclusive
- (setq count (or count 1))
- (if evil-last-find
- (let ((cmd (car evil-last-find))
- (char (nth 1 evil-last-find))
- (fwd (nth 2 evil-last-find))
- evil-last-find)
- ;; ensure count is non-negative
- (when (< count 0)
- (setq count (- count)
- fwd (not fwd)))
- ;; skip next character when repeating t or T
- (and (eq cmd #'evil-find-char-to)
- evil-repeat-find-to-skip-next
- (= count 1)
- (or (and fwd (= (char-after (1+ (point))) char))
- (and (not fwd) (= (char-before) char)))
- (setq count (1+ count)))
- (funcall cmd (if fwd count (- count)) char)
- (unless (nth 2 evil-last-find)
- (setq evil-this-type 'exclusive)))
- (user-error "No previous search")))
-
-(evil-define-motion evil-repeat-find-char-reverse (count)
- "Repeat the last find COUNT times in the opposite direction."
- :type inclusive
- (evil-repeat-find-char (- (or count 1))))
-
-;; ceci n'est pas une pipe
-(evil-define-motion evil-goto-column (count)
- "Go to column COUNT on the current line.
-Columns are counted from zero."
- :type exclusive
- (move-to-column (or count 0)))
-
-(evil-define-command evil-goto-mark (char &optional noerror)
- "Go to the marker specified by CHAR."
- :keep-visual t
- :repeat nil
- :type exclusive
- :jump t
- (interactive (list (read-char)))
- (let ((marker (evil-get-marker char)))
- (cond
- ((markerp marker)
- (switch-to-buffer (marker-buffer marker))
- (goto-char (marker-position marker)))
- ((numberp marker)
- (goto-char marker))
- ((consp marker)
- (when (or (find-buffer-visiting (car marker))
- (and (y-or-n-p (format "Visit file %s again? "
- (car marker)))
- (find-file (car marker))))
- (goto-char (cdr marker))))
- ((not noerror)
- (user-error "Marker `%c' is not set%s" char
- (if (evil-global-marker-p char) ""
- " in this buffer"))))))
-
-(evil-define-command evil-goto-mark-line (char &optional noerror)
- "Go to the line of the marker specified by CHAR."
- :keep-visual t
- :repeat nil
- :type line
- :jump t
- (interactive (list (read-char)))
- (evil-goto-mark char noerror)
- (evil-first-non-blank))
-
-(evil-define-motion evil-jump-backward (count)
- "Go to older position in jump list.
-To go the other way, press \
-\\<evil-motion-state-map>\\[evil-jump-forward]."
- (evil--jump-backward count))
-
-(evil-define-motion evil-jump-forward (count)
- "Go to newer position in jump list.
-To go the other way, press \
-\\<evil-motion-state-map>\\[evil-jump-backward]."
- (evil--jump-forward count))
-
-(evil-define-motion evil-jump-backward-swap (count)
- "Go to the previous position in jump list.
-The current position is placed in the jump list."
- (let ((pnt (point)))
- (evil--jump-backward 1)
- (evil-set-jump pnt)))
-
-(defvar xref-prompt-for-identifier)
-(evil-define-motion evil-jump-to-tag (arg)
- "Jump to tag under point.
-If called with a prefix argument, provide a prompt
-for specifying the tag."
- :jump t
- (interactive "P")
- (cond
- ((fboundp 'xref-find-definitions)
- (let ((xref-prompt-for-identifier arg))
- (call-interactively #'xref-find-definitions)))
- ((fboundp 'find-tag)
- (if arg (call-interactively #'find-tag)
- (let ((tag (funcall (or find-tag-default-function
- (get major-mode 'find-tag-default-function)
- #'find-tag-default))))
- (unless tag (user-error "No tag candidate found around point"))
- (find-tag tag))))))
-
-(evil-define-motion evil-lookup ()
- "Look up the keyword at point.
-Calls `evil-lookup-func'."
- (funcall evil-lookup-func))
-
-(defun evil-ret-gen (count indent?)
- (let* ((field (get-char-property (point) 'field))
- (button (get-char-property (point) 'button))
- (doc (get-char-property (point) 'widget-doc))
- (widget (or field button doc)))
- (cond
- ((and widget
- (fboundp 'widget-type)
- (fboundp 'widget-button-press)
- (or (and (symbolp widget)
- (get widget 'widget-type))
- (and (consp widget)
- (get (widget-type widget) 'widget-type))))
- (when (evil-operator-state-p)
- (setq evil-inhibit-operator t))
- (when (fboundp 'widget-button-press)
- (widget-button-press (point))))
- ((and (fboundp 'button-at)
- (fboundp 'push-button)
- (button-at (point)))
- (when (evil-operator-state-p)
- (setq evil-inhibit-operator t))
- (push-button))
- ((or (evil-emacs-state-p)
- (and (evil-insert-state-p)
- (not buffer-read-only)))
- (if (not indent?)
- (newline count)
- (delete-horizontal-space t)
- (newline count)
- (indent-according-to-mode)))
- (t
- (evil-next-line-first-non-blank count)))))
-
-(evil-define-motion evil-ret (count)
- "Move the cursor COUNT lines down.
-If point is on a widget or a button, click on it.
-In Insert state, insert a newline."
- :type line
- (evil-ret-gen count nil))
-
-(evil-define-motion evil-ret-and-indent (count)
- "Move the cursor COUNT lines down.
-If point is on a widget or a button, click on it.
-In Insert state, insert a newline and indent."
- :type line
- (evil-ret-gen count t))
-
-(evil-define-motion evil-window-top (count)
- "Move the cursor to line COUNT from the top of the window."
- :jump t
- :type line
- (evil-ensure-column
- (move-to-window-line (max (or count 0)
- (if (= (point-min) (window-start))
- 0
- scroll-margin)))))
-
-(evil-define-motion evil-window-middle ()
- "Move the cursor to the middle line in the window."
- :jump t
- :type line
- (evil-ensure-column
- (move-to-window-line
- (/ (1+ (save-excursion (move-to-window-line -1))) 2))))
-
-(evil-define-motion evil-window-bottom (count)
- "Move the cursor to line COUNT from the bottom of the window."
- :jump t
- :type line
- (evil-ensure-column
- (move-to-window-line (- (max (or count 1) (1+ scroll-margin))))))
-
-;; scrolling
-(evil-define-command evil-scroll-line-up (count)
- "Scrolls the window COUNT lines upwards."
- :repeat nil
- :keep-visual t
- (interactive "p")
- (let ((scroll-preserve-screen-position nil))
- (scroll-down count)))
-
-(evil-define-command evil-scroll-line-down (count)
- "Scrolls the window COUNT lines downwards."
- :repeat nil
- :keep-visual t
- (interactive "p")
- (let ((scroll-preserve-screen-position nil))
- (scroll-up count)))
-
-(evil-define-command evil-scroll-count-reset ()
- "Sets `evil-scroll-count' to 0.
-`evil-scroll-up' and `evil-scroll-down' will scroll
-for a half of the screen(default)."
- :repeat nil
- :keep-visual t
- (interactive)
- (setq evil-scroll-count 0))
-
-(evil-define-command evil-scroll-up (count)
- "Scrolls the window and the cursor COUNT lines upwards.
-If COUNT is not specified the function scrolls down
-`evil-scroll-count', which is the last used count.
-If the scroll count is zero the command scrolls half the screen."
- :repeat nil
- :keep-visual t
- (interactive "<c>")
- (evil-ensure-column
- (setq count (or count (max 0 evil-scroll-count))
- evil-scroll-count count
- this-command 'next-line)
- (when (= (point-min) (line-beginning-position))
- (signal 'beginning-of-buffer nil))
- (when (zerop count)
- (setq count (/ (window-body-height) 2)))
- (let ((xy (evil-posn-x-y (posn-at-point))))
- (condition-case nil
- (progn
- (scroll-down count)
- (goto-char (posn-point (posn-at-x-y (car xy) (cdr xy)))))
- (beginning-of-buffer
- (condition-case nil
- (with-no-warnings (previous-line count))
- (beginning-of-buffer)))))))
-
-(evil-define-command evil-scroll-down (count)
- "Scrolls the window and the cursor COUNT lines downwards.
-If COUNT is not specified the function scrolls down
-`evil-scroll-count', which is the last used count.
-If the scroll count is zero the command scrolls half the screen."
- :repeat nil
- :keep-visual t
- (interactive "<c>")
- (evil-ensure-column
- (setq count (or count (max 0 evil-scroll-count))
- evil-scroll-count count
- this-command 'next-line)
- (when (eobp) (signal 'end-of-buffer nil))
- (when (zerop count)
- (setq count (/ (window-body-height) 2)))
- ;; BUG #660: First check whether the eob is visible.
- ;; In that case we do not scroll but merely move point.
- (if (<= (point-max) (window-end))
- (with-no-warnings (next-line count nil))
- (let ((xy (evil-posn-x-y (posn-at-point))))
- (condition-case nil
- (progn
- (scroll-up count)
- (let* ((wend (window-end nil t))
- (p (posn-at-x-y (car xy) (cdr xy)))
- (margin (max 0 (- scroll-margin
- (cdr (posn-col-row p))))))
- (goto-char (posn-point p))
- ;; ensure point is not within the scroll-margin
- (when (> margin 0)
- (with-no-warnings (next-line margin))
- (recenter scroll-margin))
- (when (<= (point-max) wend)
- (save-excursion
- (goto-char (point-max))
- (recenter (- (max 1 scroll-margin)))))))
- (end-of-buffer
- (goto-char (point-max))
- (recenter (- (max 1 scroll-margin)))))))))
-
-(evil-define-command evil-scroll-page-up (count)
- "Scrolls the window COUNT pages upwards."
- :repeat nil
- :keep-visual t
- (interactive "p")
- (evil-ensure-column
- (dotimes (i count)
- (condition-case err
- (scroll-down nil)
- (beginning-of-buffer
- (if (and (bobp) (zerop i))
- (signal (car err) (cdr err))
- (goto-char (point-min))))))))
-
-(evil-define-command evil-scroll-page-down (count)
- "Scrolls the window COUNT pages downwards."
- :repeat nil
- :keep-visual t
- (interactive "p")
- (evil-ensure-column
- (dotimes (i count)
- (condition-case err
- (scroll-up nil)
- (end-of-buffer
- (if (and (eobp) (zerop i))
- (signal (car err) (cdr err))
- (goto-char (point-max))))))))
-
-(evil-define-command evil-scroll-line-to-top (count)
- "Scrolls line number COUNT (or the cursor line) to the top of the window."
- :repeat nil
- :keep-visual t
- (interactive "<c>")
- (evil-save-column
- (let ((line (or count (line-number-at-pos (point)))))
- (goto-char (point-min))
- (forward-line (1- line)))
- (recenter (1- (max 1 scroll-margin)))))
-
-(evil-define-command evil-scroll-line-to-center (count)
- "Scrolls line number COUNT (or the cursor line) to the center of the window."
- :repeat nil
- :keep-visual t
- (interactive "<c>")
- (evil-save-column
- (when count
- (goto-char (point-min))
- (forward-line (1- count)))
- (recenter nil)))
-
-(evil-define-command evil-scroll-line-to-bottom (count)
- "Scrolls line number COUNT (or the cursor line) to the bottom of the window."
- :repeat nil
- :keep-visual t
- (interactive "<c>")
- (evil-save-column
- (let ((line (or count (line-number-at-pos (point)))))
- (goto-char (point-min))
- (forward-line (1- line)))
- (recenter (- (max 1 scroll-margin)))))
-
-(evil-define-command evil-scroll-bottom-line-to-top (count)
- "Scrolls the line right below the window,
-or line COUNT to the top of the window."
- :repeat nil
- :keep-visual t
- (interactive "<c>")
- (if count
- (progn
- (goto-char (point-min))
- (forward-line (1- count)))
- (goto-char (window-end))
- (evil-move-cursor-back))
- (recenter (1- (max 0 scroll-margin)))
- (evil-first-non-blank))
-
-(evil-define-command evil-scroll-top-line-to-bottom (count)
- "Scrolls the line right below the window,
-or line COUNT to the top of the window."
- :repeat nil
- :keep-visual t
- (interactive "<c>")
- (if count
- (progn
- (goto-char (point-min))
- (forward-line (1- count)))
- (goto-char (window-start)))
- (recenter (- (max 1 scroll-margin)))
- (evil-first-non-blank))
-
-(evil-define-command evil-scroll-left (count)
- "Scrolls the window COUNT half-screenwidths to the left."
- :repeat nil
- :keep-visual t
- (interactive "p")
- (evil-with-hproject-point-on-window
- (scroll-right (* count (/ (window-width) 2)))))
-
-(evil-define-command evil-scroll-right (count)
- "Scrolls the window COUNT half-screenwidths to the right."
- :repeat nil
- :keep-visual t
- (interactive "p")
- (evil-with-hproject-point-on-window
- (scroll-left (* count (/ (window-width) 2)))))
-
-(evil-define-command evil-scroll-column-left (count)
- "Scrolls the window COUNT columns to the left."
- :repeat nil
- :keep-visual t
- (interactive "p")
- (evil-with-hproject-point-on-window
- (scroll-right count)))
-
-(evil-define-command evil-scroll-column-right (count)
- "Scrolls the window COUNT columns to the right."
- :repeat nil
- :keep-visual t
- (interactive "p")
- (evil-with-hproject-point-on-window
- (scroll-left count)))
-
-;;; Text objects
-
-;; Text objects are defined with `evil-define-text-object'. In Visual
-;; state, they modify the current selection; in Operator-Pending
-;; state, they return a pair of buffer positions. Outer text objects
-;; are bound in the keymap `evil-outer-text-objects-map', and inner
-;; text objects are bound in `evil-inner-text-objects-map'.
-;;
-;; Common text objects like words, WORDS, paragraphs and sentences are
-;; defined via a corresponding move-function. This function must have
-;; the following properties:
-;;
-;; 1. Take exactly one argument, the count.
-;; 2. When the count is positive, move point forward to the first
-;; character after the end of the next count-th object.
-;; 3. When the count is negative, move point backward to the first
-;; character of the count-th previous object.
-;; 4. If point is placed on the first character of an object, the
-;; backward motion does NOT count that object.
-;; 5. If point is placed on the last character of an object, the
-;; forward motion DOES count that object.
-;; 6. The return value is "count left", i.e., in forward direction
-;; count is decreased by one for each successful move and in
-;; backward direction count is increased by one for each
-;; successful move, returning the final value of count.
-;; Therefore, if the complete move is successful, the return
-;; value is 0.
-;;
-;; A useful macro in this regard is `evil-motion-loop', which quits
-;; when point does not move further and returns the count difference.
-;; It also provides a "unit value" of 1 or -1 for use in each
-;; iteration. For example, a hypothetical "foo-bar" move could be
-;; written as such:
-;;
-;; (defun foo-bar (count)
-;; (evil-motion-loop (var count)
-;; (forward-foo var) ; `var' is 1 or -1 depending on COUNT
-;; (forward-bar var)))
-;;
-;; If "forward-foo" and "-bar" didn't accept negative arguments,
-;; we could choose their backward equivalents by inspecting `var':
-;;
-;; (defun foo-bar (count)
-;; (evil-motion-loop (var count)
-;; (cond
-;; ((< var 0)
-;; (backward-foo 1)
-;; (backward-bar 1))
-;; (t
-;; (forward-foo 1)
-;; (forward-bar 1)))))
-;;
-;; After a forward motion, point has to be placed on the first
-;; character after some object, unless no motion was possible at all.
-;; Similarly, after a backward motion, point has to be placed on the
-;; first character of some object. This implies that point should
-;; NEVER be moved to eob or bob, unless an object ends or begins at
-;; eob or bob. (Usually, Emacs motions always move as far as possible.
-;; But we want to use the motion-function to identify certain objects
-;; in the buffer, and thus exact movement to object boundaries is
-;; required.)
-
-(evil-define-text-object evil-a-word (count &optional beg end type)
- "Select a word."
- (evil-select-an-object 'evil-word beg end type count))
-
-(evil-define-text-object evil-inner-word (count &optional beg end type)
- "Select inner word."
- (evil-select-inner-object 'evil-word beg end type count))
-
-(evil-define-text-object evil-a-WORD (count &optional beg end type)
- "Select a WORD."
- (evil-select-an-object 'evil-WORD beg end type count))
-
-(evil-define-text-object evil-inner-WORD (count &optional beg end type)
- "Select inner WORD."
- (evil-select-inner-object 'evil-WORD beg end type count))
-
-(evil-define-text-object evil-a-symbol (count &optional beg end type)
- "Select a symbol."
- (evil-select-an-unrestricted-object 'evil-symbol beg end type count))
-
-(evil-define-text-object evil-inner-symbol (count &optional beg end type)
- "Select inner symbol."
- (evil-select-inner-unrestricted-object 'evil-symbol beg end type count))
-
-(evil-define-text-object evil-a-sentence (count &optional beg end type)
- "Select a sentence."
- (evil-select-an-unrestricted-object 'evil-sentence beg end type count))
-
-(evil-define-text-object evil-inner-sentence (count &optional beg end type)
- "Select inner sentence."
- (evil-select-inner-unrestricted-object 'evil-sentence beg end type count))
-
-(evil-define-text-object evil-a-paragraph (count &optional beg end type)
- "Select a paragraph."
- :type line
- (evil-select-an-unrestricted-object 'evil-paragraph beg end type count t))
-
-(evil-define-text-object evil-inner-paragraph (count &optional beg end type)
- "Select inner paragraph."
- :type line
- (evil-select-inner-unrestricted-object 'evil-paragraph beg end type count t))
-
-(evil-define-text-object evil-a-paren (count &optional beg end type)
- "Select a parenthesis."
- :extend-selection nil
- (evil-select-paren ?\( ?\) beg end type count t))
-
-(evil-define-text-object evil-inner-paren (count &optional beg end type)
- "Select inner parenthesis."
- :extend-selection nil
- (evil-select-paren ?\( ?\) beg end type count))
-
-(evil-define-text-object evil-a-bracket (count &optional beg end type)
- "Select a square bracket."
- :extend-selection nil
- (evil-select-paren ?\[ ?\] beg end type count t))
-
-(evil-define-text-object evil-inner-bracket (count &optional beg end type)
- "Select inner square bracket."
- :extend-selection nil
- (evil-select-paren ?\[ ?\] beg end type count))
-
-(evil-define-text-object evil-a-curly (count &optional beg end type)
- "Select a curly bracket (\"brace\")."
- :extend-selection nil
- (evil-select-paren ?{ ?} beg end type count t))
-
-(evil-define-text-object evil-inner-curly (count &optional beg end type)
- "Select inner curly bracket (\"brace\")."
- :extend-selection nil
- (evil-select-paren ?{ ?} beg end type count))
-
-(evil-define-text-object evil-an-angle (count &optional beg end type)
- "Select an angle bracket."
- :extend-selection nil
- (evil-select-paren ?< ?> beg end type count t))
-
-(evil-define-text-object evil-inner-angle (count &optional beg end type)
- "Select inner angle bracket."
- :extend-selection nil
- (evil-select-paren ?< ?> beg end type count))
-
-(evil-define-text-object evil-a-single-quote (count &optional beg end type)
- "Select a single-quoted expression."
- :extend-selection t
- (evil-select-quote ?' beg end type count t))
-
-(evil-define-text-object evil-inner-single-quote (count &optional beg end type)
- "Select inner single-quoted expression."
- :extend-selection nil
- (evil-select-quote ?' beg end type count))
-
-(evil-define-text-object evil-a-double-quote (count &optional beg end type)
- "Select a double-quoted expression."
- :extend-selection t
- (evil-select-quote ?\" beg end type count t))
-
-(evil-define-text-object evil-inner-double-quote (count &optional beg end type)
- "Select inner double-quoted expression."
- :extend-selection nil
- (evil-select-quote ?\" beg end type count))
-
-(evil-define-text-object evil-a-back-quote (count &optional beg end type)
- "Select a back-quoted expression."
- :extend-selection t
- (evil-select-quote ?\` beg end type count t))
-
-(evil-define-text-object evil-inner-back-quote (count &optional beg end type)
- "Select inner back-quoted expression."
- :extend-selection nil
- (evil-select-quote ?\` beg end type count))
-
-(evil-define-text-object evil-a-tag (count &optional beg end type)
- "Select a tag block."
- :extend-selection nil
- (evil-select-xml-tag beg end type count t))
-
-(evil-define-text-object evil-inner-tag (count &optional beg end type)
- "Select inner tag block."
- :extend-selection nil
- (evil-select-xml-tag beg end type count))
-
-(defun evil-match (direction count)
- "Find COUNTth next match in DIRECTION."
- (unless (and (boundp 'evil-search-module)
- (eq evil-search-module 'evil-search))
- (user-error "Match text objects only work with Evil search module"))
- (let ((pnt (point))
- (count (abs count)) ;; Undo effect of evil-visual-direction
- (evil-ex-search-direction 'backward)
- (visual-state (evil-visual-state-p))
- on-start-match in-match on-end-match)
- (save-excursion
- (unless (eobp) (forward-char)) ;; If on start of a match, stay there
- (evil-ex-search 1)
- (setq on-start-match (= evil-ex-search-match-beg pnt)
- in-match (<= evil-ex-search-match-beg pnt (1- evil-ex-search-match-end))
- on-end-match (= (1- evil-ex-search-match-end) pnt)
- evil-ex-search-direction direction)
- (cond
- ((and visual-state on-start-match (eq 'backward direction))
- (evil-ex-search count))
- ((and visual-state on-end-match (eq 'forward direction))
- (evil-ex-search count))
- ((or in-match (eq 'backward direction))
- (evil-ex-search (1- count)))
- (t (evil-ex-search count)))
- (setq pnt (point)))
- (goto-char pnt)
- (cond
- ((evil-normal-state-p)
- (evil-visual-select evil-ex-search-match-beg
- evil-ex-search-match-end
- 'inclusive
- (cl-case direction ('forward +1) ('backward -1))
- t)
- (list evil-ex-search-match-beg evil-ex-search-match-end))
- ((and visual-state (eq 'forward direction))
- (goto-char (1- evil-ex-search-match-end)))
- ((and visual-state (eq 'backward direction))
- (goto-char evil-ex-search-match-beg))
- ;; e.g. operator pending...
- (t (list evil-ex-search-match-beg evil-ex-search-match-end)))))
-
-(evil-define-text-object evil-next-match (count &optional beg end type)
- "Select next match."
- :extend-selection t
- (evil-match 'forward count))
-
-(evil-define-text-object evil-previous-match (count &optional beg end type)
- "Select previous match."
- :extend-selection t
- (evil-match 'backward count))
-
-;;; Operator commands
-
-(evil-define-operator evil-yank (beg end type register yank-handler)
- "Saves the characters in motion into the kill-ring."
- :move-point nil
- :repeat nil
- (interactive "<R><x><y>")
- (let ((evil-was-yanked-without-register
- (and evil-was-yanked-without-register (not register))))
- (cond
- ((and (fboundp 'cua--global-mark-active)
- (fboundp 'cua-copy-region-to-global-mark)
- (cua--global-mark-active))
- (cua-copy-region-to-global-mark beg end))
- ((eq type 'block)
- (evil-yank-rectangle beg end register yank-handler))
- ((memq type '(line screen-line))
- (evil-yank-lines beg end register yank-handler))
- (t
- (evil-yank-characters beg end register yank-handler)))))
-
-(evil-define-operator evil-yank-line (beg end type register)
- "Saves whole lines into the kill-ring."
- :motion evil-line-or-visual-line
- :move-point nil
- (interactive "<R><x>")
- (when (evil-visual-state-p)
- (unless (memq type '(line block screen-line))
- (let ((range (evil-expand beg end
- (if (and evil-respect-visual-line-mode
- visual-line-mode)
- 'screen-line
- 'line))))
- (setq beg (evil-range-beginning range)
- end (evil-range-end range)
- type (evil-type range))))
- (evil-exit-visual-state))
- (evil-yank beg end type register))
-
-(evil-define-operator evil-delete (beg end type register yank-handler)
- "Delete text from BEG to END with TYPE.
-Save in REGISTER or in the kill-ring with YANK-HANDLER."
- (interactive "<R><x><y>")
- (if (and (memq type '(inclusive exclusive))
- (not (evil-visual-state-p))
- (eq 'evil-delete evil-this-operator)
- (save-excursion (goto-char beg) (bolp))
- (save-excursion (goto-char end) (eolp))
- (<= 1 (evil-count-lines beg end)))
- ;; Imitate Vi strangeness: if motion meets above criteria,
- ;; delete linewise. Not for change operator or visual state.
- (let ((new-range (evil-expand beg end 'line)))
- (evil-delete (nth 0 new-range) (nth 1 new-range) 'line register yank-handler))
- (unless register
- (let ((text (filter-buffer-substring beg end)))
- (unless (string-match-p "\n" text)
- ;; set the small delete register
- (evil-set-register ?- text))))
- (let ((evil-was-yanked-without-register nil))
- (evil-yank beg end type register yank-handler))
- (cond
- ((eq type 'block)
- (evil-apply-on-block #'delete-region beg end nil))
- ((and (eq type 'line)
- (= end (point-max))
- (or (= beg end)
- (/= (char-before end) ?\n))
- (/= beg (point-min))
- (= (char-before beg) ?\n))
- (delete-region (1- beg) end))
- (t
- (delete-region beg end)))
- (when (and (called-interactively-p 'any)
- (eq type 'line))
- (evil-first-non-blank)
- (when (and (not evil-start-of-line)
- evil-operator-start-col
- ;; Special exceptions to ever saving column:
- (not (memq evil-this-motion '(evil-forward-word-begin
- evil-forward-WORD-begin))))
- (move-to-column evil-operator-start-col)))))
-
-(evil-define-operator evil-delete-line (beg end type register yank-handler)
- "Delete to end of line."
- :motion nil
- :keep-visual t
- (interactive "<R><x>")
- ;; act linewise in Visual state
- (let* ((beg (or beg (point)))
- (end (or end beg))
- (visual-line-mode (and evil-respect-visual-line-mode
- visual-line-mode))
- (line-end (if visual-line-mode
- (save-excursion
- (end-of-visual-line)
- (point))
- (line-end-position))))
- (when (evil-visual-state-p)
- (unless (memq type '(line screen-line block))
- (let ((range (evil-expand beg end
- (if visual-line-mode
- 'screen-line
- 'line))))
- (setq beg (evil-range-beginning range)
- end (evil-range-end range)
- type (evil-type range))))
- (evil-exit-visual-state))
- (cond
- ((eq type 'block)
- ;; equivalent to $d, i.e., we use the block-to-eol selection and
- ;; call `evil-delete'. In this case we fake the call to
- ;; `evil-end-of-line' by setting `temporary-goal-column' and
- ;; `last-command' appropriately as `evil-end-of-line' would do.
- (let ((temporary-goal-column most-positive-fixnum)
- (last-command 'next-line))
- (evil-delete beg end 'block register yank-handler)))
- ((memq type '(line screen-line))
- (evil-delete beg end type register yank-handler))
- (t
- (evil-delete beg line-end type register yank-handler)))))
-
-(evil-define-operator evil-delete-whole-line
- (beg end type register yank-handler)
- "Delete whole line."
- :motion evil-line-or-visual-line
- (interactive "<R><x>")
- (evil-delete beg end type register yank-handler))
-
-(evil-define-operator evil-delete-char (beg end type register)
- "Delete next character."
- :motion evil-forward-char
- (interactive "<R><x>")
- (evil-delete beg end type register))
-
-(evil-define-operator evil-delete-backward-char (beg end type register)
- "Delete previous character."
- :motion evil-backward-char
- (interactive "<R><x>")
- (evil-delete beg end type register))
-
-(evil-define-command evil-delete-backward-char-and-join (count)
- "Delete previous character and join lines.
-If point is at the beginning of a line then the current line will
-be joined with the previous line if and only if
-`evil-backspace-join-lines'."
- (interactive "p")
- (if (or evil-backspace-join-lines (not (bolp)))
- (call-interactively 'delete-backward-char)
- (user-error "Beginning of line")))
-
-(evil-define-command evil-delete-backward-word ()
- "Delete previous word."
- (let ((beg (save-excursion (evil-backward-word-begin) (point)))
- (end (point)))
- (cond
- ((evil-replace-state-p) (while (< beg (point))
- (evil-replace-backspace)))
- ((or (not (bolp)) (bobp)) (delete-region (max beg (line-beginning-position))
- end))
- (evil-backspace-join-lines (delete-char -1))
- (t (user-error "Beginning of line")))))
-
-(evil-define-command evil-delete-back-to-indentation ()
- "Delete back to the first non-whitespace character.
-If point is before the first non-whitespace character of a
-current line then delete from the point to the beginning of the
-current line. If point is on the beginning of the line, behave
-according to `evil-backspace-join-lines'."
- (let ((beg (if (<= (current-column) (current-indentation))
- (line-beginning-position)
- (save-excursion
- (evil-first-non-blank)
- (point)))))
- (cond
- ((and (bolp) (evil-replace-state-p)) (evil-replace-backspace))
- ((bolp) (evil-delete-backward-char-and-join 1))
- ((evil-replace-state-p) (while (< beg (point))
- (evil-replace-backspace)))
- (t (delete-region beg (point))))))
-
-(defun evil-ex-delete-or-yank (should-delete beg end type register count yank-handler)
- "Execute evil-delete or evil-yank on the given region.
-If SHOULD-DELETE is t, evil-delete will be executed, otherwise
-evil-yank.
-The region specified by BEG and END will be adjusted if COUNT is
-given."
- (when count
- ;; with COUNT, the command should go the end of the region and delete/yank
- ;; COUNT lines from there
- (setq beg (save-excursion
- (goto-char end)
- (forward-line -1)
- (point))
- end (save-excursion
- (goto-char end)
- (point-at-bol count))
- type 'line))
- (funcall (if should-delete 'evil-delete 'evil-yank) beg end type register yank-handler))
-
-(evil-define-operator evil-ex-delete (beg end type register count yank-handler)
- "The Ex delete command.
-\[BEG,END]delete [REGISTER] [COUNT]"
- (interactive "<R><xc/><y>")
- (evil-ex-delete-or-yank t beg end type register count yank-handler))
-
-(evil-define-operator evil-ex-yank (beg end type register count yank-handler)
- "The Ex yank command.
-\[BEG,END]yank [REGISTER] [COUNT]"
- :restore-point t
- (interactive "<R><xc/><y>")
- (evil-ex-delete-or-yank nil beg end type register count yank-handler))
-
-(evil-define-command evil-ex-put (beg end ex-arg &optional force)
- (interactive "<r><a><!>")
- (let* ((arg-chars (remove ?\s (string-to-list ex-arg)))
- (reg (or (car arg-chars) ?\"))
- (text (cond
- ((and (< 1 (length arg-chars))
- (/= ?= reg))
- (user-error "Trailing characters"))
- ((eq ?= reg)
- (evil--eval-expr (if (= 1 (length arg-chars))
- evil-last-=-register-input
- (setq evil-last-=-register-input (substring ex-arg 1)))))
- (t (evil-get-register reg)))))
- (unless text (user-error "Nothing in register %c" reg))
- (evil-remove-yank-excluded-properties text)
- (goto-char (if (= (point-max) end) end (1- end)))
- (if force (evil-insert-newline-above) (evil-insert-newline-below))
- (evil-set-marker ?\[ (point))
- ;; `insert' rather than `insert-for-yank' as we want to ignore yank-handlers...
- (insert (if (and (< 0 (length text))
- (eq ?\n (aref text (1- (length text)))))
- (substring text 0 (1- (length text)))
- text))
- (evil-set-marker ?\] (1- (point)))
- (back-to-indentation)
- (evil-normal-state)))
-
-(evil-define-operator evil-change
- (beg end type register yank-handler delete-func)
- "Change text from BEG to END with TYPE.
-Save in REGISTER or the kill-ring with YANK-HANDLER.
-DELETE-FUNC is a function for deleting text, default `evil-delete'.
-If TYPE is `line', insertion starts on an empty line.
-If TYPE is `block', the inserted text in inserted at each line
-of the block."
- (interactive "<R><x><y>")
- (let ((delete-func (or delete-func #'evil-delete))
- (nlines (1+ (evil-count-lines beg end)))
- (opoint (save-excursion
- (goto-char beg)
- (line-beginning-position))))
- (unless (eq evil-want-fine-undo t)
- (evil-start-undo-step))
- (funcall delete-func beg end type register yank-handler)
- (cond
- ((eq type 'line)
- (setq this-command 'evil-change-whole-line) ; for evil-maybe-remove-spaces
- (if (= opoint (point))
- (evil-open-above 1)
- (evil-open-below 1)))
- ((eq type 'block)
- (evil-insert 1 nlines))
- (t
- (evil-insert 1)))
- (setq evil-this-register nil)))
-
-(evil-define-operator evil-change-line (beg end type register yank-handler)
- "Change to end of line, or change whole line if characterwise visual mode."
- :motion evil-end-of-line-or-visual-line
- (interactive "<R><x><y>")
- (if (and (evil-visual-state-p) (eq 'inclusive type))
- (cl-destructuring-bind (beg* end* &rest) (evil-line-expand beg end)
- (evil-change-whole-line beg* end* register yank-handler))
- (evil-change beg end type register yank-handler #'evil-delete-line)))
-
-(evil-define-operator evil-change-whole-line
- (beg end register yank-handler)
- "Change whole line."
- :motion evil-line-or-visual-line
- :type line
- (interactive "<r><x>")
- (evil-change beg end 'line register yank-handler #'evil-delete-whole-line))
-
-(evil-define-command evil-copy (beg end address)
- "Copy lines in BEG END below line given by ADDRESS."
- :motion evil-line-or-visual-line
- (interactive "<r><addr>")
- (goto-char (point-min))
- (forward-line address)
- (let* ((txt (buffer-substring-no-properties beg end))
- (len (length txt)))
- ;; ensure text consists of complete lines
- (when (or (zerop len) (/= (aref txt (1- len)) ?\n))
- (setq txt (concat txt "\n")))
- (when (and (eobp) (not (bolp))) (newline)) ; incomplete last line
- (insert txt)
- (forward-line -1)))
-
-(evil-define-command evil-move (beg end address)
- "Move lines in BEG END below line given by ADDRESS."
- :motion evil-line-or-visual-line
- (interactive "<r><addr>")
- (unless (= (1+ address) (line-number-at-pos beg))
- (goto-char (point-min))
- (forward-line address)
- (let* ((m (set-marker (make-marker) (point)))
- (txt (buffer-substring-no-properties beg end))
- (len (length txt))
- (last-line-blank (progn (goto-char (point-max)) (bolp))))
- (delete-region beg end)
- (unless last-line-blank ; as vim, preserve lack of blank last line
- (progn (goto-char (point-max)) (when (bolp) (delete-char -1))))
- (goto-char m)
- (set-marker m nil)
- ;; ensure text consists of complete lines
- (when (or (zerop len) (/= (aref txt (1- len)) ?\n))
- (setq txt (concat txt "\n")))
- (when (and (eobp) (not (bolp))) (newline)) ; incomplete last line
- (when (evil-visual-state-p)
- (move-marker evil-visual-mark (point)))
- (insert txt)
- (forward-line -1)
- (when (evil-visual-state-p)
- (move-marker evil-visual-point (point))))))
-
-(defun evil--check-undo-system ()
- (when (and (eq evil-undo-system 'undo-tree)
- (not (bound-and-true-p undo-tree-mode)))
- (user-error "Enable `global-undo-tree-mode' to use undo-tree commands.
-Add (add-hook 'evil-local-mode-hook 'turn-on-undo-tree-mode) to your init file for undo in non-file buffers.")))
-
-(evil-define-command evil-undo (count)
- "Undo COUNT changes in buffer using `evil-undo-function'."
- :repeat abort
- (interactive "*p")
- (evil--check-undo-system)
- (funcall evil-undo-function count))
-
-(evil-define-command evil-redo (count)
- "Undo COUNT changes in buffer using `evil-redo-function'."
- :repeat abort
- (interactive "*p")
- (evil--check-undo-system)
- (funcall evil-redo-function count))
-
-(evil-define-operator evil-substitute (beg end type register)
- "Change a character."
- :motion evil-forward-char
- (interactive "<R><x>")
- (evil-change beg end type register))
-
-(evil-define-operator evil-upcase (beg end type)
- "Convert text to upper case."
- (if (eq type 'block)
- (evil-apply-on-block #'evil-upcase beg end nil)
- (upcase-region beg end)))
-
-(evil-define-operator evil-downcase (beg end type)
- "Convert text to lower case."
- (if (eq type 'block)
- (evil-apply-on-block #'evil-downcase beg end nil)
- (downcase-region beg end)))
-
-(evil-define-operator evil-invert-case (beg end type)
- "Invert case of text."
- (let (char)
- (if (eq type 'block)
- (evil-apply-on-block #'evil-invert-case beg end nil)
- (save-excursion
- (goto-char beg)
- (while (< beg end)
- (setq char (following-char))
- (delete-char 1 nil)
- (if (eq (upcase char) char)
- (insert-char (downcase char) 1)
- (insert-char (upcase char) 1))
- (setq beg (1+ beg)))))))
-
-(evil-define-operator evil-invert-char (beg end type)
- "Invert case of character."
- :motion evil-forward-char
- (if (eq type 'block)
- (evil-apply-on-block #'evil-invert-case beg end nil)
- (evil-invert-case beg end)
- (when evil-this-motion
- (goto-char end)
- (when (and evil-cross-lines
- (not evil-move-beyond-eol)
- (not (evil-visual-state-p))
- (not (evil-operator-state-p))
- (eolp) (not (eobp)) (not (bolp)))
- (forward-char)))))
-
-(evil-define-operator evil-rot13 (beg end type)
- "ROT13 encrypt text."
- (if (eq type 'block)
- (evil-apply-on-block #'evil-rot13 beg end nil)
- (rot13-region beg end)))
-
-(evil-define-operator evil-join (beg end)
- "Join the selected lines."
- :motion evil-line
- (let ((count (count-lines beg end)))
- (when (> count 1)
- (setq count (1- count)))
- (goto-char beg)
- (dotimes (_ count)
- (join-line 1))))
-
-(evil-define-operator evil-join-whitespace (beg end)
- "Join the selected lines without changing whitespace.
-\\<evil-normal-state-map>Like \\[evil-join], \
-but doesn't insert or remove any spaces."
- :motion evil-line
- (let ((count (count-lines beg end)))
- (when (> count 1)
- (setq count (1- count)))
- (goto-char beg)
- (dotimes (_ count)
- (evil-move-end-of-line 1)
- (unless (eobp)
- (delete-char 1)))))
-
-(evil-define-operator evil-ex-join (beg end &optional count bang)
- "Join the selected lines with optional COUNT and BANG."
- (interactive "<r><a><!>")
- (if (and count (not (string-match-p "^[1-9][0-9]*$" count)))
- (user-error "Invalid count")
- (let ((join-fn (if bang 'evil-join-whitespace 'evil-join)))
- (cond
- ((not count)
- ;; without count - just join the given region
- (funcall join-fn beg end))
- (t
- ;; emulate vim's :join when count is given - start from the
- ;; end of the region and join COUNT lines from there
- (let* ((count-num (string-to-number count))
- (beg-adjusted (save-excursion
- (goto-char end)
- (forward-line -1)
- (point)))
- (end-adjusted (save-excursion
- (goto-char end)
- (point-at-bol count-num))))
- (funcall join-fn beg-adjusted end-adjusted)))))))
-
-(evil-define-operator evil-fill (beg end)
- "Fill text."
- :move-point nil
- :type line
- (save-excursion
- (condition-case nil
- (fill-region beg end)
- (error nil))))
-
-(evil-define-operator evil-fill-and-move (beg end)
- "Fill text and move point to the end of the filled region."
- :move-point nil
- :type line
- (let ((marker (make-marker)))
- (move-marker marker (1- end))
- (condition-case nil
- (progn
- (fill-region beg end)
- (goto-char marker)
- (evil-first-non-blank))
- (error nil))))
-
-(evil-define-operator evil-indent (beg end)
- "Indent text."
- :move-point nil
- :type line
- (save-restriction
- (narrow-to-region beg end)
- (if (and (= beg (line-beginning-position))
- (= end (line-beginning-position 2)))
- ;; since some Emacs modes can only indent one line at a time,
- ;; implement "==" as a call to `indent-according-to-mode'
- (indent-according-to-mode)
- (goto-char beg)
- (indent-region beg end))
- ;; Update `beg' and `end'
- (setq beg (point-min)
- end (point-max))
- ;; We also need to tabify or untabify the leading white characters
- (when evil-indent-convert-tabs
- (let* ((beg-line (line-number-at-pos beg))
- (end-line (line-number-at-pos end))
- (ln beg-line)
- (convert-white (if indent-tabs-mode 'tabify 'untabify)))
- (save-excursion
- (while (<= ln end-line)
- (goto-char (point-min))
- (forward-line (- ln 1))
- (back-to-indentation)
- ;; Whether tab or space should be used is determined by indent-tabs-mode
- (funcall convert-white (line-beginning-position) (point))
- (setq ln (1+ ln)))))
- (back-to-indentation))))
-
-(evil-define-operator evil-indent-line (beg end)
- "Indent the line."
- :motion evil-line
- (evil-indent beg end))
-
-(evil-define-operator evil-shift-left (beg end &optional count preserve-empty)
- "Shift text from BEG to END to the left.
-The text is shifted to the nearest multiple of `evil-shift-width'
-\(the rounding can be disabled by setting `evil-shift-round').
-If PRESERVE-EMPTY is non-nil, lines that contain only spaces are
-indented, too, otherwise they are ignored. Location of point
-is preserved relative to text when called from insert state.
-Otherwise, it is determined by `evil-start-of-line' and/or `evil-track-eol'.
-See also `evil-shift-right'."
- :type line
- (interactive "<r><vc>")
- (evil-shift-right beg end (- (or count 1)) preserve-empty))
-
-(evil-define-operator evil-shift-right (beg end &optional count preserve-empty)
- "Shift text from BEG to END to the right.
-The text is shifted to the nearest multiple of `evil-shift-width'
-\(the rounding can be disabled by setting `evil-shift-round').
-If PRESERVE-EMPTY is non-nil, lines that contain only spaces are
-indented, too, otherwise they are ignored. Location of point
-is preserved relative to text when called from insert or replace states.
-Otherwise, it is determined by `evil-start-of-line' and/or `evil-track-eol'.
-See also `evil-shift-left'."
- :type line
- :move-point nil ; point is moved according to `evil-start-of-line' and state
- (interactive "<r><vc>")
- (setq count (or count 1))
- (let ((beg (set-marker (make-marker) beg))
- (end (set-marker (make-marker) end))
- (col-for-insert (current-column))
- first-shift) ; shift of first line
- (save-excursion
- (goto-char beg)
- (while (< (point) end)
- (let* ((indent (current-indentation))
- (new-indent
- (max 0
- (if (not evil-shift-round)
- (+ indent (* count evil-shift-width))
- (* (+ (/ indent evil-shift-width)
- count
- (cond
- ((> count 0) 0)
- ((zerop (mod indent evil-shift-width)) 0)
- (t 1)))
- evil-shift-width)))))
- (unless first-shift
- (setq first-shift (- new-indent indent)))
- (when (or preserve-empty
- (save-excursion
- (skip-chars-forward " \t")
- (not (eolp))))
- (indent-to new-indent 0))
- (delete-region (point) (progn (skip-chars-forward " \t") (point)))
- (forward-line 1))))
- ;; in case we're in an empty buffer first-shift is still unchanged
- (unless first-shift
- (if (< count 0)
- (setq first-shift 0)
- (setq first-shift (* count evil-shift-width))
- (indent-to first-shift)))
- ;; When called from insert state (C-t or C-d) the cursor should shift with the line,
- ;; otherwise (normal state) its position is determined by `evil-start-of-line'.
- (cond
- ((or (evil-insert-state-p) (evil-replace-state-p))
- (move-to-column (max 0 (+ col-for-insert first-shift))))
- (evil-start-of-line (evil-first-non-blank))
- ((evil--stick-to-eol-p) (move-end-of-line 1))
- (t (move-to-column (or goal-column evil-operator-start-col col-for-insert))))
- (setq temporary-goal-column 0)))
-
-(defun evil-delete-indentation ()
- "Delete all indentation on current line."
- (interactive)
- (save-excursion
- (evil-beginning-of-line)
- (delete-region (point) (progn (skip-chars-forward " \t") (point)))))
-
-(evil-define-command evil-shift-right-line (count)
- "Shift the current line COUNT times to the right.
-The text is shifted to the nearest multiple of
-`evil-shift-width'. Like `evil-shift-right' but always works on
-the current line."
- (interactive "<c>")
- (evil-shift-right (line-beginning-position) (line-beginning-position 2) count t))
-
-(evil-define-command evil-shift-left-line (count)
- "Shift the current line COUNT times to the left.
-The text is shifted to the nearest multiple of
-`evil-shift-width'. Like `evil-shift-left' but always works on
-the current line."
- (interactive "<c>")
- (if (and (eq 'self-insert-command last-command)
- (eq ?0 (char-before)))
- (progn (backward-delete-char 1)
- (evil-delete-indentation))
- (evil-shift-left (line-beginning-position) (line-beginning-position 2) count t)))
-
-(evil-define-operator evil-align-left (beg end type &optional width)
- "Left-align lines in the region at WIDTH columns.
-The default for width is the value of `fill-column'."
- :motion evil-line
- :type line
- (interactive "<R><a>")
- (evil-justify-lines beg end 'left (if width
- (string-to-number width)
- 0)))
-
-(evil-define-operator evil-align-right (beg end type &optional width)
- "Right-align lines in the region at WIDTH columns.
-The default for width is the value of `fill-column'."
- :motion evil-line
- :type line
- (interactive "<R><a>")
- (evil-justify-lines beg end 'right (if width
- (string-to-number width)
- fill-column)))
-
-(evil-define-operator evil-align-center (beg end type &optional width)
- "Centers lines in the region between WIDTH columns.
-The default for width is the value of `fill-column'."
- :motion evil-line
- :type line
- (interactive "<R><a>")
- (evil-justify-lines beg end 'center (if width
- (string-to-number width)
- fill-column)))
-
-(evil-define-operator evil-replace (beg end type char)
- "Replace text from BEG to END with CHAR."
- :motion evil-forward-char
- (interactive "<R>"
- (unwind-protect
- (let ((evil-force-cursor 'replace))
- (evil-refresh-cursor)
- (list (evil-read-key)))
- (evil-refresh-cursor)))
- (when char
- (if (eq type 'block)
- (save-excursion
- (evil-apply-on-rectangle
- #'(lambda (begcol endcol char)
- (let ((maxcol (evil-column (line-end-position))))
- (when (< begcol maxcol)
- (setq endcol (min endcol maxcol))
- (let ((beg (evil-move-to-column begcol nil t))
- (end (evil-move-to-column endcol nil t)))
- (delete-region beg end)
- (insert (make-string (- endcol begcol) char))))))
- beg end char))
- (goto-char beg)
- (cond
- ((eq char ?\n)
- (delete-region beg end)
- (newline)
- (when evil-auto-indent
- (indent-according-to-mode)))
- (t
- (while (< (point) end)
- (if (eq (char-after) ?\n)
- (forward-char)
- (delete-char 1)
- (insert-char char 1)))
- (goto-char (max beg (1- end))))))))
-
-(evil-define-command evil-paste-before
- (count &optional register yank-handler)
- "Pastes the latest yanked text before the cursor position.
-The return value is the yanked text."
- :suppress-operator t
- (interactive "*P<x>")
- (setq count (prefix-numeric-value count))
- (if (evil-visual-state-p)
- (evil-visual-paste count register)
- (evil-with-undo
- (let* ((text (if register
- (evil-get-register register)
- (current-kill 0)))
- (yank-handler (or yank-handler
- (when (stringp text)
- (car-safe (get-text-property
- 0 'yank-handler text)))))
- (opoint (point)))
- (when evil-paste-clear-minibuffer-first
- (delete-minibuffer-contents)
- (setq evil-paste-clear-minibuffer-first nil))
- (when text
- (if (functionp yank-handler)
- (let ((evil-paste-count count)
- ;; for non-interactive use
- (this-command #'evil-paste-before))
- (push-mark opoint t)
- (insert-for-yank text))
- ;; no yank-handler, default
- (when (vectorp text)
- (setq text (evil-vector-to-string text)))
- (set-text-properties 0 (length text) nil text)
- (push-mark opoint t)
- (dotimes (_ (or count 1))
- (insert-for-yank text))
- (setq evil-last-paste
- (list #'evil-paste-before
- count
- opoint
- opoint ; beg
- (point))) ; end
- (evil-set-marker ?\[ opoint)
- (evil-set-marker ?\] (1- (point)))
- (when (and evil-move-cursor-back
- (> (length text) 0))
- (backward-char))))
- ;; no paste-pop after pasting from a register
- (when register
- (setq evil-last-paste nil))
- (and (> (length text) 0) text)))))
-
-(evil-define-command evil-paste-after
- (count &optional register yank-handler)
- "Pastes the latest yanked text behind point.
-The return value is the yanked text."
- :suppress-operator t
- (interactive "*P<x>")
- (setq count (prefix-numeric-value count))
- (if (evil-visual-state-p)
- (evil-visual-paste count register)
- (evil-with-undo
- (let* ((text (if register
- (evil-get-register register)
- (current-kill 0)))
- (yank-handler (or yank-handler
- (when (stringp text)
- (car-safe (get-text-property
- 0 'yank-handler text)))))
- (opoint (point)))
- (when text
- (if (functionp yank-handler)
- (let ((evil-paste-count count)
- ;; for non-interactive use
- (this-command #'evil-paste-after))
- (insert-for-yank text))
- ;; no yank-handler, default
- (when (vectorp text)
- (setq text (evil-vector-to-string text)))
- (set-text-properties 0 (length text) nil text)
- (unless (eolp) (forward-char))
- (push-mark (point) t)
- ;; TODO: Perhaps it is better to collect a list of all
- ;; (point . mark) pairs to undo the yanking for COUNT > 1.
- ;; The reason is that this yanking could very well use
- ;; `yank-handler'.
- (let ((beg (point)))
- (dotimes (_ (or count 1))
- (insert-for-yank text))
- (setq evil-last-paste
- (list #'evil-paste-after
- count
- opoint
- beg ; beg
- (point))) ; end
- (evil-set-marker ?\[ beg)
- (evil-set-marker ?\] (1- (point)))
- (when (evil-normal-state-p)
- (evil-move-cursor-back)))))
- (when register
- (setq evil-last-paste nil))
- (and (> (length text) 0) text)))))
-
-(defun evil-insert-for-yank-at-col (startcol _endcol string count)
- "Insert STRING at STARTCOL."
- (move-to-column startcol)
- (dotimes (_ (or count 1))
- (insert-for-yank string))
- (evil-set-marker ?\] (1- (point))))
-
-(evil-define-command evil-visual-paste (count &optional register)
- "Paste over Visual selection."
- :suppress-operator t
- (interactive "*P<x>")
- (setq count (prefix-numeric-value count))
- ;; evil-visual-paste is typically called from evil-paste-before or
- ;; evil-paste-after, but we have to mark that the paste was from
- ;; visual state
- (setq this-command 'evil-visual-paste)
- (let* ((text (if register
- (evil-get-register register)
- (current-kill 0)))
- (yank-handler (car-safe (get-text-property
- 0 'yank-handler text)))
- (dir (evil-visual-direction))
- beg end paste-eob)
- (evil-with-undo
- (let ((kill-ring-yank-pointer (when kill-ring (list (current-kill 0)))))
- (when (evil-visual-state-p)
- (setq beg evil-visual-beginning
- end evil-visual-end)
- (evil-visual-rotate 'upper-left)
- ;; if we replace the last buffer line that does not end in a
- ;; newline, we use `evil-paste-after' because `evil-delete'
- ;; will move point to the line above
- (when (and (= evil-visual-end (point-max))
- (/= (char-before (point-max)) ?\n))
- (setq paste-eob t))
- (evil-delete beg end (evil-visual-type) (unless evil-kill-on-visual-paste ?_))
- (when (and (eq yank-handler #'evil-yank-line-handler)
- (not (memq (evil-visual-type) '(line block)))
- (not (= evil-visual-end (point-max))))
- (insert "\n"))
- (evil-normal-state)
- (when kill-ring (current-kill 1)))
- ;; Effectively memoize `evil-get-register' because it can be
- ;; side-effecting (e.g. for the `=' register)...
- (cl-letf (((symbol-function 'evil-get-register)
- (lambda (&rest _) text)))
- (cond
- ((eq 'block (evil-visual-type))
- (when (eq yank-handler #'evil-yank-line-handler)
- (setq text (concat "\n" text)))
- (evil-set-marker ?\[ beg)
- (evil-apply-on-block #'evil-insert-for-yank-at-col beg end t text count))
- (paste-eob (evil-paste-after count register))
- (t (evil-paste-before count register)))))
- (when evil-kill-on-visual-paste
- (current-kill -1))
- ;; Ensure that gv can restore visually pasted area...
- (setq evil-visual-previous-mark evil-visual-mark
- evil-visual-mark (evil-get-marker (if (<= 0 dir) ?\[ ?\]) t)
- evil-visual-previous-point evil-visual-point
- evil-visual-point (evil-get-marker (if (<= 0 dir) ?\] ?\[) t))
- ;; mark the last paste as visual-paste
- (setq evil-last-paste
- (list (nth 0 evil-last-paste)
- (nth 1 evil-last-paste)
- (nth 2 evil-last-paste)
- (nth 3 evil-last-paste)
- (nth 4 evil-last-paste)
- t)))))
-
-(defun evil-paste-from-register (register)
- "Paste from REGISTER."
- (interactive
- (let* ((opoint (point))
- (overlay (make-overlay opoint (+ opoint (if (evil-replace-state-p) 1 0)))))
- (unwind-protect
- (progn
- (overlay-put overlay 'invisible t)
- (overlay-put overlay 'after-string (propertize "\""
- 'face 'minibuffer-prompt
- 'cursor 1))
- (list (or evil-this-register (read-char))))
- (delete-overlay overlay))))
- (let ((opoint (point))
- (evil-move-cursor-back nil)
- reg-length chars-to-delete)
- (evil-paste-before nil register t)
- (when (evil-replace-state-p)
- (setq reg-length (- (point) opoint)
- chars-to-delete (min (- (point-at-eol) (point)) reg-length))
- ;; TODO: handle multi-line paste backspacing
- (evil-update-replace-alist (point) reg-length chars-to-delete chars-to-delete)
- (delete-char chars-to-delete))))
-
-(defun evil-paste-last-insertion ()
- "Paste last insertion."
- (interactive)
- (evil-paste-from-register ?.))
-
-(defun evil-paste-last-insertion-and-stop-insert ()
- "Paste last insertion and change to normal state."
- (interactive)
- (evil-paste-last-insertion)
- (evil-normal-state))
-
-(evil-define-command evil-use-register (register)
- "Use REGISTER for the next command."
- :keep-visual t
- :repeat ignore
- (interactive "<C>")
- (setq evil-this-register register))
-
-(defvar evil-macro-buffer nil
- "The buffer that has been active on macro recording.")
-
-(defun evil-end-and-return-macro ()
- "Like `kmacro-end-macro' but also return the macro.
-Remove \\<evil-insert-state-map>\\[evil-execute-in-normal-state] from the end."
- ;; `end-kbd-macro' rather than `kmacro-end-macro' to allow clearing registers
- (end-kbd-macro nil #'kmacro-loop-setup-function)
- (let ((end-keys-seq (append evil-execute-normal-keys nil))
- (last-kbd-macro-seq (append last-kbd-macro nil)))
- (unless last-kbd-macro-seq
- (setq last-kbd-macro nil))
- (if (and end-keys-seq last-kbd-macro-seq)
- (apply #'vector (butlast last-kbd-macro-seq (length end-keys-seq)))
- last-kbd-macro)))
-
-(evil-define-command evil-record-macro (register)
- "Record a keyboard macro into REGISTER.
-If REGISTER is :, /, or ?, the corresponding command line window
-will be opened instead."
- :keep-visual t
- :suppress-operator t
- (interactive
- (list (unless (and evil-this-macro defining-kbd-macro)
- (or evil-this-register (evil-read-key)))))
- (let (last-macro)
- (cond
- ((eq register ?\C-g)
- (keyboard-quit))
- ((and evil-this-macro defining-kbd-macro)
- (setq evil-macro-buffer nil)
- (condition-case nil
- (setq last-macro (evil-end-and-return-macro))
- (error nil))
- (when last-macro
- (evil-set-register evil-this-macro last-macro))
- (setq evil-this-macro nil))
- ((eq register ?:)
- (evil-command-window-ex))
- ((eq register ?/)
- (evil-command-window-search-forward))
- ((eq register ??)
- (evil-command-window-search-backward))
- ((or (<= ?0 register ?9)
- (<= ?a register ?z)
- (<= ?A register ?Z))
- (when defining-kbd-macro (end-kbd-macro))
- (setq evil-this-macro register)
- (evil-set-register evil-this-macro nil)
- (kmacro-start-macro nil)
- (setq evil-macro-buffer (current-buffer)))
- (t (error "Invalid register")))))
-
-(evil-define-command evil-execute-macro (count macro)
- "Execute keyboard macro MACRO, COUNT times.
-When called with a non-numerical prefix \
-\(such as \\[universal-argument]),
-COUNT is infinite. MACRO is read from a register
-when called interactively."
- :keep-visual t
- :suppress-operator t
- (interactive
- (let (count macro register)
- (setq count (if current-prefix-arg
- (if (numberp current-prefix-arg)
- current-prefix-arg
- 0) 1)
- register (or evil-this-register (read-char)))
- (cond
- ((or (and (eq register ?@) (eq evil-last-register ?:))
- (eq register ?:))
- (setq macro (lambda () (evil-ex-repeat nil))
- evil-last-register ?:))
- ((eq register ?@)
- (unless evil-last-register
- (user-error "No previously executed keyboard macro."))
- (setq macro (evil-get-register evil-last-register t)))
- (t
- (setq macro (evil-get-register register t)
- evil-last-register register)))
- (list count macro)))
- (cond
- ((functionp macro)
- (evil-repeat-abort)
- (dotimes (_ (or count 1))
- (funcall macro)))
- ((or (and (not (stringp macro))
- (not (vectorp macro)))
- (member macro '("" [])))
- ;; allow references to currently empty registers
- ;; when defining macro
- (unless evil-this-macro
- (user-error "No previous macro")))
- (t
- (condition-case err
- (evil-with-single-undo
- (dotimes (_ (or count 1))
- (execute-kbd-macro macro)))
- ;; enter Normal state if the macro fails
- (error
- (evil-normal-state)
- (evil-normalize-keymaps)
- (signal (car err) (cdr err)))))))
-
-;;; Visual commands
-
-(evil-define-motion evil-visual-restore ()
- "Restore previous selection."
- (let* ((point (point))
- (mark (or (mark t) point))
- (type (evil-visual-type)))
- ;; TODO handle swapping selection in visual state...
- (unless (evil-visual-state-p)
- (cond
- ;; No previous selection.
- ((or (null evil-visual-selection)
- (null evil-visual-mark)
- (null evil-visual-point)))
- (t
- (setq mark evil-visual-mark
- point evil-visual-point)))
- (evil-visual-make-selection mark point type t))))
-
-(evil-define-motion evil-visual-exchange-corners ()
- "Rearrange corners in Visual Block mode.
-
- M---+ +---M
- | | <=> | |
- +---P P---+
-
-For example, if mark is in the upper left corner and point
-in the lower right, this function puts mark in the upper right
-corner and point in the lower left."
- (cond
- ((eq evil-visual-selection 'block)
- (let* ((point (point))
- (mark (or (mark t) point))
- (point-col (evil-column point))
- (mark-col (evil-column mark))
- (mark (save-excursion
- (goto-char mark)
- (evil-move-to-column point-col)
- (point)))
- (point (save-excursion
- (goto-char point)
- (evil-move-to-column mark-col)
- (point))))
- (evil-visual-refresh mark point)))
- (t
- (evil-exchange-point-and-mark)
- (evil-visual-refresh))))
-
-(evil-define-command evil-visual-rotate (corner &optional beg end type)
- "In Visual Block selection, put point in CORNER.
-Corner may be one of `upper-left', `upper-right', `lower-left'
-and `lower-right':
-
- upper-left +---+ upper-right
- | |
- lower-left +---+ lower-right
-
-When called interactively, the selection is rotated blockwise."
- :keep-visual t
- (interactive
- (let ((corners '(upper-left upper-right lower-right lower-left)))
- (list (or (cadr (memq (evil-visual-block-corner) corners))
- 'upper-left))))
- (let* ((beg (or beg (point)))
- (end (or end (mark t) beg))
- (type (or type evil-this-type))
- range)
- (cond
- ((memq type '(rectangle block))
- (setq range (evil-block-rotate beg end :corner corner)
- beg (pop range)
- end (pop range))
- (unless (eq corner (evil-visual-block-corner corner beg end))
- (evil-swap beg end))
- (goto-char beg)
- (when (evil-visual-state-p)
- (evil-move-mark end)
- (evil-visual-refresh nil nil nil :corner corner)))
- ((memq corner '(upper-right lower-right))
- (goto-char (max beg end))
- (when (evil-visual-state-p)
- (evil-move-mark (min beg end))))
- (t
- (goto-char (min beg end))
- (when (evil-visual-state-p)
- (evil-move-mark (max beg end)))))))
-
-;;; Insertion commands
-
-(defun evil-insert (count &optional vcount skip-empty-lines)
- "Switch to Insert state just before point.
-The insertion will be repeated COUNT times and repeated once for
-the next VCOUNT - 1 lines starting at the same column.
-If SKIP-EMPTY-LINES is non-nil, the insertion will not be performed
-on lines on which the insertion point would be after the end of the
-lines. This is the default behaviour for Visual-state insertion."
- (interactive
- (list (prefix-numeric-value current-prefix-arg)
- (and (evil-visual-state-p)
- (memq (evil-visual-type) '(line block))
- (save-excursion
- (let ((m (mark)))
- ;; go to upper-left corner temporarily so
- ;; `count-lines' yields accurate results
- (evil-visual-rotate 'upper-left)
- (prog1 (count-lines evil-visual-beginning evil-visual-end)
- (set-mark m)))))
- (evil-visual-state-p)))
- (if (and (called-interactively-p 'any)
- (evil-visual-state-p))
- (cond
- ((eq (evil-visual-type) 'line)
- (evil-visual-rotate 'upper-left)
- (evil-insert-line count vcount))
- ((eq (evil-visual-type) 'block)
- (let ((column (min (evil-column evil-visual-beginning)
- (evil-column evil-visual-end))))
- (evil-visual-rotate 'upper-left)
- (move-to-column column t)
- (evil-insert count vcount skip-empty-lines)))
- (t
- (evil-visual-rotate 'upper-left)
- (evil-insert count vcount skip-empty-lines)))
- (setq evil-insert-count count
- evil-insert-lines nil
- evil-insert-vcount (and vcount
- (> vcount 1)
- (list (line-number-at-pos)
- (current-column)
- vcount))
- evil-insert-skip-empty-lines skip-empty-lines)
- (evil-insert-state 1)))
-
-(defun evil-append (count &optional vcount skip-empty-lines)
- "Switch to Insert state just after point.
-The insertion will be repeated COUNT times and repeated once for
-the next VCOUNT - 1 lines starting at the same column. If
-SKIP-EMPTY-LINES is non-nil, the insertion will not be performed
-on lines on which the insertion point would be after the end of
-the lines."
- (interactive
- (list (prefix-numeric-value current-prefix-arg)
- (and (evil-visual-state-p)
- (memq (evil-visual-type) '(line block))
- (save-excursion
- (let ((m (mark)))
- ;; go to upper-left corner temporarily so
- ;; `count-lines' yields accurate results
- (evil-visual-rotate 'upper-left)
- (prog1 (count-lines evil-visual-beginning evil-visual-end)
- (set-mark m)))))))
- (if (and (called-interactively-p 'any)
- (evil-visual-state-p))
- (cond
- ((or (eq (evil-visual-type) 'line)
- (and (eq (evil-visual-type) 'block)
- (memq last-command '(next-line previous-line))
- (numberp temporary-goal-column)
- (= temporary-goal-column most-positive-fixnum)))
- (evil-visual-rotate 'upper-left)
- (evil-append-line count vcount))
- ((eq (evil-visual-type) 'block)
- (let ((column (max (evil-column evil-visual-beginning)
- (evil-column evil-visual-end))))
- (evil-visual-rotate 'upper-left)
- (move-to-column column t)
- (evil-insert count vcount skip-empty-lines)))
- (t
- (evil-visual-rotate 'lower-right)
- (backward-char)
- (evil-append count)))
- (unless (= (current-column)
- (save-excursion (end-of-line) (current-column)))
- ;; Subtly different from `(eolp)' - see issue #1617
- (forward-char))
- (evil-insert count vcount skip-empty-lines)
- (add-hook 'post-command-hook #'evil-maybe-remove-spaces)))
-
-(defun evil-insert-resume (count)
- "Switch to Insert state at previous insertion point.
-The insertion will be repeated COUNT times. If called from visual
-state, only place point at the previous insertion position but do not
-switch to insert state."
- (interactive "p")
- (evil-goto-mark ?^ t)
- (unless (evil-visual-state-p)
- (evil-insert count)))
-
-(defun evil-quoted-insert (count)
- "Like `quoted-insert' but delete COUNT chars forward in replace state.
-Adds a `^' overlay as an input prompt."
- (interactive "p")
- (let* ((opoint (point))
- chars-to-delete insert-prompt)
- (unwind-protect
- (progn
- (if (evil-replace-state-p)
- (progn
- (setq chars-to-delete (min (- (point-at-eol) opoint) count)
- insert-prompt (make-overlay opoint (+ chars-to-delete opoint)))
- (evil-update-replace-alist opoint count chars-to-delete))
- (setq insert-prompt (make-overlay opoint opoint)))
- (overlay-put insert-prompt 'invisible t)
- (overlay-put insert-prompt 'after-string (propertize "^"
- 'face 'escape-glyph
- 'cursor 1))
- (let (overwrite-mode) ;; Force `read-quoted-char'
- (quoted-insert count))
- (when (evil-replace-state-p) (delete-char chars-to-delete)))
- (when insert-prompt (delete-overlay insert-prompt)))))
-
-(defun evil-open-above (count)
- "Insert a new line above point and switch to Insert state.
-The insertion will be repeated COUNT times."
- (interactive "p")
- (unless (eq evil-want-fine-undo t)
- (evil-start-undo-step))
- (evil-insert-newline-above)
- (setq evil-insert-count count
- evil-insert-lines t
- evil-insert-vcount nil)
- (evil-insert-state 1)
- (when evil-auto-indent
- (indent-according-to-mode)))
-
-(defun evil-open-below (count)
- "Insert a new line below point and switch to Insert state.
-The insertion will be repeated COUNT times."
- (interactive "p")
- (unless (eq evil-want-fine-undo t)
- (evil-start-undo-step))
- (push (point) buffer-undo-list)
- (evil-insert-newline-below)
- (setq evil-insert-count count
- evil-insert-lines t
- evil-insert-vcount nil)
- (evil-insert-state 1)
- (when evil-auto-indent
- (indent-according-to-mode)))
-
-(defun evil--insert-line (count vcount non-blank-p)
- "Switch to insert state at the beginning of the current line.
-If NON-BLANK-P is non-nil, point is placed at the first non-blank character
-on the current line. If NON-BLANK-P is nil, point is placed at column 0,
-or the beginning of visual line. The insertion will be repeated COUNT times.
-If VCOUNT is non nil it should be number > 0. The insertion will be repeated
-in the next VCOUNT - 1 lines below the current one."
- (push (point) buffer-undo-list)
- (let ((move-fn (if non-blank-p #'back-to-indentation #'evil-beginning-of-line)))
- (if (and visual-line-mode
- evil-respect-visual-line-mode)
- (goto-char
- (max (save-excursion
- (funcall move-fn)
- (point))
- (save-excursion
- (beginning-of-visual-line)
- (point))))
- (funcall move-fn)))
- (setq evil-insert-count count
- evil-insert-lines nil
- evil-insert-vcount
- (and vcount
- (> vcount 1)
- (list (line-number-at-pos)
- (if non-blank-p #'evil-first-non-blank #'evil-beginning-of-line)
- vcount)))
- (evil-insert-state 1))
-
-(defun evil-insert-line (count &optional vcount)
- "Switch to insert state at beginning of current line.
-Point is placed at the first non-blank character on the current
-line. The insertion will be repeated COUNT times. If VCOUNT is
-non nil it should be number > 0. The insertion will be repeated
-in the next VCOUNT - 1 lines below the current one."
- (interactive "p")
- (evil--insert-line count vcount t))
-
-(defun evil-insert-0-line (count &optional vcount)
- "Switch to insert state at beginning of current line.
-Point is placed at column 0, or the beginning of the visual line.
-The insertion will be repeated COUNT times. If VCOUNT is
-non nil it should be number > 0. The insertion will be repeated
-in the next VCOUNT - 1 lines below the current one."
- (interactive "p")
- (evil--insert-line count vcount nil))
-
-(defun evil-append-line (count &optional vcount)
- "Switch to Insert state at the end of the current line.
-The insertion will be repeated COUNT times. If VCOUNT is non nil
-it should be number > 0. The insertion will be repeated in the
-next VCOUNT - 1 lines below the current one."
- (interactive "p")
- (if (and visual-line-mode
- evil-respect-visual-line-mode)
- (evil-end-of-visual-line)
- (evil-move-end-of-line))
- (setq evil-insert-count count
- evil-insert-lines nil
- evil-insert-vcount
- (and vcount
- (> vcount 1)
- (list (line-number-at-pos)
- #'end-of-line
- vcount)))
- (evil-insert-state 1))
-
-(evil-define-command evil-insert-digraph (count)
- "Insert COUNT digraphs."
- :repeat change
- (interactive "p")
- (let ((opoint (point))
- chars-to-delete insert-prompt)
- (if (evil-replace-state-p)
- (progn
- (setq chars-to-delete (min (- (point-at-eol) opoint) count)
- insert-prompt (make-overlay opoint (+ chars-to-delete opoint)))
- (evil-update-replace-alist opoint count chars-to-delete))
- (setq insert-prompt (make-overlay opoint opoint)))
- (insert-char (evil-read-digraph-char-with-overlay insert-prompt) count)
- (when chars-to-delete (delete-char chars-to-delete))))
-
-(evil-define-command evil-ex-show-digraphs ()
- "Shows a list of all available digraphs."
- :repeat nil
- (let ((columns 3))
- (evil-with-view-list
- :name "evil-digraphs"
- :mode-name "Evil Digraphs"
- :format
- (cl-loop repeat columns
- vconcat [("Digraph" 8 nil)
- ("Sequence" 16 nil)])
- :entries
- (let* ((digraphs (mapcar #'(lambda (digraph)
- (cons (cdr digraph)
- (car digraph)))
- (append evil-digraphs-table
- evil-digraphs-table-user)))
- (entries (cl-loop for digraph in digraphs
- collect `(,(concat (char-to-string (nth 1 digraph))
- (char-to-string (nth 2 digraph)))
- ,(char-to-string (nth 0 digraph)))))
- (row)
- (rows)
- (clength (* columns 2)))
- (cl-loop for e in entries
- do
- (push (nth 0 e) row)
- (push (nth 1 e) row)
- (when (eq (length row) clength)
- (push `(nil ,(apply #'vector row)) rows)
- (setq row nil)))
- rows))))
-
-(defun evil--self-insert-string (string)
- "Insert STRING as if typed interactively."
- (let ((chars (append string nil)))
- (dolist (char chars)
- (let ((last-command-event char))
- (self-insert-command 1)))))
-
-(defun evil-copy-from-above (arg)
- "Copy characters from preceding non-blank line.
-The copied text is inserted before point.
-ARG is the number of lines to move backward.
-See also \\<evil-insert-state-map>\\[evil-copy-from-below]."
- (interactive
- (cond
- ;; if a prefix argument was given, repeat it for subsequent calls
- ((and (null current-prefix-arg)
- (eq last-command #'evil-copy-from-above))
- (setq current-prefix-arg last-prefix-arg)
- (list (prefix-numeric-value current-prefix-arg)))
- (t
- (list (prefix-numeric-value current-prefix-arg)))))
- (evil--self-insert-string (evil-copy-chars-from-line arg -1)))
-
-(defun evil-copy-from-below (arg)
- "Copy characters from following non-blank line.
-The copied text is inserted before point.
-ARG is the number of lines to move forward.
-See also \\<evil-insert-state-map>\\[evil-copy-from-above]."
- (interactive
- (cond
- ((and (null current-prefix-arg)
- (eq last-command #'evil-copy-from-below))
- (setq current-prefix-arg last-prefix-arg)
- (list (prefix-numeric-value current-prefix-arg)))
- (t
- (list (prefix-numeric-value current-prefix-arg)))))
- (evil--self-insert-string (evil-copy-chars-from-line arg 1)))
-
-;; adapted from `copy-from-above-command' in misc.el
-(defun evil-copy-chars-from-line (n num &optional col)
- "Return N characters from line NUM, starting at column COL.
-NUM is relative to the current line and can be negative.
-COL defaults to the current column."
- (interactive "p")
- (let ((col (or col (current-column))) prefix)
- (save-excursion
- (forward-line num)
- (when (looking-at "[[:space:]]*$")
- (if (< num 0)
- (skip-chars-backward " \t\n")
- (skip-chars-forward " \t\n")))
- (evil-move-beginning-of-line)
- (move-to-column col)
- ;; if the column winds up in middle of a tab,
- ;; return the appropriate number of spaces
- (when (< col (current-column))
- (if (eq (preceding-char) ?\t)
- (let ((len (min n (- (current-column) col))))
- (setq prefix (make-string len ?\s)
- n (- n len)))
- ;; if in middle of a control char, return the whole char
- (backward-char 1)))
- (concat prefix
- (buffer-substring (point)
- (min (line-end-position)
- (+ n (point))))))))
-
-;; completion
-(evil-define-command evil-complete-next (&optional arg)
- "Complete to the nearest following word.
-Search backward if a match isn't found.
-Calls `evil-complete-next-func'."
- :repeat change
- (interactive "P")
- (if (minibufferp)
- (funcall evil-complete-next-minibuffer-func)
- (funcall evil-complete-next-func arg)))
-
-(evil-define-command evil-complete-previous (&optional arg)
- "Complete to the nearest preceding word.
-Search forward if a match isn't found.
-Calls `evil-complete-previous-func'."
- :repeat change
- (interactive "P")
- (if (minibufferp)
- (funcall evil-complete-previous-minibuffer-func)
- (funcall evil-complete-previous-func arg)))
-
-(evil-define-command evil-complete-next-line (&optional arg)
- "Complete a whole line.
-Calls `evil-complete-next-line-func'."
- :repeat change
- (interactive "P")
- (if (minibufferp)
- (funcall evil-complete-next-minibuffer-func)
- (funcall evil-complete-next-line-func arg)))
-
-(evil-define-command evil-complete-previous-line (&optional arg)
- "Complete a whole line.
-Calls `evil-complete-previous-line-func'."
- :repeat change
- (interactive "P")
- (if (minibufferp)
- (funcall evil-complete-previous-minibuffer-func)
- (funcall evil-complete-previous-line-func arg)))
-
-;;; Search
-
-(defun evil-repeat-search (flag)
- "Called to record a search command.
-FLAG is either 'pre or 'post if the function is called before resp.
-after executing the command."
- (cond
- ((and (evil-operator-state-p) (eq flag 'pre))
- (evil-repeat-record (this-command-keys))
- (evil-clear-command-keys))
- ((and (evil-operator-state-p) (eq flag 'post))
- ;; The value of (this-command-keys) at this point should be the
- ;; key-sequence that called the last command that finished the
- ;; search, usually RET. Therefore this key-sequence will be
- ;; recorded in the post-command of the operator. Alternatively we
- ;; could do it here.
- (evil-repeat-record (if evil-regexp-search
- (car-safe regexp-search-ring)
- (car-safe search-ring))))
- (t (evil-repeat-motion flag))))
-
-(evil-define-motion evil-search-forward ()
- (format "Search forward for user-entered text.
-Searches for regular expression if `evil-regexp-search' is t.%s"
- (if (and (fboundp 'isearch-forward)
- (documentation 'isearch-forward))
- (format "\n\nBelow is the documentation string \
-for `isearch-forward',\nwhich lists available keys:\n\n%s"
- (documentation 'isearch-forward)) ""))
- :jump t
- :type exclusive
- :repeat evil-repeat-search
- (evil-search-incrementally t evil-regexp-search))
-
-(evil-define-motion evil-search-backward ()
- (format "Search backward for user-entered text.
-Searches for regular expression if `evil-regexp-search' is t.%s"
- (if (and (fboundp 'isearch-forward)
- (documentation 'isearch-forward))
- (format "\n\nBelow is the documentation string \
-for `isearch-forward',\nwhich lists available keys:\n\n%s"
- (documentation 'isearch-forward)) ""))
- :jump t
- :type exclusive
- :repeat evil-repeat-search
- (evil-search-incrementally nil evil-regexp-search))
-
-(evil-define-motion evil-search-next (count)
- "Repeat the last search."
- :jump t
- :type exclusive
- (let ((orig (point))
- (search-string (if evil-regexp-search
- (car-safe regexp-search-ring)
- (car-safe search-ring))))
- (goto-char
- ;; Wrap in `save-excursion' so that multiple searches have no visual effect.
- (save-excursion
- (evil-search search-string isearch-forward evil-regexp-search)
- (when (and (> (point) orig)
- (save-excursion
- (evil-adjust-cursor)
- (= (point) orig)))
- ;; Point won't move after first attempt and `evil-adjust-cursor' takes
- ;; effect, so start again.
- (evil-search search-string isearch-forward evil-regexp-search))
- (point)))
- (when (and count (> count 1))
- (dotimes (_ (1- count))
- (evil-search search-string isearch-forward evil-regexp-search)))))
-
-(evil-define-motion evil-search-previous (count)
- "Repeat the last search in the opposite direction."
- :jump t
- :type exclusive
- (dotimes (_ (or count 1))
- (evil-search (if evil-regexp-search
- (car-safe regexp-search-ring)
- (car-safe search-ring))
- (not isearch-forward) evil-regexp-search)))
-
-(evil-define-motion evil-search-word-backward (count &optional symbol)
- "Search backward for symbol under point."
- :jump t
- :type exclusive
- (interactive (list (prefix-numeric-value current-prefix-arg)
- evil-symbol-word-search))
- (dotimes (_ (or count 1))
- (evil-search-word nil nil symbol)))
-
-(evil-define-motion evil-search-word-forward (count &optional symbol)
- "Search forward for symbol under point."
- :jump t
- :type exclusive
- (interactive (list (prefix-numeric-value current-prefix-arg)
- evil-symbol-word-search))
- (dotimes (_ (or count 1))
- (evil-search-word t nil symbol)))
-
-(evil-define-motion evil-search-unbounded-word-backward (count &optional symbol)
- "Search backward for symbol under point.
-The search is unbounded, i.e., the pattern is not wrapped in
-\\<...\\>."
- :jump t
- :type exclusive
- (interactive (list (prefix-numeric-value current-prefix-arg)
- evil-symbol-word-search))
- (dotimes (_ (or count 1))
- (evil-search-word nil t symbol)))
-
-(evil-define-motion evil-search-unbounded-word-forward (count &optional symbol)
- "Search forward for symbol under point.
-The search is unbounded, i.e., the pattern is not wrapped in
-\\<...\\>."
- :jump t
- :type exclusive
- (interactive (list (prefix-numeric-value current-prefix-arg)
- evil-symbol-word-search))
- (dotimes (_ (or count 1))
- (evil-search-word t t symbol)))
-
-(defun evil-goto-definition-imenu (string _position)
- "Find definition for STRING with imenu."
- (require 'imenu nil t)
- (let (ientry ipos)
- (when (fboundp 'imenu--make-index-alist)
- (ignore-errors (setq ientry (imenu--make-index-alist)))
- (setq ientry (imenu--in-alist string ientry))
- (setq ipos (cdr ientry))
- (when (and (markerp ipos)
- (eq (marker-buffer ipos) (current-buffer)))
- (setq ipos (marker-position ipos))
- (when (numberp ipos)
- (evil-search (format "\\_<%s\\_>" (regexp-quote string)) t t ipos)
- t)))))
-
-(defun evil-goto-definition-semantic (_string position)
- "Find definition for POSITION with semantic."
- (and (fboundp 'semantic-ia-fast-jump)
- (ignore-errors (semantic-ia-fast-jump position))))
-
-(declare-function xref-backend-identifier-at-point "xref")
-
-(defun evil-goto-definition-xref (_string position)
- "Find definition at POSITION with xref."
- (when (fboundp 'xref-find-definitions)
- (let ((identifier (save-excursion
- (goto-char position)
- (xref-backend-identifier-at-point (xref-find-backend)))))
- (condition-case ()
- (progn
- (xref-find-definitions identifier)
- t)
- (user-error nil)))))
-
-(defun evil-goto-definition-search (string _position)
- "Find definition for STRING with evil-search."
- (evil-search (format "\\_<%s\\_>" (regexp-quote string)) t t (point-min))
- t)
-
-(evil-define-motion evil-goto-definition ()
- "Go to definition or first occurrence of symbol under point.
-See also `evil-goto-definition-functions'."
- :jump t
- :type exclusive
- (let* ((match (evil--find-thing t 'symbol))
- (string (car match))
- (position (cdr match)))
- (if (null string)
- (user-error "No symbol under cursor")
- (setq isearch-forward t)
- (run-hook-with-args-until-success 'evil-goto-definition-functions
- string position))))
-
-;;; Folding
-(defun evil-fold-action (list action)
- "Perform fold ACTION for each matching major or minor mode in LIST.
-
-ACTION will be performed for the first matching handler in LIST. For more
-information on its features and format, see the documentation for
-`evil-fold-list'.
-
-If no matching ACTION is found in LIST, an error will signaled.
-
-Handler errors will be demoted, so a problem in one handler will (hopefully)
-not interfere with another."
- (if (null list)
- (user-error
- "Enable one of the following modes for folding to work: %s"
- (mapconcat 'symbol-name (mapcar 'caar evil-fold-list) ", "))
- (let* ((modes (caar list)))
- (if (evil--mode-p modes)
- (let* ((actions (cdar list))
- (fn (plist-get actions action)))
- (when fn
- (with-demoted-errors "Error: %S" (funcall fn))))
- (evil-fold-action (cdr list) action)))))
-
-(defun evil--mode-p (modes)
- "Determines whether any symbol in MODES represents the current
-buffer's major mode or any of its minors."
- (unless (eq modes '())
- (let ((mode (car modes)))
- (or (eq major-mode mode)
- (and (boundp mode) (symbol-value mode))
- (evil--mode-p (cdr modes))))))
-
-(evil-define-command evil-toggle-fold ()
- "Open or close a fold under point.
-See also `evil-open-fold' and `evil-close-fold'."
- (evil-fold-action evil-fold-list :toggle))
-
-(evil-define-command evil-open-folds ()
- "Open all folds.
-See also `evil-close-folds'."
- (evil-fold-action evil-fold-list :open-all))
-
-(evil-define-command evil-close-folds ()
- "Close all folds.
-See also `evil-open-folds'."
- (evil-fold-action evil-fold-list :close-all))
-
-(evil-define-command evil-open-fold ()
- "Open fold at point.
-See also `evil-close-fold'."
- (evil-fold-action evil-fold-list :open))
-
-(evil-define-command evil-open-fold-rec ()
- "Open fold at point recursively.
-See also `evil-open-fold' and `evil-close-fold'."
- (evil-fold-action evil-fold-list :open-rec))
-
-(evil-define-command evil-close-fold ()
- "Close fold at point.
-See also `evil-open-fold'."
- (evil-fold-action evil-fold-list :close))
-
-;;; Ex
-
-(evil-define-operator evil-write (beg end type file-or-append &optional bang)
- "Save the current buffer, from BEG to END, to FILE-OR-APPEND.
-If FILE-OR-APPEND is of the form \">> FILE\", append to FILE
-instead of overwriting. The current buffer's filename is not
-changed unless it has no associated file and no region is
-specified. If the file already exists and the BANG argument is
-non-nil, it is overwritten without confirmation."
- :motion nil
- :move-point nil
- :type line
- :repeat nil
- (interactive "<R><fsh><!>")
- (let* ((append-and-filename (evil-extract-append file-or-append))
- (append (car append-and-filename))
- (filename (cdr append-and-filename))
- (bufname (buffer-file-name (buffer-base-buffer))))
- (when (zerop (length filename))
- (setq filename bufname))
- (cond
- ((zerop (length filename))
- (user-error "Please specify a file name for the buffer"))
- ;; execute command on region
- ((eq (aref filename 0) ?!)
- (shell-command-on-region beg end (substring filename 1)))
- ;; with region or append, always save to file without resetting
- ;; modified flag
- ((or append (and beg end))
- (write-region beg end filename append nil nil (not (or append bang))))
- ;; no current file
- ((null bufname)
- (write-file filename (not bang)))
- ;; save current buffer to its file
- ((string= filename bufname)
- (if (not bang) (save-buffer) (write-file filename)))
- ;; save to another file
- (t
- (write-region nil nil filename
- nil (not bufname) nil
- (not bang))))))
-
-(evil-define-command evil-write-all (bang)
- "Saves all buffers visiting a file.
-If BANG is non nil then read-only buffers are saved, too,
-otherwise they are skipped. "
- :repeat nil
- :move-point nil
- (interactive "<!>")
- (if bang
- (save-some-buffers t)
- ;; save only buffer that are not read-only and
- ;; that are visiting a file
- (save-some-buffers t
- #'(lambda ()
- (and (not buffer-read-only)
- (buffer-file-name))))))
-
-(evil-define-command evil-update ()
- "Same as `evil-write', but only write when the buffer has been modified."
- :motion nil
- :move-point nil
- :type line
- :repeat nil
- (when (buffer-modified-p)
- (call-interactively #'evil-write)))
-
-(evil-define-command evil-save (filename &optional bang)
- "Save the current buffer to FILENAME.
-Changes the file name of the current buffer to FILENAME. If no
-FILENAME is given, the current file name is used."
- :repeat nil
- :move-point nil
- (interactive "<f><!>")
- (when (zerop (length filename))
- (setq filename (buffer-file-name (buffer-base-buffer))))
- (write-file filename (not bang)))
-
-(evil-define-command evil-edit (file &optional bang)
- "Open FILE.
-If no FILE is specified, reload the current buffer from disk."
- :repeat nil
- (interactive "<f><!>")
- (if file
- (find-file file)
- (revert-buffer bang (or bang (not (buffer-modified-p))) t)))
-
-(evil-define-command evil-read (count file)
- "Inserts the contents of FILE below the current line or line COUNT."
- :repeat nil
- :move-point nil
- (interactive "P<fsh>")
- (when (and file (not (zerop (length file))))
- (when count (goto-char (point-min)))
- (when (or (not (zerop (forward-line (or count 1))))
- (not (bolp)))
- (insert "\n"))
- (cond
- ((/= (aref file 0) ?!)
- (when (member file '("#" "%"))
- (setq file (evil-ex-replace-special-filenames file)))
- (let ((result (insert-file-contents file)))
- (save-excursion
- (forward-char (cadr result))
- (unless (bolp) (insert "\n")))))
- (t
- (shell-command (evil-ex-replace-special-filenames (substring file 1)) t)
- (goto-char (mark))
- (unless (bolp) (insert "\n"))
- (forward-line -1)))))
-
-(evil-define-command evil-show-files ()
- "Shows the file-list.
-The same as `buffer-menu', but shows only buffers visiting
-files."
- :repeat nil
- (buffer-menu 1))
-
-(evil-define-command evil-goto-error (count)
- "Go to error number COUNT.
-
-If no COUNT supplied, move to the current error.
-
-Acts like `first-error' other than when given no counts, goes
-to the current error instead of the first, like in Vim's :cc
-command."
- :repeat nil
- (interactive "<c>")
- (if count
- (first-error (if (eql 0 count) 1 count))
- (next-error 0)))
-
-(evil-define-command evil-buffer (buffer)
- "Switches to another buffer."
- :repeat nil
- (interactive "<b>")
- (cond
- ;; no buffer given, switch to "other" buffer
- ((null buffer) (switch-to-buffer (other-buffer)))
- ;; we are given the name of an existing buffer
- ((get-buffer buffer) (switch-to-buffer buffer))
- ;; try to complete the buffer
- ((let ((all-buffers (internal-complete-buffer buffer nil t)))
- (when (= (length all-buffers) 1)
- (switch-to-buffer (car all-buffers)))))
- (t
- (when (y-or-n-p
- (format "No buffer with name \"%s\" exists. Create new buffer? "
- buffer))
- (switch-to-buffer buffer)))))
-
-(evil-define-command evil-next-buffer (&optional count)
- "Goes to the `count'-th next buffer in the buffer list."
- :repeat nil
- (interactive "p")
- (dotimes (_ (or count 1))
- (next-buffer)))
-
-(evil-define-command evil-prev-buffer (&optional count)
- "Goes to the `count'-th prev buffer in the buffer list."
- :repeat nil
- (interactive "p")
- (dotimes (_ (or count 1))
- (previous-buffer)))
-
-(evil-define-command evil-delete-buffer (buffer &optional bang)
- "Deletes a buffer.
-All windows currently showing this buffer will be closed except
-for the last window in each frame."
- (interactive "<b><!>")
- (with-current-buffer (or buffer (current-buffer))
- (when bang
- (set-buffer-modified-p nil)
- (dolist (process (process-list))
- (when (eq (process-buffer process) (current-buffer))
- (set-process-query-on-exit-flag process nil))))
- ;; get all windows that show this buffer
- (let ((wins (get-buffer-window-list (current-buffer) nil t)))
- ;; if the buffer which was initiated by emacsclient,
- ;; call `server-edit' from server.el to avoid
- ;; "Buffer still has clients" message
- (if (and (fboundp 'server-edit)
- (boundp 'server-buffer-clients)
- server-buffer-clients)
- (server-edit)
- (kill-buffer nil))
- ;; close all windows that showed this buffer
- (mapc #'(lambda (w)
- (condition-case nil
- (delete-window w)
- (error nil)))
- wins))))
-
-(evil-define-command evil-quit (&optional force)
- "Closes the current window, current frame, Emacs.
-If the current frame belongs to some client the client connection
-is closed."
- :repeat nil
- (interactive "<!>")
- (condition-case nil
- (delete-window)
- (error
- (if (and (boundp 'server-buffer-clients)
- (fboundp 'server-edit)
- (fboundp 'server-buffer-done)
- server-buffer-clients)
- (if force
- (server-buffer-done (current-buffer))
- (server-edit))
- (condition-case nil
- (delete-frame)
- (error
- (if force
- (kill-emacs)
- (save-buffers-kill-emacs))))))))
-
-(evil-define-command evil-quit-all (&optional bang)
- "Exits Emacs, asking for saving."
- :repeat nil
- (interactive "<!>")
- (if (null bang)
- (save-buffers-kill-terminal)
- (let ((proc (frame-parameter (selected-frame) 'client)))
- (if proc
- (with-no-warnings
- (server-delete-client proc))
- (dolist (process (process-list))
- (set-process-query-on-exit-flag process nil))
- (kill-emacs)))))
-
-(evil-define-command evil-quit-all-with-error-code (&optional force)
- "Exits Emacs without saving, returning an non-zero error code.
-The FORCE argument is only there for compatibility and is ignored.
-This function fails with an error if Emacs is run in server mode."
- :repeat nil
- (interactive "<!>")
- (if (and (boundp 'server-buffer-clients)
- (fboundp 'server-edit)
- (fboundp 'server-buffer-done)
- server-buffer-clients)
- (user-error "Cannot exit client process with error code.")
- (kill-emacs 1)))
-
-(evil-define-command evil-save-and-quit ()
- "Save all buffers and exit Emacs."
- (save-buffers-kill-terminal t))
-
-(evil-define-command evil-save-and-close (file &optional bang)
- "Saves the current buffer and closes the window."
- :repeat nil
- (interactive "<f><!>")
- (evil-write nil nil nil file bang)
- (evil-quit))
-
-(evil-define-command evil-save-modified-and-close (file &optional bang)
- "Saves the current buffer and closes the window."
- :repeat nil
- (interactive "<f><!>")
- (when (buffer-modified-p)
- (evil-write nil nil nil file bang))
- (evil-quit))
-
-(evil-define-operator evil-shell-command
- (beg end type command &optional previous)
- "Execute a shell command.
-If BEG, END and TYPE is specified, COMMAND is executed on the region,
-which is replaced with the command's output. Otherwise, the
-output is displayed in its own buffer. If PREVIOUS is non-nil,
-the previous shell command is executed instead."
- (interactive "<R><sh><!>")
- (if (not (evil-ex-p))
- (let ((evil-ex-initial-input
- (if (and beg
- (not (evil-visual-state-p))
- (not current-prefix-arg))
- (let ((range (evil-range beg end type)))
- (evil-contract-range range)
- ;; TODO: this is not exactly the same as Vim, which
- ;; uses .,+count as range. However, this is easier
- ;; to achieve with the current implementation and
- ;; the very inconvenient range interface.
- ;;
- ;; TODO: the range interface really needs some
- ;; rework!
- (format
- "%d,%d!"
- (line-number-at-pos (evil-range-beginning range))
- (line-number-at-pos (evil-range-end range))))
- "!")))
- (call-interactively 'evil-ex))
- (when command
- (setq command (evil-ex-replace-special-filenames command)))
- (if (zerop (length command))
- (when previous (setq command evil-previous-shell-command))
- (setq evil-previous-shell-command command))
- (cond
- ((zerop (length command))
- (if previous (user-error "No previous shell command")
- (user-error "No shell command")))
- (evil-ex-range
- (if (not evil-display-shell-error-in-message)
- (shell-command-on-region beg end command nil t)
- (let ((output-buffer (generate-new-buffer " *temp*"))
- (error-buffer (generate-new-buffer " *temp*")))
- (unwind-protect
- (if (zerop (shell-command-on-region beg end
- command
- output-buffer nil
- error-buffer))
- (progn
- (delete-region beg end)
- (insert-buffer-substring output-buffer)
- (goto-char beg)
- (evil-first-non-blank))
- (display-message-or-buffer error-buffer))
- (kill-buffer output-buffer)
- (kill-buffer error-buffer)))))
- (t
- (shell-command command)))))
-
-(evil-define-command evil-make (arg)
- "Call a build command in the current directory.
-If ARG is nil this function calls `recompile', otherwise it calls
-`compile' passing ARG as build command."
- (interactive "<sh>")
- (if (and (fboundp 'recompile)
- (not arg))
- (recompile)
- (compile arg)))
-
-;; TODO: escape special characters (currently only \n) ... perhaps
-;; there is some Emacs function doing this?
-(evil-define-command evil-show-registers (registers)
- "Shows the contents of REGISTERS, or all registers, if none supplied."
- :repeat nil
- (interactive "<a>")
- (let* ((all-registers (evil-register-list))
- (reg-chars (string-to-list registers))
- (display-regs (if reg-chars
- (cl-remove-if-not (lambda (r) (memq (car r) reg-chars))
- all-registers)
- all-registers)))
- (evil-with-view-list
- :name "evil-registers"
- :mode-name "Evil Registers"
- :format
- [("Register" 10 nil)
- ("Value" 1000 nil)]
- :entries
- (cl-loop for (key . val) in display-regs
- collect `(nil [,(char-to-string key)
- ,(cond ((stringp val)
- (replace-regexp-in-string "\n" "^J" val))
- ((vectorp val)
- (key-description val))
- (t ""))])))))
-
-(evil-define-command evil-show-marks (mrks)
- "Shows all marks.
-If MRKS is non-nil it should be a string and only registers
-corresponding to the characters of this string are shown."
- :repeat nil
- (interactive "<a>")
- ;; To get markers and positions, we can't rely on 'global-mark-ring'
- ;; provided by Emacs (although it will be much simpler and faster),
- ;; because 'global-mark-ring' does not store mark characters, but
- ;; only buffer name and position. Instead, 'evil-markers-alist' is
- ;; used; this is list maintained by Evil for each buffer.
- (let ((all-markers
- ;; get global and local marks
- (append (cl-remove-if (lambda (m)
- (or (evil-global-marker-p (car m))
- (not (markerp (cdr m)))))
- evil-markers-alist)
- (cl-remove-if (lambda (m)
- (or (not (evil-global-marker-p (car m)))
- (not (markerp (cdr m)))))
- (default-value 'evil-markers-alist)))))
- (when mrks
- (setq mrks (string-to-list mrks))
- (setq all-markers (cl-delete-if (lambda (m)
- (not (member (car m) mrks)))
- all-markers)))
- ;; map marks to list of 4-tuples (char row col file)
- (setq all-markers
- (mapcar (lambda (m)
- (with-current-buffer (marker-buffer (cdr m))
- (save-excursion
- (goto-char (cdr m))
- (list (car m)
- (line-number-at-pos (point))
- (current-column)
- (buffer-name)))))
- all-markers))
- (evil-with-view-list
- :name "evil-marks"
- :mode-name "Evil Marks"
- :format [("Mark" 8 nil)
- ("Line" 8 nil)
- ("Column" 8 nil)
- ("Buffer" 1000 nil)]
- :entries (cl-loop for m in (sort all-markers (lambda (a b) (< (car a) (car b))))
- collect `(nil [,(char-to-string (nth 0 m))
- ,(number-to-string (nth 1 m))
- ,(number-to-string (nth 2 m))
- (,(nth 3 m))]))
- :select-action #'evil--show-marks-select-action)))
-
-(defun evil--show-marks-select-action (entry)
- (kill-buffer)
- (switch-to-buffer (car (elt entry 3)))
- (evil-goto-mark (string-to-char (elt entry 0))))
-
-(defun evil--parse-delmarks (to-be-parsed &optional parsed)
- "Where TO-BE-PARSED can contain ranges in the form `x-y'.
-PARSED is a list of characters whose marks should be deleted.
-Like vim, on invalid input, preceeding valid input is still parsed."
- (cl-destructuring-bind (&optional a b c &rest) to-be-parsed
- (cond
- ((null to-be-parsed) parsed)
- ;; single mark...
- ((and (not (eq ?- b)) (or (<= ?a a ?z) (<= ?A a ?Z) (<= ?0 a ?9)
- (memq a '(?\" ?^ ?. ?\[ ?\] ?< ?>))))
- (evil--parse-delmarks (cdr to-be-parsed) (cons a parsed)))
- ;; range of marks...
- ((and (eq ?- b) c (or (<= ?a a c ?z) (<= ?A a c ?Z) (<= ?0 a c ?9)))
- (evil--parse-delmarks (nthcdr 3 to-be-parsed)
- (append parsed (number-sequence a c))))
- (t (progn (message "Invalid input: %s" (apply #'string (remove nil to-be-parsed)))
- parsed)))))
-
-(evil-define-command evil-delete-marks (marks &optional force)
- "MARKS is a string denoting all marks to be deleted. Mark names are
-either single characters or a range of characters in the form `x-y'.
-If FORCE is non-nil and MARKS is blank, all local marks except 0-9 are removed."
- (interactive "<a><!>")
- (let ((mark-chars (remove ?\s (append marks nil))))
- (cond
- ((and force mark-chars) (message "Invalid input"))
- (mark-chars
- (let* ((delmarks (evil--parse-delmarks mark-chars))
- (delmarkp (lambda (m) (member (car m) delmarks))))
- ;; delete all parsed marks...
- (setq evil-markers-alist
- (cl-remove-if delmarkp evil-markers-alist))
- ;; ensure all parsed marks are deleted globally...
- (set-default 'evil-markers-alist
- (cl-remove-if delmarkp (default-value 'evil-markers-alist)))))
- ;; delete local marks except 0-9...
- (force (setq evil-markers-alist
- (cl-remove-if-not (lambda (m) (<= ?0 (car m) ?9))
- evil-markers-alist))))))
-
-(eval-when-compile (require 'ffap))
-(evil-define-command evil-find-file-at-point-with-line ()
- "Opens the file at point and goes to position if present."
- (require 'ffap)
- (let ((fname (with-no-warnings (ffap-file-at-point))))
- (unless fname
- (user-error "File does not exist."))
- (let* ((line-number-pattern ":\\([0-9]+\\)\\=" )
- (line-and-column-numbers-pattern ":\\([0-9]+\\):\\([0-9]+\\)\\=")
- (get-number (lambda (pattern match-number)
- (save-excursion
- (goto-char (cadr ffap-string-at-point-region))
- (and (re-search-backward pattern (line-beginning-position) t)
- (string-to-number (match-string match-number))))))
- (line-number (or (funcall get-number line-and-column-numbers-pattern 1)
- (funcall get-number line-number-pattern 1)))
- (column-number (funcall get-number line-and-column-numbers-pattern 2)))
- (message "line: %s, column: %s" line-number column-number)
- (with-no-warnings (find-file-at-point fname))
- (when line-number
- (goto-char (point-min))
- (forward-line (1- line-number))
- (when column-number
- (move-to-column (1- column-number)))))))
-
-(evil-define-command evil-find-file-at-point-visual ()
- "Find the filename selected by the visual region.
- Returns an error message if the file does not exist."
- (require 'ffap)
- (let ((region (buffer-substring (region-beginning) (region-end))))
- (if (file-exists-p region)
- (find-file-at-point region)
- (user-error (format "Can't find file \"%s\" in path" region)))))
-
-(evil-ex-define-argument-type state
- "Defines an argument type which can take state names."
- :collection
- (lambda (arg predicate flag)
- (let ((completions
- (append '("nil")
- (mapcar #'(lambda (state)
- (format "%s" (car state)))
- evil-state-properties))))
- (when arg
- (cond
- ((eq flag nil)
- (try-completion arg completions predicate))
- ((eq flag t)
- (all-completions arg completions predicate))
- ((eq flag 'lambda)
- (test-completion arg completions predicate))
- ((eq (car-safe flag) 'boundaries)
- (cons 'boundaries
- (completion-boundaries arg
- completions
- predicate
- (cdr flag)))))))))
-
-(evil-define-interactive-code "<state>"
- "A valid evil state."
- :ex-arg state
- (list (when (and (evil-ex-p) evil-ex-argument)
- (intern evil-ex-argument))))
-
-;; TODO: should we merge this command with `evil-set-initial-state'?
-(evil-define-command evil-ex-set-initial-state (state)
- "Set the initial state for the current major mode to STATE.
-This is the state the buffer comes up in. See `evil-set-initial-state'."
- :repeat nil
- (interactive "<state>")
- (if (not (or (assq state evil-state-properties)
- (null state)))
- (user-error "State %s cannot be set as initial Evil state" state)
- (let ((current-initial-state (evil-initial-state major-mode)))
- (unless (eq current-initial-state state)
- ;; only if we selected a new mode
- (when (y-or-n-p (format "Major-mode `%s' has initial mode `%s'. \
-Change to `%s'? "
- major-mode
- (or current-initial-state "DEFAULT")
- (or state "DEFAULT")))
- (evil-set-initial-state major-mode state)
- (when (y-or-n-p "Save setting in customization file? ")
- (dolist (s (list current-initial-state state))
- (when s
- (let ((var (intern (format "evil-%s-state-modes" s))))
- (customize-save-variable var (symbol-value var)))))))))))
-
-(evil-define-command evil-force-normal-state ()
- "Switch to normal state without recording current command."
- :repeat abort
- :suppress-operator t
- (evil-normal-state))
-
-(evil-define-motion evil-ex-search-next (count)
- "Goes to the next occurrence."
- :jump t
- :type exclusive
- (evil-ex-search count))
-
-(evil-define-motion evil-ex-search-previous (count)
- "Goes the the previous occurrence."
- :jump t
- :type exclusive
- (let ((evil-ex-search-direction
- (if (eq evil-ex-search-direction 'backward) 'forward 'backward)))
- (evil-ex-search count)))
-
-(defun evil-repeat-ex-search (flag)
- "Called to record a search command.
-FLAG is either 'pre or 'post if the function is called before
-resp. after executing the command."
- (cond
- ((and (evil-operator-state-p) (eq flag 'pre))
- (evil-repeat-record (this-command-keys))
- (evil-clear-command-keys))
- ((and (evil-operator-state-p) (eq flag 'post))
- (evil-repeat-record (evil-ex-pattern-regex evil-ex-search-pattern))
- ;; If it weren't for the fact that `exit-minibuffer' throws an `exit'
- ;; tag, which bypasses the source of `this-command-keys', we'd be able
- ;; to capture the key(s) in the post-command of the operator as usual.
- ;; Fortunately however, `last-input-event' can see the key (by default, `return')
- (unless (append (this-command-keys) nil)
- (evil-repeat-record (vector last-input-event))))
- (t (evil-repeat-motion flag))))
-
-(evil-define-motion evil-ex-search-forward (count)
- "Starts a forward search."
- :jump t
- :type exclusive
- :repeat evil-repeat-ex-search
- (evil-ex-start-search 'forward count))
-
-(evil-define-motion evil-ex-search-backward (count)
- "Starts a forward search."
- :jump t
- :repeat evil-repeat-ex-search
- (evil-ex-start-search 'backward count))
-
-(evil-define-motion evil-ex-search-word-forward (count &optional symbol)
- "Search for the next occurrence of word under the cursor."
- :jump t
- :type exclusive
- (interactive (list (prefix-numeric-value current-prefix-arg)
- evil-symbol-word-search))
- (evil-ex-start-word-search nil 'forward count symbol))
-
-(evil-define-motion evil-ex-search-word-backward (count &optional symbol)
- "Search for the next occurrence of word under the cursor."
- :jump t
- :type exclusive
- (interactive (list (prefix-numeric-value current-prefix-arg)
- evil-symbol-word-search))
- (evil-ex-start-word-search nil 'backward count symbol))
-
-(evil-define-motion evil-ex-search-unbounded-word-forward (count &optional symbol)
- "Search for the next occurrence of word under the cursor."
- :jump t
- :type exclusive
- (interactive (list (prefix-numeric-value current-prefix-arg)
- evil-symbol-word-search))
- (evil-ex-start-word-search t 'forward count symbol))
-
-(evil-define-motion evil-ex-search-unbounded-word-backward (count &optional symbol)
- "Search for the next occurrence of word under the cursor."
- :jump t
- :type exclusive
- (interactive (list (prefix-numeric-value current-prefix-arg)
- evil-symbol-word-search))
- (evil-ex-start-word-search t 'backward count symbol))
-
-(defun evil-revert-reveal (open-spots)
- "Unconditionally close overlays in OPEN-SPOTS in current window.
-Modified version of `reveal-close-old-overlays' from
-reveal.el. OPEN-SPOTS is a local version of `reveal-open-spots'."
- (dolist (spot open-spots)
- (let ((window (car spot))
- (ol (cdr spot)))
- (unless (eq window (selected-window))
- (error "evil-revert-reveal: slot with wrong window"))
- (let* ((inv (overlay-get ol 'reveal-invisible))
- (open (or (overlay-get ol 'reveal-toggle-invisible)
- (get inv 'reveal-toggle-invisible)
- (overlay-get ol 'isearch-open-invisible-temporary))))
- (if (and (overlay-start ol) ;Check it's still live.
- open)
- (condition-case err
- (funcall open ol t)
- (error (message "!!Reveal-hide (funcall %s %s t): %s !!"
- open ol err)))
- (overlay-put ol 'invisible inv))
- ;; Remove the overlay from the list of open spots.
- (overlay-put ol 'reveal-invisible nil)))))
-
-(evil-define-operator evil-ex-substitute
- (beg end pattern replacement flags)
- "The Ex substitute command.
-\[BEG,END]substitute/PATTERN/REPLACEMENT/FLAGS"
- :repeat nil
- :jump t
- :move-point nil
- :motion evil-line
- (interactive "<r><s/>")
- (evil-ex-nohighlight)
- (unless pattern
- (user-error "No pattern given"))
- (setq replacement (or replacement ""))
- (setq evil-ex-last-was-search nil)
- (let* ((flags (append flags nil))
- (count-only (memq ?n flags))
- (confirm (and (memq ?c flags) (not count-only)))
- (case-fold-search (evil-ex-pattern-ignore-case pattern))
- (case-replace case-fold-search)
- (evil-ex-substitute-regex (evil-ex-pattern-regex pattern))
- (evil-ex-substitute-nreplaced 0)
- (evil-ex-substitute-last-point (point))
- (whole-line (evil-ex-pattern-whole-line pattern))
- (evil-ex-substitute-overlay (make-overlay (point) (point)))
- (orig-point-marker (move-marker (make-marker) (point)))
- (end-marker (move-marker (make-marker) end))
- (use-reveal confirm)
- reveal-open-spots
- zero-length-match
- match-contains-newline
- transient-mark-mode)
- (setq evil-ex-substitute-pattern pattern
- evil-ex-substitute-replacement replacement
- evil-ex-substitute-flags flags
- isearch-string evil-ex-substitute-regex)
- (isearch-update-ring evil-ex-substitute-regex t)
- (unwind-protect
- (progn
- (evil-ex-hl-change 'evil-ex-substitute pattern)
- (overlay-put evil-ex-substitute-overlay 'face 'isearch)
- (overlay-put evil-ex-substitute-overlay 'priority 1001)
- (goto-char beg)
- (catch 'exit-search
- (while (re-search-forward evil-ex-substitute-regex end-marker t)
- (when (not (and query-replace-skip-read-only
- (text-property-any (match-beginning 0) (match-end 0) 'read-only t)))
- (let ((match-str (match-string 0))
- (match-beg (move-marker (make-marker) (match-beginning 0)))
- (match-end (move-marker (make-marker) (match-end 0)))
- (match-data (match-data)))
- (goto-char match-beg)
- (setq match-contains-newline
- (string-match-p "\n" (buffer-substring-no-properties
- match-beg match-end)))
- (setq zero-length-match (= match-beg match-end))
- (when (and (= match-end end-marker) (not match-contains-newline) (bolp))
- ;; The range (beg end) includes the final newline which means
- ;; end-marker is on one line down.
- ;; With the exception of explicitly substituting newlines,
- ;; we abort when the match ends here and it's an empty line
- (throw 'exit-search t))
- (setq evil-ex-substitute-last-point match-beg)
- (if confirm
- (let ((prompt
- (format "Replace %s with %s (y/n/a/q/l/^E/^Y)? "
- match-str
- (evil-match-substitute-replacement
- evil-ex-substitute-replacement
- (not case-replace))))
- (search-invisible t)
- response)
- (move-overlay evil-ex-substitute-overlay match-beg match-end)
- ;; Simulate `reveal-mode'. `reveal-mode' uses
- ;; `post-command-hook' but that won't work here.
- (when use-reveal
- (reveal-post-command))
- (catch 'exit-read-char
- (while (setq response (read-char prompt))
- (when (member response '(?y ?a ?l))
- (unless count-only
- (set-match-data match-data)
- (evil-replace-match evil-ex-substitute-replacement
- (not case-replace)))
- (setq evil-ex-substitute-nreplaced
- (1+ evil-ex-substitute-nreplaced))
- (evil-ex-hl-set-region 'evil-ex-substitute
- (save-excursion
- (forward-line)
- (point))
- (evil-ex-hl-get-max
- 'evil-ex-substitute)))
- (cl-case response
- ((?y ?n) (throw 'exit-read-char t))
- (?a (setq confirm nil)
- (throw 'exit-read-char t))
- ((?q ?l ?\C-\[) (throw 'exit-search t))
- (?\C-e (evil-scroll-line-down 1))
- (?\C-y (evil-scroll-line-up 1))))))
- (setq evil-ex-substitute-nreplaced
- (1+ evil-ex-substitute-nreplaced))
- (unless count-only
- (set-match-data match-data)
- (evil-replace-match evil-ex-substitute-replacement
- (not case-replace))))
- (goto-char match-end)
- (cond ((>= (point) end-marker)
- ;; Don't want to perform multiple replacements at the end
- ;; of the search region.
- (throw 'exit-search t))
- ((and (not whole-line)
- (not match-contains-newline))
- (forward-line)
- ;; forward-line just moves to the end of the line on the
- ;; last line of the buffer.
- (when (or (eobp)
- (> (point) end-marker))
- (throw 'exit-search t)))
- ;; For zero-length matches check to see if point won't
- ;; move next time. This is a problem when matching the
- ;; regexp "$" because we can enter an infinite loop,
- ;; repeatedly matching the same character
- ((and zero-length-match
- (let ((pnt (point)))
- (save-excursion
- (and
- (re-search-forward
- evil-ex-substitute-regex end-marker t)
- (= pnt (point))))))
- (if (or (eobp)
- (>= (point) end-marker))
- (throw 'exit-search t)
- (forward-char)))))))))
- (evil-ex-delete-hl 'evil-ex-substitute)
- (delete-overlay evil-ex-substitute-overlay)
-
- (if count-only
- (goto-char orig-point-marker)
- (goto-char evil-ex-substitute-last-point))
-
- (move-marker orig-point-marker nil)
- (move-marker end-marker nil)
-
- (when use-reveal
- (evil-revert-reveal reveal-open-spots)))
-
- (message "%s %d occurrence%s"
- (if count-only "Found" "Replaced")
- evil-ex-substitute-nreplaced
- (if (/= evil-ex-substitute-nreplaced 1) "s" ""))
- (evil-first-non-blank)))
-
-(evil-define-operator evil-ex-repeat-substitute
- (beg end flags)
- "Repeat last substitute command.
-This is the same as :s//~/"
- :repeat nil
- :jump t
- :move-point nil
- :motion evil-line
- (interactive "<r><a>")
- (apply #'evil-ex-substitute beg end
- (evil-ex-get-substitute-info (concat "//~/" flags))))
-
-(evil-define-operator evil-ex-repeat-substitute-with-flags
- (beg end flags)
- "Repeat last substitute command with last flags.
-This is the same as :s//~/&"
- :repeat nil
- :jump t
- :move-point nil
- :motion evil-line
- (interactive "<r><a>")
- (apply #'evil-ex-substitute beg end
- (evil-ex-get-substitute-info (concat "//~/&" flags))))
-
-(evil-define-operator evil-ex-repeat-substitute-with-search
- (beg end flags)
- "Repeat last substitute command with last search pattern.
-This is the same as :s//~/r"
- :repeat nil
- :jump t
- :move-point nil
- :motion evil-line
- (interactive "<r><a>")
- (apply #'evil-ex-substitute beg end
- (evil-ex-get-substitute-info (concat "//~/r" flags))))
-
-(evil-define-operator evil-ex-repeat-substitute-with-search-and-flags
- (beg end flags)
- "Repeat last substitute command with last search pattern and last flags.
-This is the same as :s//~/&r"
- :repeat nil
- :jump t
- :move-point nil
- :motion evil-line
- (interactive "<r><a>")
- (apply #'evil-ex-substitute beg end
- (evil-ex-get-substitute-info (concat "//~/&r" flags))))
-
-(evil-define-operator evil-ex-repeat-global-substitute ()
- "Repeat last substitute command on the whole buffer.
-This is the same as :%s//~/&"
- :repeat nil
- :jump t
- :move-point nil
- :motion evil-line
- (interactive)
- (apply #'evil-ex-substitute (point-min) (point-max)
- (evil-ex-get-substitute-info (concat "//~/&"))))
-
-(evil-define-operator evil-ex-global
- (beg end pattern command &optional invert)
- "The Ex global command.
-\[BEG,END]global[!]/PATTERN/COMMAND"
- :motion mark-whole-buffer
- :move-point nil
- (interactive "<r><g/><!>")
- (unless pattern
- (user-error "No pattern given"))
- (unless command
- (user-error "No command given"))
- ;; TODO: `evil-ex-make-substitute-pattern' should be executed so
- ;; :substitute can re-use :global's pattern depending on its `r'
- ;; flag. This isn't supported currently but should be simple to add
- (evil-with-single-undo
- (let ((case-fold-search
- (eq (evil-ex-regex-case pattern evil-ex-search-case) 'insensitive))
- (command-form (evil-ex-parse command))
- (transient-mark-mode transient-mark-mode)
- (deactivate-mark deactivate-mark)
- match markers)
- (when (and pattern command)
- (when evil-ex-search-vim-style-regexp
- (setq pattern (evil-transform-vim-style-regexp pattern)))
- (setq isearch-string pattern)
- (isearch-update-ring pattern t)
- (goto-char beg)
- (evil-move-beginning-of-line)
- (while (< (point) end)
- (setq match (re-search-forward pattern (line-end-position) t))
- (when (or (and match (not invert))
- (and invert (not match)))
- (push (move-marker (make-marker)
- (or (and match (match-beginning 0))
- (line-beginning-position)))
- markers))
- (forward-line))
- (setq markers (nreverse markers))
- (unwind-protect
- (dolist (marker markers)
- (goto-char marker)
- (eval command-form))
- ;; ensure that all markers are deleted afterwards,
- ;; even in the event of failure
- (dolist (marker markers)
- (set-marker marker nil)))))))
-
-(evil-define-operator evil-ex-global-inverted
- (beg end pattern command &optional invert)
- "The Ex vglobal command.
-\[BEG,END]vglobal/PATTERN/COMMAND"
- :motion mark-whole-buffer
- :move-point nil
- (interactive "<r><g/><!>")
- (evil-ex-global beg end pattern command (not invert)))
-
-(evil-define-operator evil-ex-normal (beg end commands)
- "The Ex normal command.
-Execute the argument as normal command on each line in the
-range. The given argument is passed straight to
-`execute-kbd-macro'. The default is the current line."
- :motion evil-line
- (interactive "<r><a>")
- (evil-with-single-undo
- (let (markers evil-ex-current-buffer prefix-arg current-prefix-arg)
- (goto-char beg)
- (while
- (and (< (point) end)
- (progn
- (push (move-marker (make-marker) (line-beginning-position))
- markers)
- (and (= (forward-line) 0) (bolp)))))
- (setq markers (nreverse markers))
- (deactivate-mark)
- (evil-force-normal-state)
- ;; replace ^[ by escape
- (setq commands
- (vconcat
- (mapcar #'(lambda (ch) (if (equal ch ?) 'escape ch))
- (append commands nil))))
- (dolist (marker markers)
- (goto-char marker)
- (condition-case nil
- (execute-kbd-macro commands)
- (error nil))
- (evil-force-normal-state)
- (set-marker marker nil)))))
-
-(evil-define-command evil-goto-char (position)
- "Go to POSITION in the buffer.
-Default position is the beginning of the buffer."
- :jump t
- (interactive "<N>")
- (let ((position (evil-normalize-position
- (or position (point-min)))))
- (goto-char position)))
-
-(evil-define-operator evil-ex-line-number (beg end)
- "Print the last line number."
- :motion mark-whole-buffer
- :move-point nil
- (interactive "<r>")
- (message "%d" (count-lines (point-min) end)))
-
-(evil-define-command evil-show-file-info ()
- "Shows basic file information."
- (let* ((nlines (count-lines (point-min) (point-max)))
- (curr (line-number-at-pos (point)))
- (perc (if (> nlines 0)
- (format "%d%%" (* (/ (float curr) (float nlines)) 100.0))
- "No lines in buffer"))
- (file (buffer-file-name (buffer-base-buffer)))
- (writable (and file (file-writable-p file)))
- (readonly (if (and file (not writable)) "[readonly] " "")))
- (if file
- (message "\"%s\" %d %slines --%s--" file nlines readonly perc)
- (message "%d lines --%s--" nlines perc))))
-
-(defvar sort-fold-case)
-(evil-define-operator evil-ex-sort (beg end &optional options reverse)
- "The Ex sort command.
-\[BEG,END]sort[!] [i][u]
-The following additional options are supported:
-
- * i ignore case
- * u remove duplicate lines
-
-The 'bang' argument means to sort in reverse order."
- :motion mark-whole-buffer
- :move-point nil
- (interactive "<r><a><!>")
- (let ((beg (copy-marker beg))
- (end (copy-marker end))
- sort-fold-case uniq)
- (dolist (opt (append options nil))
- (cond
- ((eq opt ?i) (setq sort-fold-case t))
- ((eq opt ?u) (setq uniq t))
- (t (user-error "Unsupported sort option: %c" opt))))
- (sort-lines reverse beg end)
- (when uniq
- (let (line prev-line)
- (goto-char beg)
- (while (and (< (point) end) (not (eobp)))
- (setq line (buffer-substring-no-properties
- (line-beginning-position)
- (line-end-position)))
- (if (and (stringp prev-line)
- (eq t (compare-strings line nil nil
- prev-line nil nil
- sort-fold-case)))
- (delete-region (progn (forward-line 0) (point))
- (progn (forward-line 1) (point)))
- (setq prev-line line)
- (forward-line 1)))))
- (goto-char beg)
- (set-marker beg nil)
- (set-marker end nil)))
-
-;;; Window navigation
-
-(defmacro evil-save-side-windows (&rest body)
- "Toggle side windows, evaluate BODY, restore side windows."
- (declare (indent defun) (debug (&rest form)))
- (let ((sides (make-symbol "sidesvar")))
- `(let ((,sides (and (functionp 'window-toggle-side-windows)
- (window-with-parameter 'window-side))))
- (when ,sides
- (window-toggle-side-windows))
- (unwind-protect
- (progn ,@body)
- (when ,sides
- (window-toggle-side-windows))))))
-
-(defun evil-resize-window (new-size &optional horizontal)
- "Set the current window's width or height to NEW-SIZE.
-If HORIZONTAL is non-nil the width of the window is changed,
-otherwise its height is changed."
- (let ((count (- new-size (if horizontal (window-width) (window-height)))))
- (enlarge-window count horizontal)))
-
-(defun evil-move-window (side)
- "Move the `selected-window' to SIDE.
-The state of the `selected-window' is saved along with the state
-of the window tree consisting of all the other windows. Then, all
-windows are deleted, the remaining window is split according to
-SIDE, the state of the window at SIDE is replaced with the saved
-state of the `selected-window', and, finally, the state of the
-saved window tree is reconstructed on the opposite side.
-
-SIDE has the same meaning as in `split-window'.
-
-Note, this function only operates on the window tree rooted in
-the frame's main window and effectively preserves any side
-windows \(i.e. windows with a valid window-side window
-parameter\)."
- (evil-save-side-windows
- (unless (one-window-p)
- (save-excursion
- (let ((w (window-state-get (selected-window))))
- (delete-window)
- (let ((wtree (window-state-get)))
- (delete-other-windows)
- (let ((subwin (selected-window))
- ;; NOTE: SIDE is new in Emacs 24
- (newwin (split-window nil nil side)))
- (window-state-put wtree subwin)
- (window-state-put w newwin)
- (select-window newwin)))))
- (balance-windows))))
-
-(defun evil-alternate-buffer (&optional window)
- "Return the last buffer WINDOW has displayed other than the
-current one (equivalent to Vim's alternate buffer).
-
-Returns the first item in `window-prev-buffers' that isn't
-`window-buffer' of WINDOW."
- ;; If the last buffer visited has been killed, then `window-prev-buffers'
- ;; returns a list with `current-buffer' at the head, we account for this
- ;; possibility.
- (let* ((prev-buffers (window-prev-buffers))
- (head (car prev-buffers)))
- (if (eq (car head) (window-buffer window))
- (cadr prev-buffers)
- head)))
-
-(evil-define-command evil-switch-to-windows-last-buffer ()
- "Switch to current windows last open buffer."
- :repeat nil
- (let ((previous-place (evil-alternate-buffer)))
- (when previous-place
- (switch-to-buffer (car previous-place))
- (goto-char (car (last previous-place))))))
-
-(evil-define-command evil-window-delete ()
- "Deletes the current window.
-If `evil-auto-balance-windows' is non-nil then all children of
-the deleted window's parent window are rebalanced."
- (let ((p (window-parent)))
- (delete-window)
- (when evil-auto-balance-windows
- ;; balance-windows raises an error if the parent does not have
- ;; any further children (then rebalancing is not necessary anyway)
- (condition-case nil
- (balance-windows p)
- (error)))))
-
-(evil-define-command evil-window-split (&optional count file)
- "Splits the current window horizontally, COUNT lines height,
-editing a certain FILE. The new window will be created below
-when `evil-split-window-below' is non-nil. If COUNT and
-`evil-auto-balance-windows' are both non-nil then all children
-of the parent of the splitted window are rebalanced."
- :repeat nil
- (interactive "P<f>")
- (select-window
- (split-window (selected-window) (when count (- count))
- (if evil-split-window-below 'below 'above)))
- (when (and (not count) evil-auto-balance-windows)
- (balance-windows (window-parent)))
- (when file
- (evil-edit file)))
-
-(evil-define-command evil-window-vsplit (&optional count file)
- "Splits the current window vertically, COUNT columns width,
-editing a certain FILE. The new window will be created to the
-right when `evil-vsplit-window-right' is non-nil. If COUNT and
-`evil-auto-balance-windows'are both non-nil then all children
-of the parent of the splitted window are rebalanced."
- :repeat nil
- (interactive "P<f>")
- (select-window
- (split-window (selected-window) (when count (- count))
- (if evil-vsplit-window-right 'right 'left)))
- (when (and (not count) evil-auto-balance-windows)
- (balance-windows (window-parent)))
- (when file
- (evil-edit file)))
-
-(evil-define-command evil-split-buffer (buffer)
- "Splits window and switches to another buffer."
- :repeat nil
- (interactive "<b>")
- (evil-window-split)
- (evil-buffer buffer))
-
-(evil-define-command evil-split-next-buffer (&optional count)
- "Splits the window and goes to the COUNT-th next buffer in the buffer list."
- :repeat nil
- (interactive "p")
- (evil-window-split)
- (evil-next-buffer count))
-
-(evil-define-command evil-split-prev-buffer (&optional count)
- "Splits window and goes to the COUNT-th prev buffer in the buffer list."
- :repeat nil
- (interactive "p")
- (evil-window-split)
- (evil-prev-buffer count))
-
-(evil-define-command evil-window-left (count)
- "Move the cursor to new COUNT-th window left of the current one."
- :repeat nil
- (interactive "p")
- (dotimes (_ count)
- (windmove-left)))
-
-(evil-define-command evil-window-right (count)
- "Move the cursor to new COUNT-th window right of the current one."
- :repeat nil
- (interactive "p")
- (dotimes (_ count)
- (windmove-right)))
-
-(evil-define-command evil-window-up (count)
- "Move the cursor to new COUNT-th window above the current one."
- :repeat nil
- (interactive "p")
- (dotimes (_ (or count 1))
- (windmove-up)))
-
-(evil-define-command evil-window-down (count)
- "Move the cursor to new COUNT-th window below the current one."
- :repeat nil
- (interactive "p")
- (dotimes (_ (or count 1))
- (windmove-down)))
-
-(evil-define-command evil-window-bottom-right ()
- "Move the cursor to bottom-right window."
- :repeat nil
- (let ((last-sibling (frame-root-window)))
- (while (and last-sibling (not (window-live-p last-sibling)))
- (setq last-sibling (window-last-child last-sibling)))
- (when last-sibling
- (select-window last-sibling))))
-
-(evil-define-command evil-window-top-left ()
- "Move the cursor to top-left window."
- :repeat nil
- (let ((first-child (window-child (frame-root-window))))
- (while (and first-child (not (window-live-p first-child)))
- (setq first-child (window-child first-child)))
- (when first-child
- (select-window
- first-child))))
-
-(evil-define-command evil-window-mru ()
- "Move the cursor to the previous (last accessed) buffer in another window.
-More precisely, it selects the most recently used buffer that is
-shown in some other window, preferably of the current frame, and
-is different from the current one."
- :repeat nil
- (catch 'done
- (dolist (buf (buffer-list (selected-frame)))
- (let ((win (get-buffer-window buf)))
- (when (and (not (eq buf (current-buffer)))
- win
- (not (eq win (selected-window))))
- (select-window win)
- (throw 'done nil))))))
-
-(evil-define-command evil-window-next (count)
- "Move the cursor to the next window in the cyclic order.
-With COUNT go to the count-th window in the order starting from
-top-left."
- :repeat nil
- (interactive "<c>")
- (if (not count)
- (select-window (next-window))
- (evil-window-top-left)
- (other-window (1- count))))
-
-(evil-define-command evil-window-prev (count)
- "Move the cursor to the previous window in the cyclic order.
-With COUNT go to the count-th window in the order starting from
-top-left."
- :repeat nil
- (interactive "<c>")
- (if (not count)
- (select-window (previous-window))
- (evil-window-top-left)
- (other-window (1- count))))
-
-(evil-define-command evil-window-new (count file)
- "Splits the current window horizontally
-and opens a new buffer or edits a certain FILE."
- :repeat nil
- (interactive "P<f>")
- (let ((new-window (split-window (selected-window) (when count (- count))
- (if evil-split-window-below 'below 'above))))
- (when (and (not count) evil-auto-balance-windows)
- (balance-windows (window-parent)))
- (let ((buffer (generate-new-buffer "*new*")))
- (set-window-buffer new-window buffer)
- (select-window new-window)
- (with-current-buffer buffer
- (funcall (default-value 'major-mode))))
- (when file
- (evil-edit file))))
-
-(evil-define-command evil-window-vnew (count file)
- "Splits the current window vertically
-and opens a new buffer name or edits a certain FILE."
- :repeat nil
- (interactive "P<f>")
- (let ((new-window (split-window (selected-window) (when count (- count))
- (if evil-vsplit-window-right 'right 'left))))
- (when (and (not count) evil-auto-balance-windows)
- (balance-windows (window-parent)))
- (let ((buffer (generate-new-buffer "*new*")))
- (set-window-buffer new-window buffer)
- (select-window new-window)
- (with-current-buffer buffer
- (funcall (default-value 'major-mode))))
- (when file
- (evil-edit file))))
-
-(evil-define-command evil-buffer-new (count file)
- "Creates a new buffer replacing the current window, optionally
- editing a certain FILE"
- :repeat nil
- (interactive "P<f>")
- (if file
- (evil-edit file)
- (let ((buffer (generate-new-buffer "*new*")))
- (set-window-buffer nil buffer)
- (with-current-buffer buffer
- (funcall (default-value 'major-mode))))))
-
-(evil-define-command evil-window-increase-height (count)
- "Increase current window height by COUNT."
- :repeat nil
- (interactive "p")
- (evil-resize-window (+ (window-height) count)))
-
-(evil-define-command evil-window-decrease-height (count)
- "Decrease current window height by COUNT."
- :repeat nil
- (interactive "p")
- (evil-resize-window (- (window-height) count)))
-
-(evil-define-command evil-window-increase-width (count)
- "Increase current window width by COUNT."
- :repeat nil
- (interactive "p")
- (evil-resize-window (+ (window-width) count) t))
-
-(evil-define-command evil-window-decrease-width (count)
- "Decrease current window width by COUNT."
- :repeat nil
- (interactive "p")
- (evil-resize-window (- (window-width) count) t))
-
-(evil-define-command evil-window-set-height (count)
- "Sets the height of the current window to COUNT."
- :repeat nil
- (interactive "<c>")
- (evil-resize-window (or count (frame-height)) nil))
-
-(evil-define-command evil-window-set-width (count)
- "Sets the width of the current window to COUNT."
- :repeat nil
- (interactive "<c>")
- (evil-resize-window (or count (frame-width)) t))
-
-(evil-define-command evil-ex-resize (arg)
- "The ex :resize command.
-
-If ARG is a signed positive integer, increase the current window
-height by ARG.
-
-If ARG is a signed negative integer, decrease the current window
-height by ARG.
-
-If ARG is a positive integer without explicit sign, set the current
-window height to ARG.
-
-If ARG is empty, maximize the current window height."
- (interactive "<a>")
- (if (or (not arg) (= 0 (length arg)))
- (evil-window-set-height nil)
- (let ((n (string-to-number arg)))
- (if (> n 0)
- (if (= ?+ (aref arg 0))
- (evil-window-increase-height n)
- (evil-window-set-height n))
- (evil-window-decrease-height (- n))))))
-
-(evil-define-command evil-window-rotate-upwards ()
- "Rotates the windows according to the current cyclic ordering."
- :repeat nil
- (evil-save-side-windows
- (let ((wlist (window-list))
- (slist (mapcar #'window-state-get (window-list))))
- (setq slist (append (cdr slist) (list (car slist))))
- (while (and wlist slist)
- (window-state-put (car slist) (car wlist))
- (setq wlist (cdr wlist)
- slist (cdr slist)))
- (select-window (car (last (window-list)))))))
-
-(evil-define-command evil-window-rotate-downwards ()
- "Rotates the windows according to the current cyclic ordering."
- :repeat nil
- (evil-save-side-windows
- (let ((wlist (window-list))
- (slist (mapcar #'window-state-get (window-list))))
- (setq slist (append (last slist) slist))
- (while (and wlist slist)
- (window-state-put (car slist) (car wlist))
- (setq wlist (cdr wlist)
- slist (cdr slist)))
- (select-window (cadr (window-list))))))
-
-(evil-define-command evil-window-move-very-top ()
- "Closes the current window, splits the upper-left one horizontally
-and redisplays the current buffer there."
- :repeat nil
- (evil-move-window 'above))
-
-(evil-define-command evil-window-move-far-left ()
- "Closes the current window, splits the upper-left one vertically
-and redisplays the current buffer there."
- :repeat nil
- (evil-move-window 'left))
-
-(evil-define-command evil-window-move-far-right ()
- "Closes the current window, splits the lower-right one vertically
-and redisplays the current buffer there."
- :repeat nil
- (evil-move-window 'right))
-
-(evil-define-command evil-window-move-very-bottom ()
- "Closes the current window, splits the lower-right one horizontally
-and redisplays the current buffer there."
- :repeat nil
- (evil-move-window 'below))
-
-;;; Mouse handling
-
-;; Large parts of this code are taken from mouse.el which is
-;; distributed with GNU Emacs
-(defun evil-mouse-drag-region (start-event)
- "Set the region to the text that the mouse is dragged over.
-Highlight the drag area as you move the mouse.
-This must be bound to a button-down mouse event.
-
-If the click is in the echo area, display the `*Messages*' buffer.
-
-START-EVENT should be the event that started the drag."
- (interactive "e")
- ;; Give temporary modes such as isearch a chance to turn off.
- (run-hooks 'mouse-leave-buffer-hook)
- (evil-mouse-drag-track start-event t))
-(evil-set-command-property 'evil-mouse-drag-region :keep-visual t)
-
-(defun evil-mouse-drag-track (start-event &optional
- do-mouse-drag-region-post-process)
- "Track mouse drags by highlighting area between point and cursor.
-The region will be defined with mark and point.
-DO-MOUSE-DRAG-REGION-POST-PROCESS should only be used by
-`mouse-drag-region'."
- (mouse-minibuffer-check start-event)
- (setq mouse-selection-click-count-buffer (current-buffer))
- (deactivate-mark)
- (let* ((scroll-margin 0) ; Avoid margin scrolling (Bug#9541).
- (original-window (selected-window))
- ;; We've recorded what we needed from the current buffer and
- ;; window, now let's jump to the place of the event, where things
- ;; are happening.
- (_ (mouse-set-point start-event))
- (echo-keystrokes 0)
- (start-posn (event-start start-event))
- (start-point (posn-point start-posn))
- (start-window (posn-window start-posn))
- (start-window-start (window-start start-window))
- (start-hscroll (window-hscroll start-window))
- (bounds (window-edges start-window))
- (make-cursor-line-fully-visible nil)
- (top (nth 1 bounds))
- (bottom (if (or (window-minibuffer-p start-window)
- (not mode-line-format))
- (nth 3 bounds)
- ;; Don't count the mode line.
- (1- (nth 3 bounds))))
- (on-link (and mouse-1-click-follows-link
- (or mouse-1-click-in-non-selected-windows
- (eq start-window original-window))
- ;; Use start-point before the intangibility
- ;; treatment, in case we click on a link inside an
- ;; intangible text.
- (mouse-on-link-p start-posn)))
- (click-count (1- (event-click-count start-event)))
- (remap-double-click (and on-link
- (eq mouse-1-click-follows-link 'double)
- (= click-count 1)))
- ;; Suppress automatic hscrolling, because that is a nuisance
- ;; when setting point near the right fringe (but see below).
- (auto-hscroll-mode-saved auto-hscroll-mode)
- (auto-hscroll-mode nil)
- event end end-point)
-
- (setq mouse-selection-click-count click-count)
- ;; In case the down click is in the middle of some intangible text,
- ;; use the end of that text, and put it in START-POINT.
- (if (< (point) start-point)
- (goto-char start-point))
- (setq start-point (point))
- (if remap-double-click
- (setq click-count 0))
-
- (setq click-count (mod click-count 4))
-
- ;; activate correct visual state
- (let ((range (evil-mouse-start-end start-point start-point click-count)))
- (set-mark (nth 0 range))
- (goto-char (nth 1 range)))
-
- (cond
- ((= click-count 0)
- (when (evil-visual-state-p) (evil-exit-visual-state)))
- ((= click-count 1)
- (evil-visual-char)
- (evil-visual-post-command))
- ((= click-count 2)
- (evil-visual-line)
- (evil-visual-post-command))
- ((= click-count 3)
- (evil-visual-block)
- (evil-visual-post-command)))
-
- ;; Track the mouse until we get a non-movement event.
- (track-mouse
- (while (progn
- (setq event (read-key))
- (or (mouse-movement-p event)
- (memq (car-safe event) '(switch-frame select-window))))
- (unless (evil-visual-state-p)
- (cond
- ((= click-count 0) (evil-visual-char))
- ((= click-count 1) (evil-visual-char))
- ((= click-count 2) (evil-visual-line))
- ((= click-count 3) (evil-visual-block))))
-
- (evil-visual-pre-command)
- (unless (memq (car-safe event) '(switch-frame select-window))
- ;; Automatic hscrolling did not occur during the call to
- ;; `read-event'; but if the user subsequently drags the
- ;; mouse, go ahead and hscroll.
- (let ((auto-hscroll-mode auto-hscroll-mode-saved))
- (redisplay))
- (setq end (event-end event)
- end-point (posn-point end))
- (if (and (eq (posn-window end) start-window)
- (integer-or-marker-p end-point))
- (evil-mouse--drag-set-mark-and-point start-point
- end-point click-count)
- (let ((mouse-row (cdr (cdr (mouse-position)))))
- (cond
- ((null mouse-row))
- ((< mouse-row top)
- (mouse-scroll-subr start-window (- mouse-row top)
- nil start-point))
- ((>= mouse-row bottom)
- (mouse-scroll-subr start-window (1+ (- mouse-row bottom))
- nil start-point))))))
- (evil-visual-post-command)))
-
- ;; Handle the terminating event if possible.
- (when (consp event)
- ;; Ensure that point is on the end of the last event.
- (when (and (setq end-point (posn-point (event-end event)))
- (eq (posn-window end) start-window)
- (integer-or-marker-p end-point)
- (/= start-point end-point))
- (evil-mouse--drag-set-mark-and-point start-point
- end-point click-count))
-
- ;; Find its binding.
- (let* ((fun (key-binding (vector (car event))))
- (do-multi-click (and (> (event-click-count event) 0)
- (functionp fun)
- (not (memq fun '(mouse-set-point
- mouse-set-region))))))
- (if (and (or (/= (mark) (point))
- (= click-count 1) ; word selection
- (and (memq (evil-visual-type) '(line block))))
- (not do-multi-click))
-
- ;; If point has moved, finish the drag.
- (let (last-command this-command)
- (and mouse-drag-copy-region
- do-mouse-drag-region-post-process
- (let (deactivate-mark)
- (evil-visual-expand-region)
- (copy-region-as-kill (mark) (point))
- (evil-visual-contract-region))))
-
- ;; If point hasn't moved, run the binding of the
- ;; terminating up-event.
- (if do-multi-click
- (goto-char start-point)
- (deactivate-mark))
- (when (and (functionp fun)
- (= start-hscroll (window-hscroll start-window))
- ;; Don't run the up-event handler if the window
- ;; start changed in a redisplay after the
- ;; mouse-set-point for the down-mouse event at
- ;; the beginning of this function. When the
- ;; window start has changed, the up-mouse event
- ;; contains a different position due to the new
- ;; window contents, and point is set again.
- (or end-point
- (= (window-start start-window)
- start-window-start)))
- (when (and on-link
- (= start-point (point))
- (evil-mouse--remap-link-click-p start-event event))
- ;; If we rebind to mouse-2, reselect previous selected
- ;; window, so that the mouse-2 event runs in the same
- ;; situation as if user had clicked it directly. Fixes
- ;; the bug reported by juri@jurta.org on 2005-12-27.
- (if (or (vectorp on-link) (stringp on-link))
- (setq event (aref on-link 0))
- (select-window original-window)
- (setcar event 'mouse-2)
- ;; If this mouse click has never been done by the
- ;; user, it doesn't have the necessary property to be
- ;; interpreted correctly.
- (put 'mouse-2 'event-kind 'mouse-click)))
- (push event unread-command-events)))))))
-
-;; This function is a plain copy of `mouse--drag-set-mark-and-point',
-;; which is only available in Emacs 24
-(defun evil-mouse--drag-set-mark-and-point (start click click-count)
- (let* ((range (evil-mouse-start-end start click click-count))
- (beg (nth 0 range))
- (end (nth 1 range)))
- (cond ((eq (mark) beg)
- (goto-char end))
- ((eq (mark) end)
- (goto-char beg))
- ((< click (mark))
- (set-mark end)
- (goto-char beg))
- (t
- (set-mark beg)
- (goto-char end)))))
-
-;; This function is a plain copy of `mouse--remap-link-click-p',
-;; which is only available in Emacs 23
-(defun evil-mouse--remap-link-click-p (start-event end-event)
- (or (and (eq mouse-1-click-follows-link 'double)
- (= (event-click-count start-event) 2))
- (and
- (not (eq mouse-1-click-follows-link 'double))
- (= (event-click-count start-event) 1)
- (= (event-click-count end-event) 1)
- (or (not (integerp mouse-1-click-follows-link))
- (let ((t0 (posn-timestamp (event-start start-event)))
- (t1 (posn-timestamp (event-end end-event))))
- (and (integerp t0) (integerp t1)
- (if (> mouse-1-click-follows-link 0)
- (<= (- t1 t0) mouse-1-click-follows-link)
- (< (- t0 t1) mouse-1-click-follows-link))))))))
-
-(defun evil-mouse-start-end (start end mode)
- "Return a list of region bounds based on START and END according to MODE.
-If MODE is not 1 then set point to (min START END), mark to (max
-START END). If MODE is 1 then set point to start of word at (min
-START END), mark to end of word at (max START END)."
- (evil-sort start end)
- (setq mode (mod mode 4))
- (if (/= mode 1) (list start end)
- (list
- (save-excursion
- (goto-char (min (point-max) (1+ start)))
- (if (zerop (forward-thing evil-mouse-word -1))
- (let ((bpnt (point)))
- (forward-thing evil-mouse-word +1)
- (if (> (point) start) bpnt (point)))
- (point-min)))
- (save-excursion
- (goto-char end)
- (1-
- (if (zerop (forward-thing evil-mouse-word +1))
- (let ((epnt (point)))
- (forward-thing evil-mouse-word -1)
- (if (<= (point) end) epnt (point)))
- (point-max)))))))
-
-;;; State switching
-
-(evil-define-command evil-exit-emacs-state (&optional buffer message)
- "Exit Emacs state.
-Changes the state to the previous state, or to Normal state
-if the previous state was Emacs state."
- :keep-visual t
- :suppress-operator t
- (interactive '(nil t))
- (with-current-buffer (or buffer (current-buffer))
- (when (evil-emacs-state-p)
- (evil-change-to-previous-state buffer message)
- (when (evil-emacs-state-p)
- (evil-normal-state (and message 1))))))
-
-(defvar evil-execute-normal-keys nil
- "The keys used to invoke the current `evil-execute-in-normal-state'.
-Can be used to detect if we are currently in that quasi-state.
-With current bindings, it will be \\<evil-insert-state-map>\\[evil-execute-in-normal-state]")
-
-(evil-define-local-var evil--execute-normal-eol-pos nil
- "Vim has special behaviour for executing in normal state at eol.
-This var stores the eol position, so it can be restored when necessary.")
-
-(defun evil--restore-repeat-hooks ()
- "No insert-state repeat info is recorded after executing in normal state.
-Restore the disabled repeat hooks on insert-state exit."
- (evil-repeat-stop)
- (add-hook 'pre-command-hook 'evil-repeat-pre-hook)
- (add-hook 'post-command-hook 'evil-repeat-post-hook)
- (remove-hook 'evil-insert-state-exit-hook 'evil--restore-repeat-hooks))
-
-(defvar evil--execute-normal-return-state nil
- "The state to return to after executing in normal state.")
-
-(defun evil-execute-in-normal-state ()
- "Execute the next command in Normal state."
- (interactive)
- (evil-delay '(not (memq this-command
- '(nil
- evil-execute-in-normal-state
- evil-replace-state
- evil-use-register
- digit-argument
- negative-argument
- universal-argument
- universal-argument-minus
- universal-argument-more
- universal-argument-other-key)))
- `(progn
- (with-current-buffer ,(current-buffer)
- (when (and evil--execute-normal-eol-pos
- (= (point) (1- evil--execute-normal-eol-pos))
- (not (memq this-command '(evil-insert
- evil-goto-mark))))
- (forward-char))
- (unless (memq evil-state '(replace insert))
- (evil-change-state ',evil-state))
- (when (eq 'insert evil-state)
- (remove-hook 'pre-command-hook 'evil-repeat-pre-hook)
- (remove-hook 'post-command-hook 'evil-repeat-post-hook)
- (add-hook 'evil-insert-state-exit-hook 'evil--restore-repeat-hooks))
- (setq evil-move-cursor-back ',evil-move-cursor-back
- evil-move-beyond-eol ',evil-move-beyond-eol
- evil-execute-normal-keys nil)))
- 'post-command-hook)
- (setq evil-insert-count nil
- evil--execute-normal-return-state evil-state
- evil--execute-normal-eol-pos (when (eolp) (point))
- evil-move-cursor-back nil
- evil-execute-normal-keys (this-command-keys))
- (evil-normal-state)
- (setq evil-move-beyond-eol t)
- (evil-echo "Switched to Normal state for the next command ..."))
-
-(defun evil-stop-execute-in-emacs-state ()
- (when (and (not (eq this-command #'evil-execute-in-emacs-state))
- (not (minibufferp)))
- (remove-hook 'post-command-hook 'evil-stop-execute-in-emacs-state)
- (when (buffer-live-p evil-execute-in-emacs-state-buffer)
- (with-current-buffer evil-execute-in-emacs-state-buffer
- (if (and (eq evil-previous-state 'visual)
- (not (use-region-p)))
- (progn
- (evil-change-to-previous-state)
- (evil-exit-visual-state))
- (evil-change-to-previous-state))))
- (setq evil-execute-in-emacs-state-buffer nil)))
-
-(evil-define-command evil-execute-in-emacs-state ()
- "Execute the next command in Emacs state."
- (add-hook 'post-command-hook #'evil-stop-execute-in-emacs-state t)
- (setq evil-execute-in-emacs-state-buffer (current-buffer))
- (cond
- ((evil-visual-state-p)
- (let ((mrk (mark))
- (pnt (point)))
- (evil-emacs-state)
- (set-mark mrk)
- (goto-char pnt)))
- (t
- (evil-emacs-state)))
- (evil-echo "Switched to Emacs state for the next command ..."))
-
-(defun evil-exit-visual-and-repeat (event)
- "Exit insert state and repeat event.
-This special command should be used if some command called from
-visual state should actually be called in normal-state. The main
-reason for doing this is that the repeat system should *not*
-record the visual state information for some command. This
-command should be bound to exactly the same event in visual state
-as the original command is bound in normal state. EVENT is the
-event that triggered the execution of this command."
- (interactive "e")
- (when (evil-visual-state-p)
- (evil-exit-visual-state)
- (push event unread-command-events)))
-(evil-declare-ignore-repeat 'evil-exit-visual-and-repeat)
-
-(provide 'evil-commands)
-
-;;; evil-commands.el ends here