diff --git a/doc/emacs/buffers.texi b/doc/emacs/buffers.texi index 7b4e070d1b9..fc2ee6f638d 100644 --- a/doc/emacs/buffers.texi +++ b/doc/emacs/buffers.texi @@ -13,6 +13,10 @@ the directory listing. If you send a message with @kbd{C-x m}, a buffer is used to hold the text of the message. When you ask for a command's documentation, that appears in a buffer named @file{*Help*}. + Buffers exist as long as they are in use, and are deleted +(``killed'') when no longer needed, either by you (@pxref{Kill +Buffer}) or by Emacs (e.g., when you exit Emacs, @pxref{Exiting}). + Each buffer has a unique name, which can be of any length. When a buffer is displayed in a window, its name is shown in the mode line (@pxref{Mode Line}). The distinction between upper and lower case diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el index e21600ffe09..74c2bf91c41 100644 --- a/lisp/progmodes/project.el +++ b/lisp/progmodes/project.el @@ -262,8 +262,15 @@ backend implementation of `project-external-roots'.") (defun project-try-vc (dir) (let* ((backend (ignore-errors (vc-responsible-backend dir))) - (root (and backend (ignore-errors - (vc-call-backend backend 'root dir))))) + (root + (pcase backend + ('Git + ;; Don't stop at submodule boundary. + (or (vc-file-getprop dir 'project-git-root) + (vc-file-setprop dir 'project-git-root + (vc-find-root dir ".git/")))) + ('nil nil) + (_ (ignore-errors (vc-call-backend backend 'root dir)))))) (and root (cons 'vc root)))) (cl-defmethod project-roots ((project (head vc))) @@ -303,7 +310,8 @@ backend implementation of `project-external-roots'.") (pcase backend (`Git (let ((default-directory (expand-file-name (file-name-as-directory dir))) - (args '("-z"))) + (args '("-z")) + files) ;; Include unregistered. (setq args (append args '("-c" "-o" "--exclude-standard"))) (when extra-ignores @@ -315,11 +323,26 @@ backend implementation of `project-external-roots'.") (format ":!/:%s" (substring i 2)) (format ":!:%s" i))) extra-ignores))))) - (mapcar - (lambda (file) (concat default-directory file)) - (split-string - (apply #'vc-git--run-command-string nil "ls-files" args) - "\0" t)))) + (setq files + (mapcar + (lambda (file) (concat default-directory file)) + (split-string + (apply #'vc-git--run-command-string nil "ls-files" args) + "\0" t))) + ;; Unfortunately, 'ls-files --recurse-submodules' conflicts with '-o'. + (let* ((submodules (project--git-submodules)) + (sub-files + (mapcar + (lambda (module) + (when (file-directory-p module) + (project--vc-list-files + (concat default-directory module) + backend + extra-ignores))) + submodules))) + (setq files + (apply #'nconc files sub-files))) + files)) (`Hg (let ((default-directory (expand-file-name (file-name-as-directory dir))) args) @@ -337,6 +360,18 @@ backend implementation of `project-external-roots'.") (lambda (s) (concat default-directory s)) (split-string (buffer-string) "\0" t))))))) +(defun project--git-submodules () + ;; 'git submodule foreach' is much slower. + (condition-case nil + (with-temp-buffer + (insert-file-contents ".gitmodules") + (let (res) + (goto-char (point-min)) + (while (re-search-forward "path *= *\\(.+\\)" nil t) + (push (match-string 1) res)) + (nreverse res))) + (file-missing nil))) + (cl-defmethod project-ignores ((project (head vc)) dir) (let* ((root (cdr project)) backend) @@ -485,7 +520,7 @@ pattern to search for." (buffer-substring (point-min) (line-end-position)))) (while (re-search-forward grep-re nil t) (push (list (string-to-number (match-string line-group)) - (concat remote-id (match-string file-group)) + (match-string file-group) (buffer-substring-no-properties (point) (line-end-position))) hits))) (setq xrefs (xref--convert-hits (nreverse hits) regexp)) diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el index 13a1600594f..bbd3940be4f 100644 --- a/lisp/progmodes/xref.el +++ b/lisp/progmodes/xref.el @@ -1291,8 +1291,11 @@ Such as the current syntax table and the applied syntax properties." (defun xref--collect-matches (hit regexp tmp-buffer) (pcase-let* ((`(,line ,file ,text) hit) - (file (and file (concat (file-remote-p default-directory) file))) - (buf (xref--find-buffer-visiting file)) + (remote-id (file-remote-p default-directory)) + (file (and file (concat remote-id file))) + (buf (unless remote-id + ;; find-buffer-visiting is slow on remote. + (xref--find-buffer-visiting file))) (syntax-needed (xref--regexp-syntax-dependent-p regexp))) (if buf (with-current-buffer buf