diff options
Diffstat (limited to 'lisp')
-rw-r--r-- | lisp/progmodes/eglot.el | 41 |
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 ?^)) |