From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Stefan Kangas Newsgroups: gmane.emacs.bugs Subject: bug#67687: Feature request: automatic tags management Date: Sat, 30 Dec 2023 17:02:35 -0800 Message-ID: References: <2f86b882-9ec1-f63f-d90b-5f8f7ae114f2@gutov.dev> <58D84A29-9A63-45BA-AD8B-B476CDC931A1@gmail.com> <812729c8-726f-d60e-2603-2d8e588929fd@gutov.dev> <835y0sgg12.fsf@gnu.org> <661f4951-cb0a-5257-63b0-efe71a0d217e@gutov.dev> <83y1de7jyr.fsf@gnu.org> <1a8c51fb-a114-42a4-ae40-8314d3f21104@gutov.dev> <83tto0400p.fsf@gnu.org> <6a684420-2098-4c9f-a17c-61150e9f3321@gutov.dev> Mime-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="33060"; mail-complaints-to="usenet@ciao.gmane.io" Cc: 67687@debbugs.gnu.org, eskinjp@gmail.com To: Dmitry Gutov , Eli Zaretskii Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Sun Dec 31 02:03:25 2023 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1rJkEf-0008No-17 for geb-bug-gnu-emacs@m.gmane-mx.org; Sun, 31 Dec 2023 02:03:25 +0100 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rJkEJ-0000eu-Ep; Sat, 30 Dec 2023 20:03:03 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rJkEH-0000dt-RJ for bug-gnu-emacs@gnu.org; Sat, 30 Dec 2023 20:03:01 -0500 Original-Received: from debbugs.gnu.org ([2001:470:142:5::43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1rJkEH-0004yX-HQ for bug-gnu-emacs@gnu.org; Sat, 30 Dec 2023 20:03:01 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1rJkEH-000353-UO for bug-gnu-emacs@gnu.org; Sat, 30 Dec 2023 20:03:01 -0500 X-Loop: help-debbugs@gnu.org Resent-From: Stefan Kangas Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sun, 31 Dec 2023 01:03:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 67687 X-GNU-PR-Package: emacs Original-Received: via spool by 67687-submit@debbugs.gnu.org id=B67687.170398456711822 (code B ref 67687); Sun, 31 Dec 2023 01:03:01 +0000 Original-Received: (at 67687) by debbugs.gnu.org; 31 Dec 2023 01:02:47 +0000 Original-Received: from localhost ([127.0.0.1]:45336 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rJkE2-00034b-R8 for submit@debbugs.gnu.org; Sat, 30 Dec 2023 20:02:47 -0500 Original-Received: from mail-ed1-x532.google.com ([2a00:1450:4864:20::532]:42277) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rJkDy-00034M-UT for 67687@debbugs.gnu.org; Sat, 30 Dec 2023 20:02:45 -0500 Original-Received: by mail-ed1-x532.google.com with SMTP id 4fb4d7f45d1cf-5559df64497so3783105a12.1 for <67687@debbugs.gnu.org>; Sat, 30 Dec 2023 17:02:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1703984556; x=1704589356; darn=debbugs.gnu.org; h=content-transfer-encoding:cc:to:subject:message-id:date :mime-version:references:in-reply-to:from:from:to:cc:subject:date :message-id:reply-to; bh=XwOu1prVybvb9Vu1/hpee4JtoQY1EFvf7fgvYBFDSco=; b=g3Y5lW57utut4Y/pwaHgq1K3uq7xN07m6fh8J57Lp0Q2GefZ2iDy6ykv+eGh1+sv7Z oCnlMdF4EXc7cpxRIztlQhU/K7kMN+Cq3YWuEcC+VFB933zZv+Hfd+NQkk8ZcDepLlMD WGmHQgkZvM6Vhq1mYz7QZuSdcyhyJYdd0JYBpcpxBOxceOHjtpfzEkhXbBRL5NLm4VAQ 6V0vQedCYj2oKoinHnvQUiNDLlfVs9WzV9FfHi3z+6HrAW9Ju4FYjfmHhaDT+b2e/V1r ouYiWjRdHkzPUjccD07fffxZxFnTJIb2ehRsLIN8OhVnEs2pAZdHVa8L0I4gjbFBtk7B n7zQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1703984556; x=1704589356; h=content-transfer-encoding:cc:to:subject:message-id:date :mime-version:references:in-reply-to:from:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=XwOu1prVybvb9Vu1/hpee4JtoQY1EFvf7fgvYBFDSco=; b=jNNM/ViWfkhm+xooRwj0fAUfCpDDIreJ3YmYBWXaXEvgqdXLPJ17LtHBQEhU+AzlJJ uA+Y7Tl8wyQjQw12ZR1cMD2BTfRRzQbkOq2eENT/J90UI8VEiy3xzDOAp5mJONzmpT4O ZXR/mIwyjPZF4HFRHneSD8kNanYAbaY+2EYFCeKLxxN2ZPfBzWYQGIL0Yg/8Fe8OPmyb QYZL+jTSby+1+WP+3FKodFAO1Ksa/4tZZygYk+JDlzoSENIwMURiSBuhv1bkgu4Rgb+c gTK7VRK7yU/EPIM1uW+ZGohye85lXGdBvtsP0jFlmlycytF0849LTd7BxIPi4W1+m/Vf zaEg== X-Gm-Message-State: AOJu0YyScDLDl3ba+HpVI1RCtvHQpPso9WEnntsUf0IYw6KpwdUo+CvU o0uqm+EqCOFpLmEAlfLB+tOCFTS4oEm+mUkHmMk= X-Google-Smtp-Source: AGHT+IFI6lJpWtD3JYAcLUV+6hTHYnD0Zf7ChWDu/gF8YZIFYLRnTrBmUrm1S2/fiEN0f49amQYnUXFQNioZ25vdW/E= X-Received: by 2002:a50:8a94:0:b0:554:25b6:8fc with SMTP id j20-20020a508a94000000b0055425b608fcmr12674729edj.31.1703984555918; Sat, 30 Dec 2023 17:02:35 -0800 (PST) Original-Received: from 753933720722 named unknown by gmailapi.google.com with HTTPREST; Sat, 30 Dec 2023 17:02:35 -0800 In-Reply-To: <6a684420-2098-4c9f-a17c-61150e9f3321@gutov.dev> X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.bugs:277121 Archived-At: My review below. I wasn't paying attention to the full discussion, so please just ignore any points that you have already discussed with Eli. Dmitry Gutov writes: > diff --git a/etc/NEWS b/etc/NEWS > index f82564946b7..6d6bca187de 100644 > --- a/etc/NEWS > +++ b/etc/NEWS > @@ -1243,6 +1243,11 @@ the needs of users with red-green or blue-yellow c= olor deficiency. > The Info manual "(modus-themes) Top" describes the details and > showcases all their customization options. > > +** New global minor mode 'etags-regen-mode'. > +This minor mode generates the tags table automatically based on the > +current project configuration, and later updates it as you edit the > +files and save the changes. Consider referring to the relevant section in the info manual. > + > =0C > * Incompatible Lisp Changes in Emacs 30.1 > > diff --git a/lisp/progmodes/etags-regen.el b/lisp/progmodes/etags-regen.e= l > new file mode 100644 > index 00000000000..e1fca1c4e44 > --- /dev/null > +++ b/lisp/progmodes/etags-regen.el > @@ -0,0 +1,424 @@ > +;;; etags-regen.el --- Auto-(re)regenerating tags -*- lexical-binding: = t -*- > + > +;; Copyright (C) 2021-2023 Free Software Foundation, Inc. > + > +;; Author: Dmitry Gutov > +;; Keywords: tools > + > +;; This file is part of GNU Emacs. > + > +;; GNU Emacs is free software: you can redistribute it and/or modify > +;; it under the terms of the GNU General Public License as published by > +;; the Free Software Foundation, either version 3 of the License, or > +;; (at your option) any later version. > + > +;; GNU Emacs is distributed in the hope that it will be useful, > +;; but WITHOUT ANY WARRANTY; without even the implied warranty of > +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +;; GNU General Public License for more details. > + > +;; You should have received a copy of the GNU General Public License > +;; along with GNU Emacs. If not, see . > + > +;;; Commentary: > + > +;; Simple automatic tags generation with updates on save. > +;; > +;; This mode provides automatic indexing for Emacs "go to definition" > +;; feature, the `xref-go-forward' command (bound to `M-.' by default). > +;; > +;; At the moment reindexing works off before/after-save-hook, but to > +;; handle more complex changes (for example, the user switching to > +;; another branch from the terminal) we can look into plugging into > +;; something like `filenotify'. > +;; > +;; Note that this feature disables itself if the user has some tags > +;; table already visited (with `M-x visit-tags-table', or through an > +;; explicit prompt triggered by some feature that requires tags). > + > +;;; Code: > + > +(require 'cl-lib) > + > +(defgroup etags-regen nil > + "Auto-(re)generating tags." > + :group 'tools) How about: "Auto-generate \"tags\" file." > + > +(defvar etags-regen--tags-file nil) > +(defvar etags-regen--tags-root nil) > +(defvar etags-regen--new-file nil) > + > +(declare-function project-root "project") > +(declare-function project-files "project") > +(declare-function dired-glob-regexp "dired") > + > +(defcustom etags-regen-program (executable-find "etags") > + "Name of the etags program used by `etags-regen-mode'. > + > +If you only have `ctags' installed, you can also set this to > +\"ctags -e\". Some features might not be supported this way." > + ;; Always having our 'etags' here would be easier, but we can't > + ;; always rely on it being installed. So it might be ctags's etags. > + :type 'file > + :version "30.1") > + > +(defcustom etags-regen-tags-file "TAGS" > + "Name of the tags file to create inside the project by `etags-regen-mo= de'. > + > +The value should either be a simple file name (no directory > +specified), or a function that accepts the project root directory > +and returns a distinct absolute file name for its tags file. The > +latter possibility is useful when you prefer to store the tag > +files somewhere else, for example in `temporary-file-directory'." > + :type '(choice (string :tag "File name") > + (function :tag "Function that returns file name")) > + :version "30.1") Did you consider making it always store the TAGS files somewhere in `temporary-file-directory'? They should be rather ephemereal in any case, I think? In that case, we could perhaps even ignore an existing TAGS file, if this mode is enabled. Perhaps as an option. > + > +(defcustom etags-regen-program-options nil > + "List of additional options for etags program invoked by `etags-regen-= mode'." > + :type '(repeat string) > + :version "30.1") Perhaps add: See the full list of options that `etags' accepts in Info node `(emacs) Create Tags Table'. Should this be marked unsafe? Actually, same question for all of the above defcustoms, given that we use `shell-command-to-string'. Speaking of which, should we have more `shell-quote-argument' below? I didn't look at every example, but maybe you did. > + > +(defcustom etags-regen-regexp-alist nil > + "Mapping of languages to etags regexps for `etags-regen-mode'. > + > +These regexps are used in addition to the tags made with the > +standard parsing based on the language. > + > +The value must be a list of conses (LANGUAGES . TAG-REGEXPS) > +where both car and cdr are lists of strings. I think that should better be: where both LANGUAGES and TAG-REGEXPS are lists of strings. I'm not sure we should say "conses" there, or should we? I think we usually prefer something like: The value is a list where each element has the form (LANGUAGES . TAG-REGEXPS) I think this is better because it sounds less foreign to random users with no background in ELisp. But Eli is much better than me at this. :-) > + > +Each language should be one of the recognized by etags, see > +`etags --help'. Each tag regexp should be a string in the format > +as documented for the `--regex' arguments (without `{language}'). ^^ Nit, but I think "as" could be scratched. > + > +We currently support only Emacs's etags program with this option." > + :type '(repeat > + (cons > + :tag "Languages group" > + (repeat (string :tag "Language name")) > + (repeat (string :tag "Tag Regexp")))) > + :version "30.1") > + > +;;;###autoload > +(put 'etags-regen-regexp-alist 'safe-local-variable > + (lambda (value) > + (and (listp value) > + (seq-every-p > + (lambda (group) > + (and (consp group) > + (listp (car group)) > + (listp (cdr group)) > + (seq-every-p #'stringp (car group)) > + (seq-every-p #'stringp (cdr group)))) > + value)))) > + > +;; We have to list all extensions: etags falls back to Fortran > +;; when it cannot determine the type of the file. (A battle-tested default, if nothing else. ;-) > +;; http://lists.gnu.org/archive/html/emacs-devel/2018-01/msg00323.html > +(defcustom etags-regen-file-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") > + "Code file extensions for `etags-regen-mode'. > +File extensions to generate the tags for." > + :type '(repeat (string :tag "File extension")) > + :version "30.1") > + > +;;;###autoload > +(put 'etags-regen-file-extensions 'safe-local-variable > + (lambda (value) (and (listp value) (seq-every-p #'stringp value)))) > + > +;; FIXME: We don't support root anchoring yet. What is root anchoring? Does it deserve a sentence that explains what it is? > +(defcustom etags-regen-ignores nil > + "Additional ignore rules, in the format of `project-ignores'." > + :type '(repeat > + (string :tag "Glob to ignore")) > + :version "30.1") > + > +;;;###autoload > +(put 'etags-regen-ignores 'safe-local-variable > + (lambda (value) (and (listp value) (seq-every-p #'stringp value)))) > + > +(defvar etags-regen--errors-buffer-name "*etags-regen-tags-errors*") > + > +(defvar etags-regen--rescan-files-limit 100) > + > +(defun etags-regen--all-mtimes (proj) > + (let ((files (etags-regen--all-files proj)) > + (mtimes (make-hash-table :test 'equal)) > + file-name-handler-alist) > + (dolist (f files) > + (condition-case nil > + (puthash f > + (file-attribute-modification-time > + (file-attributes f)) > + mtimes) > + (file-missing nil))) > + mtimes)) Could we use file notifications for this? Maybe as a future improvement. Other than that, LGTM. Thanks again for working on this.