Package: emacs;
Reported by: Visuwesh <visuweshm <at> gmail.com>
Date: Wed, 26 Feb 2025 14:01:02 UTC
Severity: wishlist
Found in version 31.0.50
Done: Dmitry Gutov <dmitry <at> gutov.dev>
Bug is archived. No further changes may be made.
View this message in rfc822 format
From: Visuwesh <visuweshm <at> gmail.com> To: Dmitry Gutov <dmitry <at> gutov.dev> Cc: 76587 <at> debbugs.gnu.org Subject: bug#76587: 31.0.50; [FR] project.el should have a way to exclude certain projects from being saved Date: Thu, 27 Feb 2025 09:34:16 +0530
[வியாழன் பிப்ரவரி 27, 2025] Dmitry Gutov wrote: > Hi! Hello! > On 26/02/2025 15:59, Visuwesh wrote: >> It is quite frustrating to use C-x p p to jump to projects when it can >> easily get cluttered with projects that you never want to jump to. >> E.g., as my user-emacs-directory only really tracks init.el, I don't >> want project.el to save it in the projects file. When it does, it gets >> in the way when I am completing ~/lib/ports/emacs which is where I keep >> my checkout of the Emacs repo. >> Likewise, I do not want to save remote projects at all. > > This sounds reasonable. Should we call it something like > project-list-exclude[-regexps]? Sounds good to me. >> AFAIU, the current way is to use project-forget-project and friends, but >> they are cumbersome. They work nice when you want to remove a >> "completed" project but they don't help when you want to use project >> commands judiciously for "temporary" projects (like a checkout that >> you're editing for a patch). > > Temporary checkouts might not be worth it in terms of that user option > (calling M-x ...-forget-project is faster than doing the checkout), > but that's just my opinion. You're right. I don't know/remember what I was thinking when I wrote it honestly. >> P.S. I wish there was a way for project backends to bow out from >> project--write-project-list too. Context: I have a "sibling-file" >> project backend which mainly offers meaningful candidates to C-x p f >> when visiting a file that has associated siblings. > > This sounds a bit confusing. When you use this other backend (how? is > it enabled manually?), do you visit disjoint repositories through it? > Or only a subset of a files in a repository? What do you do when you > want to visit other files in it? There are no repositories here to speak of. I use this project backend when there is no associated vc backend with the file I'm visiting (i.e., project-vc fails). To make my example more concrete, consider the following example of find-sibling-rules: '(find-sibling-rules (rx-let ((basename (group (1+ (not ?/))))) ;; Supplementary info. `((,(rx "papers/" basename ".pdf" eos) "papers/\\1_si_*.pdf" "papers/\\1_si.pdf") (,(rx "papers/" basename "_si" (? "_" (+ num)) ".pdf" eos) "papers/\\1.pdf")))) With this rule in place, when I say M-x find-sibling-file when I'm visiting ~/doc/.../papers/X.pdf, it visits ~/doc/.../papers/X_si.pdf for me. With my sibling-file backend (see at end), I can say M-x project-list-buffers, or C-x p b, or C-x p f to switch to related files easily. I was thinking of writing a project-specific C-x <right>/<left> commands to switch between project buffers easily. >> I could use >> find-sibling-file but using project.el comes with bonuses like >> project-list-buffer, etc. > > From where I'm standing, it might be more ergonomical to add a few > extra commands for the "siblings" search, and bind them to a > submap. But I'm probably missing something. I think we have different notions of a "project." I see it as a list of related files, but the current project backend is built upon a singular, exact definition of a root directory inside which all files can be found. For my use case, this root directory is a bit hard to define since the sibling file need not be restricted to be under the same directory (see an example of such a rule in the docstring of find-sibling-rules). Perhaps, my idea of a project is most closest to what the satchel package does. I could definitely add yet another submap to my config but I would like to merge "regular" project.el projects, and my personal "transient-but-a-bit-more-defined" projects into a single one. This elevates the pain of having to remember two different sets of commands. All this complexity arises because I don't/can't use Git (or other VC) for most of my files. (Emacs' backup and vc-backup does everything I need.) Here's the promised implementation: (defun vz/project-sibling-file (dir) "Return project object for current file-visiting buffer's sibling files. If the current file-visiting buffer has siblings, then return them if the current file is under DIR." (when (and (buffer-file-name) (not (string-prefix-p "../" (file-relative-name (buffer-file-name) dir)))) (let ((siblings (find-sibling-file-search (buffer-file-name)))) (when siblings `(vz/sibling ,(buffer-file-name) ,@siblings))))) (cl-defmethod project-root ((project (head vz/sibling))) (file-name-parent-directory (nth 1 project))) (cl-defmethod project-external-roots ((_project (head vz/sibling))) nil) (cl-defmethod project-name ((project (head vz/sibling))) (file-name-base (nth 1 project))) (cl-defmethod project-ignores ((_project (head vz/sibling)) _dir) nil) (cl-defmethod project-files ((project (head vz/sibling)) &optional dirs) (let ((files (cdr project))) (if (or (null dirs) (equal (car dirs) (project-root project))) files (mapcan (lambda (f) (when (seq-some (lambda (d) (string-prefix-p d f)) dirs) (list f))) files)))) (cl-defmethod project-buffers ((project (head vz/sibling))) (mapcan (lambda (f) (let ((buf (find-buffer-visiting f))) (and buf (list buf)))) (project-files project))) (with-eval-after-load 'project (add-to-list 'project-find-functions #'vz/project-sibling-file t))
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.