Files
@ 3edbfb87fe7d
Branch filter:
Location: workgroups2/src/workgroups-restore.el
3edbfb87fe7d
10.0 KiB
text/x-elisp
Save/restore frames (#11)
Probably works (for me) with usual file buffers
Probably works (for me) with usual file buffers
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 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 | ;;; workgroups-restore --- Functions to restore buffers and frames
;;; Commentary:
;;
;; TIPS
;;---------
;; Each Emacs frame ("window") can contain several workgroups.
;; WCONFIG is settings for each workgroup (buffers, parameters,...)
;;
;; So restoring WCONFIG using `wg-restore-wconfig' is restoring buffers
;; for current workgroup. Generally speaking each Workgroup can have
;; several WCONFIGs.
;;
;;; Code:
(require 'workgroups-variables)
(defun wg-restore-default-buffer ()
"Switch to `wg-default-buffer'."
(switch-to-buffer wg-default-buffer t))
(defun wg-restore-existing-buffer (buf)
"Switch to and return BUF's referrent (some live buffer) if it exists."
(wg-awhen (wg-find-buf-in-buffer-list buf (buffer-list))
(switch-to-buffer it t)
(wg-set-buffer-uid-or-error (wg-buf-uid buf))
it))
(defun wg-restore-file-buffer (buf)
"Restore BUF by finding its file. Return the created buffer.
If BUF's file doesn't exist, call `wg-restore-default-buffer'"
(wg-when-let ((file-name (wg-buf-file-name buf)))
(when (or wg-restore-remote-buffers
(not (file-remote-p file-name)))
(cond ((file-exists-p file-name)
(find-file file-name)
(rename-buffer (wg-buf-name buf) t)
(wg-set-buffer-uid-or-error (wg-buf-uid buf))
(when wg-restore-mark
(set-mark (wg-buf-mark buf))
(deactivate-mark))
(wg-deserialize-buffer-local-variables buf)
(current-buffer))
(t
;; try directory
(if (not (file-remote-p file-name))
(if (file-directory-p (file-name-directory file-name))
(progn
(dired (file-name-directory file-name))
(current-buffer))
(progn
(message "Attempt to restore nonexistent file: %S" file-name)
nil))
nil)
)))))
(defun wg-restore-special-buffer (buf)
"Restore a buffer BUF with DESERIALIZER-FN."
(wg-when-let
((special-data (wg-buf-special-data buf))
(buffer (save-window-excursion
(condition-case err
(funcall (car special-data) buf)
(error (message "Error deserializing %S: %S"
(wg-buf-name buf) err)
nil)))))
(switch-to-buffer buffer t)
(wg-set-buffer-uid-or-error (wg-buf-uid buf))
buffer))
(defun wg-restore-buffer (buf)
"Restore BUF and return it."
(let (wg-buffer-auto-association-on)
(or (wg-restore-existing-buffer buf)
(wg-restore-special-buffer buf)
(wg-restore-file-buffer buf)
(progn (wg-restore-default-buffer) nil))))
(defun wg-restore-window-positions (win &optional window)
"Restore various positions in WINDOW from their values in WIN."
(let ((window (or window (selected-window))))
(wg-with-slots win
((win-point wg-win-point)
(win-start wg-win-start)
(win-hscroll wg-win-hscroll))
(set-window-start window win-start t)
(set-window-hscroll window win-hscroll)
(set-window-point
window
(cond ((not wg-restore-point) win-start)
((eq win-point :max) (point-max))
(t win-point)))
(when (>= win-start (point-max)) (recenter)))))
(defun wg-restore-window (win)
"Restore WIN in `selected-window'."
(let ((selwin (selected-window))
(buf (wg-find-buf-by-uid (wg-win-buf-uid win))))
(if (not buf) (wg-restore-default-buffer)
(when (wg-restore-buffer buf)
(wg-restore-window-positions win selwin)
(when wg-restore-window-dedicated-p
(set-window-dedicated-p selwin (wg-win-dedicated win)))))))
(defun wg-reset-window-tree ()
"Delete all but one window in `selected-frame', and reset
various parameters of that window in preparation for restoring
a wtree."
(delete-other-windows)
(set-window-dedicated-p nil nil))
(defun wg-restore-window-tree-helper (w)
"Recursion helper for `wg-restore-window-tree'."
(if (wg-wtree-p w)
(cl-loop with dir = (wg-wtree-dir w)
for (win . rest) on (wg-wtree-wlist w)
do (when rest (split-window nil (wg-w-size win dir) (not dir)))
do (wg-restore-window-tree-helper win))
(wg-restore-window w)
(when (wg-win-selected w)
(setq wg-window-tree-selected-window (selected-window)))
(when (wg-win-minibuffer-scroll w)
(setq minibuffer-scroll-window (selected-window)))
(other-window 1)))
(defun wg-restore-window-tree (wtree)
"Restore WTREE in `selected-frame'."
(let ((window-min-width wg-window-min-width)
(window-min-height wg-window-min-height)
(wg-window-tree-selected-window nil))
(wg-reset-window-tree)
(wg-restore-window-tree-helper wtree)
(wg-awhen wg-window-tree-selected-window (select-window it))))
(defun wg-wconfig-restore-frame-position (wconfig &optional frame)
"Use WCONFIG to restore FRAME's position.
If frame is nil then `selected-frame'."
(wg-when-let ((left (wg-wconfig-left wconfig))
(top (wg-wconfig-top wconfig)))
;; Check that arguments are integers
;; Problem: https://github.com/pashinin/workgroups2/issues/15
(if (and (integerp left)
(integerp top))
(set-frame-position frame left top))))
(defun wg-wconfig-restore-scroll-bars (wconfig)
"Restore `selected-frame's scroll-bar settings from WCONFIG."
(set-frame-parameter
nil 'vertical-scroll-bars (wg-wconfig-vertical-scroll-bars wconfig))
(set-frame-parameter
nil 'scroll-bar-width (wg-wconfig-scroll-bar-width wconfig)))
;;(defun wg-wconfig-restore-fullscreen (wconfig)
;; "Restore `selected-frame's fullscreen settings from WCONFIG."
;; (set-frame-parameter
;; nil 'fullscreen (wg-wconfig-parameters wconfig))
;; )
(defun wg-scale-wconfig-to-frame (wconfig)
"Scale WCONFIG buffers to fit current frame size.
Return a scaled copy of WCONFIG."
(interactive)
(wg-scale-wconfigs-wtree wconfig
(frame-parameter nil 'width)
(frame-parameter nil 'height)))
(defun wg-frame-resize-and-position (wconfig &optional frame)
"Apply WCONFIG's size and position to a FRAME."
(interactive)
(unless frame
(setq frame (selected-frame)))
(let* ((params (wg-wconfig-parameters wconfig))
fullscreen)
(set-frame-parameter frame 'fullscreen (if (assoc 'fullscreen params)
(cdr (assoc 'fullscreen params))
nil))
(when (and wg-restore-frame-position
(not (frame-parameter frame 'fullscreen)))
(wg-wconfig-restore-frame-position wconfig frame))
))
(defun wg-restore-frame-size-position (wconfig &optional fs)
"Smart-restore of frame size and position.
Depending on `wg-remember-frame-for-each-wg' frame parameters may
be restored for each workgroup.
If `wg-remember-frame-for-each-wg' is nil (by default) then
current frame parameters are saved/restored to/from first
workgroup. And frame parameters for all other workgroups are just
ignored.
"
(interactive)
(let* ((params (wg-wconfig-parameters wconfig))
fullscreen)
;; Frame maximized / fullscreen / none
(unless wg-remember-frame-for-each-wg
(setq params (wg-wconfig-parameters (wg-workgroup-working-wconfig (wg-first-workgroup)))))
(setq fullscreen (if (assoc 'fullscreen params)
(cdr (assoc 'fullscreen params))
nil))
(when (and fs
fullscreen
(or wg-remember-frame-for-each-wg
(null (wg-current-workgroup t))))
(set-frame-parameter nil 'fullscreen fullscreen)
;; I had bugs restoring maximized frame:
;; Frame could be maximized but buffers are not scaled to fit it.
;;
;; Maybe because of `set-frame-parameter' takes some time to finish and is async.
;; So I tried this and it helped
(sleep-for 0 100))
;; Position
(when (and wg-restore-frame-position
wg-remember-frame-for-each-wg
(not (frame-parameter nil 'fullscreen)))
(wg-wconfig-restore-frame-position wconfig))
))
(defun wg-restore-frames ()
"Try to recreate opened frames, take info from session's 'frame-list parameter."
(interactive)
(delete-other-frames)
(when (wg-current-session t)
(let ((fl (wg-session-parameter (wg-current-session t) 'frame-list nil))
(frame (selected-frame)))
(mapc (lambda (wconfig)
(with-selected-frame (make-frame)
;;(wg-frame-resize-and-position wconfig)
;;(wg-restore-frame-size-position wconfig)
;;(wg-wconfig-restore-frame-position wconfig)
(wg-restore-wconfig wconfig)
)) fl)
(select-frame-set-input-focus frame))))
;; FIXME: throw a specific error if the restoration was unsuccessful
(defun wg-restore-wconfig (wconfig &optional frame)
"Restore a workgroup configuration WCONFIG in a FRAME.
Runs each time you're switching workgroups."
(unless frame
(setq frame (selected-frame)))
(let ((wg-record-incorrectly-restored-bufs t)
(wg-incorrectly-restored-bufs nil)
(params (wg-wconfig-parameters wconfig))
fullscreen wtree)
(wg-barf-on-active-minibuffer)
(when wg-restore-scroll-bars
(wg-wconfig-restore-scroll-bars wconfig))
(setq wtree (wg-scale-wconfig-to-frame wconfig)) ; scale wtree to frame size
;; Restore buffers
(wg-restore-window-tree wtree)
;; Restore frame position
(when (and wg-restore-frame-position
(not (frame-parameter nil 'fullscreen))
(null (wg-current-workgroup t)))
(wg-wconfig-restore-frame-position wconfig frame))
(when wg-incorrectly-restored-bufs
(message "Unable to restore these buffers: %S\
If you want, restore them manually and try again."
(mapcar 'wg-buf-name wg-incorrectly-restored-bufs)))))
(provide 'workgroups-restore)
;;; workgroups-restore.el ends here
|