Subject: bug#67687: Feature request: automatic tags management

From: Dmitry Gutov <[email-masked]>
Date: Tue, 2 Jan 2024 03:40:05 +0200

On 01/01/2024 21:25, Eli Zaretskii wrote:
>> Date: Mon, 1 Jan 2024 20:48:37 +0200
>> Cc: [email-masked], [email-masked], [email-masked],
>>   [email-masked]
>> From: Dmitry Gutov <[email-masked]>
>>
>> On 01/01/2024 19:39, Eli Zaretskii wrote:
>>>> Date: Mon, 1 Jan 2024 19:23:28 +0200
>>>> Cc: [email-masked], [email-masked], [email-masked],
>>>>    [email-masked]
>>>> From: Dmitry Gutov <[email-masked]>
>>>>
>>>> On 01/01/2024 18:50, Eli Zaretskii wrote:
>>>>>> +The exception is made when the user has already selected a tags
>>>>>> +table manually (for example, using \\[visit-tags-table]).  Then
>>>>>> +this mode doesn't do anything.  Reset the visited tags tables
>>>>>> +using \\[tags-reset-tags-tables]."
>>>>>
>>>>> The above is only true for the project whose TAGS was manually
>>>>> visited, right?  IOW, it's not that once the use invokes
>>>>> visit-tags-table once, this mode will be effectively disabled for the
>>>>> entire session, right?
>>>>
>>>> No, it's the latter. It's off for the whole session, just like a visited
>>>> TAGS file is active for the whole session (not limited to any specific
>>>> project).
>>>
>>> OK, then please tweak my suggested text to explain the situation
>>> correctly instead.
>>
>> How about this?
>>
>> If you select a tags table manually (for example, using
>> \\[visit-tags-table]), then this mode will be effectively
>> disabled for the entire session.  Use \\[tags-reset-tags-tables]
>> to countermand the effect of a previous \\[visit-tags-table].
> 
> SGTM, thanks.

All right. I think I'll wait a days or two for any more comments and 
then install the feature.

>> (defun project-visit-tags ()
>>     (let* ((pr (project-current))
>>            (tags-file (and pr
>>                            (expand-file-name "TAGS" (project-root pr)))))
>>       (and tags-file
>>            (file-exists-p tags-file)
>>            (visit-tags-table tags-file t))))
>>
>> (add-hook 'find-file-hook #'project-visit-tags)
> 
> This could work, but IMO it would be more elegant to avoid use of
> find-file-hook, and instead have some data structure that maps
> projects or directories to tags table files.

Looking into it, the variable default-tags-table-function seemed like it 
could work for this purpose, with settings like this:

(defun my/project-default-tags-table ()
   (let* ((pr (project-current))
          (tags-file (and pr
                          (expand-file-name "TAGS" (project-root pr)))))
     (and tags-file
          (file-exists-p tags-file)
          tags-file)))

(setq
  tags-table-list '("~/vc/emacs-master/") ; List with all your projects
  default-tags-table-function #'my/project-default-tags-table)

But alas it only changes which table is used first for finding a 
definition (before all others are tried), and all completions are 
collected from all completion tables in a global variable 
(tags-completion-table). So there is more work to be done to support 
simultaneously loaded independent tags tables. The new user option could 
look like this one, but it would also be used for the case of CONT=t, 
and tags-completion-table would need to be set buffer-locally in tags 
table buffers.

Note that etags-regen-mode switches between the tables automatically 
already, so this would be orthogonal functionality at best. Though 
hopefully compatible, and something that'd help avoid rescanning the 
completions table when switching between projects.