From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: Dmitry Gutov Newsgroups: gmane.emacs.devel Subject: Generation of tags for the current project on the fly Date: Fri, 12 Jan 2018 04:02:06 +0300 Message-ID: <4559858d-eb32-d071-fdad-e51430700260@yandex.ru> NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="------------657B36124785DAE9B8BB2657" X-Trace: blaine.gmane.org 1515718870 13096 195.159.176.226 (12 Jan 2018 01:01:10 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Fri, 12 Jan 2018 01:01:10 +0000 (UTC) User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:58.0) Gecko/20100101 Thunderbird/58.0 To: emacs-devel Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Fri Jan 12 02:01:06 2018 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1eZniR-0002v8-5m for ged-emacs-devel@m.gmane.org; Fri, 12 Jan 2018 02:01:03 +0100 Original-Received: from localhost ([::1]:57694 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eZnkQ-0004zD-Ti for ged-emacs-devel@m.gmane.org; Thu, 11 Jan 2018 20:03:06 -0500 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:40066) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eZnja-0004yV-OA for emacs-devel@gnu.org; Thu, 11 Jan 2018 20:02:15 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eZnjX-0002f7-Mm for emacs-devel@gnu.org; Thu, 11 Jan 2018 20:02:14 -0500 Original-Received: from mail-lf0-x230.google.com ([2a00:1450:4010:c07::230]:46560) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1eZnjX-0002eL-Dp for emacs-devel@gnu.org; Thu, 11 Jan 2018 20:02:11 -0500 Original-Received: by mail-lf0-x230.google.com with SMTP id a12so4206823lfe.13 for ; Thu, 11 Jan 2018 17:02:11 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:to:from:subject:message-id:date:user-agent:mime-version :content-language; bh=hP1j2pK1BqWqAM6QSZlQdqc6HfFEBBOci8iRAKDkJQU=; b=GxKxOoEz+EMRatWjFyBL6W5eu1kafyMMqdDdqMLzXHkJnOLAI/8fo7vN7q2pb/BgXz /8yQTG3Ff9Os7NEyeiomn2lZ5vLBqWs1f0B5GCfb3HHQLmrTI1BqBa7tGBfd3r7nCJ0i +2r2wpaXRkUHZQ7NHvywBGEMfGROdbaW7DOcRWvOD/VISpPJ7UiAoDYB3XgwDf64uISE /PbPQr9CrAy+0zubIxixpGqv7IMYlnTyrqtbPS9Y+gjWJYQ3XwvCml8UcxHwtS95CgAy giRThFpfs30xWxbZe9LbPTp8LSWKsqRnVXWxIRZyJFbdNRwTUV3FxN0/be4g90muDCvL Xqng== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:to:from:subject:message-id:date :user-agent:mime-version:content-language; bh=hP1j2pK1BqWqAM6QSZlQdqc6HfFEBBOci8iRAKDkJQU=; b=JIlpgninXFATYERuPllIOk5nyT81A+sGpCBIDq/7//BuaJdomRDG4WIpXta+2ILskB B8v7JLZJT5cvneiKDktCOize9olJQ5o4Qy64eZnYnuWvp1VSVyg1R5edkFpGQsT+IMVJ hFtClcncPEVLvTfhSDJNuH8LRgF5kOqmQHAy3CwN16isSAimyCvFFqWcA2fMT7iC1kKA 2yG4NLtHDL98o4RTmykbzT6os6K+V7Bx5BYVl5JKbKUvUC0SIKK6WZ7pVMj3W7N/47uE jcFPVjDrPd1Uwtp3webaGleYxxRfRwJXIilISNNOm5abLTvdwlavy6bTz7EC+Xfl0RCG o9cw== X-Gm-Message-State: AKwxytcpkAKBYqbnT+Qe6HT7zGTj+2eYbnAX2KBiKuLnSHEdXnDbkL5/ 6Fy1ySM3B4WE7av+5rEcQzK142rZ X-Google-Smtp-Source: ACJfBos5HJTSGE7x4YBwM6f/ZkiFr4twRo/21nI2tpfeo37sj2wz72pNcn2Vk6Z5/6E2EKlM665BWw== X-Received: by 10.25.23.27 with SMTP id n27mr4067752lfi.89.1515718929201; Thu, 11 Jan 2018 17:02:09 -0800 (PST) Original-Received: from [192.168.1.174] ([178.252.127.239]) by smtp.googlemail.com with ESMTPSA id 1sm4007709ljt.35.2018.01.11.17.02.07 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 11 Jan 2018 17:02:07 -0800 (PST) Content-Language: en-US X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4010:c07::230 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.org gmane.emacs.devel:221866 Archived-At: This is a multi-part message in MIME format. --------------657B36124785DAE9B8BB2657 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit Here's an idea I've been working on. We generate tags for all files the current project contains (except the ignored ones) when the user calls one of the xref commands, but hasn't explicitly visited any tags table. The result is used until they make a change in a file somewhere and save the buffer, then the generated table is discarded. I think it will be helpful for new users (who don't really know how to generate tags), as well as people who are used to certain other editors performing the indexing automatically, in small-to-medium sized projects. With some effort, we could implement re-indexing and invalidation on a more granular level (so it's usable in bigger projects too), but transitioning to GNU Global would probably be better. For reference, indexing the Emacs sources takes ~1.1sec here. What do people think? See the attached patch. --------------657B36124785DAE9B8BB2657 Content-Type: text/x-patch; name="project-auto-tags.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="project-auto-tags.diff" diff --git a/lisp/progmodes/etags.el b/lisp/progmodes/etags.el index a31668e1ba..b0c398ec8e 100644 --- a/lisp/progmodes/etags.el +++ b/lisp/progmodes/etags.el @@ -2109,7 +2109,9 @@ etags-xref-find-definitions-tag-order "Tag order used in `xref-backend-definitions' to look for definitions.") ;;;###autoload -(defun etags--xref-backend () 'etags) +(defun etags--xref-backend () + (etags--maybe-use-project-tags) + 'etags) (cl-defmethod xref-backend-identifier-at-point ((_backend (eql etags))) (find-tag--default)) @@ -2180,6 +2182,53 @@ xref-make-etags-location (nth 1 tag-info))) +;;; Simple tags generation, with automatic invalidation + +(defvar etags--project-tags-file nil) + +(defun etags--maybe-use-project-tags () + (let (proj) + (when (and (not (or tags-file-name + tags-table-list)) + (setq proj (project-current))) + (etags--project-tags-generate proj) + ;; Invalidate the scanned tags after any change is written to disk. + (add-hook 'after-save-hook #'etags--project-tags-cleanup) + (visit-tags-table etags--project-tags-file) + ;; Explicit return, this is no backend function. + nil))) + +(defun etags--project-tags-generate (proj) + (let* ((root (cl-find default-directory + (project-roots proj) + :test #'file-in-directory-p)) + (default-directory root) + (files (all-completions "" (project-file-completion-table proj (list root)))) + (etags-command (executable-find "etags")) + ;; FIXME: List all extensions, or wait for etags fix. + ;; http://lists.gnu.org/archive/html/emacs-devel/2018-01/msg00323.html + (extensions '("rb" "js" "py" "pl" "el" "c" "cpp" "cc" "h" "hh" "hpp" + "java" "go" "cl" "lisp" "prolog" "php" "erl" "hrl" + "F" "f" "f90" "for" "cs" "a" "asm" "ads" "adb" "ada")) + (file-regexp (format "\\.%s\\'" (regexp-opt extensions)))) + (setq etags--project-tags-file (make-temp-file "emacs-project-tags-")) + (with-temp-buffer + (mapc (lambda (f) + (when (string-match-p file-regexp f) + (insert f "\n"))) + files) + (shell-command-on-region (point-min) (point-max) + (format "%s - -o %s" etags-command etags--project-tags-file) + nil nil "*etags-project-tags-errors*" t)))) + +(defun etags--project-tags-cleanup () + (when etags--project-tags-file + (delete-file etags--project-tags-file) + (setq tags-file-name nil + tags-table-list nil + etags--project-tags-file nil)) + (remove-hook 'after-save-hook #'etags--project-tags-cleanup)) + (provide 'etags) ;;; etags.el ends here --------------657B36124785DAE9B8BB2657--