all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
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

  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.