2017-09-27 01:21:10 +02:00
|
|
|
;;; core/autoload/scratch.el -*- lexical-binding: t; -*-
|
|
|
|
|
2019-04-17 11:01:51 -04:00
|
|
|
(defvar doom-scratch-default-file "__default"
|
|
|
|
"The default file name for a project-less scratch buffer.
|
2017-09-27 01:21:10 +02:00
|
|
|
|
2019-04-17 11:01:51 -04:00
|
|
|
Will be saved in `doom-scratch-dir'.")
|
|
|
|
|
|
|
|
(defvar doom-scratch-dir (concat doom-etc-dir "scratch")
|
|
|
|
"Where to save persistent scratch buffers.")
|
2018-03-28 18:38:55 -04:00
|
|
|
|
2020-02-25 20:30:23 -05:00
|
|
|
(defvar doom-scratch-initial-major-mode nil
|
|
|
|
"What major mode to start fresh scratch buffers in.
|
|
|
|
|
|
|
|
Scratch buffers preserve their last major mode, however, so this only affects
|
|
|
|
the first, fresh scratch buffer you create. This accepts:
|
2018-03-28 18:38:55 -04:00
|
|
|
|
|
|
|
t Inherits the major mode of the last buffer you had selected.
|
|
|
|
nil Uses `fundamental-mode'
|
|
|
|
MAJOR-MODE Any major mode symbol")
|
2018-03-07 21:07:38 -05:00
|
|
|
|
2019-04-17 11:01:51 -04:00
|
|
|
(defvar doom-scratch-buffers nil
|
|
|
|
"A list of active scratch buffers.")
|
|
|
|
|
2019-08-15 01:02:00 -04:00
|
|
|
(defvar doom-scratch-current-project nil
|
2019-04-17 11:01:51 -04:00
|
|
|
"The name of the project associated with the current scratch buffer.")
|
|
|
|
|
2017-09-27 01:21:10 +02:00
|
|
|
(defvar doom-scratch-buffer-hook ()
|
2019-04-17 11:01:51 -04:00
|
|
|
"The hooks to run after a scratch buffer is created.")
|
|
|
|
|
2019-08-15 01:02:00 -04:00
|
|
|
|
2019-04-17 11:01:51 -04:00
|
|
|
(defun doom--load-persistent-scratch-buffer (name)
|
2019-08-15 01:02:00 -04:00
|
|
|
(setq-local doom-scratch-current-project
|
|
|
|
(or name
|
|
|
|
doom-scratch-default-file))
|
2020-02-25 20:30:23 -05:00
|
|
|
(let ((smart-scratch-file
|
|
|
|
(expand-file-name (concat doom-scratch-current-project ".el")
|
2019-08-15 01:02:00 -04:00
|
|
|
doom-scratch-dir)))
|
2019-04-17 11:01:51 -04:00
|
|
|
(make-directory doom-scratch-dir t)
|
2020-05-08 14:44:48 -04:00
|
|
|
(when (file-readable-p smart-scratch-file)
|
|
|
|
(message "Reading %s" smart-scratch-file)
|
|
|
|
(cl-destructuring-bind (content point mode)
|
|
|
|
(with-temp-buffer
|
|
|
|
(save-excursion (insert-file-contents smart-scratch-file))
|
|
|
|
(read (current-buffer)))
|
|
|
|
(erase-buffer)
|
|
|
|
(funcall mode)
|
|
|
|
(insert content)
|
|
|
|
(goto-char point)
|
|
|
|
t))))
|
2019-04-17 11:01:51 -04:00
|
|
|
|
|
|
|
;;;###autoload
|
2020-03-03 12:41:38 -05:00
|
|
|
(defun doom-scratch-buffer (&optional dont-restore-p mode directory project-name)
|
2019-04-17 11:01:51 -04:00
|
|
|
"Return a scratchpad buffer in major MODE."
|
2020-02-25 20:30:23 -05:00
|
|
|
(let* ((buffer-name (if project-name
|
|
|
|
(format "*doom:scratch (%s)*" project-name)
|
|
|
|
"*doom:scratch*"))
|
|
|
|
(buffer (get-buffer buffer-name)))
|
|
|
|
(with-current-buffer
|
|
|
|
(or buffer (get-buffer-create buffer-name))
|
|
|
|
(setq default-directory directory)
|
|
|
|
(setq-local so-long--inhibited t)
|
2020-03-03 12:41:38 -05:00
|
|
|
(if dont-restore-p
|
|
|
|
(erase-buffer)
|
|
|
|
(unless buffer
|
|
|
|
(doom--load-persistent-scratch-buffer project-name)
|
|
|
|
(when (and (eq major-mode 'fundamental-mode)
|
|
|
|
(functionp mode))
|
|
|
|
(funcall mode))))
|
2020-02-25 20:30:23 -05:00
|
|
|
(cl-pushnew (current-buffer) doom-scratch-buffers)
|
|
|
|
(add-transient-hook! 'doom-switch-buffer-hook (doom-persist-scratch-buffers-h))
|
|
|
|
(add-transient-hook! 'doom-switch-window-hook (doom-persist-scratch-buffers-h))
|
|
|
|
(add-hook 'kill-buffer-hook #'doom-persist-scratch-buffer-h nil 'local)
|
|
|
|
(run-hooks 'doom-scratch-buffer-created-hook)
|
|
|
|
(current-buffer))))
|
2017-09-27 01:21:10 +02:00
|
|
|
|
2018-03-07 21:07:38 -05:00
|
|
|
|
|
|
|
;;
|
2019-04-17 11:01:51 -04:00
|
|
|
;;; Persistent scratch buffer
|
|
|
|
|
|
|
|
;;;###autoload
|
2019-07-18 15:27:20 +02:00
|
|
|
(defun doom-persist-scratch-buffer-h ()
|
2019-04-17 11:01:51 -04:00
|
|
|
"Save the current buffer to `doom-scratch-dir'."
|
2020-02-25 20:30:23 -05:00
|
|
|
(let ((content (buffer-substring-no-properties (point-min) (point-max)))
|
|
|
|
(point (point))
|
|
|
|
(mode major-mode))
|
|
|
|
(with-temp-file
|
|
|
|
(expand-file-name (concat (or doom-scratch-current-project
|
|
|
|
doom-scratch-default-file)
|
|
|
|
".el")
|
|
|
|
doom-scratch-dir)
|
|
|
|
(prin1 (list content
|
|
|
|
point
|
|
|
|
mode)
|
|
|
|
(current-buffer)))))
|
2018-03-07 21:07:38 -05:00
|
|
|
|
|
|
|
;;;###autoload
|
2019-07-18 15:27:20 +02:00
|
|
|
(defun doom-persist-scratch-buffers-h ()
|
2019-04-17 11:01:51 -04:00
|
|
|
"Save all scratch buffers to `doom-scratch-dir'."
|
2019-08-15 01:02:00 -04:00
|
|
|
(setq doom-scratch-buffers
|
|
|
|
(cl-delete-if-not #'buffer-live-p doom-scratch-buffers))
|
2019-05-15 20:53:11 -04:00
|
|
|
(dolist (buffer doom-scratch-buffers)
|
2018-03-07 21:07:38 -05:00
|
|
|
(with-current-buffer buffer
|
2019-07-18 15:27:20 +02:00
|
|
|
(doom-persist-scratch-buffer-h))))
|
2017-09-27 01:21:10 +02:00
|
|
|
|
2019-08-15 01:07:45 -04:00
|
|
|
;;;###autoload
|
|
|
|
(defun doom-persist-scratch-buffers-after-switch-h ()
|
|
|
|
"Kill scratch buffers when they are no longer visible, saving them to disk."
|
|
|
|
(unless (cl-some #'get-buffer-window doom-scratch-buffers)
|
|
|
|
(mapc #'kill-buffer doom-scratch-buffers)
|
|
|
|
(remove-hook 'doom-switch-buffer-hook #'doom-persist-scratch-buffers-after-switch-h)))
|
|
|
|
|
2017-09-27 01:21:10 +02:00
|
|
|
;;;###autoload
|
2019-04-24 18:04:17 -04:00
|
|
|
(unless noninteractive
|
2019-07-18 15:27:20 +02:00
|
|
|
(add-hook 'kill-emacs-hook #'doom-persist-scratch-buffers-h))
|
2017-09-27 01:21:10 +02:00
|
|
|
|
2018-02-02 19:10:43 -05:00
|
|
|
|
2019-04-17 11:01:51 -04:00
|
|
|
;;
|
|
|
|
;;; Commands
|
|
|
|
|
2020-02-02 02:05:20 -05:00
|
|
|
(defvar projectile-enable-caching)
|
2019-04-17 11:01:51 -04:00
|
|
|
;;;###autoload
|
2020-03-03 12:41:38 -05:00
|
|
|
(defun doom/open-scratch-buffer (&optional arg project-p same-window-p)
|
2019-12-25 21:04:52 -05:00
|
|
|
"Pop up a persistent scratch buffer.
|
2019-04-17 11:01:51 -04:00
|
|
|
|
2020-03-03 12:41:38 -05:00
|
|
|
If passed the prefix ARG, do not restore the last scratch buffer.
|
2019-04-19 19:55:25 -04:00
|
|
|
If PROJECT-P is non-nil, open a persistent scratch buffer associated with the
|
|
|
|
current project."
|
2018-02-02 19:10:43 -05:00
|
|
|
(interactive "P")
|
2018-03-07 21:07:38 -05:00
|
|
|
(let (projectile-enable-caching)
|
|
|
|
(funcall
|
2020-03-03 12:41:38 -05:00
|
|
|
(if same-window-p
|
2019-04-17 11:01:51 -04:00
|
|
|
#'switch-to-buffer
|
|
|
|
#'pop-to-buffer)
|
2018-03-07 21:07:38 -05:00
|
|
|
(doom-scratch-buffer
|
2020-03-03 12:41:38 -05:00
|
|
|
arg
|
2020-02-26 09:19:08 -05:00
|
|
|
(cond ((eq doom-scratch-initial-major-mode t)
|
2018-03-28 18:38:55 -04:00
|
|
|
(unless (or buffer-read-only
|
|
|
|
(derived-mode-p 'special-mode)
|
|
|
|
(string-match-p "^ ?\\*" (buffer-name)))
|
|
|
|
major-mode))
|
2020-02-26 09:19:08 -05:00
|
|
|
((null doom-scratch-initial-major-mode)
|
2019-04-17 11:01:51 -04:00
|
|
|
nil)
|
2020-02-26 09:19:08 -05:00
|
|
|
((symbolp doom-scratch-initial-major-mode)
|
|
|
|
doom-scratch-initial-major-mode))
|
2019-04-17 11:01:51 -04:00
|
|
|
default-directory
|
|
|
|
(when project-p
|
|
|
|
(doom-project-name))))))
|
2017-09-27 01:21:10 +02:00
|
|
|
|
2019-05-20 15:54:40 -04:00
|
|
|
;;;###autoload
|
2020-03-03 12:41:38 -05:00
|
|
|
(defun doom/switch-to-scratch-buffer (&optional arg project-p)
|
2019-07-21 15:47:40 +02:00
|
|
|
"Like `doom/open-scratch-buffer', but switches to it in the current window.
|
|
|
|
|
2020-03-03 12:41:38 -05:00
|
|
|
If passed the prefix ARG, do not restore the last scratch buffer."
|
2019-07-21 15:47:40 +02:00
|
|
|
(interactive "P")
|
2020-03-03 12:41:38 -05:00
|
|
|
(doom/open-scratch-buffer arg project-p 'same-window))
|
2019-05-20 15:54:40 -04:00
|
|
|
|
2018-03-07 21:07:38 -05:00
|
|
|
;;;###autoload
|
2020-03-03 12:41:38 -05:00
|
|
|
(defun doom/open-project-scratch-buffer (&optional arg same-window-p)
|
2019-04-17 11:01:51 -04:00
|
|
|
"Opens the (persistent) project scratch buffer in a popup.
|
2018-03-07 21:07:38 -05:00
|
|
|
|
2020-03-03 12:41:38 -05:00
|
|
|
If passed the prefix ARG, do not restore the last scratch buffer."
|
2018-03-07 21:07:38 -05:00
|
|
|
(interactive "P")
|
2020-03-03 12:41:38 -05:00
|
|
|
(doom/open-scratch-buffer arg 'project same-window-p))
|
2018-03-07 21:07:38 -05:00
|
|
|
|
2019-05-20 15:54:40 -04:00
|
|
|
;;;###autoload
|
2020-03-03 12:41:38 -05:00
|
|
|
(defun doom/switch-to-project-scratch-buffer (&optional arg)
|
2019-05-20 15:54:40 -04:00
|
|
|
"Like `doom/open-project-scratch-buffer', but switches to it in the current
|
2020-03-03 12:41:38 -05:00
|
|
|
window.
|
|
|
|
|
|
|
|
If passed the prefix ARG, do not restore the last scratch buffer."
|
|
|
|
(interactive "P")
|
|
|
|
(doom/open-project-scratch-buffer arg 'same-window))
|
2019-05-20 15:54:40 -04:00
|
|
|
|
2018-03-07 21:07:38 -05:00
|
|
|
;;;###autoload
|
2019-04-17 11:01:51 -04:00
|
|
|
(defun doom/revert-scratch-buffer ()
|
|
|
|
"Revert scratch buffer to last persistent state."
|
|
|
|
(interactive)
|
|
|
|
(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."
|
2018-03-07 21:07:38 -05:00
|
|
|
(interactive)
|
2019-04-17 11:01:51 -04:00
|
|
|
(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 "Successfully deleted %S" (abbreviate-file-name file))))))
|