Function: eglot--watch-globs

eglot--watch-globs is a byte-compiled function defined in eglot.el.gz.

Signature

(eglot--watch-globs SERVER ID GLOBS DIR IN-ROOT)

Documentation

Set up file watching for relative file names matching GLOBS under DIR.

GLOBS is a list of (COMPILED-GLOB . KIND) pairs, where COMPILED-GLOB is a compiled glob predicate and KIND is a bitmask of change types. DIR is the directory to watch (nil means entire project). IN-ROOT says if DIR happens to be inside or matching the project root.

Source Code

;; Defined in /usr/src/emacs/lisp/progmodes/eglot.el.gz
(cl-defun eglot--watch-globs (server id globs dir in-root
                                     &aux (project (eglot--project server))
                                     success)
  "Set up file watching for relative file names matching GLOBS under DIR.
GLOBS is a list of (COMPILED-GLOB . KIND) pairs, where COMPILED-GLOB is
a compiled glob predicate and KIND is a bitmask of change types.  DIR is
the directory to watch (nil means entire project).  IN-ROOT says if DIR
happens to be inside or matching the project root."
  (cl-labels
      ((subdirs-using-project ()
         (delete-dups
          (mapcar #'file-name-directory
                  (project-files project (and dir (list dir))))))
       (subdirs-using-find ()
         (with-temp-buffer
           (call-process find-program nil t nil dir "-type" "d" "-print0")
           (cl-loop initially (goto-char (point-min))
                    for start = (point) while (search-forward "\0" nil t)
                    collect (expand-file-name
                             (buffer-substring-no-properties start (1- (point)))
                             dir))))
       (handle-event (event)
         (pcase-let* ((`(,desc ,action ,file ,file1) event)
                      (action-type (cl-case action
                                     (created 1) (changed 2) (deleted 3)))
                      (action-bit (when action-type
                                    (ash 1 (1- action-type))))
                      (candidate (if dir (file-relative-name file dir) file)))
           (cond
            ((and (memq action '(created changed deleted))
                  (cl-loop for (compiled . kind) in globs
                           thereis (and (> (logand kind action-bit) 0)
                                        (funcall compiled candidate))))
             (jsonrpc-notify
              server :workspace/didChangeWatchedFiles
              `(:changes ,(vector `(:uri ,(eglot-path-to-uri file)
                                         :type ,action-type))))
             (when (and (eq action 'created)
                        (file-directory-p file))
               (add-watch file)))
            ((eq action 'renamed)
             (handle-event `(,desc deleted ,file))
             (handle-event `(,desc created ,file1))))))
       (add-watch (subdir)
         (when (file-readable-p subdir)
           (push (file-notify-add-watch subdir '(change) #'handle-event)
                 (gethash id (eglot--file-watches server))))))
    (let ((subdirs (if (or (null dir) in-root)
                       (subdirs-using-project)
                     (condition-case _ (subdirs-using-find)
                       (error (subdirs-using-project))))))
      (unwind-protect
          (cl-loop for sd in subdirs do (add-watch sd) finally (setq success t))
        (unless success
          (eglot-unregister-capability server 'workspace/didChangeWatchedFiles id))))))