blob: f7f89a08f68321640c378bb84e4bb1f64f7113f6 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
;;; garden-preview.el --- side-window note preview -*- lexical-binding: t; -*-
;;; Commentary:
;; Shows garden notes in a read-only side window on the right. Two
;; entry points: `garden-preview-show' for one-off peeks (wired to
;; per-row eye buttons), and `garden-preview-mode', a buffer-local
;; minor mode for the VUI dashboards that previews the note under
;; point as you move around. Buffers opened purely for previewing
;; are killed again by `garden-preview-quit'.
;;; Code:
(require 'garden-core)
(require 'cl-lib)
(declare-function vui-element-at "vui")
(declare-function vui-element-get "vui")
(defcustom garden-preview-width 45
"Width of the preview side window in columns."
:type 'integer :group 'garden)
(defvar garden-preview--opened nil
"Buffers the preview opened itself and may kill on quit.")
(defvar-local garden-preview--owned nil
"Non-nil when this buffer was created by `garden-preview-show'.")
(defvar garden-preview--last nil
"File shown in the preview window most recently.")
(defun garden-preview-show (file)
"Display FILE read-only in a side window on the right.
Focus returns to the window that was selected before the call."
(interactive "fPreview note: ")
(let* ((existing (find-buffer-visiting file))
(buf (or existing (find-file-noselect file)))
(origin (selected-window)))
(if existing
(progn
(with-current-buffer buf (setq garden-preview--owned nil))
(setq garden-preview--opened (delq buf garden-preview--opened)))
(with-current-buffer buf
(setq garden-preview--owned t)
(cl-pushnew buf garden-preview--opened)))
(setq garden-preview--last file)
(with-current-buffer buf (setq buffer-read-only t))
(or (with-selected-window (window-main-window)
(display-buffer-in-side-window
buf
`((side . right) (slot . 0) (window-width . ,garden-preview-width)
(window-parameters . ((no-delete-other-windows . t))))))
(display-buffer buf '((display-buffer-reuse-window display-buffer-use-some-window)
(inhibit-same-window . t))))
(select-window origin)))
(defun garden-preview-quit ()
"Close the preview window and kill buffers opened for previewing.
Only buffers that the preview itself created are killed."
(interactive)
(when-let* ((buf (and garden-preview--last (find-buffer-visiting garden-preview--last)))
(win (get-buffer-window buf)))
(when (window-parameter win 'window-side)
(delete-window win)))
(dolist (buf garden-preview--opened)
(when (and (buffer-live-p buf)
(buffer-local-value 'garden-preview--owned buf)
(not (buffer-modified-p buf))
(not (get-buffer-window buf 'visible)))
(kill-buffer buf)))
(setq garden-preview--opened nil
garden-preview--last nil))
(defun garden-preview--file-at-line ()
"Return the note file referenced by a VUI element on the current line, if any.
Works with both `button.el' text buttons (vui 1.3+) and widget fields."
(save-excursion
(let ((end (line-end-position))
(file nil))
(beginning-of-line)
(while (and (not file) (< (point) end))
(let* ((elt (vui-element-at (point)))
(echo (and elt (vui-element-get elt 'help-echo))))
(when (and (stringp echo)
(string-suffix-p ".org" echo)
(file-exists-p echo))
(setq file echo)))
(forward-char 1))
file)))
(defun garden-preview--post-command ()
"Preview the note under point when it changed."
(when-let* ((file (garden-preview--file-at-line)))
(unless (equal file garden-preview--last)
(garden-preview-show file))))
;;;###autoload
(define-minor-mode garden-preview-mode
"Preview the note under point in a right side window.
Buffer-local; meant for the garden VUI dashboards."
:lighter " peek"
(if garden-preview-mode
(progn
(add-hook 'post-command-hook #'garden-preview--post-command nil t)
(garden-preview--post-command))
(remove-hook 'post-command-hook #'garden-preview--post-command t)
(garden-preview-quit)))
(provide 'garden-preview)
;;; garden-preview.el ends here
|