From: Dmitry Gutov <dgutov@yandex.ru>
To: "Philip K." <philipk@posteo.net>
Cc: 43086@debbugs.gnu.org
Subject: bug#43086: [PATCH] Allow tags backend to not query for TAGS file
Date: Wed, 16 Sep 2020 13:53:46 +0300 [thread overview]
Message-ID: <f225337a-23d4-0aaf-a178-1fe1f9826749@yandex.ru> (raw)
In-Reply-To: <87d02yefr5.fsf@posteo.net>
[-- Attachment #1: Type: text/plain, Size: 4399 bytes --]
On 07.09.2020 00:50, Philip K. wrote:
> Dmitry Gutov <dgutov@yandex.ru> writes:
>
>> Hi!
>>
>> On 28.08.2020 15:50, Philip K. wrote:
>>
>>> the xref backend for etags can be annoying at times, especially in
>>> combination with other backends. This patch should improve the
>>> situation, by allowing the user to configure how and when the etags
>>> backend is activated. The new user option etags-query-file would allow
>>> the backend to never query a TAGS file, or conditionally, depending on
>>> the existence of a TAGS file (in which case it can also be automatically
>>> loaded).
>>
>> This is a interesting patch, but it calls for some discussion:
>>
>> - The possible values all look pretty clever, but there are a lot of
>> them! Do we expect them all to be in demand? Ideally, I'd only leave 2-3
>> of them, to reduce the number of workflows we need to care about.
>
> I'm ok with that, the variable could also be turned into a hook if
> reducing preconfigured options while making it easy to add new
> behaviours.
Not sure how the direct conversion to a hook would look like.
In any case, when I talked about using a hook (find-file-hook in
particular), the main benefit I had in mind is that the effect would
cover all uses of etags.el. Meaning, also tags-completion-at-point-function.
>> The rest could probably be set up in individual user configurations in
>> find-file-hook (like Projectile does).
>
> I'm not familiar with how Projectile does this, or how this would work
> in general? Could you give an example?
projectile-mode adds projectile-find-file-hook-function to
find-file-hook, which, upon visiting any file, looks for
projectile-tags-file-name (usually "TAGS")'s presence in the root of the
project. When such file exists, it calls (visit-tags-table tags-file t),
to visit the tags table "locally".
Since project.el does not have a minor mode, and out of general
(admittedly handwavy) considerations of performance, we don't do that.
But a user could customize their find-file-hook with a similar logic. If
you like, you could also add a pre-existing function like that to
project.el that a user could then just add to find-file-hook.
>> - The variable name implies it affects how etags.el works globally, but
>> the actual effect seems limited to the xref backend function. We should
>> either rename it to something like etags-xref-query-file, or consider
>> having it affect tags-completion-at-point-function as well.
>
> I'm fine with either, but the first option seems simpler, unless there
> is still interest in maintaining the non-xref interface.
There might be some other benefit to the latter, but it doesn't seem
trivial, so the former sounds fine to me as well.
>> - One current persistent annoyance is that currently
>> xref-find-references doesn't work well in many files where the xref
>> backend is the default one (etags) when ido-mode or icomplete-mode are
>> enabled because it prompts for the tags file to do identifier
>> completion. I wonder if the "no query" option will help with this, too.
>
> Unless I'm misunderstanding something, that's exactly the situation
> that motivated me to write these patches (just because of Ivy not Ido).
I set etags-query-file to nil and call xref-find-references with
ido-mode enabled. And still get queried for a tags file.
Because etags--xref-backend still returns 'etags, but then
xref-backend-identifier-completion-table calls
tags-lazy-completion-table, which does the prompting.
If I make etags--xref-backend return nil, I simply get "No applicable
method: xref-backend-identifier-completion-table, nil" instead.
So a deeper change is needed.
>>> I could imagine this might be extended to allow an auto-generate option,
>>> but that feature seems out of scope of this patch, and probably would
>>> require some interoperation with project.el.
>>
>> Indeed. Actually, I have an old, WIP patch for tag file auto-generation
>> which, yes, uses project.el. I can post it again if you're curious.
>
> Sure, why not?
Here it is. It might even be functional.
The reason it's not installed yet, is I was looking to create a seamless
user experience with it, when they don't need to know which tags file is
visited, and when. And with tags being quickly updated after a file is
changed and saved.
The related discussion about necessary changes to etags fizzled out,
however.
[-- Attachment #2: etags-project.diff --]
[-- Type: text/x-patch, Size: 3058 bytes --]
diff --git a/lisp/progmodes/etags.el b/lisp/progmodes/etags.el
index a31668e1ba..9da2143525 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,58 @@ xref-make-etags-location
(nth 1 tag-info)))
\f
+;;; Simple tags generation, with automatic invalidation
+
+(defvar etags--project-tags-file nil)
+(defvar etags--project-tags-root nil)
+
+(defun etags--maybe-use-project-tags ()
+ (let (proj)
+ (when (and etags--project-tags-root
+ (not (file-in-directory-p default-directory
+ etags--project-tags-root)))
+ (etags--project-tags-cleanup))
+ (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))))
+
+(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-")
+ etags--project-tags-root root)
+ (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
+ etags--project-tags-root nil))
+ (remove-hook 'after-save-hook #'etags--project-tags-cleanup))
+
(provide 'etags)
;;; etags.el ends here
next prev parent reply other threads:[~2020-09-16 10:53 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-08-28 12:50 bug#43086: [PATCH] Allow tags backend to not query for TAGS file Philip K.
2020-09-05 0:45 ` Dmitry Gutov
2020-09-06 21:50 ` Philip K.
2020-09-16 10:53 ` Dmitry Gutov [this message]
2021-11-12 8:25 ` Lars Ingebrigtsen
2021-11-14 0:02 ` Philip Kaludercic
2022-09-11 11:36 ` Lars Ingebrigtsen
2022-09-13 4:07 ` Richard Stallman
2024-09-03 16:39 ` Philip Kaludercic
2024-09-06 22:16 ` Dmitry Gutov
2024-09-07 6:18 ` Eli Zaretskii
2024-09-09 0:29 ` Dmitry Gutov
2024-09-09 11:54 ` Eli Zaretskii
2024-09-09 23:32 ` Dmitry Gutov
2024-09-10 11:41 ` Eli Zaretskii
2024-09-10 12:45 ` Eli Zaretskii
2024-09-10 13:32 ` Dmitry Gutov
2024-09-10 13:30 ` Dmitry Gutov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=f225337a-23d4-0aaf-a178-1fe1f9826749@yandex.ru \
--to=dgutov@yandex.ru \
--cc=43086@debbugs.gnu.org \
--cc=philipk@posteo.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.