From 9cb47b7476dfbaf0e9e45001d174da848ebf904d Mon Sep 17 00:00:00 2001 From: Spencer Baugh Date: Thu, 17 Aug 2023 15:41:04 -0400 Subject: [PATCH] Support adjusting file-name-history to the current project This add project-file-name-history-relativize which has the effect described in its docstring. This implements a sort of sharing of file-name-history between projects. * lisp/progmodes/project.el (project-file-name-history-relativize): Add. (bug#63829) (project--expand-file-name): Add. (project--read-file-cpd-relative): Move history manipulations to project--read-file-name. (project--read-file-name): Add and use project-file-name-history-relativize. (project-find-file-in): Use project--read-file-name. (project-find-dir): Use project--read-file-name. --- lisp/progmodes/project.el | 62 +++++++++++++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 12 deletions(-) diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el index c1ce5ce7b1f..e0f1f995ff2 100644 --- a/lisp/progmodes/project.el +++ b/lisp/progmodes/project.el @@ -1046,6 +1046,26 @@ project-read-file-name-function :group 'project :version "27.1") +(defcustom project-file-name-history-relativize nil + "If non-nil, paths in `file-name-history' are adjusted for the current project. + +When non-nil and in `project-find-file' or `project-find-dir', +paths in `file-name-history' are adjusted to be relative to +whatever the current project is, instead of the project which +added those paths. This only affects history entries added by +earlier calls to `project-find-file' or `project-find-dir'. + +When `project-read-file-name-function' is +`project--read-file-cpd-relative' (the default), this has the +effect of sharing more history between projects.") + +(defun project--expand-file-name (filename project) + (when-let ((old-root (get-text-property 0 'project filename))) + (abbreviate-file-name + (expand-file-name + (file-relative-name filename old-root) + (project-root project))))) + (defun project--read-file-cpd-relative (prompt all-files &optional predicate hist mb-default) @@ -1079,8 +1099,7 @@ project--read-file-cpd-relative (new-collection (project--file-completion-table substrings)) (abbr-cpd (abbreviate-file-name common-parent-directory)) (abbr-cpd-length (length abbr-cpd)) - (relname (cl-letf ((history-add-new-input nil) - ((symbol-value hist) + (relname (cl-letf (((symbol-value hist) (mapcan (lambda (s) (and (string-prefix-p abbr-cpd s) @@ -1092,8 +1111,6 @@ project--read-file-cpd-relative predicate hist mb-default))) (absname (expand-file-name relname common-parent-directory))) - (when (and hist history-add-new-input) - (add-to-history hist (abbreviate-file-name absname))) absname)) (defun project--read-file-absolute (prompt @@ -1104,6 +1121,26 @@ project--read-file-absolute predicate hist mb-default)) +(defun project--read-file-name (project prompt + all-files &optional predicate + hist mb-default) + "Call `project-read-file-name-function' with project-relative history." + (let ((file + (cl-letf ((history-add-new-input nil) + ((symbol-value hist) + (if project-file-name-history-relativize + (mapcar + (lambda (f) + (or (project--expand-file-name f project) f)) + (symbol-value hist)) + (symbol-value hist)))) + (funcall project-read-file-name-function + prompt all-files predicate hist mb-default)))) + (when (and hist history-add-new-input) + (add-to-history hist + (propertize file 'project (project-root project)))) + file)) + (defun project-find-file-in (suggested-filename dirs project &optional include-all) "Complete a file name in DIRS in PROJECT and visit the result. @@ -1124,9 +1161,10 @@ project-find-file-in dirs) (project-files project dirs))) (completion-ignore-case read-file-name-completion-ignore-case) - (file (funcall project-read-file-name-function - "Find file" all-files nil 'file-name-history - suggested-filename))) + (file (project--read-file-name + project "Find file" + all-files nil 'file-name-history + suggested-filename))) (if (string= file "") (user-error "You didn't specify the file") (find-file file)))) @@ -1158,11 +1196,11 @@ project-find-dir ;; https://stackoverflow.com/a/50685235/615245 for possible ;; implementation. (all-dirs (mapcar #'file-name-directory all-files)) - (dir (funcall project-read-file-name-function - "Dired" - ;; Some completion UIs show duplicates. - (delete-dups all-dirs) - nil 'file-name-history))) + (dir (project--read-file-name + project "Dired" + ;; Some completion UIs show duplicates. + (delete-dups all-dirs) + nil 'file-name-history))) (dired dir))) ;;;###autoload -- 2.39.3