Package: emacs;
Reported by: Stephen Berman <stephen.berman <at> gmx.net>
Date: Tue, 27 May 2025 15:55:02 UTC
Severity: normal
Found in version 31.0.50
Done: Stephen Berman <stephen.berman <at> gmx.net>
Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):
From: Stephen Berman <stephen.berman <at> gmx.net> To: bug-gnu-emacs <at> gnu.org Subject: 31.0.50; Todo mode bug revealed by setq-default change Date: Tue, 27 May 2025 17:53:24 +0200
[Message part 1 (text/plain, inline)]
TL;DR: There is a bug in the command `todo-jump-to-category' from todo-mode.el that manifests itself differently in master and in earlier versions of Emacs due to the change to `setq-default' made in commit f3e0bdf1b98. A patch that fixes both manifestations is provided. Background: As documented, `todo-jump-to-category' visits a user-specified category of a given Todo file, and if the specified category does not exist in the Todo file, the user is prompted whether to add the category to the file, and if confirmed, then by default there is a further prompt to add the first Todo item to the category. The command can also be invoked from outside of a todo-mode buffer, but since it is not autoloaded, todo-mode must be loaded before it can be so invoked. Problem (master): Recently, I started observing aberrant behavior when invoking `todo-jump-to-category' before visiting any Todo file in todo-mode (I load todo-mode in my init file): upon jumping to an existing category, I get prompted to add a Todo item, although the category is not new. To reproduce this: 0. HOME=/tmp/${USER} emacs -Q (start Emacs in a clean environment) 1. Type `M-x todo-show' and at the prompt type "test RET test1 RET item1 RET" to initialize the Todo file "test" with the category "test1" containing the item "item1". The current buffer displays that category in todo-mode. 2. (Sanity check) Type `q' to save the newly created Todo file and bury the buffer, so that the current buffer is no longer a todo-mode buffer. Then type `M-x todo-jump-to-category': this switches the buffer back to the todo-mode buffer displaying the category "test1" with the item "item1"; there is no prompt for a Todo item. 3. Kill the Emacs session and restart as in step 0. 4. Type `M-x load-library' and at the prompt enter `todo-mode RET'. 5. Type `M-x todo-jump-to-category' and at the prompt enter "test1" (or type TAB, which automatically inserts "test1" after the prompt, since it's the only category in the Todo file). => The category "test1" is displayed but now the minibuffer displays the prompt "Todo item: ". Solution: The following patch fixes this, so that at step 5 the category is displayed and there is no prompt to add an item.
[todo-jump-to-category.diff (text/x-patch, attachment)]
[Message part 3 (text/plain, inline)]
Analysis: The current code in `todo-jump-to-category' compares, via the buffer-local variable `todo-categories', the length of the list of Todo categories in the specified Todo file before and after specifying the category to jump to. When `todo-jump-to-category' is invoked outside of todo-mode, `todo-categories' is always nil, so its length is zero, but when the user specifies the category to jump to, `todo-categories' gets (via `todo-read-category' and functions called from it) a non-nil list value, so the post-specification length of `todo-categories' is greater than the pre-specification length, and together with the non-nil default value of `todo-add-item-if-new-category', this results in the prompt for a Todo item. The above patch eliminates the before and after comparison involving `todo-categories' and replaces it by a check of whether there are any items in the category, since an existing category should always have at least one item (perhaps done or archived). Trigger: After I debugged the problem on master and came up with the above patch, I wondered why I had never encountered the problem until recently, because most of the code involved hasn't changed since the current version of Todo mode was added to the Emacs repo twelve years ago. So I executed the above recipe in the emacs-30 branch and was surprised to find that the bug does not happen there: after step 5, the category "test1" is displayed and there is no prompt for a Todo item. Debugging showed that this is because the value of `todo-categories' is nil in emacs-30, both before and after specifying a category to jump to. This difference between emacs-30 and master manifests itself in the function `todo-category-completions' (called from `todo-read-category') around the following code: (with-current-buffer (find-file-noselect f 'nowarn) [...] (todo-mode) [...]) In both master and emacs-30, before entering this sexp, the buffer-local value of `todo-categories' is nil, but after invoking `todo-mode' its value (for the buffer visiting the Todo file `f') becomes non-nil. After leaving the `with-current-buffer' form, `todo-categories' retains its non-nil value in master, but reverts to nil in emacs-30. The mode function `todo-mode' calls `todo-modes-set-3', which contains the form `(setq-local todo-categories (todo-set-categories))'. This led me to commit f3e0bdf1b98, and indeed, when I undo that change in master, the problematic prompt on calling `todo-jump-to-category' does not happen. Problem (pre-master): Then I tested invoking `todo-jump-to-category' from outside of a todo-mode buffer and specifying a non-existing category, and saw the same pattern, which, however, now reverses the problem status: the new (empty) category is displayed and there is the now expected prompt for a Todo item in master but, now wrongly, not in emacs-30; thus, in this case the behavior in emacs-30 (and earlier) contradicts the documentation. To reproduce, carry out the above recipe (in master and in emacs-30), but in step 5 enter "test2" at the prompt instead of "test1". (When I implemented `todo-jump-to-category', I apparently failed to test this case and haven't made use of it since.) Applying the above patch to emacs-30 also fixes this problem, and with the patch the other case (specifying an existing category) still works correctly in emacs-30. The fact that the latter case also works correctly in emacs-30 without the patch is evidently due to the problematic behavior of `setq-local' fixed by f3e0bdf1b98. The patch has a narrow scope, so I think it's safe enough to commit to emacs-30, even though the bug there is not a regression; but if that's not acceptable, I'll commit it to master. In GNU Emacs 31.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.49, cairo version 1.18.4) of 2025-05-24 built on strobelfs2 Repository revision: 492adf20b91520e96fb198e6e936e3145359c43b Repository branch: master Windowing system distributor 'The X.Org Foundation', version 11.0.12101016 System Description: Linux From Scratch r12.3-20 Configured using: 'configure -C 'CFLAGS=-Og -g3' PKG_CONFIG_PATH=/opt/qt6/lib/pkgconfig' Configured features: ACL CAIRO DBUS FREETYPE GIF GLIB GMP GNUTLS GPM GSETTINGS HARFBUZZ JPEG LCMS2 LIBSYSTEMD LIBXML2 MODULES NATIVE_COMP NOTIFY INOTIFY PDUMPER PNG RSVG SECCOMP SOUND SQLITE3 THREADS TIFF TOOLKIT_SCROLL_BARS TREE_SITTER WEBP X11 XDBE XIM XINERAMA XINPUT2 XPM XRANDR GTK3 ZLIB
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.