mirror of
https://github.com/chrisbarrett/nursery
synced 2025-08-29 14:33:30 -05:00
Add org-roam-gc
This commit is contained in:
136
lisp/org-roam-gc.el
Normal file
136
lisp/org-roam-gc.el
Normal file
@@ -0,0 +1,136 @@
|
||||
;;; org-roam-gc.el --- Clean up empty roam files -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2022 Chris Barrett
|
||||
|
||||
;; Author: Chris Barrett <chris+emacs@walrus.cool>
|
||||
|
||||
;; Homepage: https://github.com/chrisbarrett/nursery
|
||||
|
||||
;; Version: 0.0.1-pre
|
||||
|
||||
;; Package-Requires: ((emacs "27.1") (org "9.5.3") (org-roam "2.2.2"))
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; Simple package that deletes dailies files that don't have anything in them.
|
||||
|
||||
;; Example configuration:
|
||||
;;
|
||||
;; (use-package org-roam-gc
|
||||
;; :after org-roam
|
||||
;; :demand t
|
||||
;; :hook (org-mode . org-roam-gc-automatically))
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'org-roam)
|
||||
(require 'org-roam-dailies)
|
||||
|
||||
(defconst org-roam-gc-prompt-before-deleting-p nil
|
||||
"Whether to prompt before removing files when run interactively.")
|
||||
|
||||
(defconst org-roam-gc-debug nil
|
||||
"Whether to output extra messages for debugging purposes.")
|
||||
|
||||
(defun org-roam-gc--empty-content-p (buf)
|
||||
(with-current-buffer buf
|
||||
(save-restriction
|
||||
(widen)
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(while (equal 'property-drawer (org-element-type (org-element-at-point)))
|
||||
(org-forward-element))
|
||||
(while (and (equal 'keyword (org-element-type (org-element-at-point)))
|
||||
(ignore-errors
|
||||
(org-forward-element)
|
||||
t)))
|
||||
(or (eobp)
|
||||
(string-blank-p (buffer-substring (1+ (point)) (point-max))))))))
|
||||
|
||||
(defun org-roam-gc--empty-file-content-p (file)
|
||||
(with-temp-buffer
|
||||
(insert-file-contents file)
|
||||
(org-roam-gc--empty-content-p (current-buffer))))
|
||||
|
||||
(defun org-roam-gc-dailies-files ()
|
||||
(require 'org-roam)
|
||||
(require 'org-roam-dailies)
|
||||
(let ((path (expand-file-name org-roam-dailies-directory org-roam-directory)))
|
||||
(seq-filter #'file-regular-p (directory-files path t))))
|
||||
|
||||
(defmacro org-roam-gc--log (msg &rest args)
|
||||
`(when org-roam-gc-debug
|
||||
(message (concat "org-roam-gc: " ,msg) ,@args)
|
||||
nil))
|
||||
|
||||
(defun org-roam-gc--file-editing-p (file)
|
||||
(when-let* ((buf (find-buffer-visiting file)))
|
||||
(or (buffer-modified-p buf)
|
||||
(get-buffer-window-list buf))))
|
||||
|
||||
(defun org-roam-gc--remove-file (file confirm-p)
|
||||
(let ((file (expand-file-name file)))
|
||||
(cond
|
||||
((org-roam-gc--file-editing-p file)
|
||||
(org-roam-gc--log "Skipping open file: %s" file))
|
||||
|
||||
(t
|
||||
(org-roam-gc--log "Removing file: %s" file)
|
||||
(with-current-buffer (find-file file)
|
||||
(when (or (not confirm-p)
|
||||
(y-or-n-p (format "Delete file `%s'? " (abbreviate-file-name file))))
|
||||
(kill-buffer)
|
||||
(delete-file file)))
|
||||
t))))
|
||||
|
||||
(defun org-roam-gc (&optional interactive)
|
||||
"Delete empty org-roam dailies.
|
||||
|
||||
Optional arg INTERACTIVE determines whether to query before
|
||||
removing files."
|
||||
(interactive "p")
|
||||
(let ((count
|
||||
(thread-last (org-roam-gc-dailies-files)
|
||||
(seq-filter #'org-roam-gc--empty-file-content-p)
|
||||
(seq-filter (lambda (file)
|
||||
(org-roam-gc--remove-file file (and interactive
|
||||
org-roam-gc-prompt-before-deleting-p))))
|
||||
(length))))
|
||||
(cond
|
||||
(interactive
|
||||
(message "Deleted %s file%s" count (if (eq 1 count) "" "s")))
|
||||
((< 0 count)
|
||||
(message "org-roam-gc deleted %s file%s" count (if (eq 1 count) "" "s"))))))
|
||||
|
||||
(defun org-roam-gc--maybe-remove-this-file ()
|
||||
(when-let* ((file (buffer-file-name)))
|
||||
(cond
|
||||
((not (derived-mode-p 'org-mode))
|
||||
(org-roam-gc--log "Skipping non-org file: %s" file))
|
||||
((and (org-roam-gc--empty-content-p (current-buffer))
|
||||
(org-roam-dailies--daily-note-p))
|
||||
(org-roam-gc--log "Removing file: %s" file)
|
||||
(delete-file (buffer-file-name)))
|
||||
(t
|
||||
(org-roam-gc--log "Skipping file: %s" file)))))
|
||||
|
||||
;;;###autoload
|
||||
(defun org-roam-gc-automatically ()
|
||||
(add-hook 'kill-buffer-hook #'org-roam-gc--maybe-remove-this-file nil t))
|
||||
|
||||
(provide 'org-roam-gc)
|
||||
|
||||
;;; org-roam-gc.el ends here
|
Reference in New Issue
Block a user