Persist scratch buffer across sessions
- Adds doom/open-project-scratch-buffer (persistent project scratch buffers) - Prefix arg = open scratch buffer in current window, for both doom/open-scratch-buffer and doom/open-project-scratch-buffer. - Rename doom/delete-scratch-files -> doom/delete-persistent-scratch-file - Remove doom-scratch-buffer-display-fn - Rename doom-scratch-files-dir -> doom-scratch-dir - Add SPC p s keybind to open project scratch buffer
This commit is contained in:
parent
20a63a35ab
commit
6cd30c926b
3 changed files with 104 additions and 51 deletions
|
@ -1,12 +1,12 @@
|
|||
;;; core/autoload/scratch.el -*- lexical-binding: t; -*-
|
||||
|
||||
(defvar doom-scratch-files-dir (concat doom-etc-dir "scratch/")
|
||||
"Where to store project scratch files, created by
|
||||
`doom/open-project-scratch-buffer'.")
|
||||
(defvar doom-scratch-default-file "__default"
|
||||
"The default file name for a project-less scratch buffer.
|
||||
|
||||
(defvar doom-scratch-buffer-display-fn #'display-buffer
|
||||
"The function to use to display the scratch buffer. Must accept one argument:
|
||||
the buffer to display.")
|
||||
Will be saved in `doom-scratch-dir'.")
|
||||
|
||||
(defvar doom-scratch-dir (concat doom-etc-dir "scratch")
|
||||
"Where to save persistent scratch buffers.")
|
||||
|
||||
(defvar doom-scratch-buffer-major-mode nil
|
||||
"What major mode to use in scratch buffers. This can be one of the
|
||||
|
@ -16,77 +16,129 @@ following:
|
|||
nil Uses `fundamental-mode'
|
||||
MAJOR-MODE Any major mode symbol")
|
||||
|
||||
(defvar doom-scratch-buffers nil
|
||||
"A list of active scratch buffers.")
|
||||
|
||||
(defvar-local doom-scratch-current-project nil
|
||||
"The name of the project associated with the current scratch buffer.")
|
||||
|
||||
(defvar doom-scratch-buffer-hook ()
|
||||
"The hooks to run after a scratch buffer is made.")
|
||||
"The hooks to run after a scratch buffer is created.")
|
||||
|
||||
(defun doom--load-persistent-scratch-buffer (name)
|
||||
(let ((scratch-file (expand-file-name (or name doom-scratch-default-file)
|
||||
doom-scratch-dir)))
|
||||
(make-directory doom-scratch-dir t)
|
||||
(if (not (file-readable-p scratch-file))
|
||||
nil
|
||||
(erase-buffer)
|
||||
(insert-file-contents scratch-file)
|
||||
(set-auto-mode)
|
||||
t)))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom-scratch-buffer (&optional mode directory project-name)
|
||||
"Return a scratchpad buffer in major MODE."
|
||||
(let* ((buffer-name (if project-name
|
||||
(format "*doom:scratch (%s)*" project-name)
|
||||
"*doom:scratch*"))
|
||||
(buffer (get-buffer buffer-name)))
|
||||
(with-current-buffer (get-buffer-create buffer-name)
|
||||
(unless buffer
|
||||
(setq buffer (current-buffer)
|
||||
default-directory directory
|
||||
doom-scratch-current-project project-name)
|
||||
(setq doom-scratch-buffers (cl-delete-if-not #'buffer-live-p doom-scratch-buffers))
|
||||
(cl-pushnew buffer doom-scratch-buffers)
|
||||
(doom--load-persistent-scratch-buffer project-name)
|
||||
(when (and (eq major-mode 'fundamental-mode)
|
||||
(functionp mode))
|
||||
(funcall mode))
|
||||
(add-hook 'kill-buffer-hook #'doom|persist-scratch-buffer nil 'local)
|
||||
(run-hooks 'doom-scratch-buffer-created-hook))
|
||||
buffer)))
|
||||
|
||||
|
||||
;;
|
||||
;; Library
|
||||
;;; Persistent scratch buffer
|
||||
|
||||
;;;###autoload
|
||||
(defun doom-scratch-buffer (&optional file mode text)
|
||||
"Return a scratchpad buffer in major MODE with TEXT in it.
|
||||
(defun doom|persist-scratch-buffer ()
|
||||
"Save the current buffer to `doom-scratch-dir'."
|
||||
(write-region
|
||||
(point-min) (point-max)
|
||||
(expand-file-name (or doom-scratch-current-project doom-scratch-default-file)
|
||||
doom-scratch-dir)))
|
||||
|
||||
If FILE is a valid path, open it as if it were a persistent scratchpad."
|
||||
(if file (setq file (file-truename file)))
|
||||
(let ((buffer
|
||||
(if file
|
||||
(with-current-buffer (find-file-noselect file)
|
||||
(rename-buffer (format "*doom:scratch (%s)*" (file-name-nondirectory file)))
|
||||
(current-buffer))
|
||||
(get-buffer-create "*doom:scratch*"))))
|
||||
;;;###autoload
|
||||
(defun doom|persist-scratch-buffers ()
|
||||
"Save all scratch buffers to `doom-scratch-dir'."
|
||||
(dolist (buffer (cl-delete-if-not #'buffer-live-p doom-scratch-buffers))
|
||||
(with-current-buffer buffer
|
||||
(when (and (functionp mode)
|
||||
(not (eq major-mode mode)))
|
||||
(funcall mode))
|
||||
(when text
|
||||
(insert text))
|
||||
(run-hooks 'doom-scratch-buffer-hook)
|
||||
(current-buffer))))
|
||||
(doom|persist-scratch-buffer))))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom/open-scratch-buffer (&optional arg)
|
||||
"Opens a scratch pad window in the same major-mode.
|
||||
(add-hook 'kill-emacs-hook #'doom|persist-scratch-buffers)
|
||||
|
||||
If ARG (universal argument), then open a persistent scratch pad buffer. You'll
|
||||
be prompted for its name, or to open a previously created. These are stored in
|
||||
`doom-scratch-files-dir'.
|
||||
|
||||
If a region is active, copy its contents to the scratch pad."
|
||||
;;
|
||||
;;; Commands
|
||||
|
||||
;;;###autoload
|
||||
(defun doom/open-scratch-buffer (&optional arg project-p)
|
||||
"Opens the (persistent) scratch buffer in a popup.
|
||||
|
||||
If ARG, switch to it in the current window."
|
||||
(interactive "P")
|
||||
(let (projectile-enable-caching)
|
||||
(funcall
|
||||
doom-scratch-buffer-display-fn
|
||||
(if arg
|
||||
#'switch-to-buffer
|
||||
#'pop-to-buffer)
|
||||
(doom-scratch-buffer
|
||||
(when arg
|
||||
(if-let* ((file (read-file-name "Open scratch file > " doom-scratch-files-dir "scratch")))
|
||||
file
|
||||
(user-error "Aborting")))
|
||||
(cond ((eq doom-scratch-buffer-major-mode t)
|
||||
(unless (or buffer-read-only
|
||||
(derived-mode-p 'special-mode)
|
||||
(string-match-p "^ ?\\*" (buffer-name)))
|
||||
major-mode))
|
||||
((null doom-scratch-buffer-major-mode) nil)
|
||||
((null doom-scratch-buffer-major-mode)
|
||||
nil)
|
||||
((symbolp doom-scratch-buffer-major-mode)
|
||||
doom-scratch-buffer-major-mode))
|
||||
(and (region-active-p)
|
||||
(buffer-substring-no-properties
|
||||
(region-beginning) (region-end)))))))
|
||||
default-directory
|
||||
(when project-p
|
||||
(doom-project-name))))))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom/switch-to-scratch-buffer (&optional arg)
|
||||
"Switches to a scratch pad buffer in the current window.
|
||||
(defun doom/open-project-scratch-buffer (&optional arg)
|
||||
"Opens the (persistent) project scratch buffer in a popup.
|
||||
|
||||
Otherwise, does exactly what `doom/open-scratch-buffer' does."
|
||||
If ARG, switch to it in the current window."
|
||||
(interactive "P")
|
||||
(let ((doom-scratch-buffer-display-fn #'switch-to-buffer))
|
||||
(doom/open-scratch-buffer arg)))
|
||||
(doom/open-scratch-buffer arg 'project))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom/delete-scratch-files ()
|
||||
"Deletes all scratch buffers in `doom-scratch-files-dir'."
|
||||
(defun doom/revert-scratch-buffer ()
|
||||
"Revert scratch buffer to last persistent state."
|
||||
(interactive)
|
||||
(dolist (file (directory-files doom-scratch-files-dir t "^[^.]" t))
|
||||
(unless (string-match-p "^\\*doom:scratch" (buffer-name))
|
||||
(user-error "Not in a scratch buffer"))
|
||||
(when (doom--load-persistent-scratch-buffer doom-scratch-current-project)
|
||||
(message "Reloaded scratch buffer")))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom/delete-persistent-scratch-file (&optional arg)
|
||||
"Deletes a scratch buffer file in `doom-scratch-dir'.
|
||||
|
||||
If prefix ARG, delete all persistent scratches."
|
||||
(interactive)
|
||||
(if arg
|
||||
(progn
|
||||
(delete-directory doom-scratch-dir t)
|
||||
(message "Cleared %S" (abbreviate-file-name doom-scratch-dir)))
|
||||
(make-directory doom-scratch-dir t)
|
||||
(let ((file (read-file-name "Delete scratch file > " doom-scratch-dir "scratch")))
|
||||
(if (not (file-exists-p file))
|
||||
(message "%S does not exist" (abbreviate-file-name file))
|
||||
(delete-file file)
|
||||
(message "Deleted '%s'" (file-name-nondirectory file))))
|
||||
(message "Successfully deleted %S" (abbreviate-file-name file))))))
|
||||
|
|
|
@ -735,6 +735,7 @@
|
|||
:desc "Find other file" "o" #'projectile-find-other-file
|
||||
:desc "Switch project" "p" #'projectile-switch-project
|
||||
:desc "Find recent project files" "r" #'projectile-recentf
|
||||
:desc "Scratch buffer" "s" #'doom/open-project-scratch-buffer
|
||||
:desc "List project tasks" "t" #'+default/project-tasks
|
||||
(:prefix ("x" . "terminal")
|
||||
:desc "Open eshell in project" "e" #'projectile-run-eshell
|
||||
|
|
|
@ -136,7 +136,7 @@ prevent the popup(s) from messing up the UI (or vice versa)."
|
|||
:slot -1 :vslot -2 :ttl 0)
|
||||
("^\\*Compil\\(?:ation\\|e-Log\\)"
|
||||
:vslot -2 :size 0.3 :ttl nil :quit t)
|
||||
("^\\*\\(?:\\(?:doom:\\)?scratch\\|Messages\\)"
|
||||
("^\\*\\(?:scratch\\|Messages\\)"
|
||||
:autosave t :ttl nil)
|
||||
("^\\*Man "
|
||||
:size 0.45 :vslot -3 :ttl 0 :quit t :select t)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue