From: Dmitry Gutov Date: Sun, 12 Jul 2015 14:18:09 +0000 (+0300) Subject: Add `project-ignores' X-Git-Tag: emacs-25.0.90~1499 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=62d5d46551c2adca780d5da1e58ea7f37d6fb933;p=emacs.git Add `project-ignores' * lisp/progmodes/project.el (project-ignores): New generic function, and an implementation for the VC project type. * lisp/progmodes/xref.el (xref--rgrep-command): Split, as a variant of rgrep-default-command that handles a generic list of ignores. (xref-collect-matches): Use it, and pass through to it the value of the newly added argument. (xref-find-regexp): Handle ignored paths within the project. Remove outdated comment. * lisp/vc/vc.el (vc-default-ignore-completion-table): Skip the comments and the empty lines. --- diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el index aa02b040083..a7e0bb47a1f 100644 --- a/lisp/progmodes/elisp-mode.el +++ b/lisp/progmodes/elisp-mode.el @@ -584,7 +584,6 @@ It can be quoted, or be inside a quoted form." (declare-function xref-make-bogus-location "xref" (message)) (declare-function xref-make "xref" (description location)) -(declare-function xref-collect-matches "xref" (symbol dir)) (declare-function xref-collect-references "xref" (symbol dir)) (defun elisp-xref-find (action id) diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el index 26b32b4b750..437c865dc08 100644 --- a/lisp/progmodes/project.el +++ b/lisp/progmodes/project.el @@ -84,6 +84,19 @@ of any currently open related projects, if they're meant to be edited together. The directory names should be absolute." (list (project-root project))) +(cl-defgeneric project-ignores (_project) + "Return the list of glob patterns that match ignored files. +To root an entry, start it with `./'. To match directories only, +end it with `/'." + (require 'grep) + (defvar grep-find-ignored-files) + (nconc + (mapcar + (lambda (dir) + (concat dir "/")) + vc-directory-exclusion-list) + grep-find-ignored-files)) + (defun project-try-vc (dir) (let* ((backend (ignore-errors (vc-responsible-backend dir))) (root (and backend (ignore-errors @@ -93,6 +106,18 @@ edited together. The directory names should be absolute." (cl-defmethod project-root ((project (head vc))) (cdr project)) +(cl-defmethod project-ignores ((project (head vc))) + (nconc + (cl-call-next-method) + (let* ((dir (cdr project)) + (backend (vc-responsible-backend dir))) + (mapcar + (lambda (entry) + (if (string-match "\\`/" entry) + (replace-match "./" t t entry) + entry)) + (vc-call-backend backend 'ignore-completion-table dir))))) + (defun project-ask-user (dir) (cons 'user (read-directory-name "Project root: " dir nil t))) diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el index 32d1215f157..cc475e6e7e4 100644 --- a/lisp/progmodes/xref.el +++ b/lisp/progmodes/xref.el @@ -662,20 +662,19 @@ With prefix argument, prompt for the identifier." "Find all matches for REGEXP. With \\[universal-argument] prefix, you can specify the directory to search in." - ;; FIXME: Prompt for directory. (interactive (list (xref--read-identifier "Find regexp: "))) - (let* ((dirs (if current-prefix-arg + (let* ((proj (project-current)) + (dirs (if current-prefix-arg (list (read-directory-name "In directory: ")) - (let ((proj (project-current))) - (project--prune-directories - (nconc - (project-directories proj) - (project-search-path proj)))))) + (project--prune-directories + (nconc + (project-directories proj) + (project-search-path proj))))) (xref-find-function (lambda (_kind regexp) (cl-mapcan (lambda (dir) - (xref-collect-matches regexp dir)) + (xref-collect-matches regexp dir (project-ignores proj))) dirs)))) (xref--show-xrefs regexp 'matches regexp nil))) @@ -756,7 +755,7 @@ tools are used, and when." (mapc #'kill-buffer (cl-set-difference (buffer-list) orig-buffers))))) -(defun xref-collect-matches (regexp dir) +(defun xref-collect-matches (regexp dir ignores) "Collect matches for REGEXP inside DIR using rgrep." (cl-assert (directory-name-p dir)) (require 'semantic/fw) @@ -766,8 +765,8 @@ tools are used, and when." (let* ((grep-find-template (replace-regexp-in-string "-e " "-E " grep-find-template t t)) (grep-highlight-matches nil) - (command (rgrep-default-command (xref--regexp-to-extended regexp) - "*.*" dir)) + (command (xref--rgrep-command (xref--regexp-to-extended regexp) + "*.*" dir ignores)) (orig-buffers (buffer-list)) (buf (get-buffer-create " *xref-grep*")) (grep-re (caar grep-regexp-alist)) @@ -787,6 +786,40 @@ tools are used, and when." (mapc #'kill-buffer (cl-set-difference (buffer-list) orig-buffers))))) +(defun xref--rgrep-command (regexp files dir ignores) + (require 'find-dired) ; for `find-name-arg' + (defvar grep-find-template) + (defvar find-name-arg) + (grep-expand-template + grep-find-template + regexp + (concat (shell-quote-argument "(") + " " find-name-arg " " + (mapconcat + #'shell-quote-argument + (split-string files) + (concat " -o " find-name-arg " ")) + " " + (shell-quote-argument ")")) + dir + (concat + (shell-quote-argument "(") + " -path " + (mapconcat + (lambda (ignore) + (when (string-match "\\(\\.\\)/" ignore) + (setq ignore (replace-match dir t t ignore 1))) + (when (string-match-p "/\\'" ignore) + (setq ignore (concat ignore "*"))) + (unless (string-prefix-p "*" ignore) + (setq ignore (concat "*/" ignore))) + (shell-quote-argument ignore)) + ignores + " -o -path ") + " " + (shell-quote-argument ")") + " -prune -o "))) + (defun xref--regexp-to-extended (str) (replace-regexp-in-string ;; FIXME: Add tests. Move to subr.el, make a public function. diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el index 1bd04e13430..3b9e788b7ab 100644 --- a/lisp/vc/vc.el +++ b/lisp/vc/vc.el @@ -1423,8 +1423,12 @@ Argument BACKEND is the backend you are using." (defun vc-default-ignore-completion-table (backend file) "Return the list of ignored files under BACKEND." - (vc--read-lines - (vc-call-backend backend 'find-ignore-file file))) + (cl-delete-if + (lambda (str) + ;; Commented or empty lines. + (string-match-p "\\`\\(?:#\\|[ \t\r\n]*\\'\\)" str)) + (vc--read-lines + (vc-call-backend backend 'find-ignore-file file)))) (defun vc--read-lines (file) "Return a list of lines of FILE."