Subject: bug#41868: [PATCH] Add project-clean-up command

From: "Philip K." <[email-masked]>
Date: Mon, 15 Jun 2020 20:18:24 +0200

Dmitry Gutov <[email-masked]> writes:

> On 15.06.2020 13:00, Philip K. wrote:
>> I wanted to propose a command for project.el to kill all opened buffers
>> in a project, called when one finishes working on some specific
>> code-base. I gave it the name "project-clean-up", but maybe it should be
>> renamed?
>
> I've just looked it up, and Projectile has a command called 
> project-kill-buffers. Perhaps follow its example?
>
> https://github.com/bbatsov/projectile/blob/33bc91e7518fb8cecd89580f16e0ac21799de2c2/projectile.el#L3642
>
> I somewhat prefer the explicit naming. Looking at it, you won't mistake 
> it for a command that removes build artefacts, or "tidies up" the code, 
> for instance.

I changed the name to project-kill-buffer in the patch below. It kind of
feels like a ripoff now, but there probably aren't that many way to
implement the idea either.

Hope I didn't miss any of the issues brought up.

-- 
	Philip K.

>From 35c10566382dd31442fd59bf8e3ee695dc595386 Mon Sep 17 00:00:00 2001
From: Philip K <[email-masked]>
Date: Fri, 12 Jun 2020 23:37:51 +0200
Subject: [PATCH] Add project-kill-buffers command

---
 lisp/progmodes/project.el | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el
index f3df44fa7b..6fe5dfa880 100644
--- a/lisp/progmodes/project.el
+++ b/lisp/progmodes/project.el
@@ -744,6 +744,39 @@ project-compile
          (default-directory (project-root pr)))
     (compile command comint)))
 
+(defcustom project-spare-buffers-regexps
+  '("\\*Help\\*")
+  "List of regular expressions to be ignored by `project-clean-up'."
+  :type '(repeat regexp)
+  :version "28.1")
+
+(defun project--buffer-list (pr)
+  "Return a list of all buffers in project PR."
+  (let ((root (project-root pr))
+        bufs)
+    (dolist (buf (buffer-list))
+      (let ((filename (or (buffer-file-name buf)
+                          (buffer-local-value 'default-directory buf))))
+        (when (and filename (file-in-directory-p filename root))
+          (push buf bufs))))
+    (nreverse bufs)))
+
+;;;###autoload
+(defun project-kill-buffers ()
+  "Kill all live buffers of a project."
+  (interactive)
+  (let* ((pr (project-current t))
+         (bufs (project--buffer-list pr)))
+    (with-temp-buffer
+      (setf (buffer-name) " *project buffer list*")
+      (when (yes-or-no-p (format "Kill %d buffers in %s? "
+                                 (length bufs) (project-root pr)))
+        (dolist (buf bufs)
+          (unless (seq-some (lambda (re)
+                              (string-match-p re (buffer-name buf)))
+                            project-spare-buffers-regexps)
+            (kill-buffer buf)))))))
+
 
 ;;; Project list
 
-- 
2.20.1