aboutsummaryrefslogtreecommitdiff
path: root/.config/emacs/lisp/evil/evil-commands.el
diff options
context:
space:
mode:
Diffstat (limited to '.config/emacs/lisp/evil/evil-commands.el')
-rw-r--r--.config/emacs/lisp/evil/evil-commands.el5288
1 files changed, 0 insertions, 5288 deletions
diff --git a/.config/emacs/lisp/evil/evil-commands.el b/.config/emacs/lisp/evil/evil-commands.el
deleted file mode 100644
index 5dbda83..0000000
--- a/.config/emacs/lisp/evil/evil-commands.el
+++ /dev/null
@@ -1,5288 +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/>.
-
-;;; Code:
-
-(require 'evil-common)
-(require 'evil-search)
-(require 'evil-states)
-(require 'evil-ex)
-(require 'evil-types)
-(require 'evil-command-window)
-(require 'evil-jumps)
-(require 'evil-vars)
-(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.
-
-(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
- ((not crosslines)
- ;; For efficiency, narrow the buffer to the projected
- ;; movement before determining the current line
- (evil-with-restriction nil (min (+ (point) (or count 1) 1) (point-max))
- (condition-case err
- (evil-narrow-to-line (forward-char count))
- (error
- ;; Restore the previous command (this one never happened).
- ;; This preserves the current column if the previous command
- ;; was `evil-next-line' or `evil-previous-line'.
- (setq this-command last-command)
- (unless noerror (signal (car err) (cdr err)))))))
- (noerror (ignore-errors (evil-forward-char count crosslines)))
- (t (evil-motion-loop (nil (or count 1))
- (forward-char)
- ;; don't put the cursor on a newline
- (or evil-move-beyond-eol
- (evil-visual-state-p) (evil-operator-state-p)
- (not (eolp)) (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
- ((not crosslines)
- ;; Restrict movement to the current line
- (evil-with-restriction
- (max (- (point) (or count 1)) (point-min))
- (min (1+ (point)) (point-max))
- (condition-case err
- (evil-narrow-to-line (backward-char count))
- (error
- ;; Restore the previous command (this one never happened).
- ;; This preserves the current column if the previous command
- ;; was `evil-next-line' or `evil-previous-line'.
- (setq this-command last-command)
- (unless noerror (signal (car err) (cdr err)))))))
- (noerror (ignore-errors (evil-backward-char count crosslines)))
- (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)
- (evil-line-move (1- (or count 1)) t)))
-
-(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)))
- (evil-line-move (1- (or count 1)) t)))
-
-(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))
- (let ((evil-move-beyond-eol
- (if (evil-visual-state-p) (not evil-v$-excludes-newline)
- evil-move-beyond-eol)))
- (evil-adjust-cursor))
- ;; Prevent "c$" and "d$" from deleting blank lines
- (when (eolp) (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
- (beginning-of-visual-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
- (end-of-visual-line count)
- (evil-move-cursor-back t))
-
-(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 evil-respect-visual-line-mode
- visual-line-mode)
- (evil-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 (/ (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))))
-
-(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
- (evil-move-end-of-line count)
- (skip-chars-backward " \t")
- (unless (bolp) (backward-char)))
-
-(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)
- (progn
- (goto-char (point-max))
- (when (and (eq (current-buffer) (window-buffer))
- (> (point) (window-end nil t)))
- ;; If the end of the buffer is not already on the screen, scroll to
- ;; position it near the bottom.
- (overlay-recenter (point))
- (recenter (and (< 100 scroll-conservatively) -1))))
- (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 then
-`end-of-buffer' is signaled."
- :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
- (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 c-ts-mode c++-ts-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 (ignore-errors
- (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))))))
- (close-pair (ignore-errors
- (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))))))
- (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)))))))
-
-(declare-function flyspell-overlay-p "flyspell")
-(evil-define-motion evil-next-flyspell-error (count)
- "Go to the COUNT'th spelling mistake after point."
- :jump t
- (unless (bound-and-true-p flyspell-mode) (signal 'search-failed nil))
- (let ((fwd (> (or count 1) 0)) (start (point)) (pos (point)) ov)
- (dotimes (_ (abs (or count 1)))
- (let ((limit (if fwd (point-max) (point-min))) wrappedp)
- (when fwd (setq pos (save-excursion (goto-char pos)
- (skip-syntax-forward "w") (point))))
- (while (progn (if (if fwd (>= pos limit) (<= pos limit))
- (if (or wrappedp (not evil-search-wrap))
- (signal 'search-failed nil)
- (setq wrappedp t
- limit start
- pos (if fwd (point-min)
- (previous-overlay-change (point-max)))))
- (setq pos (if fwd (next-overlay-change pos)
- (previous-overlay-change pos))))
- (not (setq ov (seq-find #'flyspell-overlay-p
- (overlays-at pos))))))
- (when wrappedp (let (message-log-max) (message "Search wrapped")))))
- (goto-char (overlay-start ov))))
-
-(evil-define-motion evil-prev-flyspell-error (count)
- "Go to the COUNT'th spelling mistake preceding point."
- :jump t
- (evil-next-flyspell-error (- (or count 1))))
-
-(evil-define-motion evil-previous-open-paren (count)
- "Go to COUNT previous unmatched \"(\"."
- :jump t
- :type exclusive
- (evil-up-paren ?\( ?\) (- (or count 1))))
-
-(evil-define-motion evil-next-close-paren (count)
- "Go to COUNT next unmatched \")\"."
- :jump t
- :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 \"{\"."
- :jump t
- :type exclusive
- (evil-up-paren ?{ ?} (- (or count 1))))
-
-(evil-define-motion evil-next-close-brace (count)
- "Go to COUNT next unmatched \"}\"."
- :jump t
- :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 non-nil, and backward otherwise. Loop back
-to the beginning of buffer if the end is reached."
- (let* ((pos (if forwardp (1+ (point)) (point)))
- (centered-markers
- (cl-sort
- (or (evil--lowercase-markers) (user-error "No marks in this buffer"))
- (if forwardp #'< #'>)
- :key (lambda (x) (+ (if (< (cdr x) pos) 0 most-negative-fixnum)
- (cdr x))))))
- (goto-char (cdar centered-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
- (unless (evil--lowercase-markers) (user-error "No marks in this buffer"))
- (dotimes (_ (or count 1))
- (move-end-of-line nil)
- (evil--next-mark t))
- (evil-first-non-blank))
-
-(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
- (unless (evil--lowercase-markers) (user-error "No marks in this buffer"))
- (dotimes (_ (or count 1))
- (move-beginning-of-line nil)
- (evil--next-mark nil))
- (evil-first-non-blank))
-
-(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))
- case-fold-search)
- (setq evil-last-find (list #'evil-find-char char fwd))
- (when fwd (evil-forward-char 1 evil-cross-lines))
- (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
- (evil-find-char count char)
- (setcar evil-last-find #'evil-find-char-to))
- (if (> (or count 1) 0)
- (backward-char)
- (forward-char)))
-
-(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))
- (cl-destructuring-bind (cmd char fwd)
- (or evil-last-find (user-error "No previous search"))
- ;; 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)
- (eql (if fwd (char-after (1+ (point))) (char-before)) char)
- (setq count (1+ count)))
- (let (evil-last-find)
- (funcall cmd (if fwd count (- count)) char)
- (unless (nth 2 evil-last-find)
- (setq evil-this-type 'exclusive)))))
-
-(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))
- ((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))
-
-(declare-function goto-last-change "ext:goto-chg")
-(declare-function goto-last-change-reverse "ext:goto-chg")
-
-(evil-define-motion evil-goto-last-change (count)
- "Like `goto-last-change' but takes a COUNT rather than a span."
- (setq this-command 'goto-last-change)
- (dotimes (_ (or count 1))
- (goto-last-change nil)))
-
-(evil-define-motion evil-goto-last-change-reverse (count)
- "Like `goto-last-change-reverse' but takes a COUNT rather than a span."
- (setq this-command 'goto-last-change-reverse)
- (dotimes (_ (or count 1))
- (goto-last-change-reverse nil)))
-
-(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))))
- (find-tag (or tag (user-error "No tag found around point"))))))))
-
-(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 ((widget (or (get-char-property (point) 'field)
- (get-char-property (point) 'button)
- (get-char-property (point) 'widget-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 (or (zerop scroll-margin)
- (= (point-min) (window-start))
- (< (count-screen-lines (window-start) (point))
- scroll-margin))
- 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 nil)))
-
-(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)
- (if (or (zerop scroll-margin)
- (< (count-screen-lines (point) (window-end))
- scroll-margin))
- 1
- (1+ scroll-margin)))))))
-
-;; scrolling
-(evil-define-command evil-scroll-line-up (count)
- "Scroll the window COUNT lines upwards."
- :repeat nil
- :keep-visual t
- (interactive "p")
- (let (scroll-preserve-screen-position) (scroll-down count)))
-
-(evil-define-command evil-scroll-line-down (count)
- "Scroll the window COUNT lines downwards."
- :repeat nil
- :keep-visual t
- (interactive "p")
- (let (scroll-preserve-screen-position) (scroll-up count)))
-
-(evil-define-command evil-scroll-count-reset ()
- "Set `evil-scroll-count' to 0.
-`evil-scroll-up' and `evil-scroll-down' will then scroll by half of
-the screen (the default)."
- :repeat nil
- :keep-visual t
- (interactive)
- (setq evil-scroll-count 0))
-
-(defun evil--get-scroll-count (count)
- "Given a user-supplied COUNT, return scroll count."
- (cl-flet ((posint (x) (and (natnump x) (< 0 x) x)))
- (or (posint count)
- (posint evil-scroll-count)
- (/ (window-body-height) 2))))
-
-;; With `scroll-preserve-screen-position' `scroll-up'/`scroll-down'
-;; target the same cursor pixel Y-coordinate while `last-command' has
-;; the `scroll-command' property. However the target needs updating
-;; when e.g. scrolling maximally to the first or last line and then
-;; switching scroll direction. Do this by resetting `last-command'
-;; when `real-this-command' (`evil-ensure-column' modifies
-;; `this-command') changed from last value:
-
-(evil-define-command evil-scroll-up (count)
- "Scroll the window and the cursor COUNT lines upwards.
-If COUNT is not specified the function scrolls up `evil-scroll-count'
-lines, 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>")
- (when (= (line-beginning-position) (point-min))
- (signal 'beginning-of-buffer nil))
- (setq count (evil--get-scroll-count count))
- (evil-ensure-column
- (let ((opoint (point)))
- (condition-case nil
- (let ((scroll-preserve-screen-position 'always)
- (last-command (when (eq real-last-command real-this-command)
- real-last-command)))
- (scroll-down count))
- (:success
- ;; Redo if `scroll-down' only did partial scroll up to BOB
- (when (<= (window-start) (point-min))
- (goto-char opoint)
- (vertical-motion (- count))))
- (beginning-of-buffer (vertical-motion (- count)))))))
-(put 'evil-scroll-up 'scroll-command t)
-
-(evil-define-command evil-scroll-down (count)
- "Scroll the window and the cursor COUNT lines downwards.
-If COUNT is not specified the function scrolls down
-`evil-scroll-count' lines, 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>")
- (when (= (line-end-position) (point-max))
- (signal 'end-of-buffer nil))
- (setq count (evil--get-scroll-count count))
- (evil-ensure-column
- ;; 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))
- (vertical-motion count)
- (condition-case nil
- (let ((scroll-preserve-screen-position 'always)
- (last-command (when (eq real-last-command real-this-command)
- real-last-command)))
- (scroll-up count))
- (:success
- ;; If EOB became visible: Scroll it to the bottom
- (save-excursion
- (goto-char (window-start))
- (vertical-motion (max 0 (- (window-height) 1 scroll-margin)))
- (when (<= (point-max) (point)) (recenter -1))))
- (end-of-buffer (goto-char (point-max)) (recenter -1))))))
-(put 'evil-scroll-down 'scroll-command t)
-
-(evil-define-command evil-scroll-page-up (count)
- "Scroll 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)
- "Scroll 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)
- "Scroll line number COUNT (or the cursor line) to the top of the window."
- :repeat nil
- :keep-visual t
- (interactive "<c>")
- (when count
- (evil-save-column
- (goto-char (point-min))
- (forward-line (1- count))))
- (recenter 0))
-
-(evil-define-command evil-scroll-line-to-top-first-non-blank (count)
- "Scroll line number COUNT (or the cursor line) to the top of the window.
-Then move the cursor to the first non-blank character of that line."
- :repeat nil
- :keep-visual t
- (interactive "<c>")
- (evil-scroll-line-to-top count)
- (evil-first-non-blank))
-
-(evil-define-command evil-scroll-line-to-center (count)
- "Scroll line number COUNT (or the cursor line) to the center of the window."
- :repeat nil
- :keep-visual t
- (interactive "<c>")
- (when count
- (evil-save-column
- (goto-char (point-min))
- (forward-line (1- count))))
- (recenter))
-
-(evil-define-command evil-scroll-line-to-center-first-non-blank (count)
- "Scroll line number COUNT (or the cursor line) to the center of the window.
-Then move the cursor to the first non-blank character of that line."
- :repeat nil
- :keep-visual t
- (interactive "<c>")
- (evil-scroll-line-to-center count)
- (evil-first-non-blank))
-
-(evil-define-command evil-scroll-line-to-bottom (count)
- "Scroll line number COUNT (or the cursor line) to the bottom of the window."
- :repeat nil
- :keep-visual t
- (interactive "<c>")
- (when count
- (evil-save-column
- (goto-char (point-min))
- (forward-line (1- count))))
- (recenter -1))
-
-(evil-define-command evil-scroll-line-to-bottom-first-non-blank (count)
- "Scroll line number COUNT (or the cursor line) to the bottom of the window.
-Then move the cursor to the first non-blank character of that line."
- :repeat nil
- :keep-visual t
- (interactive "<c>")
- (evil-scroll-line-to-bottom count)
- (evil-first-non-blank))
-
-(evil-define-command evil-scroll-bottom-line-to-top (count)
- "Scroll the line right below the window,
-or line COUNT to the top of the window."
- :repeat nil
- :keep-visual t
- (interactive "<c>")
- (unless count
- (goto-char (window-end))
- (evil-first-non-blank))
- (evil-scroll-line-to-top count))
-
-(evil-define-command evil-scroll-top-line-to-bottom (count)
- "Scroll the line right above the window,
-or line COUNT to the bottom of the window."
- :repeat nil
- :keep-visual t
- (interactive "<c>")
- (unless count
- (goto-char (window-start))
- (evil-first-non-blank))
- (evil-scroll-line-to-bottom count))
-
-(evil-define-command evil-scroll-left (count)
- "Scroll 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)
- "Scroll 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)
- "Scroll 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)
- "Scroll the window COUNT columns to the right."
- :repeat nil
- :keep-visual t
- (interactive "p")
- (evil-with-hproject-point-on-window
- (scroll-left count)))
-
-(evil-define-command evil-scroll-end-column ()
- "Scroll the window to position the cursor at the end (right side) of the screen.
-Warn if `hscroll-margin' > 0, as cursor will be `hscroll-margin' chars from
-the right edge."
- :repeat nil
- :keep-visual t
- (interactive)
- (let* ((window-hpos (- (current-column) (window-hscroll)))
- (dist-from-right-edge (- (window-width) window-hpos)))
- (when (< 0 hscroll-margin)
- (evil-echo "%s: hscroll-margin = %d" this-command hscroll-margin))
- (evil-scroll-column-left (- dist-from-right-edge (abs (* 2 hscroll-margin))))))
-
-(evil-define-command evil-scroll-start-column ()
- "Scroll the window to position the cursor at the start (left side) of the screen.
-Warn if `hscroll-margin' > 0, as cursor will be `hscroll-margin' chars from
-the left edge."
- :repeat nil
- :keep-visual t
- (interactive)
- (let ((initial-column (current-column))
- (initial-hscroll (window-hscroll)))
- (when (< 0 hscroll-margin)
- (evil-echo "%s: hscroll-margin = %d" this-command hscroll-margin))
- (evil-scroll-column-right (- initial-column initial-hscroll hscroll-margin 1))))
-
-;;; 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-a-restricted-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-restricted-object 'evil-word beg end type count))
-
-(evil-define-text-object evil-a-WORD (count &optional beg end _type)
- "Select a WORD."
- (evil-select-a-restricted-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-restricted-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-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-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-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-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-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-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."
- (defvar evil-search-module)
- (unless (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
- (pcase 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)
- "Save 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)
- (goto-char beg)))))
-
-(defun evil-expand-line-for-line-based-operators (beg end type)
- "Expand to line when in visual mode possibly changing BEG, END and TYPE.
-Avoids double expansion for line-based commands like \"V\" or \"D\"."
- (when (evil-visual-state-p)
- (unless (memq type '(line block screen-line))
- ;; Subtract 1 from end to avoid expanding to the next line
- ;; when \n is part of the visually selected region.
- ;; If removed (evil-expand beg end 'line)
- ;; will expand to the end of the next line instead of the current
- ;; line which will cause line expanding commands like 'Y' to
- ;; misbehave when used in visual state.
- (when (eq ?\n (char-before end))
- (cl-decf end))
- (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))
- (list beg end type))
-
-(evil-define-operator evil-yank-line (beg end type register)
- "Save whole lines into the kill-ring."
- :motion evil-line-or-visual-line
- :move-point nil
- (interactive "<R><x>")
- (cl-destructuring-bind
- (beg end type) (evil-expand-line-for-line-based-operators beg end type)
- (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>")
- (when (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-line-expand beg end)))
- (setq beg (car new-range)
- end (cadr new-range)
- type 'line)))
- (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 (eq type 'line)
- (called-interactively-p 'any))
- (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 (if (and (eq most-positive-fixnum temporary-goal-column)
- (memq last-command '(next-line previous-line)))
- temporary-goal-column
- evil-operator-start-col)))))
-
-(evil-define-operator evil-delete-line (beg end type register yank-handler)
- "Delete to end of line."
- :motion evil-end-of-line-or-visual-line
- (interactive "<R><x>")
- (cl-destructuring-bind
- (beg end type) (evil-expand-line-for-line-based-operators beg end type)
- (if (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))
- (evil-delete beg end type register yank-handler)
- (when (eq 'line type)
- (evil-first-non-blank)
- (when (and (not evil-start-of-line) evil-operator-start-col)
- (move-to-column (if (and (eq most-positive-fixnum temporary-goal-column)
- (memq last-command '(next-line previous-line)))
- temporary-goal-column
- evil-operator-start-col)))))))
-
-(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)
- (signal 'beginning-of-line nil)))
-
-(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 (signal 'beginning-of-line nil)))))
-
-(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)
- (line-beginning-position 0))
- end (save-excursion (goto-char end)
- (line-beginning-position 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 leftmost-point)
- (save-excursion
- (goto-char beg)
- (setq opoint (line-beginning-position))
- (setq leftmost-point
- (let ((inhibit-field-text-motion t)) (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
- (cond
- ((/= opoint leftmost-point) (evil-insert 1)) ; deletion didn't delete line
- ((= opoint (point)) (evil-open-above 1))
- (t (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 type 'inclusive))
- (cl-destructuring-bind
- (beg end _type) (evil-expand-line-for-line-based-operators beg end type)
- (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-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 the 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
- :jump t
- (interactive "*p")
- (evil--check-undo-system)
- (let ((state-before evil-state))
- (unless (memq state-before '(normal visual)) (evil-normal-state))
- (funcall evil-undo-function count)
- (unless (memq state-before '(normal visual)) (evil-change-state state-before))))
-
-(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."
- (if (eq type 'block)
- (evil-apply-on-block #'evil-invert-case beg end nil)
- (save-excursion
- (goto-char beg)
- (while (< beg end)
- (let ((char (following-char)))
- (delete-char 1)
- (insert-char
- (if (eq (upcase char) char) (downcase char) (upcase char))))
- (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 #'rot13-region 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))
- last-line-blank)
- (when (> count 1)
- (setq count (1- count)))
- (goto-char beg)
- (dotimes (i count)
- (when (= (1+ i) count) ; i.e. we're just before the last join
- (evil-move-beginning-of-line)
- (setq last-line-blank (looking-at "[ \t]*$")))
- (join-line 1))
- (and last-line-blank (indent-according-to-mode))))
-
-(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><!>")
- (let ((join-fn (if bang 'evil-join-whitespace 'evil-join)))
- (if (not count)
- ;; without count - just join the given region
- (funcall join-fn beg end)
- (unless (string-match-p "^[1-9][0-9]*$" count)
- (user-error "Invalid count"))
- ;; emulate Vim's :join when count is given - start from the
- ;; end of the region and join COUNT lines from there
- (save-excursion
- (goto-char end)
- (let ((beg-adjusted (line-beginning-position 0))
- (end-adjusted (line-beginning-position (string-to-number count))))
- (funcall join-fn beg-adjusted end-adjusted))))))
-
-(defun evil--ex-string-for-print (beg end linump borderline)
- "Return a string to be printed by :print etc.
-Starts at line of BEG and end at line of END.
-Include line number at the start of each line if LINUMP is non-nil.
-Surround line denoted by BORDERLINE with dashes if non-nil."
- (let ((result-string "")
- (continue t)
- (line-move-visual nil))
- (save-excursion
- (goto-char beg)
- (while continue
- (let* ((line-num (line-number-at-pos))
- (border (and (natnump borderline) (= borderline line-num)))
- (raw-line (thing-at-point 'line))
- (line (if (string= "\n" (substring raw-line -1))
- raw-line (concat raw-line "\n")))
- (border-length (1- (min (length line) (frame-width)))))
- (when border
- (setq result-string
- (concat result-string (make-string border-length ?-) "\n")))
- (when linump
- (setq result-string
- (concat result-string
- (propertize (number-to-string (line-number-at-pos))
- 'face 'line-number-current-line)
- " ")))
- (unless (eobp)
- (setq result-string (concat result-string line)))
- (when border
- (setq result-string
- (concat result-string (make-string border-length ?-) "\n")))
- (when (or (= (point) (progn (evil-line-move 1 t) (point)))
- (> (line-end-position) end))
- (setq continue nil)))))
- (string-trim-right result-string "\n")))
-
-(defun evil--ex-print-to-minibuffer (string)
- "Print STRING to the minibuffer for better persistence."
- (let ((keymap (make-keymap))
- minibuffer-local-map)
- (set-char-table-range (nth 1 keymap) t 'abort-recursive-edit)
- (setq minibuffer-local-map keymap)
- (read-from-minibuffer "" (propertize string 'read-only t))))
-
-(defun evil--ex-print (beg end count &optional linump borderline)
- "Print lines in range to the minibuffer.
-Starting at BEG and ending at END + COUNT lines.
-Include line number at the start of each line if LINUMP is non-nil.
-Surround line denoted by BORDERLINE with dashes if non-nil."
- (let* ((count (cond ((stringp count) (string-to-number count))
- ((natnump count) count)
- (t 1)))
- (end (save-excursion (goto-char (if (= (point-max) end) end (1- end)))
- (line-end-position count)))
- (substring (evil--ex-string-for-print beg end linump borderline)))
- (cond ((> 1 count) (user-error "Positive count required"))
- (evil--ex-global-active-p
- (setq evil--ex-print-accumulator
- (if (string= "" evil--ex-print-accumulator)
- (concat evil--ex-print-accumulator substring)
- (concat evil--ex-print-accumulator "\n" substring))))
- (t (evil--ex-print-to-minibuffer substring)
- (when (string-match-p "\n" substring)
- (goto-char end)
- (evil-beginning-of-line))))))
-
-(defun evil--global-print+clear ()
- "Print accumulated print output from :global print, and clear."
- (let ((s evil--ex-print-accumulator))
- (unless (string= s "")
- (setq evil--ex-print-accumulator "")
- (evil--ex-print-to-minibuffer s))))
-(add-hook 'evil-after-global-hook #'evil--global-print+clear)
-
-(evil-define-command evil-ex-print (beg end &optional count)
- (interactive "<r><a>")
- (evil--ex-print beg end count))
-
-(evil-define-command evil-ex-numbered-print (beg end &optional count)
- (interactive "<r><a>")
- (evil--ex-print beg end count t))
-
-(evil-define-command evil-ex-z (_beg end &optional zmarks _bang)
- "Display several lines of text surrounding the line specified by range.
-BEG and END represent the range, ZMARKS represents the args in string form.
-With a count supplied in the args, display that number of lines. Without a
-count, display `evil-scroll-count' number of lines, or half the window height.
-This table explains what each mark argument does.
-
-mark | first line | last line | new cursor line
------+-------------------------+----------------------------+----------------
-+ | current line | 1 scr (or 1 count) forward | last line
-- | 1 scr (or 1 count) back | current line | last line
-^ | 2 scr (or 2 count) back | 1 scr (or 1 count) back | last line
-. | ½ scr (or ½ count) back | ½ scr (or ½ count) forward | last line
-= | ½ scr (or ½ count) back | ½ scr (or ½ count) forward | current line
-
-Specifying no mark at all is the same as `+'.
-If the mark is `=' a line of dashes is printed around the current line.
-If a `#' is included before the mark args, the lines are numbered."
- ;; TODO implement bang argument.
- (interactive "<r><a><!>")
- (goto-char (setq end (1- end)))
- (save-match-data
- (string-match "\\(#?\\)\\([^0-9]*\\)\\([0-9]*\\)" (or zmarks ""))
- (cl-destructuring-bind (_ _ hs he ms me cs ce) (match-data)
- (let* ((linump (/= hs he))
- (mark-string (if (= ms me) "+" (substring zmarks ms me)))
- (count-string (if (= cs ce) "" (substring zmarks cs ce)))
- (count (evil--get-scroll-count (string-to-number count-string)))
- (max-mini-window-height 0.5))
- (cond
- ((< 1 (- me ms))
- (evil-beginning-of-line)
- (user-error "Too many mark args (got %d, expected 1)" (- me ms)))
- ((string= "+" mark-string)
- (ignore-errors (beginning-of-line count))
- (evil--ex-print end end count linump))
- ((string= "-" mark-string)
- (evil-beginning-of-line)
- (evil--ex-print (line-beginning-position (- 2 count)) end 1 linump))
- ((string= "^" mark-string)
- (let ((end* (progn (move-end-of-line (- 1 count)) (point)))
- (beg* (line-beginning-position (- 2 count))))
- (evil-beginning-of-line)
- (evil--ex-print beg* end* 1 linump)))
- ((string= "." mark-string)
- (let ((beg* (line-beginning-position (- 1 (floor count 2))))
- (end* (progn (move-end-of-line (ceiling count 2)) (point))))
- (evil-beginning-of-line)
- (evil--ex-print beg* end* 1 linump)))
- ((string= "=" mark-string)
- (let ((beg* (line-beginning-position (- 1 (floor count 2))))
- (end* (line-end-position (ceiling count 2))))
- (evil-beginning-of-line)
- (evil--ex-print beg* end* 1 linump (line-number-at-pos end))))
- (t (evil-beginning-of-line)
- (user-error "Invalid mark arg: %s" mark-string)))))))
-
-(evil-define-operator evil-fill (beg end)
- "Fill text."
- :move-point nil
- :type line
- (save-excursion
- (ignore-errors (fill-region beg end))))
-
-(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))
- (ignore-errors
- (fill-region beg end)
- (goto-char marker)
- (evil-first-non-blank))))
-
-(evil-define-operator evil-indent (beg end)
- "Indent text."
- :move-point nil
- :type line
- (evil-ensure-column
- (setq this-command real-this-command) ; Reset change made by evil-ensure-column
- (save-restriction
- (narrow-to-region beg end)
- (if (save-excursion (goto-char beg) (= 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))
- ;; Tabify or untabify leading whitespace characters
- (when evil-indent-convert-tabs
- ;; Whether tab or space should be used is determined by indent-tabs-mode
- (let ((convert-fun (if indent-tabs-mode #'tabify #'untabify)))
- (save-excursion
- (goto-char (point-min))
- (while (not (eolp))
- (funcall convert-fun (point) (progn (skip-chars-forward " \t") (point)))
- (forward-line))))))))
-
-(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))))))
-
-(defun evil-delete-indentation ()
- "Delete all indentation on current line."
- (interactive)
- (save-excursion
- (move-beginning-of-line nil)
- (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 (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)
- "Center 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)
- "Paste 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)
- ;; This is the only difference with evil-paste-after in visual-state
- (let ((evil-kill-on-visual-paste (not evil-kill-on-visual-paste)))
- (evil-visual-paste count register))
- (evil-with-undo
- (let* ((text (copy-sequence
- (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))))
- (when evil--cursor-after
- (if (eq 'evil-yank-line-handler yank-handler)
- (ignore-errors (evil-next-line-first-non-blank))
- (evil-forward-char 1 nil t))
- (setq evil--cursor-after nil))
- ;; 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)
- "Paste 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 (copy-sequence
- (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 evil--cursor-after
- (if (eq 'evil-yank-line-handler yank-handler)
- (ignore-errors (evil-next-line-first-non-blank 1))
- (evil-forward-char 1 nil t))
- (setq evil--cursor-after nil))
- (when register
- (setq evil-last-paste nil))
- (and (> (length text) 0) text)))))
-
-(evil-define-command evil-paste-before-cursor-after
- (count &optional register yank-handler)
- "The same as `evil-paste-before' but
-leave the cursor just after the new text."
- :suppress-operator t
- (interactive "*P<x>")
- (setq count (prefix-numeric-value count)
- evil--cursor-after t)
- (evil-paste-before count register yank-handler))
-
-(evil-define-command evil-paste-after-cursor-after
- (count &optional register yank-handler)
- "The same as `evil-paste-after' but
-leave the cursor just after the new text."
- :suppress-operator t
- (interactive "*P<x>")
- (setq count (prefix-numeric-value count)
- evil--cursor-after t)
- (evil-paste-after count register yank-handler))
-
-(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 type)
- (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
- type (evil-visual-type))
- ;; When pasting charwise text into linewise selection, keep trailing NL
- (when (and text end
- (eq 'line type)
- (not (eq ?\n (aref text (1- (length text))))))
- (cl-decf end))
- (evil-visual-rotate 'upper-left)
- (evil-delete beg end type (unless evil-kill-on-visual-paste ?_))
- (when (and (eq yank-handler #'evil-yank-line-handler)
- (not (memq type '(line block)))
- (/= 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
- ;; When replacing the last buffer line and it does not end
- ;; in a newline, use `evil-paste-after' because
- ;; `evil-delete' will have moved point to the line above.
- ((cond ((eq type 'line) (= end (point-max)))
- ((eq type 'block) (eq yank-handler #'evil-yank-line-handler)))
- (goto-char end)
- (evil-paste-after count register))
- ((and (eq type 'block)
- (not (eq yank-handler #'evil-yank-block-handler))
- (not (string-match-p "\n" text)))
- (evil-apply-on-block #'evil-insert-for-yank-at-col beg end t text count))
- (t (evil-paste-before count register)))))
- (when evil-kill-on-visual-paste
- (current-kill -1))
- ;; Ensure that gv can restore visually pasted area...
- (set-marker evil-visual-point (evil-get-marker (if (< dir 0) ?\[ ?\]) t))
- (set-marker evil-visual-mark (evil-get-marker (if (< dir 0) ?\] ?\[) 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 ((ov (make-overlay (point) (+ (point) (if (evil-replace-state-p) 1 0)))))
- (unwind-protect
- (progn
- (overlay-put ov 'invisible t)
- (overlay-put ov 'after-string
- #("\"" 0 1 (face minibuffer-prompt cursor 1)))
- (list (or evil-this-register (read-char))))
- (delete-overlay ov))))
- (let ((opoint (point))
- evil-move-cursor-back)
- (evil-paste-before nil register t)
- (when (evil-replace-state-p)
- (let* ((reg-length (- (point) opoint))
- (chars-to-delete (min (- (line-end-position) (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
- :suppress-operator t
- (interactive "<C>")
- (setq evil-this-register register))
-
-(defvar evil-macro-buffer nil
- "The buffer that has been active on macro recording.")
-
-(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]")
-
-(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
- last-macro (ignore-errors (evil-end-and-return-macro)))
- (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-last-recorded-register register)
- (evil-set-register evil-this-macro nil)
- (kmacro-start-macro nil)
- (setq evil-macro-buffer (current-buffer)))
- (t (error "Invalid register `%s'" register)))))
-
-(defun evil-repeat-execute-macro (flag)
- "Called to record a macro execution.
-FLAG is either `pre' or `post' if the function is called before resp.
-after executing the command."
- (pcase flag
- ('pre (evil-repeat-record (this-command-keys)))
- ('post (evil-repeat-record (string evil-last-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
- :repeat evil-repeat-execute-macro
- (interactive
- (let (count macro register)
- (setq count (cond ((null current-prefix-arg) 1)
- ((numberp current-prefix-arg) current-prefix-arg)
- (t 0))
- register (or evil-this-register (read-char)))
- (cond
- ((or (eq register ?:)
- (and (eq register ?@) (eq evil-last-register ?:)))
- (setq macro #'evil-ex-repeat
- 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)
- (if (zerop count)
- (while t (funcall macro))
- (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
- (let (pre-command-hook post-command-hook) ; For performance
- (combine-after-change-calls
- (execute-kbd-macro macro count)
- (setq this-command 'evil-execute-macro)))) ; For repeatability
- ;; enter Normal state if the macro fails
- (error
- (evil-normal-state)
- (signal (car err) (cdr err)))))))
-
-(evil-define-command evil-execute-last-recorded-macro (count)
- "Execute last recorded keyboard macro COUNT times.
-When called with a non-numerical prefix \
-\(such as \\[universal-argument]),
-COUNT is infinite."
- :keep-visual t
- :suppress-operator t
- (interactive
- (list (cond
- ((and current-prefix-arg (numberp current-prefix-arg)) current-prefix-arg)
- (current-prefix-arg 0)
- (t 1))))
- (if evil-last-recorded-register
- (evil-execute-macro count (evil-get-register evil-last-recorded-register t))
- (user-error "No previous macro"))
- (setq evil-last-register evil-last-recorded-register))
-
-;;; Visual commands
-
-(evil-define-motion evil-visual-restore ()
- "Restore previous selection."
- (cond
- ;; Called from visual state
- ((and (evil-visual-state-p)
- evil-prev-visual-mark evil-prev-visual-point evil-prev-visual-selection)
- (let ((tmp-visual-mark (marker-position evil-visual-mark))
- (tmp-visual-point (marker-position evil-visual-point))
- (tmp-visual-selection evil-visual-selection))
- (evil-visual-make-selection evil-prev-visual-mark
- evil-prev-visual-point
- evil-prev-visual-selection
- t)
- (move-marker evil-prev-visual-mark tmp-visual-mark)
- (move-marker evil-prev-visual-point tmp-visual-point)
- (setq evil-prev-visual-selection tmp-visual-selection)))
- ;; Called from other state
- ((and evil-visual-selection evil-visual-mark evil-visual-point)
- (evil-visual-make-selection evil-visual-mark
- evil-visual-point
- (evil-visual-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)
- "Move point to CORNER of the Visual selection.
-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 clockwise."
- :keep-visual t
- (interactive
- (let ((corners '(#1=upper-left upper-right lower-right lower-left #1#)))
- (list (cadr (memq (evil-visual-block-corner) corners)))))
- (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 on the next VCOUNT 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
- (if (not (evil-visual-state-p))
- (list (prefix-numeric-value current-prefix-arg))
- (evil-visual-rotate 'upper-left)
- (list (prefix-numeric-value current-prefix-arg)
- (when (memq (evil-visual-type) '(line block))
- (1+ (evil-count-lines evil-visual-point evil-visual-mark)))
- t)))
- (and evil-want-fine-undo vcount (evil-start-undo-step))
- (if (and (evil-visual-state-p) (eq (evil-visual-type) 'line))
- (evil-insert-line count vcount)
- (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))
- (1+ (evil-count-lines evil-visual-point evil-visual-mark)))))
- (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))
- (eq 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 (eolp) (forward-char))
- (evil-insert count vcount skip-empty-lines)
- (add-hook 'post-command-hook #'evil-maybe-remove-spaces)))
-
-(evil-define-command 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."
- :keep-visual t
- :type exclusive
- :jump t
- (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
- (ov (if (not (evil-replace-state-p))
- (make-overlay opoint opoint)
- (setq chars-to-delete (min (- (line-end-position) opoint) count))
- (evil-update-replace-alist opoint count chars-to-delete)
- (make-overlay opoint (+ chars-to-delete opoint)))))
- (unwind-protect
- (progn
- (overlay-put ov 'invisible t)
- (overlay-put ov 'after-string #("^" 0 1 (face escape-glyph cursor 1)))
- (let (overwrite-mode) ; Force `read-quoted-char'
- (quoted-insert count))
- (when chars-to-delete (delete-char chars-to-delete)))
- (delete-overlay ov))))
-
-(evil-define-command evil-open-above (count)
- "Insert a new line above point and switch to Insert state.
-The insertion will be repeated COUNT times."
- :suppress-operator t
- (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)
- (unwind-protect
- (when evil-auto-indent
- (indent-according-to-mode))
- (evil-insert-state 1)))
-
-(evil-define-command evil-open-below (count)
- "Insert a new line below point and switch to Insert state.
-The insertion will be repeated COUNT times."
- :suppress-operator t
- (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)
- (unwind-protect
- (when evil-auto-indent
- (indent-according-to-mode))
- (evil-insert-state 1)))
-
-(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 #'evil-first-non-blank #'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)
- move-fn
- 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))
-
-(evil-define-command 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."
- :keep-visual t
- :type exclusive
- (interactive "p")
- (if (evil-visual-state-p)
- (evil-beginning-of-line)
- (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)
- (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 (- (line-end-position) 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 ()
- "Show a list of all available digraphs."
- :repeat nil
- (eval-and-compile (require 'evil-digraphs))
- (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
- (cl-loop
- with xs = (append evil-digraphs-table-user evil-digraphs-table)
- while xs collect
- (cl-loop
- repeat columns vconcat
- (cl-destructuring-bind (chars . digraph) (or (pop xs) '(() . ?\ ))
- (list (char-to-string digraph) (concat chars)))
- into row finally return (list nil row))))))
-
-(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))))))))
-
-(defun evil-enter-replace-state (count)
- "Switch to Replace state at point.
-The insertion will be repeated COUNT times."
- (interactive "p")
- (setq evil-insert-count count)
- (setq evil-insert-count count
- evil-insert-lines nil
- evil-insert-vcount nil)
- (evil-replace-state 1))
-
-;; 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 nil
- (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)
- "Determine 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)
- "Save 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)
- (read-only-mode -1)))
-
-(evil-define-command evil-view (file &optional bang)
- "Open FILE but don't allow changes.
-If no FILE is specified, reload the current buffer from disk as read-only."
- :repeat nil
- (interactive "<f><!>")
- (if file
- (find-file-read-only file)
- (revert-buffer bang (or bang (not (buffer-modified-p))) t)
- (read-only-mode +1)))
-
-(evil-define-command evil-buffer-add (file)
- "Add FILE to the buffer list, but don't visit it. "
- :repeat nil
- (interactive "<f>")
- (if (or (not file) (string= "" file))
- (user-error "No file specified")
- (find-file-noselect file)))
-
-(evil-define-command evil-read (count file)
- "Insert 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 ()
- "Show 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 is 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)
- "Switch 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)
- "Go to the COUNTth next buffer in the buffer list."
- :repeat nil
- (interactive "p")
- (next-buffer count))
-
-(evil-define-command evil-prev-buffer (&optional count)
- "Go to the COUNTth prev buffer in the buffer list."
- :repeat nil
- (interactive "p")
- (previous-buffer count))
-
-(evil-define-command evil-delete-buffer (buffer &optional bang)
- "Delete 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 (bound-and-true-p server-buffer-clients)
- (fboundp 'server-edit))
- (server-edit)
- (kill-buffer nil))
- ;; close all windows that showed this buffer
- (dolist (w wins) (ignore-errors (delete-window w))))))
-
-(evil-define-command evil-quit (&optional force)
- "Close the current window, current frame, current tab, Emacs.
-If the current frame belongs to some client the client connection
-is closed."
- :repeat nil
- (interactive "<!>")
- (condition-case nil
- (evil-window-delete)
- (error
- (if (and (bound-and-true-p server-buffer-clients)
- (fboundp 'server-edit)
- (fboundp 'server-buffer-done))
- (if force
- (server-buffer-done (current-buffer))
- (server-edit))
- (condition-case nil
- (delete-frame)
- (error
- (condition-case nil
- (tab-bar-close-tab)
- (error
- (if force
- (kill-emacs)
- (save-buffers-kill-emacs))))))))))
-
-(evil-define-command evil-quit-all (&optional bang)
- "Exit 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 err-code _force)
- "Exit 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 "<N><!>")
- (if (bound-and-true-p server-buffer-clients)
- (user-error "Cannot exit client process with error code")
- (kill-emacs (or err-code 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)
- "Save the current buffer and close 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)
- "Save the current buffer and close 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-called-from-ex-p)
- (let ((current-prefix-arg
- (if (or current-prefix-arg (evil-visual-state-p))
- current-prefix-arg
- (goto-char (min beg end))
- (count-lines beg end)))
- (evil-ex-initial-input "!"))
- (call-interactively #'evil-ex))
- (if (zerop (length command))
- (when previous (setq command evil-previous-shell-command))
- (setq command (evil-ex-replace-special-filenames command)
- evil-previous-shell-command command))
- (cond
- ((zerop (length command))
- (user-error "No%s shell command" (if previous " previous" "")))
- (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)
- "Show 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)
- "Show 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 (evil-echo "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) (evil-echo "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))))))
-
-(declare-function ffap-file-at-point "ffap")
-(defvar ffap-string-at-point-region)
-(evil-define-command evil-find-file-at-point-with-line ()
- "Open the file at point and go to position if present.
-Supports positions in the following formats: \"path:line path(line)\",
-\"path:line:col\" and \"path(line,col)\"."
- (require 'ffap)
- (let ((fname (ffap-file-at-point)))
- (unless fname
- (user-error "File does not exist."))
- (let* ((line-number-pattern ":\\([0-9]+\\)\\=" ) ; path:line format
- (line-number-pattern-alt "\\=(\\([0-9]+\\))") ; path(line) format
- (line-and-column-numbers-pattern ":\\([0-9]+\\):\\([0-9]+\\)\\=") ; path:line:col format
- (line-and-column-numbers-pattern-alt "\\=(\\([0-9]+\\),\\([0-9]+\\))") ; file(line,col) format
- (get-number (lambda (pattern match-number backward)
- (save-excursion
- (goto-char (cadr ffap-string-at-point-region))
- (and (if backward
- (re-search-backward pattern (line-beginning-position) t)
- (re-search-forward pattern (line-end-position) t))
- (string-to-number (match-string match-number))))))
- (line-number (or (funcall get-number line-and-column-numbers-pattern 1 t)
- (funcall get-number line-and-column-numbers-pattern-alt 1 nil)
- (funcall get-number line-number-pattern 1 t)
- (funcall get-number line-number-pattern-alt 1 nil)))
- (column-number (or (funcall get-number line-and-column-numbers-pattern 2 t)
- (funcall get-number line-and-column-numbers-pattern-alt 2 nil))))
- (evil-echo "%s, %s"
- (if line-number (format "line: %s" line-number) "no line")
- (if column-number (format "column: %s" column-number) "no column"))
- (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.
-Signal an error if the file does not exist."
- (let ((region (buffer-substring (region-beginning) (region-end))))
- (if (file-exists-p region)
- (find-file-at-point region)
- (user-error "Can't find file \"%s\" in path" region))))
-
-(evil-ex-define-argument-type state
- "Define an argument type which can take state names."
- :collection
- (lambda (arg predicate flag)
- (let ((completions (cons '(nil) evil-state-properties)))
- (when arg
- (cond
- ((null flag)
- (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 (and evil-called-from-ex-p evil-ex-argument
- (intern-soft 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)
- "Go to the next occurrence."
- :jump t
- :type exclusive
- (evil-ex-search count))
-
-(evil-define-motion evil-ex-search-previous (count)
- "Go 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))
- (let ((search-separator (car (last evil-repeat-info))))
- (evil-repeat-record (evil-ex-pattern-regex evil-ex-search-pattern))
- (when evil-ex-search-offset
- (evil-repeat-record (concat search-separator evil-ex-search-offset))))
- ;; 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')
- (when (zerop (length (this-command-keys)))
- (evil-repeat-record (vector last-input-event))))
- (t (evil-repeat-motion flag))))
-
-(evil-define-motion evil-ex-search-forward (count)
- "Start 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)
- "Start a backward 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 if 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)))))
-
-(defun evil--ex-substitute-final-message (nreplaced flags)
- "Display message according to replacements and flags.
-If FLAGS contains \"p\" or \"#\" and NREPLACED is more than 0, print
-the last line to the echo area. Otherwise, print the number of
-replacements made or found."
- (let ((replaced-any (< 0 nreplaced)))
- (cond
- ((and replaced-any (memq ?p flags))
- (evil-echo "%s" (buffer-substring (line-beginning-position)
- (line-end-position))))
- ((and replaced-any (memq ?# flags))
- (evil-echo "%s %s" (propertize (number-to-string (line-number-at-pos))
- 'face 'line-number-current-line)
- (buffer-substring (line-beginning-position)
- (line-end-position))))
- (t (evil-echo "%s %d occurrence%s"
- (if (memq ?n flags) "Found" "Replaced")
- nreplaced
- (if (/= nreplaced 1) "s" ""))))))
-
-(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 "")
- flags (append flags)
- evil-ex-last-was-search nil
- evil-ex-substitute-pattern pattern
- evil-ex-substitute-replacement replacement
- evil-ex-substitute-flags flags)
- (let* ((inhibit-field-text-motion t)
- (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)
- (regex (evil-ex-pattern-regex pattern))
- (nreplaced 0)
- (orig-point (point-marker))
- (last-point (point))
- (whole-line (evil-ex-pattern-whole-line pattern))
- (evil-ex-substitute-overlay (make-overlay (point) (point)))
- (end-marker (move-marker (make-marker) end))
- (use-reveal confirm)
- match-data
- reveal-open-spots
- transient-mark-mode)
- (unwind-protect
- (catch 'exit-search
- (isearch-update-ring (setq isearch-string regex) t)
- (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)
- (while (re-search-forward regex end-marker t)
- (unless (and query-replace-skip-read-only
- (text-property-any (match-beginning 0) (match-end 0) 'read-only t))
- (let* ((match-beg (match-beginning 0))
- (match-end (match-end 0))
- (zero-length-match (= match-beg match-end))
- match-contains-newline)
- (goto-char match-beg)
- (when (and (= match-beg end-marker) (> end-marker beg) (bolp))
- ;; This line is not included due to range being exclusive
- (throw 'exit-search nil))
- (setq match-data (match-data t match-data)
- match-contains-newline (search-forward "\n" match-end t))
- (goto-char match-end)
- (if confirm
- (let* ((next-replacement
- (if (stringp replacement) replacement
- (funcall (car replacement) (cdr replacement) nreplaced)))
- (prompt
- (format "Replace %s with %s (y/n/a/q/l/^E/^Y)? "
- (match-string 0)
- (match-substitute-replacement
- next-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)
- (replace-match next-replacement (not case-replace)))
- (cl-incf nreplaced)
- (evil-ex-hl-set-region
- 'evil-ex-substitute
- (line-beginning-position 2)
- (evil-ex-hl-get-max 'evil-ex-substitute)))
- (cl-case response
- ((?y ?n) (throw 'exit-read-char nil))
- (?a (setq confirm nil)
- (throw 'exit-read-char nil))
- ((?q ?l ?\C-\[) (throw 'exit-search nil))
- (?\C-e (evil-scroll-line-down 1))
- (?\C-y (evil-scroll-line-up 1))))))
- (unless count-only
- (let ((next-replacement
- (if (stringp replacement) replacement
- (funcall (car replacement) (cdr replacement) nreplaced))))
- (set-match-data match-data)
- (replace-match next-replacement (not case-replace))))
- (cl-incf nreplaced))
- (setq last-point (point))
- (cond ((>= (point) end-marker)
- ;; Don't want to perform multiple replacements at the end
- ;; of the search region.
- (throw 'exit-search nil))
- ((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 (>= (point) end-marker) (throw 'exit-search nil)))
- ;; 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 regex end-marker t)
- (= pnt (point))))))
- (when (eobp) (throw 'exit-search nil))
- (forward-char)))))))
- (evil-ex-delete-hl 'evil-ex-substitute)
- (delete-overlay evil-ex-substitute-overlay)
- (goto-char (if count-only orig-point last-point))
- (move-marker orig-point nil)
- (move-marker end-marker nil)
-
- (when use-reveal
- (evil-revert-reveal reveal-open-spots)))
-
- (evil--ex-substitute-final-message nreplaced flags)
-
- (if (and (= nreplaced 0) evil-ex-point)
- (goto-char evil-ex-point)
- (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 "//~/&"))))
-
-(declare-function hi-lock-read-face-name "hi-lock")
-(evil-define-command evil-ex-match (args &optional bang)
- "Define a pattern to highlight in the current buffer.
-With no args, clear a highlight from the buffer
-With only an ! argument, clear all highlights from the buffer.
-With one arg, interpret as the pattern, and prompt for a face.
-With two args, interpret as :match {face} /{pattern}/.
-Unlike Vim, multiple highlights can be set at once, so there is no need for
-\":2match\" and \":3match\" Ex commands."
- (interactive "<a><!>")
- (unless args (setq args ""))
- (string-match "\\` *\\([^ ]+\\)? *\\(.+\\)?\\'" args)
- (let* ((face (match-string 1 args))
- (search-string (match-string 2 args))
- (raw-patterns (evil-delimited-arguments (or search-string face "")))
- (raw-pattern (or (car raw-patterns) ""))
- (case-fold-search ; ignore case if non-nil
- (eq (evil-ex-regex-case raw-pattern evil-ex-search-case) 'insensitive))
- search-upper-case ; bypass isearch-no-upper-case-p
- (pattern-no-case (evil-ex-regex-without-case raw-pattern))
- (pattern (if evil-ex-search-vim-style-regexp
- (evil-transform-vim-style-regexp pattern-no-case)
- pattern-no-case)))
- (cond
- ((or (not face) (string= "none" face))
- (if bang
- (hi-lock-unface-buffer t)
- (call-interactively #'hi-lock-unface-buffer)))
- ((/= 1 (length raw-patterns))
- (user-error "Invalid pattern argument"))
- ((not search-string)
- (require 'hi-lock)
- (hi-lock-face-buffer pattern (hi-lock-read-face-name)))
- (t (hi-lock-face-buffer pattern face)))))
-
-(defun evil-keep-lines (pattern beg end)
- "Stripped down version of `keep-lines'.
-Delete lines between BEG & END which don't match PATTERN."
- (goto-char (min beg end))
- (setq end
- (progn
- (save-excursion
- (goto-char (max beg end))
- (unless (or (bolp) (eobp))
- (forward-line 0))
- (point-marker))))
- (save-excursion
- (or (bolp) (forward-line 1))
- (let ((start (point)))
- (while (< (point) end)
- ;; Start is first char not preserved by previous match.
- (if (not (re-search-forward pattern end 'move))
- (delete-region start end)
- (let ((end (save-excursion (goto-char (match-beginning 0))
- (forward-line 0)
- (point))))
- ;; Now end is first char preserved by the new match.
- (if (< start end)
- (delete-region start end))))
-
- (setq start (save-excursion (forward-line 1) (point)))
- ;; If the match was empty, avoid matching again at same place.
- (and (< (point) end)
- (= (match-beginning 0) (match-end 0))
- (forward-char 1)))))
- (set-marker end nil)
- nil)
-
-(defun evil-flush-lines (pattern beg end)
- "Stripped down version of `flush-lines'.
-Delete lines between BEG & END which match PATTERN."
- (goto-char (min beg end))
- (setq end (copy-marker (max beg end)))
- (save-excursion
- (while (and (< (point) end)
- (re-search-forward pattern end t))
- (delete-region (save-excursion (goto-char (match-beginning 0))
- (forward-line 0)
- (point))
- (progn (forward-line 1) (point)))))
- (set-marker end nil))
-
-(defun evil--ex-performant-global-delete (beg end pattern invert)
- "Use fast functions for fast line deletion.
-Delete lines between BEG & END which match PATTERN.
-Use `evil-flush-lines' if INVERT is nil, or `evil-keep-lines' if not."
- (goto-char end)
- (re-search-backward pattern beg t)
- (let ((end-marker (point-marker)))
- (if invert
- (evil-keep-lines pattern beg end)
- (evil-flush-lines pattern beg end))
- (goto-char end-marker)
- (set-marker end-marker nil)))
-
-(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
- (let* ((case-fold-search
- (eq (evil-ex-regex-case pattern evil-ex-search-case) 'insensitive))
- (pattern (evil-ex-regex-without-case pattern))
- (command-form (evil-ex-parse command))
- (ex-delete (eq 'evil-ex-delete (evil-ex-completed-binding (nth 2 command-form))))
- (transient-mark-mode transient-mark-mode)
- (deactivate-mark deactivate-mark)
- markers)
- (when (and pattern command)
- (when evil-ex-search-vim-style-regexp
- (setq pattern (evil-transform-vim-style-regexp pattern)))
- (if (and ex-delete (not (nth 3 command-form)) (not (nth 1 command-form)))
- (evil--ex-performant-global-delete beg end pattern invert)
- (setq isearch-string pattern)
- (isearch-update-ring pattern t)
- (goto-char beg)
- (evil-move-beginning-of-line)
- (while (< (point) end)
- (let ((match (re-search-forward pattern (line-end-position) t)))
- (when (if invert (not match) match)
- (push (move-marker (make-marker)
- (or (and match (match-beginning 0))
- (line-beginning-position)))
- markers)))
- (forward-line))
- (setq markers (nreverse markers))
- (unwind-protect
- (evil-with-single-undo
- (let ((evil--ex-global-active-p t))
- (dolist (marker markers)
- (goto-char marker)
- (eval command-form t))))
- ;; ensure that all markers are deleted afterwards,
- ;; even in the event of failure
- (dolist (marker markers)
- (set-marker marker nil))
- (run-hooks 'evil-after-global-hook))))))
-
-(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>")
- ;; replace ^[ by escape
- (setq commands
- (vconcat (mapcar (lambda (ch) (if (eq ch ?) 'escape ch))
- commands)))
- (let (markers evil-called-from-ex-p prefix-arg current-prefix-arg)
- (goto-char beg)
- (beginning-of-line)
- (while (when (< (point) end)
- (push (point-marker) markers)
- (and (= (forward-line) 0) (bolp))))
- (setq markers (nreverse markers))
- (deactivate-mark)
- (evil-force-normal-state)
- (evil-with-single-undo
- (dolist (marker markers)
- (goto-char marker)
- (ignore-errors (execute-kbd-macro commands))
- (evil-force-normal-state)
- (set-marker marker nil)))))
-
-(evil-define-motion evil-goto-char (position)
- "Go to POSITION in the buffer.
-Default position is the beginning of the buffer."
- :jump t
- (interactive "<N>")
- (goto-char (or position (point-min))))
-
-(evil-define-operator evil-ex-line-number (beg end)
- "Print the last line number."
- :motion mark-whole-buffer
- :move-point nil
- (interactive "<r>")
- (evil-echo "%d" (count-lines (point-min) end)))
-
-(evil-define-command evil-show-file-info ()
- "Show 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
- (evil-echo "\"%s\" %d %slines --%s--" file nlines readonly perc)
- (evil-echo "%d lines --%s--" nlines perc))))
-
-(defvar sort-fold-case)
-(evil-define-operator evil-ex-sort (beg end &optional args reverse)
- "The Ex sort command.
-\[BEG,END]sort[!] [/PATTERN/] [b][i][u][r][n][x][o]
-The following additional options are supported:
-
- * i ignore case
- * u remove duplicate lines
- * r sort the contents of pattern
- * n sort by the first decimal number
- * x sort by the first hexadecimal number (with optional \"0x\" prefix)
- * o sort by the first octal number
- * b sort by the first binary number
-
-If a pattern is supplied without supplying the \"r\" option, sort
-the contents of the lines after skipping the pattern.
-If the pattern is empty, the last search pattern is used instead.
-
-The \"!\" argument means to sort in reverse order."
- :motion mark-whole-buffer
- :move-point nil
- (interactive "<r><a><!>")
- (unless args (setq args ""))
- (let ((inhibit-field-text-motion t)
- options sort-fold-case unique base sort-pat pat)
- ;; Handle arguments like
- ;; /[^,]*,/ n
- ;; and
- ;; nu
- (if (or (zerop (length args)) (memq (aref args 0) '(?i ?n ?x ?o ?b ?u ?r)))
- (setq options args)
- (setq args (evil-delimited-arguments args 2)
- ;; Use last search pattern when an empty pattern is provided
- pat (if (string= (car args) "")
- (evil-ex-pattern-regex evil-ex-search-pattern)
- (car args))
- options (cadr args)))
- (cl-loop
- for opt across options do
- (cond
- ((eq opt ?i) (setq sort-fold-case t))
- ((eq opt ?b) (setq base 2))
- ((eq opt ?o) (setq base 8))
- ((eq opt ?n) (setq base 10))
- ((eq opt ?x) (setq base 16))
- ((eq opt ?r) (setq sort-pat t))
- ((eq opt ?u) (setq unique t))
- ((eq opt ? ))
- (t (user-error "Invalid sort option `%c'" opt))))
- (evil-with-restriction beg end
- (goto-char beg)
- (let ((num-re
- (cond
- ((null base) nil)
- ((= base 2) "[01]+")
- ((= base 8) "[0-7]+")
- ((= base 10) "-?[0-9]+")
- ((= base 16) "\\(-\\)?\\(?:0x\\)?\\([0-9a-f]+\\)")))
- key-end)
- (sort-subr
- reverse
- #'forward-line
- #'end-of-line
- (lambda ()
- ;; Find the boundary of the key to match on the line
- (setq key-end (line-end-position))
- (and (> (length pat) 0)
- ;; When matching a pattern and one doesn't exist on the line,
- ;; skip the line
- (re-search-forward pat key-end 'move)
- sort-pat ; Otherwise go to the start of the key
- (progn (setq key-end (point))
- (goto-char (match-beginning 0))))
- ;; Return the key for the line when sorting numbers, otherwise let
- ;; `sort-subr' extract the key
- (when base
- (let ((case-fold-search t))
- (if (not (re-search-forward num-re key-end t))
- ;; When sorting numbers and a number doesn't exist on the
- ;; line, place it above all the numeric lines
- most-negative-fixnum
- (let ((num (string-to-number
- (buffer-substring
- (match-beginning (if (= base 16) 2 0))
- (match-end 0))
- base)))
- (if (and (= base 16) (match-beginning 1))
- (- num)
- num))))))
- ;; Only called when sorting lexicographically
- (lambda () (goto-char key-end))))
- (when unique
- (goto-char (point-min))
- (let ((case-fold-search sort-fold-case)
- prev-line-beg)
- (while (not (eobp))
- (if (and prev-line-beg
- (eq 0 (compare-buffer-substrings
- nil prev-line-beg (1- (point))
- nil (point) (line-end-position))))
- (delete-region (point) (line-beginning-position 2))
- (setq prev-line-beg (point))
- (forward-line)))))))
- (goto-char beg))
-
-;;; Window navigation
-
-(defvar evil--window-digit nil)
-
-(defun evil--window-keep-pred ()
- (eq 'evil-window-digit-argument this-command))
-
-(defun evil--window-reset-digit ()
- (setq evil--window-digit nil)
- (remove-hook 'post-command-hook #'evil--window-reset-digit))
-
-(defun evil--window-on-exit ()
- (add-hook 'post-command-hook #'evil--window-reset-digit))
-
-(defun evil-window-digit-argument ()
- "Like `digit-argument' but maintains the window map."
- (interactive)
- (unless (eq 'evil-window-digit-argument last-command)
- (set-transient-map evil-window-map #'evil--window-keep-pred #'evil--window-on-exit))
- (let* ((char (if (integerp last-command-event)
- last-command-event
- (get last-command-event 'ascii-character)))
- (digit (- (logand char ?\177) ?0)))
- (setq evil--window-digit (+ (* 10 (or evil--window-digit 0)) digit))))
-
-(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 (fboundp 'window-toggle-side-windows)
- (window-with-parameter 'window-side))))
- ;; The compiler doesn't understand that all uses are protected
- ;; by `fboundp' :-(
- (declare-function window-toggle-side-windows "window")
- (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.
-This is equivalent to Vim's alternate buffer."
- ;; If the last buffer visited has been killed, then `window-prev-buffers'
- ;; returns a list with `window-buffer' at the head.
- (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 the last open buffer of the current window."
- :repeat nil
- (let ((previous-place (evil-alternate-buffer)))
- (when previous-place
- (switch-to-buffer (car previous-place)))))
-
-(evil-define-command evil-window-delete ()
- "Delete the current window or tab.
-If `evil-auto-balance-windows' is non-nil then all children of
-the deleted window's parent window are rebalanced."
- (let ((p (window-parent)))
- ;; If tabs are enabled and this is the only visible window, then attempt to
- ;; close this tab.
- (if (and (bound-and-true-p tab-bar-mode)
- (null p))
- (tab-close)
- (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)
- (ignore-errors (balance-windows p))))))
-
-(evil-define-command evil-window-split (&optional count file read-only)
- "Split 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 "<wc><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
- (funcall (if read-only #'evil-view #'evil-edit) file)))
-
-(evil-define-command evil-window-split-view (&optional count file)
- "As with `evil-window-split' but the file is opened read-only."
- :repeat nil
- (interactive "<c><f>")
- (evil-window-split count file t))
-
-(evil-define-command evil-window-vsplit (&optional count file)
- "Split 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 "<wc><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)
- "Split window and switch to another buffer."
- :repeat nil
- (interactive "<b>")
- (evil-window-split)
- (evil-buffer buffer))
-
-(evil-define-command evil-split-next-buffer (&optional count)
- "Split the window and go to the COUNT-th next buffer in the buffer list."
- :repeat nil
- (interactive "p")
- (evil-window-split)
- (next-buffer count))
-
-(evil-define-command evil-split-prev-buffer (&optional count)
- "Split window and go to the COUNT-th prev buffer in the buffer list."
- :repeat nil
- (interactive "p")
- (evil-window-split)
- (previous-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 "<w>")
- (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 "<w>")
- (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 "<w>")
- (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 "<w>")
- (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 "<wc>")
- (if (not count)
- (other-window +1)
- (evil-window-top-left)
- (other-window (1- (min count (length (window-list)))))))
-
-(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 "<wc>")
- (if (not count)
- (other-window -1)
- (evil-window-top-left)
- (other-window (1- (min count (length (window-list)))))))
-
-(evil-define-command evil-window-new (count file)
- "Split the current window horizontally
-and open a new buffer or edit a certain FILE."
- :repeat nil
- (interactive "<wc><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)))
- (select-window new-window)
- (evil-buffer-new file)))
-
-(evil-define-command evil-window-vnew (count file)
- "Split the current window vertically
-and open a new buffer name or edit a certain FILE."
- :repeat nil
- (interactive "<wc><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)))
- (select-window new-window)
- (evil-buffer-new file)))
-
-(evil-define-command evil-buffer-new (&optional file)
- "Edit a new unnamed buffer or FILE."
- :repeat nil
- (interactive "<f>")
- (if file
- (evil-edit file)
- (let ((buffer (generate-new-buffer "*new*")))
- (set-buffer-major-mode buffer)
- (set-window-buffer nil buffer))))
-
-(evil-define-command evil-window-increase-height (count)
- "Increase current window height by COUNT."
- :repeat nil
- (interactive "<w>")
- (enlarge-window count))
-
-(evil-define-command evil-window-decrease-height (count)
- "Decrease current window height by COUNT."
- :repeat nil
- (interactive "<w>")
- (enlarge-window (- count)))
-
-(evil-define-command evil-window-increase-width (count)
- "Increase current window width by COUNT."
- :repeat nil
- (interactive "<w>")
- (enlarge-window count t))
-
-(evil-define-command evil-window-decrease-width (count)
- "Decrease current window width by COUNT."
- :repeat nil
- (interactive "<w>")
- (enlarge-window (- count) t))
-
-(evil-define-command evil-window-set-height (count)
- "Set the height of the current window to COUNT."
- :repeat nil
- (interactive "<wc>")
- (evil-resize-window (or count (frame-height)) nil))
-
-(evil-define-command evil-window-set-width (count)
- "Set the width of the current window to COUNT."
- :repeat nil
- (interactive "<wc>")
- (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 ()
- "Rotate 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 (window-list))))))
-
-(evil-define-command evil-window-rotate-downwards ()
- "Rotate 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 (car (window-list))))))
-
-(evil-define-command evil-window-exchange (&optional count)
- "Exchange the current window with the next, or the COUNT-th, one."
- :repeat nil
- (interactive "<wc>")
- (let ((original-window (selected-window)))
- (evil-window-next count)
- (if (fboundp 'window-swap-states)
- (window-swap-states nil original-window t)
- (let* ((other-window (selected-window))
- (original-state (window-state-get original-window))
- (other-state (window-state-get other-window)))
- (window-state-put other-state original-window t)
- (window-state-put original-state other-window t)))))
-
-(evil-define-command evil-window-move-very-top ()
- "Close the current window, split the upper-left one horizontally
-and redisplay the current buffer there."
- :repeat nil
- (evil-move-window 'above))
-
-(evil-define-command evil-window-move-far-left ()
- "Close the current window, split the upper-left one vertically
-and redisplay the current buffer there."
- :repeat nil
- (evil-move-window 'left))
-
-(evil-define-command evil-window-move-far-right ()
- "Close the current window, split the lower-right one vertically
-and redisplay the current buffer there."
- :repeat nil
- (evil-move-window 'right))
-
-(evil-define-command evil-window-move-very-bottom ()
- "Close the current window, split the lower-right one horizontally
-and redisplay the current buffer there."
- :repeat nil
- (evil-move-window 'below))
-
-;;; Tab commands
-
-(evil-define-command evil-tab-next (arg)
- "Switch to the next tab.
-If ARG is non-nil, parse ARG as an index and go to the tab at that
-index."
- :repeat nil
- (interactive "<c>")
- (if arg
- (tab-bar-select-tab arg)
- (tab-bar-switch-to-next-tab)))
-
-;;; 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)
-
-;; Make sure `touch-screen-handle-touch' processes touch screen gestures by
-;; ignoring `evil-mouse-drag-region' (bound to `down-mouse-1') during mouse
-;; click emulation.
-(put 'evil-mouse-drag-region 'ignored-mouse-command 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)))
-
- ;; Store the fact that the current region was set by the mouse
- (setq evil--region-from-mouse t)
-
- ;; 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))))))
-
-(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.")
-
-(evil-define-local-var evil--execute-normal-eol-pos nil
- "Point position if it was at EOL before `evil-execute-in-normal-state'.")
-
-(defun evil-execute-in-normal-state ()
- "Execute the next command in Normal state."
- (interactive)
- (let ((buf (current-buffer))
- (state evil-state))
- (evil-with-delay (not (memq this-command
- '(nil
- evil-execute-in-normal-state
- evil-replace-state
- evil-use-register
- evil-window-digit-argument
- digit-argument
- negative-argument
- universal-argument
- universal-argument-minus
- universal-argument-more
- universal-argument-other-key)))
- post-command-hook
- (with-current-buffer buf
- ;; If cursor was after EOL before CTRL-O and is now at EOL,
- ;; put it after EOL.
- (and (or (when evil--execute-normal-eol-pos
- (= (1+ (point)) (save-excursion
- (goto-char evil--execute-normal-eol-pos)
- (set-marker evil--execute-normal-eol-pos nil)
- (line-end-position))))
- (and (eq (or goal-column temporary-goal-column) most-positive-fixnum)
- (memq this-command '(next-line previous-line))))
- (not (eolp))
- (not (memq this-command
- '(evil-insert evil-beginning-of-line evil-first-non-blank)))
- (forward-char))
- (unless (memq evil-state '(replace insert))
- (evil-change-state 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-execute-normal-keys nil))))
- (setq evil-insert-count nil
- evil--execute-normal-return-state evil-state
- evil--execute-normal-eol-pos (when (eolp) (point-marker))
- evil-execute-normal-keys (this-command-keys))
- (let (evil-move-cursor-back) (evil-normal-state))
- (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)
-
-(evil-define-command evil-retab (tabstop)
- "Convert all tabs to spaces or the other way around.
-Replace all sequences of white-space containing a <Tab> with new
-strings of white-space using the new TABSTOP value given.
-If you do not specify a new TABSTOP size or it is zero, Evil uses the
-current value of `tab-width'."
- (interactive "<a>")
- (unless (or (not tabstop) (string-match-p "^[0-9]*$" tabstop))
- (user-error "Invalid argument: %s" tabstop))
- (let ((beg (if (use-region-p) (region-beginning) (point-min)))
- (end (if (use-region-p) (region-end) (point-max)))
- (retab (if indent-tabs-mode #'tabify #'untabify))
- (tab-width (cond ((not tabstop) tab-width)
- ((equal tabstop "0") tab-width)
- (t (string-to-number tabstop)))))
- (funcall retab beg end)))
-
-(provide 'evil-commands)
-
-;;; evil-commands.el ends here