summaryrefslogtreecommitdiff
path: root/lisp
diff options
context:
space:
mode:
Diffstat (limited to 'lisp')
-rw-r--r--lisp/progmodes/eglot.el41
1 files changed, 28 insertions, 13 deletions
diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el
index 5845aff39b7..31948a12d69 100644
--- a/lisp/progmodes/eglot.el
+++ b/lisp/progmodes/eglot.el
@@ -3879,7 +3879,7 @@ at point. With prefix argument, prompt for ACTION-KIND."
with grammar = '((:** "\\*\\*/?" eglot--glob-emit-**)
(:* "\\*" eglot--glob-emit-*)
(:? "\\?" eglot--glob-emit-?)
- (:{} "{[^][*{}]+}" eglot--glob-emit-{})
+ (:{} "{[^{}]+}" eglot--glob-emit-{})
(:range "\\[\\^?[^][/,*{}]+\\]" eglot--glob-emit-range)
(:literal "[^][,*?{}]+" eglot--glob-emit-self))
until (eobp)
@@ -3889,20 +3889,25 @@ at point. With prefix argument, prompt for ACTION-KIND."
(list (cl-gensym "state-") emitter (match-string 0)))
finally (error "Glob '%s' invalid at %s" (buffer-string) (point))))))
+(cl-defun eglot--glob-fsm (states &key (exit 'eobp) noerror)
+ `(cl-labels ,(cl-loop for (this that) on states
+ for (self emit text) = this
+ for next = (or (car that) exit)
+ collect (funcall emit text self next))
+ ,(if noerror
+ `(,(caar states))
+ `(or (,(caar states))
+ (error "Glob done but more unmatched text: '%s'"
+ (buffer-substring (point) (point-max)))))))
+
(defun eglot--glob-compile (glob &optional byte-compile noerror)
"Convert GLOB into Elisp function. Maybe BYTE-COMPILE it.
If NOERROR, return predicate, else erroring function."
- (let* ((states (eglot--glob-parse glob))
+ (let* ((states (eglot--glob-parse glob))
(body `(with-current-buffer (get-buffer-create " *eglot-glob-matcher*")
(erase-buffer)
(save-excursion (insert string))
- (cl-labels ,(cl-loop for (this that) on states
- for (self emit text) = this
- for next = (or (car that) 'eobp)
- collect (funcall emit text self next))
- (or (,(caar states))
- (error "Glob done but more unmatched text: '%s'"
- (buffer-substring (point) (point-max)))))))
+ ,(eglot--glob-fsm states)))
(form `(lambda (string) ,(if noerror `(ignore-errors ,body) body))))
(if byte-compile (byte-compile form) form)))
@@ -3922,10 +3927,20 @@ If NOERROR, return predicate, else erroring function."
(defun eglot--glob-emit-{} (arg self next)
(let ((alternatives (split-string (substring arg 1 (1- (length arg))) ",")))
- `(,self ()
- (or (re-search-forward ,(concat "\\=" (regexp-opt alternatives)) nil t)
- (error "Failed matching any of %s" ',alternatives))
- (,next))))
+ (if (cl-notany (lambda (a) (string-match "\\*" a)) alternatives)
+ `(,self ()
+ (or (re-search-forward ,(concat "\\=" (regexp-opt alternatives)) nil t)
+ (error "No alternatives match: %s" ',alternatives))
+ (,next))
+ (let ((fsms (mapcar (lambda (a)
+ `(save-excursion
+ (ignore-errors
+ ,(eglot--glob-fsm (eglot--glob-parse a)
+ :exit next :noerror t))))
+ alternatives)))
+ `(,self ()
+ (or ,@fsms
+ (error "Glob match fail after alternatives %s" ',alternatives)))))))
(defun eglot--glob-emit-range (arg self next)
(when (eq ?! (aref arg 1)) (aset arg 1 ?^))