Package: emacs;
Reported by: Spencer Baugh <sbaugh <at> janestreet.com>
Date: Mon, 20 Nov 2023 19:59:02 UTC
Severity: wishlist
Tags: patch
View this message in rfc822 format
From: Spencer Baugh <sbaugh <at> janestreet.com> To: Dmitry Gutov <dmitry <at> gutov.dev> Cc: 67310 <at> debbugs.gnu.org, eliz <at> gnu.org, juri <at> linkov.net Subject: bug#67310: [PATCH] Include the project--list as history when prompting for a project Date: Fri, 24 Nov 2023 10:50:43 -0500
[Message part 1 (text/plain, inline)]
Dmitry Gutov <dmitry <at> gutov.dev> writes: > On 23/11/2023 01:14, Spencer Baugh wrote: >> @@ -1769,27 +1778,40 @@ project-prompt-project-dir >> ;; completion style). >> (project--file-completion-table >> (append project--list `(,dir-choice)))) >> + (project--dir-history project--list) >> (pr-dir "")) >> (while (equal pr-dir "") >> ;; If the user simply pressed RET, do this again until they don't. >> - (setq pr-dir (completing-read "Select project: " choices nil t))) >> + (setq pr-dir >> + (let ((history-add-new-input nil)) >> + (completing-read "Select project: " choices nil t nil 'project--dir-history)))) >> (if (equal pr-dir dir-choice) >> (read-directory-name "Select directory: " default-directory nil t) >> + (let q((history-delete-duplicates t) > ^ > typo > >> + (history-length t)) >> + (add-to-history 'project--list pr-dir)) >> pr-dir))) > > Sorry, I thought we agreed that project-prompt-project-dir and > project-prompt-project-name shouldn't add-to-history? > > Because project-current calls project-remember-project already > (including the cases when the prompter isn't used: when the project is > auto-detected). And to cover the remaining cases, we can have > project-switch-project call project-remember-project as well. > > This way also we keep the project-prompter implementations with less > logic inside, meaning it's a bit easier to write the next one. > > More DRY, too. At least while there's no other code using > project-prompter directly (but then we could add a helper). Oops, sorry, that was just the old version of the patch. Correct version attached. (Perhaps I should find a better workflow for submitting patches than manually running format-patch and copy-pasting the resulting patch to attach it to a subsequent email)
[0001-Use-the-project-list-as-history-when-prompting-for-a.patch (text/x-patch, inline)]
From 6b7b82be8a9a2d218a124e8205f3627d77dbb0a1 Mon Sep 17 00:00:00 2001 From: Spencer Baugh <sbaugh <at> janestreet.com> Date: Tue, 21 Nov 2023 10:11:52 -0500 Subject: [PATCH] Use the project--list as history when prompting for a project The project--list is already ordered such that the most recently used projects are at the front. Now we use it as the minibuffer history when prompting for a project. To avoid savehist from picking up project--list as a minibuffer history variable and overriding our own persistence mechanism, we don't pass project--list directly as a history variable, but instead pass project--dir-history or project--name-history, dynamically-bound to an appropriate value. project--dir-history and project--name-history won't be persisted since they're always unbound at the top level; but if they are persisted anyway somehow, it won't affect us. If we later find a way to rely on savehist for persistence instead of having our own mechanism, we can change the in-memory format of project--list to be just a list of directories, and our explicit calls to project--add-dir can be replaced by let-binding history-delete-duplicates=t, history-length=t. * lisp/progmodes/project.el (project--add-dir): Add. (project-remember-project): Use project--add-dir. (project--name-history, project-prompt-project-name) (project--dir-history, project-prompt-project-dir): Pass a preprocessed project--list as HIST to completing-read. (bug#67310) (project-switch-project): Call project--add-dir. --- lisp/progmodes/project.el | 39 ++++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el index 95db9d0ef4c..fb4f42a844c 100644 --- a/lisp/progmodes/project.el +++ b/lisp/progmodes/project.el @@ -1721,13 +1721,12 @@ project--write-project-list (current-buffer))) (write-region nil nil filename nil 'silent)))) -;;;###autoload -(defun project-remember-project (pr &optional no-write) - "Add project PR to the front of the project list. +(defun project--add-dir (root &optional no-write) + "Add project root ROOT to the front of the project list. Save the result in `project-list-file' if the list of projects has changed, and NO-WRITE is nil." (project--ensure-read-project-list) - (let ((dir (abbreviate-file-name (project-root pr)))) + (let ((dir (abbreviate-file-name root))) (unless (equal (caar project--list) dir) (dolist (ent project--list) (when (equal dir (car ent)) @@ -1736,6 +1735,13 @@ project-remember-project (unless no-write (project--write-project-list))))) +;;;###autoload +(defun project-remember-project (pr &optional no-write) + "Add project PR to the front of the project list. +Save the result in `project-list-file' if the list of projects +has changed, and NO-WRITE is nil." + (project--add-dir (project-root pr) no-write)) + (defun project--remove-from-project-list (project-root report-message) "Remove directory PROJECT-ROOT of a missing project from the project list. If the directory was in the list before the removal, save the @@ -1757,6 +1763,8 @@ project-forget-project (project--remove-from-project-list project-root "Project `%s' removed from known projects")) +(defvar project--dir-history) + (defun project-prompt-project-dir () "Prompt the user for a directory that is one of the known project roots. The project is chosen among projects known from the project list, @@ -1769,27 +1777,37 @@ project-prompt-project-dir ;; completion style). (project--file-completion-table (append project--list `(,dir-choice)))) + (project--dir-history (project-known-project-roots)) (pr-dir "")) (while (equal pr-dir "") ;; If the user simply pressed RET, do this again until they don't. - (setq pr-dir (completing-read "Select project: " choices nil t))) + (setq pr-dir + (let ((history-add-new-input nil)) + (completing-read "Select project: " choices nil t nil 'project--dir-history)))) (if (equal pr-dir dir-choice) (read-directory-name "Select directory: " default-directory nil t) pr-dir))) +(defvar project--name-history) + (defun project-prompt-project-name () "Prompt the user for a project, by name, that is one of the known project roots. The project is chosen among projects known from the project list, see `project-list-file'. It's also possible to enter an arbitrary directory not in the list." (let* ((dir-choice "... (choose a dir)") + project--name-history (choices (let (ret) - (dolist (dir (project-known-project-roots)) + ;; Iterate in reverse order so project--name-history is in + ;; the correct order. + (dolist (dir (reverse (project-known-project-roots))) ;; we filter out directories that no longer map to a project, ;; since they don't have a clean project-name. - (if-let (proj (project--find-in-directory dir)) - (push (cons (project-name proj) proj) ret))) + (when-let (proj (project--find-in-directory dir)) + (let ((name (project-name proj))) + (push name project--name-history) + (push (cons name proj) ret)))) ret)) ;; XXX: Just using this for the category (for the substring ;; completion style). @@ -1798,7 +1816,9 @@ project-prompt-project-name (pr-name "")) (while (equal pr-name "") ;; If the user simply pressed RET, do this again until they don't. - (setq pr-name (completing-read "Select project: " table nil t))) + (setq pr-name + (let ((history-add-new-input nil)) + (completing-read "Select project: " table nil t nil 'project--name-history)))) (if (equal pr-name dir-choice) (read-directory-name "Select directory: " default-directory nil t) (let ((proj (assoc pr-name choices))) @@ -2064,6 +2084,7 @@ project-switch-project When called in a program, it will use the project corresponding to directory DIR." (interactive (list (funcall project-prompter))) + (project--add-dir dir) (let ((command (if (symbolp project-switch-commands) project-switch-commands (project--switch-project-command))) -- 2.39.3
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.