diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el index b6a886f731..5b1c92ec9d 100644 --- a/lisp/progmodes/project.el +++ b/lisp/progmodes/project.el @@ -895,6 +895,22 @@ project-vc-dir (interactive) (vc-dir (project-root (project-current t)))) +(defvar-local project--origin-project-root nil) + +(defun project--find-existing-buffer (mode root) + (seq-find + (lambda (buf) + (and + (buffer-live-p buf) + (provided-mode-derived-p + (buffer-local-value 'major-mode buf) + mode) + (equal (buffer-local-value + 'project--origin-project-root + buf) + root))) + (buffer-list))) + ;;;###autoload (defun project-shell () "Start an inferior shell in the current project's root directory. @@ -904,15 +920,16 @@ project-shell if one already exists." (interactive) (let* ((default-directory (project-root (project-current t))) - (default-project-shell-name - (concat "*" (file-name-nondirectory - (directory-file-name - (file-name-directory default-directory))) - "-shell*")) - (shell-buffer (get-buffer default-project-shell-name))) - (if (and shell-buffer (not current-prefix-arg)) - (pop-to-buffer-same-window shell-buffer) - (shell (generate-new-buffer-name default-project-shell-name))))) + (existing-buffer (unless current-prefix-arg + (project--find-existing-buffer 'shell-mode + default-directory)))) + (if existing-buffer + (pop-to-buffer-same-window existing-buffer) + (let* ((uniquify-list-buffers-directory-modes + (cons 'shell-mode uniquify-list-buffers-directory-modes))) + (shell (create-file-buffer (expand-file-name "*shell*"))) + (setq list-buffers-directory (expand-file-name "*shell*" default-directory)) + (setq project--origin-project-root default-directory))))) ;;;###autoload (defun project-eshell () @@ -922,17 +939,22 @@ project-eshell With \\[universal-argument] prefix arg, create a new Eshell buffer even if one already exists." (interactive) + (require 'eshell) (defvar eshell-buffer-name) (let* ((default-directory (project-root (project-current t))) - (eshell-buffer-name - (concat "*" (file-name-nondirectory - (directory-file-name - (file-name-directory default-directory))) - "-eshell*")) - (eshell-buffer (get-buffer eshell-buffer-name))) - (if (and eshell-buffer (not current-prefix-arg)) - (pop-to-buffer-same-window eshell-buffer) - (eshell t)))) + (existing-buffer (unless current-prefix-arg + (project--find-existing-buffer 'eshell-mode + default-directory)))) + (if existing-buffer + (pop-to-buffer-same-window existing-buffer) + (let* ((uniquify-list-buffers-directory-modes + (cons 'eshell-mode uniquify-list-buffers-directory-modes)) + (buf (create-file-buffer (expand-file-name eshell-buffer-name)))) + (pop-to-buffer-same-window buf) + (unless (derived-mode-p 'eshell-mode) + (eshell-mode)) + (setq list-buffers-directory (expand-file-name eshell-buffer-name default-directory)) + (setq project--origin-project-root default-directory))))) ;;;###autoload (defun project-async-shell-command ()