aboutsummaryrefslogtreecommitdiff
path: root/.config/emacs/lisp/evil/evil-ex.el
diff options
context:
space:
mode:
authorJack Jamison <jackqjamison@gmail.com>2026-07-30 20:09:00 -0400
committerJack Jamison <jackqjamison@gmail.com>2026-07-30 20:18:37 -0400
commit8c4e09dff83847ac7f07bf1da7751e9328006c4d (patch)
treea0e245567ce225f8bcb63b66e4d2373b5d033e4a /.config/emacs/lisp/evil/evil-ex.el
parent1e33b30749bb1043ffc6ceb5a2fb0977446788b3 (diff)
actual final changes and get rid of junk in lisp dir
actually works fine
Diffstat (limited to '.config/emacs/lisp/evil/evil-ex.el')
-rw-r--r--.config/emacs/lisp/evil/evil-ex.el940
1 files changed, 0 insertions, 940 deletions
diff --git a/.config/emacs/lisp/evil/evil-ex.el b/.config/emacs/lisp/evil/evil-ex.el
deleted file mode 100644
index 94edd6e..0000000
--- a/.config/emacs/lisp/evil/evil-ex.el
+++ /dev/null
@@ -1,940 +0,0 @@
-;;; evil-ex.el --- Ex mode -*- lexical-binding: t; -*-
-
-;; Author: Frank Fischer <frank fischer at mathematik.tu-chemnitz.de>
-;; 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/>.
-
-;;; Commentary:
-
-;; Ex is implemented as an extensible minilanguage, whose grammar
-;; is stored in `evil-ex-grammar'. Ex commands are defined with
-;; `evil-ex-define-cmd', which creates a binding from a string
-;; to an interactive function. It is also possible to define key
-;; sequences which execute a command immediately when entered:
-;; such shortcuts go in `evil-ex-shortcut-map'.
-
-;; To provide buffer and filename completion, as well as interactive
-;; feedback, Ex defines the concept of an argument handler, specified
-;; with `evil-ex-define-argument-type'. In the case of the
-;; substitution command (":s/foo/bar"), the handler incrementally
-;; highlights matches in the buffer as the substitution is typed.
-
-;;; Code:
-
-(require 'evil-common)
-(require 'evil-states)
-
-(declare-function evil-goto-line "evil-commands")
-
-(eval-when-compile
- (defconst evil-ex-grammar
- '((expression
- (count command argument #'evil-ex-call-command)
- ((\? range) command argument #'evil-ex-call-command)
- (line #'evil-goto-line)
- (sexp #'eval-expression))
- (count
- number)
- (command #'evil-ex-parse-command)
- (binding
- "[~&*@<>=:#]+\\|[[:alpha:]_]+\\|!")
- (emacs-binding
- "[[:alpha:]-][[:alnum:][:punct:]]*")
- (argument
- ((\? "\\(?:.\\|\n\\)+") #'$1))
- (range
- ("%" #'(evil-ex-full-range))
- ("*" #'(evil-ex-last-visual-range))
- ((\? line) "[,;]" (\? line)
- #'(let ((l1 $1))
- (save-excursion
- (and l1 (string= $2 ";") (goto-line l1))
- (evil-ex-range l1 $3))))
- (line #'evil-ex-range)
- ("`" marker-name ",`" marker-name
- #'(evil-ex-char-marker-range $2 $4)))
- (line
- ((\? base) (\? offset) search (\? offset)
- #'(save-excursion
- (goto-line (evil-ex-line $1 $2))
- (evil-ex-line $3 $4)))
- (base (\? offset) #'evil-ex-line)
- (nil offset #'evil-ex-line))
- (base
- number
- ("'" marker-name #'(evil-ex-marker $2))
- search
- ("\\^" #'(evil-ex-first-line))
- ("\\$" #'(evil-ex-last-line))
- ("\\." #'(evil-ex-current-line)))
- (offset
- (+ signed-number #'+))
- ;; TODO - handle offset & ;next-pattern search elements
- (search
- forward
- backward
- next
- prev
- subst)
- (forward
- ("/" "\\(?:\\\\.\\|[^/]\\)+" "/\\|$" #'(evil-ex-re-fwd $2)))
- (backward
- ("?" "\\(?:\\\\.\\|[^?]\\)+" "?\\|$" #'(evil-ex-re-bwd $2)))
- (marker-name
- "[]\\[-a-zA-Z_<>'}{)(]")
- (next
- "\\\\/" #'(evil-ex-prev-search))
- (prev
- "\\\\\\?" #'(evil-ex-prev-search))
- (subst
- "\\\\&" #'(evil-ex-prev-search))
- (signed-number
- (sign (\? number) #'evil-ex-signed-number))
- (sign
- "[+-]" #'intern)
- (number
- "[0-9]+" #'string-to-number)
- (sexp
- "(.*)?" #'(car (read-from-string $0))))
- "Grammar for Ex.
-An association list of syntactic symbols and their definitions.
-The first entry is the start symbol. A symbol's definition may
-reference other symbols, but the grammar cannot contain
-left recursion. See `evil-parser' for a detailed explanation
-of the syntax.")
-
- (defun evil-parser--dexp (obj)
- "Parse a numerical dollar-sign symbol.
-Given e.g. $4, return 4."
- (when (symbolp obj)
- (let ((str (symbol-name obj)))
- (when (string-match "\\`\\$\\([0-9]+\\)\\'" str)
- (string-to-number (match-string 1 str))))))
-
- (defmacro evil-parser (grammar &rest entrypoints)
- "Construct a parser for GRAMMAR with ENTRYPOINTS.
-The result is a function taking the arguments SYMBOL and SYNTAX, that
-parses the text after point. SYMBOL should be one of ENTRYPOINTS.
-
-If parsing succeeds, point is moved to the end of the parsed text and
-a 1-tuple (RESULT) is returned. Otherwise, the return value is nil.
-
-GRAMMAR is an association list of symbols and their definitions.
-A definition is a list of production rules, which are tried in
-succession. A production rule can be one of the following:
-
- nil matches the empty string.
- A regular expression matches a substring.
- A symbol matches a production for that symbol.
- (X Y) matches X followed by Y.
- (\\? X) matches zero or one of X.
- (* X) matches zero or more of X.
- (+ X) matches one or more of X.
- (& X) matches X, but does not consume.
- (! X) matches anything but X, but does not consume.
-
-Thus, a simple grammar may look like:
-
- ((plus \"\\\\+\") ; plus <- \"+\"
- (minus \"-\") ; minus <- \"-\"
- (operator plus minus)) ; operator <- plus / minus
-
-All input-consuming rules have a value. A regular expression evaluates
-to the text matched, while a list evaluates to a list of values.
-The value of a list may be overridden with a semantic action, which is
-specified with a #\\='-quoted expression at the end:
-
- (X Y #\\='foo)
-
-The value of this rule is the result of calling foo with the values
-of X and Y as arguments. Alternatively, the function call may be
-specified explicitly:
-
- (X Y #\\='(foo $1 $2))
-
-Here, $1 refers to X and $2 refers to Y. $0 refers to the whole list.
-Dollar expressions can also be used directly:
-
- (X Y #\\='$1)
-
-This matches X followed by Y, but ignores the value of Y;
-the value of the list is the same as the value of X.
-
-If the SYNTAX argument is non-nil, then all semantic actions
-are ignored, and a syntax tree is constructed instead. The
-syntax tree obeys the property that all the leaf nodes are
-parts of the input string. Thus, by traversing the syntax tree,
-one can determine how each character was parsed.
-
-The following symbols have reserved meanings within a grammar:
-`\\?', `*', `+', `&', `!', `function', `alt', `seq' and nil."
- (cl-labels
- ;; Return code for parsing PRODUCTION.
- ((compile
- (production)
- (pcase production
- ('nil '(list (when syntax (point)))) ; Epsilon
- ((and (pred stringp) regexp) ; Token
- `(when (progn
- (skip-chars-forward " \t\n\r") ; Ignore leading whitespace
- (looking-at ,regexp))
- (goto-char (match-end 0))
- (list (if syntax (point) (match-string 0)))))
- ((and (pred symbolp) symbol) ; Symbol
- `(let ((result (,symbol syntax)))
- (and syntax result (push ',symbol (car result)))
- result))
- (`(function ,fun) ; Function
- `(let ((result (funcall #',fun)))
- (and syntax result (setcar result (point)))
- result))
- ;; Positive lookahead
- (`(& . ,rule) `(when ,(compile rule) ,(compile nil)))
- ;; Negative lookahead
- (`(! . ,rule) `(unless ,(compile rule) ,(compile nil)))
- ;; Zero or one
- (`(\? . ,(or `(,rule) rule)) (compile `(alt ,rule nil)))
- ;; Zero or more
- (`(* . ,rules) (compile `(alt (+ ,@rules) nil)))
- ;; Lists
- ((or `(,(and (or '+ 'alt 'seq) symbol) . ,rules)
- (and (pred listp) rules (let symbol 'seq)))
- (let ((func (unless (eq symbol 'alt) #'list)))
- (pcase (when (> (length rules) 1) (car (last rules)))
- (`(function ,x) (setq func x
- rules (butlast rules))))
- `(let ((cell
- ,(pcase symbol
- ('+ ; One or more
- (when (cdr rules) (error "Too many `+' rules"))
- `(cl-loop for x = ,(compile (car rules))
- while x collect (car x) into result until (eobp)
- finally return (when result (list result))))
- ('alt `(or ,@(mapcar #'compile rules)))
- ('seq
- (cl-loop
- for rule in rules collect
- (macroexp-let2 nil x (compile rule)
- (if (memq (car-safe rule) '(& !)) x
- `(when ,x (push (car ,x) result))))
- into items finally return
- `(let ((pos (point)) result)
- (if (and ,@items) (list (nreverse result))
- (goto-char pos)
- nil)))))))
- ;; Semantic action
- (when (and ',func cell (not syntax))
- (setcar
- cell
- (let ((result (car cell)))
- (ignore result) ; Suppress unused var warning
- ,(pcase func
- ;; Dollar expression
- ((or (pred evil-parser--dexp) (pred listp))
- (dval func))
- ((pred symbolp)
- `(,(if (eq symbol 'alt) #'list #'cons) #',func result))
- (_ (error "Invalid semantic action `%S'" func))))))
- cell)))))
- ;; Substitute all dollar-sign symbols in X.
- ;; Each dollar-sign symbol is replaced with the corresponding
- ;; element in RESULT, so that $1 becomes the first element, etc.
- ;; The special value $0 is substituted with the whole list RESULT.
- (dval
- (x)
- (if (listp x) (cons #'list (mapcar #'dval x))
- (let ((num (evil-parser--dexp x)))
- (cond ((null num) `',x)
- ((eq num 0) 'result)
- (t `(nth (1- ,num) result)))))))
- `(lambda (symbol &optional syntax)
- (cl-labels
- (,@(cl-loop for (symbol . def) in (eval grammar t) collect
- `(,symbol (syntax) ,(compile `(alt . ,def))))
- (evil-ex-parse-command
- ()
- (let* ((result (binding nil))
- (command (car result)))
- (cond
- ((not result) nil)
- ;; Check whether the parsed command is followed by a slash,
- ;; dash or number and either the part before is NOT known to be
- ;; a binding, or the complete string IS known to be a binding.
- ((and (let ((ch (char-after)))
- (and ch (or (memq ch '(?- ?/)) (<= ?0 ch ?9))))
- (or (evil-ex-binding
- (concat command (buffer-substring (point) (point-max))) t)
- (not (evil-ex-binding command t))))
- (backward-char (length command))
- (emacs-binding nil))
- ;; Parse a following "!" as bang only if the command
- ;; has the property :ex-bang t.
- ((when (eq (char-after) ?!)
- (let ((binding (evil-ex-completed-binding command t)))
- (and binding (evil-get-command-property binding :ex-bang))))
- (forward-char)
- (setcar result (concat command "!"))
- result)
- (t result)))))
- (pcase symbol
- ,@(cl-loop for sym in entrypoints collect `(',sym ,(compile sym)))
- (_ (error "Unknown entrypoint `%s'" symbol))))))))
-
-(defvar evil-ex-argument-types nil
- "Association list of argument handlers.")
-
-(defvar evil-ex-commands nil
- "Association list of command bindings and functions.")
-
-(defvar evil-ex-reverse-range nil
- "Whether the current Ex range was entered reversed.")
-
-(defvar evil--ex-cmd nil
- "The current Ex command string.")
-
-(defvar evil--ex-argument-handler nil
- "The argument handler for the current Ex command.")
-
-(defvar evil--ex-shortcut-command nil
- "Interactive command to use instead of an Ex command.")
-
-(define-error 'evil-ex-error "Ex syntax error")
-
-(defun evil-ex-p ()
- "Return non-nil if currently in Ex state."
- (when evil-ex-original-buffer t))
-
-(evil-define-command evil-ex (&optional initial-input)
- "Enter an Ex command.
-The Ex command line is initialized with the value of INITIAL-INPUT. If
-the command is called interactively the initial input depends on the
-current state. In Normal state if a prefix count is given then the
-initial input is \".,.+count\", otherwise it is empty. In Visual state
-the initial input is the visual region '<,'> or `<,`>. The variable
-`evil-ex-initial-input', if non-nil, is appended to the line."
- :keep-visual t
- :repeat abort
- (interactive
- (let ((s (concat
- (cond
- ((and (evil-visual-state-p)
- evil-ex-visual-char-range
- (memq (evil-visual-type) '(inclusive exclusive)))
- "`<,`>")
- ((evil-visual-state-p) "'<,'>")
- (current-prefix-arg
- (let ((arg (prefix-numeric-value current-prefix-arg)))
- (cond ((< arg 0) (setq arg (1+ arg)))
- ((> arg 0) (setq arg (1- arg))))
- (if (= arg 0) "." (format ".,.%+d" arg)))))
- evil-ex-initial-input)))
- (list (unless (string= s "") s))))
- (let ((buffer (current-buffer))
- (previous-command (when evil-want-empty-ex-last-command
- (car evil-ex-history)))
- s evil--ex-cmd evil--ex-argument-handler evil--ex-shortcut-command)
- (minibuffer-with-setup-hook
- (lambda ()
- (setq-local evil-ex-original-buffer buffer)
- (evil-ex-setup)
- (if initial-input (evil--ex-update)
- (when previous-command
- (add-hook 'pre-command-hook #'evil-ex-remove-default nil t))))
- (setq s (read-from-minibuffer
- ":"
- (or initial-input
- (and previous-command (propertize previous-command 'face 'shadow)))
- evil-ex-completion-map nil 'evil-ex-history)))
- (if evil--ex-shortcut-command
- (call-interactively evil--ex-shortcut-command)
- (when (string= s "") (setq s previous-command))
- (unless (string= s "") (evil-ex-execute s)))))
-
-(defun evil-ex-execute (string)
- "Execute STRING as an Ex command."
- (eval (or (evil-ex-parse string) (signal 'evil-ex-error string)) t))
-
-(defun evil-ex-parse (&optional string syntax entrypoint)
- "Parse STRING as an Ex expression and return its evaluation tree.
-If STRING is nil, parse the text after point instead. If SYNTAX is
-non-nil, return a syntax tree instead. ENTRYPOINT is the start
-symbol, which defaults to `expression'."
- (if string
- (with-temp-buffer
- (insert string)
- (goto-char (point-min))
- (evil-ex-parse nil syntax entrypoint))
- (let ((result (funcall (evil-parser evil-ex-grammar expression range)
- (or entrypoint 'expression) syntax)))
- (and result
- ;; Disallow incomplete matches (ignore trailing WS)
- (not (search-forward "[^ \t\n\r]" nil t))
- (car result)))))
-
-(defun evil-ex-delete-backward-char ()
- "Close the minibuffer if it is empty, otherwise call `delete-backward-char'."
- (interactive)
- (call-interactively
- (if (< (minibuffer-prompt-end) (point-max))
- #'delete-backward-char
- #'abort-recursive-edit)))
-
-(cl-defstruct (evil-ex-argument-handler (:type list) (:constructor nil)
- (:copier nil) (:predicate nil))
- (runner nil :read-only t) (completer nil :read-only t))
-
-(defun evil-ex-setup ()
- "Initialize Ex minibuffer.
-This function registers hooks that are used for the interactive
-actions during Ex state."
- (add-hook 'after-change-functions #'evil--ex-update nil t)
- (add-hook 'minibuffer-exit-hook #'evil-ex-teardown nil t)
- (add-hook 'completion-at-point-functions #'evil-ex-completion-at-point nil t))
-
-(defsubst evil--ex-bang-p (command)
- "Return non-nil if the string COMMAND has a \"!\" suffix."
- (and (> (length command) 1) (eq (aref command (1- (length command))) ?!)))
-
-(defun evil--ex-update (&optional beg _end _old-len)
- "Update Ex variables when the minibuffer changes.
-This function is usually called from `after-change-functions'
-hook. If BEG is non-nil (which is the case when called from
-`after-change-functions'), then an error description is shown
-in case of incomplete or unknown commands."
- (when (and beg (eq this-command #'self-insert-command))
- (let ((cmd (lookup-key evil-ex-shortcut-map (minibuffer-contents-no-properties))))
- (when (commandp cmd)
- (setq evil--ex-shortcut-command cmd)
- (exit-minibuffer))))
-
- (setq evil--ex-cmd nil)
- (let ((expr (save-excursion (goto-char (minibuffer-prompt-end))
- (evil-ex-parse)))
- func handler current-prefix-arg evil-ex-range evil-ex-bang evil-ex-argument)
- (when (eq (car expr) #'evil-ex-call-command)
- (with-current-buffer evil-ex-original-buffer
- (let* ((range (eval (nth 1 expr) t))
- (count (when (integerp range) range)))
- (setq current-prefix-arg count
- evil-ex-range (if count (evil-ex-range count count) range)
- evil--ex-cmd (eval (nth 2 expr) t)
- evil-ex-bang (evil--ex-bang-p evil--ex-cmd)
- evil-ex-argument (eval (nth 3 expr) t))))
- (cond
- ((not beg))
- ;; Test the current command when called from `after-change-functions'
- ((setq func (evil-ex-completed-binding evil--ex-cmd t))
- ;; Update argument handler
- (let ((type (evil-get-command-property func :ex-arg)))
- (when type (setq handler (cdr (assq type evil-ex-argument-types)))))
- (if (eq handler evil--ex-argument-handler)
- (let ((runner (evil-ex-argument-handler-runner handler)))
- (when runner (funcall runner 'update evil-ex-argument)))
- (let ((runner (evil-ex-argument-handler-runner evil--ex-argument-handler)))
- (when runner (funcall runner 'stop)))
- (setq evil--ex-argument-handler handler)
- (let ((runner (evil-ex-argument-handler-runner handler)))
- (when runner (funcall runner 'start evil-ex-argument)))))
- (t (let* ((evil-ex-complete-emacs-commands 'in-turn)
- (prefix (try-completion evil--ex-cmd (evil-ex-completion-table))))
- (cond ((stringp prefix) (evil-ex-echo "Incomplete command"))
- ((null prefix) (evil-ex-echo "Unknown command")))))))))
-
-(defun evil-ex-teardown ()
- "Deinitialize Ex minibuffer.
-Clean up everything set up by `evil-ex-setup'."
- (let ((runner (evil-ex-argument-handler-runner evil--ex-argument-handler)))
- (when runner (funcall runner 'stop))))
-
-(defvar-local evil--ex-echo-overlay nil
- "Overlay for displaying info messages during Ex.")
-
-(defun evil-ex-echo (string &rest args)
- "Display a message after the current Ex command."
- ;; Differs from minibuffer-message, which see, in that it does not
- ;; use sit-for, since it may be called in the middle of a command.
- (unless (or evil-no-display (zerop (length string)))
- (let ((string (concat " [" (apply #'format string args) "]")))
- (put-text-property 0 1 'cursor t string) ; Place cursor before message
- (put-text-property 1 (length string) 'face 'evil-ex-info string)
- (with-selected-window (minibuffer-window)
- (if evil--ex-echo-overlay
- (move-overlay evil--ex-echo-overlay (point-max) (point-max))
- (setq evil--ex-echo-overlay (make-overlay (point-max) (point-max) nil t t)))
- (add-hook 'pre-command-hook #'evil--ex-remove-echo-overlay nil t)
- (overlay-put evil--ex-echo-overlay 'after-string string)))))
-
-(defun evil--ex-remove-echo-overlay ()
- "Remove echo overlay from Ex minibuffer."
- (delete-overlay evil--ex-echo-overlay)
- (setq evil--ex-echo-overlay nil)
- (remove-hook 'pre-command-hook #'evil--ex-remove-echo-overlay t))
-
-(cl-defun evil-ex-completion-at-point ()
- "Function used for `completion-at-point-functions' in Ex state."
- (cl-flet ((fix-beg (b) (min (save-excursion
- (+ (goto-char b) (skip-chars-forward " \t\n\r")))
- (point))))
- (pcase (nreverse (evil--ex-syntactic-context))
- ((or (and 'nil (let beg (minibuffer-prompt-end)))
- `((expression) (command . ,beg) . ,_)
- (and `((expression) (line) . ,_)
- (guard (looking-at-p "[ \t\n\r]*\\'"))
- (let beg (point))))
- (list (fix-beg beg) (point) (evil-ex-completion-table)))
- (`((expression) (argument . ,beg))
- (setq beg (fix-beg beg))
- ;; If it's an autoload, load the function; this allows external
- ;; packages to register autoloaded Ex commands which will be
- ;; loaded when ex argument completion is triggered.
- (let ((binding (evil-ex-binding evil--ex-cmd t))) (autoload-do-load binding))
-
- (let* ((binding (evil-ex-completed-binding evil--ex-cmd))
- (arg-type (evil-get-command-property binding :ex-arg))
- (arg-handler (cdr (assq arg-type evil-ex-argument-types))))
- (pcase (evil-ex-argument-handler-completer arg-handler)
- (`(collection . ,table) (list beg (point-max) table))
- (`(completion-at-point . ,completer)
- (save-restriction (narrow-to-region beg (point-max))
- (funcall completer))))))
- (`((expression) (sexp . ,_))
- (when (fboundp 'elisp-completion-at-point) (elisp-completion-at-point))))))
-
-(defun evil-ex-completion-table ()
- (let ((ex-cmds
- (cl-loop
- for (cmd . fun) in evil-ex-commands unless (stringp fun)
- collect cmd
- ;; Append ! to all commands that may take a bang argument
- when (evil-get-command-property fun :ex-bang)
- collect (concat cmd "!")))
- (emacs-cmds (lambda (str pred action)
- (completion-table-with-predicate
- obarray #'commandp t str pred action))))
- (cond
- ((null evil-ex-complete-emacs-commands) ex-cmds)
- ((eq evil-ex-complete-emacs-commands 'in-turn)
- (completion-table-in-turn ex-cmds emacs-cmds))
- (t (cl-loop for s in-ref ex-cmds do
- (setf s (propertize s 'face 'evil-ex-commands)))
- (evil-completion-table-concat ex-cmds emacs-cmds)))))
-
-(defun evil-completion-table-concat (table1 table2)
- (lambda (string pred action)
- (cond
- ((null action)
- (let (matches)
- (dolist (table (list table1 table2) (try-completion string matches))
- (let ((x (try-completion string table pred)))
- (when x (push (if (eq x 't) string x) matches))))))
- ((eq action t)
- (delete-dups
- (append (all-completions string table1 pred)
- (all-completions string table2 pred))))
- ((eq action 'lambda)
- (when (or (test-completion string table1 pred)
- (test-completion string table2 pred))
- t))
- ((eq (car-safe action) 'boundaries)
- (or (completion-boundaries string table1 pred (cdr action))
- (completion-boundaries string table2 pred (cdr action))))
- ((eq action 'metadata)
- '(metadata (display-sort-function . evil-ex-sort-completions))))))
-
-(defun evil-ex-sort-completions (completions)
- (sort completions
- (lambda (str1 str2)
- (let ((p1 (eq (get-text-property 0 'face str1) 'evil-ex-commands))
- (p2 (eq (get-text-property 0 'face str2) 'evil-ex-commands)))
- (if (eq p1 p2) (string< str1 str2) p1)))))
-
-(define-obsolete-function-alias 'evil-ex-completion #'completion-at-point "1.15.0")
-
-(define-obsolete-function-alias
- 'evil-ex-command-completion-at-point #'evil-ex-completion-at-point "1.15.0")
-
-(defalias 'evil-ex-argument-completion-at-point #'ignore)
-(make-obsolete
- 'evil-ex-argument-completion-at-point #'evil-ex-completion-at-point "1.15.0")
-
-(define-obsolete-function-alias
- 'evil-ex-elisp-completion-at-point #'elisp-completion-at-point "1.15.0")
-
-(defun evil-ex-define-cmd (cmd function)
- "Bind the function FUNCTION to the command CMD."
- (if (not (string-match-p "\\[" cmd))
- (evil--add-to-alist evil-ex-commands cmd function)
- (string-match "\\(.*\\)\\[\\(.*\\)\\]" cmd)
- (let ((mandatory (match-string 1 cmd))
- (optional (match-string 2 cmd)))
- (dotimes (n (1+ (length optional)))
- (evil--add-to-alist evil-ex-commands
- (concat mandatory (substring optional 0 n))
- function)))))
-
-(defmacro evil-ex-define-argument-type (arg-type doc &rest body)
- "Define a new handler for argument-type ARG-TYPE.
-DOC is the documentation string. It is followed by a list of keywords
-and function:
-
-:collection COLLECTION
-
- A collection for completion as required by `all-completions'.
-
-:completion-at-point FUNC
-
- Function to be called to initialize a potential completion. FUNC
- must match the requirements as described for the variable
- `completion-at-point-functions'. When FUNC is called the minibuffer
- content is narrowed to exactly match the argument.
-
-:runner FUNC
-
- Function to be called when the type of the current argument changes
- or when the content of this argument changes. This function should
- take one obligatory argument FLAG followed by an optional argument
- ARG. FLAG is one of three symbol `start', `stop' or `update'. When
- the argument type is recognized for the first time and this handler
- is started the FLAG is `start'. If the argument type changes to
- something else or ex state finished the handler FLAG is `stop'. If
- the content of the argument has changed FLAG is `update'. If FLAG is
- either `start' or `update' then ARG is the current value of this
- argument. If FLAG is `stop' then arg is nil."
- (declare (indent defun)
- (doc-string 2)
- (debug (&define name
- [&optional stringp]
- [&rest [keywordp function-form]])))
- (unless (stringp doc) (push doc body))
- (let (runner completer)
- (while (keywordp (car body))
- (let ((key (pop body))
- (func (pop body)))
- (cond
- ((eq key :runner)
- (setq runner `#',func))
- ((eq key :collection)
- (setq completer `(cons 'collection #',func)))
- ((eq key :completion-at-point)
- (setq completer `(cons 'completion-at-point #',func))))))
- `(evil--add-to-alist evil-ex-argument-types
- ',arg-type (list ,runner ,completer))))
-
-(evil-ex-define-argument-type file
- "Handle a file argument."
- :collection read-file-name-internal)
-
-(evil-ex-define-argument-type buffer
- "Called to complete a buffer name argument."
- :collection internal-complete-buffer)
-
-(declare-function comint-completion-at-point "comint")
-(declare-function shell-completion-vars "shell" ())
-
-(defvar-local evil--ex-shell-argument-initialized nil
- "This variable is set to t if shell command completion has been initialized.
-See `evil-ex-init-shell-argument-completion'.")
-
-(defun evil-ex-init-shell-argument-completion (flag &optional _arg)
- "Prepare the current minibuffer for completion of shell commands.
-This function must be called from the :runner function of some
-argument handler that requires shell completion."
- (when (and (eq flag 'start)
- (not evil--ex-shell-argument-initialized))
- (setq evil--ex-shell-argument-initialized t)
- (require 'shell)
- ;; Set up Comint for Shell mode, except
- ;; `comint-completion-at-point' will be called manually.
- (shell-completion-vars)
- (remove-hook 'completion-at-point-functions #'comint-completion-at-point t)))
-
-(evil-ex-define-argument-type shell
- "Shell argument type, supports completion."
- :completion-at-point comint-completion-at-point
- :runner evil-ex-init-shell-argument-completion)
-
-(defun evil-ex-file-or-shell-command-completion-at-point ()
- (if (eq (char-after (point-min)) ?!)
- (save-restriction
- (narrow-to-region (1+ (point-min)) (point-max))
- (comint-completion-at-point))
- (list (point-min) (point-max) #'read-file-name-internal)))
-
-(evil-ex-define-argument-type file-or-shell
- "File or shell argument type.
-If the current argument starts with a ! the rest of the argument
-is considered a shell command, otherwise a file-name. Completion
-works accordingly."
- :completion-at-point evil-ex-file-or-shell-command-completion-at-point
- :runner evil-ex-init-shell-argument-completion)
-
-(defun evil-ex-binding (command &optional noerror)
- "Return the final binding of COMMAND."
- (let ((binding (if (evil--ex-bang-p command) (substring command 0 -1)
- command)))
- (while (stringp
- (setq binding (cdr (assoc binding evil-ex-commands)))))
- (unless binding (setq binding (intern-soft command)))
- (if (commandp binding)
- (or (command-remapping binding) binding)
- (unless noerror (user-error "Unknown command: `%s'" command)))))
-
-(defun evil-ex-completed-binding (command &optional noerror)
- "Return the final binding of the completion of COMMAND."
- (let ((completion (try-completion command evil-ex-commands)))
- (evil-ex-binding (if (eq completion t) command
- (or completion command))
- noerror)))
-
-;; TODO: extensions like :p :~ <cfile> ...
-(defun evil-ex-replace-special-filenames (file-name)
- "Replace special symbols in FILE-NAME.
-Replaces % by the current file-name,
-Replaces # by the alternate file-name in FILE-NAME."
- (let ((remote (file-remote-p file-name))
- (current-fname (buffer-file-name))
- (alternate-fname (and (other-buffer)
- (buffer-file-name (other-buffer)))))
- (setq file-name (or (file-remote-p file-name 'localname) file-name))
- (when current-fname
- (setq current-fname (or (file-remote-p current-fname 'localname)
- current-fname))
- (setq file-name
- (replace-regexp-in-string "\\(^\\|[^\\\\]\\)\\(%\\)"
- current-fname file-name
- t t 2)))
- (when alternate-fname
- (setq alternate-fname (or (file-remote-p alternate-fname 'localname)
- alternate-fname))
- (setq file-name
- (replace-regexp-in-string "\\(^\\|[^\\\\]\\)\\(#\\)"
- alternate-fname file-name
- t t 2)))
- (setq file-name
- (replace-regexp-in-string "\\\\\\([#%]\\)"
- "\\1" file-name t))
- (setq file-name (concat remote file-name)))
- file-name)
-
-(defun evil-ex-file-arg ()
- "Return the current Ex argument as a file name.
-This function interprets special file names like # and %."
- (unless (zerop (length evil-ex-argument))
- (evil-ex-replace-special-filenames evil-ex-argument)))
-
-(define-error 'evil-ex-no-previous-cmd "No previous command line")
-
-(defun evil-ex-repeat (&optional count)
- "Repeat the last Ex command."
- (interactive "P")
- (when count
- (goto-char (point-min))
- (forward-line (1- count)))
- (cl-loop
- with evil-ex-original-buffer = (current-buffer)
- for last-cmd in evil-ex-history do
- (condition-case nil
- (cl-return (let (evil-ex-history) (evil-ex-execute last-cmd)))
- (evil-ex-no-previous-cmd))
- finally (signal 'evil-ex-no-previous-cmd nil)))
-
-(defun evil-ex-call-command (range command argument)
- "Execute the given command COMMAND."
- (when evil-ex-reverse-range
- (setq evil-ex-reverse-range nil)
- (unless (y-or-n-p "Backward range given, OK to swap? ")
- (user-error "")))
- (let* ((count (when (integerp range) range))
- (current-prefix-arg count)
- (evil-ex-range (if count (evil-ex-range count count) range))
- (cmd (evil-ex-completed-binding command))
- (evil-ex-bang (evil--ex-bang-p command))
- (evil-ex-argument argument)
- (evil-this-type (evil-type evil-ex-range))
- (evil-ex-point (point))
- (restore-point
- (and evil-ex-range
- (evil-get-command-property cmd :restore-point)
- (if (evil-visual-state-p) evil-visual-beginning evil-ex-point)))
- (evil-called-from-ex-p t))
- (evil-exit-visual-state)
- (deactivate-mark)
- (when evil-ex-range
- ;; Set region if an explicit range has been specified
- (cl-destructuring-bind (beg end &rest) (evil-expand-range evil-ex-range t)
- (goto-char beg)
- (set-marker (mark-marker) end)))
- (setq this-command cmd)
- (let ((mark-active evil-ex-range))
- (run-hooks 'pre-command-hook)
- (call-interactively cmd))
- (run-hooks 'post-command-hook)
- (when restore-point (goto-char restore-point))))
-
-(defun evil-ex-line (base &optional offset)
- "Return the line number of BASE plus OFFSET."
- (+ (or base (line-number-at-pos))
- (or offset 0)))
-
-(defun evil-ex-first-line ()
- "Return the line number of the first line."
- (line-number-at-pos (point-min)))
-
-(defun evil-ex-current-line ()
- "Return the line number of the current line."
- (line-number-at-pos))
-
-(defun evil-ex-last-line ()
- "Return the line number of the last line."
- (save-excursion
- (goto-char (point-max))
- (when (bolp)
- (forward-line -1))
- (line-number-at-pos)))
-
-(defun evil-ex-range (beg-line &optional end-line)
- "Return the first and last position of the current range."
- (let* ((beg (if beg-line (evil-line-position beg-line)
- (line-beginning-position)))
- (end (if end-line (evil-line-position (1+ end-line))
- (save-excursion (goto-char beg) (line-beginning-position 2)))))
- (when (< end beg)
- (setq evil-ex-reverse-range t)
- (evil-swap beg end))
- (evil-range beg end 'line :expanded t)))
-
-(defun evil-ex-full-range ()
- "Return a range encompassing the whole buffer."
- (evil-range (point-min) (point-max) 'line :expanded t))
-
-(defun evil-ex-last-visual-range ()
- "Return a linewise range of the last visual selection."
- (evil-range evil-visual-mark evil-visual-point 'line))
-
-(defun evil-ex-marker (marker)
- "Return MARKER's line number in the current buffer.
-Signal an error if MARKER is in a different buffer."
- (setq marker (evil-get-marker
- (if (stringp marker) (aref marker 0) marker)))
- (if (numberp marker)
- (line-number-at-pos marker)
- (user-error "Ex does not support markers in other files")))
-
-(defun evil-ex-char-marker-range (beg end)
- (setq beg (evil-get-marker (if (stringp beg) (aref beg 0) beg))
- end (evil-get-marker (if (stringp end) (aref end 0) end)))
- (unless (and (numberp beg) (numberp end))
- (user-error "Ex does not support markers in other files"))
- (evil-expand-range
- (evil-range beg end
- (if (evil-visual-state-p)
- (evil-visual-type)
- 'inclusive))))
-
-(declare-function evil-ex-make-search-pattern "evil-search")
-
-(defun evil-ex-re-fwd (pattern)
- "Search forward for PATTERN.
-Return the line number of the match."
- (when evil-ex-search-vim-style-regexp
- (setq pattern (evil-transform-vim-style-regexp pattern)))
- (set-text-properties 0 (length pattern) nil pattern)
- (setq evil-ex-search-pattern (evil-ex-make-search-pattern pattern)
- evil-ex-search-direction 'forward)
- (condition-case err
- (save-excursion
- (evil-move-beginning-of-line 2)
- (when (or (re-search-forward pattern nil t)
- (progn
- (goto-char (point-min))
- (re-search-forward pattern nil t)))
- (line-number-at-pos (match-beginning 0))))
- (invalid-regexp
- (evil-ex-echo (cadr err))
- nil)))
-
-(defun evil-ex-re-bwd (pattern)
- "Search backward for PATTERN.
-Return the line number of the match."
- (when evil-ex-search-vim-style-regexp
- (setq pattern (evil-transform-vim-style-regexp pattern)))
- (set-text-properties 0 (length pattern) nil pattern)
- (setq evil-ex-search-pattern (evil-ex-make-search-pattern pattern)
- evil-ex-search-direction 'backward)
- (condition-case err
- (save-excursion
- (evil-move-beginning-of-line)
- (when (or (re-search-backward pattern nil t)
- (progn
- (goto-char (point-max))
- (re-search-backward pattern nil t)))
- (line-number-at-pos (match-beginning 0))))
- (invalid-regexp
- (evil-ex-echo (cadr err))
- nil)))
-
-(defun evil-ex-prev-search ()
- (error "Previous search not yet implemented"))
-
-(defun evil-ex-signed-number (sign &optional number)
- "Return a signed number like -3 and +1.
-NUMBER defaults to 1."
- (funcall sign (or number 1)))
-
-(defun evil-ex-command-force-p (command)
- "Whether COMMAND accepts the bang argument."
- (declare (obsolete evil-get-command-property "1.15.0"))
- (let ((binding (evil-ex-completed-binding command t)))
- (when binding
- (evil-get-command-property binding :ex-bang))))
-
-(cl-defun evil--ex-syntactic-context
- (&optional (pos (point))
- (tree (save-excursion (goto-char (minibuffer-prompt-end))
- (evil-ex-parse nil t)))
- &aux i result)
- "Return the syntactical context in TREE of the character at POS.
-POS defaults to the current position of point."
- ;; Iterate over syntax tree leaves (i.e. the strings), and return
- ;; the path to the leaf containing the cursor. Or, if not found,
- ;; e.g. because of trailing whitespace, the leaf at most one char
- ;; past the rightmost non-empty string.
- (cl-labels
- ((traverse
- (node path)
- (while (and (consp node) (symbolp (car node)))
- (push (cons (pop node) i) path))
- (if (listp node)
- (dolist (child node) (traverse child path))
- ;; NODE is the end position of a parsed string
- (when (>= node pos) (cl-return-from evil--ex-syntactic-context path))
- (when (or (null result) (> node i))
- (setq i node
- result path)))))
- (traverse tree ()))
- result)
-
-(provide 'evil-ex)
-
-;;; evil-ex.el ends here