Changeset - c584e55ee1e7
[Not reviewed]
0 2 0
Sergey Pashinin - 13 years ago 2013-05-07 02:26:32
sergey@pashinin.com
new var wg-restore-remote-buffers - restore remote dirs or not
2 files changed with 10 insertions and 1 deletions:
0 comments (0 inline, 0 general)
src/workgroups-specialbufs.el
Show inline comments
 
;;; special buffer serdes functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
;;
 
;; TODO: Possibly add restore-special-data customization option
 
;; TODO: These could be a little more thorough
 
;;
 

	
 
(require 'dflet)
 
(require 'workgroups-misc)
 

	
 
;; Dired
 

	
 
(defun wg-deserialize-dired-buffer (buf)
 
  "Deserialize Dired buffer."
 
  (wg-dbind (this-function params) (wg-buf-special-data buf)
 
    (let ((dir (car params)))
 
      (if (or wg-restore-remote-buffers (not (wg-is-file-remote dir)))
 
          (if (file-exists-p dir)
 
          (dired dir))
 
              (dired dir)))
 
      (current-buffer))))
 

	
 
(defun wg-serialize-dired-buffer (buffer)
 
  "Serialize Dired buffer."
 
  (with-current-buffer buffer
 
    (when (eq major-mode 'dired-mode)
 
      (list 'wg-deserialize-dired-buffer
 
            (wg-take-until-unreadable (list (or (buffer-file-name) default-directory)))
 
            ))))
 

	
 
;; Info buffer serdes
 

	
 
(defun wg-deserialize-Info-buffer (buf)
 
  "Deserialize an Info buffer."
 
  (require 'info)
 
  (wg-aif (cdr (wg-buf-special-data buf))
 
      (apply #'Info-find-node it)
 
    (info))
 
  (current-buffer))
 

	
 
(defun wg-serialize-Info-buffer (buffer)
 
  "Serialize an Info buffer."
 
  (with-current-buffer buffer
 
    (when (eq major-mode 'Info-mode)
 
      (wg-when-boundp (Info-current-file Info-current-node)
 
        (list 'wg-deserialize-Info-buffer
 
              Info-current-file
 
              Info-current-node)))))
 

	
 

	
 
;; help buffer serdes
 

	
 
(defun wg-deserialize-help-buffer (buf)
 
  "Deserialize a help buffer.
 
See `wg-serialize-help-buffer'."
 
  (require 'help-mode)
 
  (wg-dbind (this-function item stack forward-stack) (wg-buf-special-data buf)
 
    (condition-case err
 
        (apply (car item) (cdr item))
 
      (error (message "%s" err)))
 
    (wg-awhen (get-buffer "*Help*")
 
      (set-buffer it)
 
      (wg-when-boundp (help-xref-stack help-xref-forward-stack)
 
        (setq help-xref-stack stack
 
              help-xref-forward-stack forward-stack))
 
      (current-buffer))))
 

	
 
(defun wg-serialize-help-buffer (buffer)
 
  "Serialize a help buffer.
 
Since `help-mode' is used by many buffers that aren't actually
 
*Help* buffers (e.g. *Process List*), we also check that
 
`help-xref-stack-item' has a local binding."
 
  (with-current-buffer buffer
 
    (when (and (eq major-mode 'help-mode)
 
               (local-variable-p 'help-xref-stack-item)
 
               (boundp 'help-xref-stack-item)
 
               (boundp 'help-xref-stack)
 
               (boundp 'help-xref-forward-stack))
 
      (list 'wg-deserialize-help-buffer
 
            (wg-take-until-unreadable help-xref-stack-item)
 
            (mapcar 'wg-take-until-unreadable help-xref-stack)
 
            (mapcar 'wg-take-until-unreadable help-xref-forward-stack)))))
 

	
 

	
 
;; ielm buffer serdes
 

	
 
(defun wg-deserialize-ielm-buffer (buf)
 
  "Deserialize an `inferior-emacs-lisp-mode' buffer."
 
  (ielm)
 
  (current-buffer))
 

	
 
(defun wg-serialize-ielm-buffer (buffer)
 
  "Serialize an `inferior-emacs-lisp-mode' buffer."
 
  (with-current-buffer buffer
 
    (when (eq major-mode 'inferior-emacs-lisp-mode)
 
      (list 'wg-deserialize-ielm-buffer))))
 

	
 

	
 
;; Magit buffers
 

	
 
(defun wg-deserialize-magit-buffer (buf)
 
  ""
 
  (if (require 'magit nil 'noerror)
 
      (if (fboundp 'magit-status)
 
          (wg-dbind (this-function dir) (wg-buf-special-data buf)
 
            (let ((default-directory (car dir)))
 
              (if (file-exists-p default-directory)
 
                  (magit-status default-directory))
 
              (current-buffer))))))
 

	
 
(defun wg-serialize-magit-buffer (buffer)
 
  ""
 
  (if (fboundp 'magit-status-mode)
 
      (with-current-buffer buffer
 
        (when (eq major-mode 'magit-status-mode)
 
          (list 'wg-deserialize-magit-buffer
 
                (wg-take-until-unreadable (list (or (buffer-file-name) default-directory)))
 
                )))))
 

	
 

	
 
;; shell buffer serdes
 

	
 
(defun wg-deserialize-shell-buffer (buf)
 
  "Deserialize a `shell-mode' buffer.
 
Run shell with last working dir"
 
  (wg-dbind (this-function dir) (wg-buf-special-data buf)
 
    (let ((default-directory (car dir)))
 
      (shell (wg-buf-name buf))
 
      (current-buffer)
 
      )))
 

	
 
(defun wg-serialize-shell-buffer (buffer)
 
  "Serialize a `shell-mode' buffer.
 
Save shell directory"
 
  (with-current-buffer buffer
 
    (when (eq major-mode 'shell-mode)
 
      (list 'wg-deserialize-shell-buffer
 
            (wg-take-until-unreadable (list (or (buffer-file-name) default-directory)))
 
            ))))
 

	
 

	
 
;; org-agenda buffer serdes
 

	
 
(defun wg-get-org-agenda-view-commands ()
 
  "Get commands by which the current state of Agenda buffer can
 
be restored using \"(eval commands)\"."
 
  (interactive)
 
  (if (get-buffer org-agenda-buffer-name)
 
      (with-current-buffer org-agenda-buffer-name
 
        (let* ((p (or (and (looking-at "\\'") (1- (point))) (point)))
 
               (series-redo-cmd (get-text-property p 'org-series-redo-cmd)))
 
          (if series-redo-cmd
 
              (get-text-property p 'org-series-redo-cmd)
 
            (get-text-property p 'org-redo-cmd))))))
 

	
 
(defun wg-run-agenda-cmd (f)
 
  "Run commands \"f\" in Agenda buffer. You can get these
 
commands using \"wg-get-org-agenda-view-commands\"."
 
  (if (get-buffer org-agenda-buffer-name)
 
      (save-window-excursion
 
        (with-current-buffer org-agenda-buffer-name
 
          (let* ((line (org-current-line))
 
                 (series-redo-cmd (xdev/get-org-agenda-view-commands)))
 
            (if f (eval f))
 
            (org-goto-line line))))))
 

	
 
(defun wg-deserialize-org-agenda-buffer (buf)
 
  "Deserialize a `org-agenda-mode' buffer."
 
  (org-agenda-list)
 
  (wg-dbind (this-function item) (wg-buf-special-data buf)
 
    (wg-awhen (get-buffer org-agenda-buffer-name)
 
      (set-buffer it)
 
      (wg-run-agenda-cmd item)
 
      (current-buffer))))
 

	
 
(defun wg-serialize-org-agenda-buffer (buffer)
 
  "Serialize a `org-agenda-mode' buffer."
 
  (with-current-buffer buffer
 
    (when (eq major-mode 'org-agenda-mode)
 
      (list 'wg-deserialize-org-agenda-buffer
 
            (wg-take-until-unreadable (wg-get-org-agenda-view-commands))
 
            ))))
 

	
 

	
 
;; eshell buffer serdes
 

	
 
(defun wg-deserialize-eshell-buffer (buf)
 
  "Deserialize an `eshell-mode' buffer."
 
  (prog1 (eshell t)
 
    (rename-buffer (wg-buf-name buf) t)))
 

	
 
(defun wg-serialize-eshell-buffer (buffer)
 
  "Serialize an `eshell-mode' buffer."
 
  (with-current-buffer buffer
 
    (when (eq major-mode 'eshell-mode)
 
      (list 'wg-deserialize-eshell-buffer))))
 

	
 

	
 
;; term and ansi-term buffer serdes
 

	
 
(defun wg-deserialize-term-buffer (buf)
 
  "Deserialize a `term-mode' buffer."
 
  (require 'term)
 
  ;; flet'ing these prevents scrunched up wrapping when restoring during morph
 
  (dflet ((term-window-width () 80)
 
         (window-height () 24))
 
    (prog1 (term (nth 1 (wg-buf-special-data buf)))
 
      (rename-buffer (wg-buf-name buf) t))))
 

	
 
(defun wg-serialize-term-buffer (buffer)
 
  "Serialize a `term-mode' buffer.
 
This should work for `ansi-term's, too, as there doesn't seem to
src/workgroups-variables.el
Show inline comments
 
@@ -51,384 +51,392 @@ off and then on again to take effect."
 
(defcustom wg-switch-to-workgroup-hook nil
 
  "Hook run by `wg-switch-to-workgroup'."
 
  :type 'hook
 
  :group 'workgroups)
 

	
 
(defcustom wg-buffer-list-finalization-hook nil
 
  "Functions in this hook can modify `wg-temp-buffer-list'
 
arbitrarily, provided its final value is still a list of the
 
names of live buffer.  Any final adjustments the user wishes to
 
make to the filtered buffer list before ido/iswitchb get ahold of
 
it should be made here."
 
  :type 'hook
 
  :group 'workgroups)
 

	
 
(defcustom wg-pre-window-configuration-change-hook nil
 
  "Hook run before any function that triggers
 
`window-configuration-change-hook'."
 
  :type 'hook
 
  :group 'workgroups)
 

	
 

	
 
;; save and load customization
 

	
 
(defcustom wg-use-default-session-file t
 
  "Generally, non-nil means take care of saving and loading automatically,
 
and nil means leave it up to the user.
 

	
 
FIXME: docstring this"
 
  :type 'boolean
 
  :group 'workgroups)
 

	
 
(defcustom wg-default-session-file
 
  (concat user-emacs-directory ".emacs-wg-session")
 
  "Default filename to be used to save workgroups."
 
  :type 'file
 
  :group 'workgroups)
 

	
 
(defcustom wg-switch-to-first-workgroup-on-find-session-file t
 
  "Non-nil means switch to the first workgroup in a session file
 
when it's found with `wg-find-session-file'."
 
  :type 'boolean
 
  :group 'workgroups)
 

	
 
(defcustom wg-emacs-exit-save-behavior 'save
 
  "Determines save behavior on Emacs exit.
 
Possible values:
 

	
 
`ask'           Ask the user whether to save if there are unsaved changes
 

	
 
`save'          Call `wg-save-session' when there are unsaved changes
 

	
 
Anything else   Exit Emacs without saving changes"
 
  :type 'symbol
 
  :group 'workgroups)
 

	
 
(defcustom wg-workgroups-mode-exit-save-behavior 'save
 
  "Determines save behavior on `workgroups-mode' exit.
 
Possible values:
 

	
 
`ask'           Ask the user whether to saveif there are unsaved changes
 

	
 
`save'          Call `wg-save-session' when there are unsaved changes
 

	
 
Anything else   Exit `workgroups-mode' without saving changes"
 
  :type 'symbol
 
  :group 'workgroups)
 

	
 

	
 
;; minibuffer customization
 

	
 
(defcustom wg-confirm-on-get-workgroup-create nil
 
  "Non-nil means request confirmation before creating a new
 
workgroup when `wg-get-workgroup-create' is called with a string
 
that doesn't name an existing workgroup."
 
  :type 'boolean
 
  :group 'workgroups)
 

	
 
(defcustom wg-no-confirm-on-destructive-operation nil
 
  "Non-nil means don't request confirmation before various
 
destructive operations, like `wg-reset'."
 
  :type 'boolean
 
  :group 'workgroups)
 

	
 
(defcustom wg-minibuffer-message-timeout 0.75
 
  "Bound to `minibuffer-message-timeout' when messaging while the
 
minibuffer is active."
 
  :type 'float
 
  :group 'workgroups)
 

	
 

	
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
;;
 
;; FIXME:
 
;;
 
;; Only set `wg-workgroup-base-wconfig' on `wg-write-session-file' or
 
;; `delete-frame' and only with the most recently changed working-wconfig.
 
;; Then, since it's not overwritten on every call to
 
;; `wg-workgroup-working-wconfig', its restoration can be retried after manually
 
;; recreating buffers that couldn't be restored.  So it takes over the
 
;; 'incorrect restoration' portion of the base wconfig's duty.  All that leaves
 
;; to base wconfigs is that they're a saved wconfig the user felt was important.
 
;; So why not allow more of of them?  A workgroup could stash an unlimited
 
;; number of wconfigs.
 
;;
 
;; TODO:
 
;;
 
;;   * Write new commands for restoring stashed wconfigs
 
;;
 
;;   * Add this message on improper restoration of `base-wconfig':
 
;;
 
;;       "Unable to restore 'buf1', 'buf2'... Hit C-whatever to retry after
 
;;        manually recreating these buffers."
 
;;
 
;;
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 

	
 

	
 
;; workgroup restoration customization
 

	
 
;; TODO: possibly add `buffer-file-coding-system', `text-scale-mode-amount'
 
(defcustom wg-buffer-local-variables-alist
 
  `((major-mode nil wg-deserialize-buffer-major-mode)
 
    (mark-ring wg-serialize-buffer-mark-ring wg-deserialize-buffer-mark-ring)
 
    (left-fringe-width nil nil)
 
    (right-fringe-width nil nil)
 
    (fringes-outside-margins nil nil)
 
    (left-margin-width nil nil)
 
    (right-margin-width nil nil)
 
    (vertical-scroll-bar nil nil))
 
  "Alist mapping buffer-local variable symbols to serdes functions.
 

	
 
The `car' of each entry should be a buffer-local variable symbol.
 

	
 
The `cadr' of the entry should be either nil or a function of no
 
arguments.  If nil, the variable's value is used as-is, and
 
should have a readable printed representation.  If a function,
 
`funcall'ing it should yield a serialization of the value of the
 
variable.
 

	
 
The `caddr' of the entry should be either nil or a function of
 
one argument.  If nil, the serialized value from above is
 
assigned to the variable as-is.  It a function, `funcall'ing it
 
on the serialized value from above should do whatever is
 
necessary to properly restore the original value of the variable.
 
For example, in the case of `major-mode' it should funcall the
 
value (a major-mode function symbol) rather than just assigning
 
it to `major-mode'."
 
  :type 'alist
 
  :group 'workgroups)
 

	
 
(defcustom wg-special-buffer-serdes-functions
 
  '(wg-serialize-Info-buffer
 
    wg-serialize-dired-buffer
 
    wg-serialize-org-agenda-buffer
 
    wg-serialize-help-buffer
 
    wg-serialize-ielm-buffer
 
    wg-serialize-shell-buffer
 
    wg-serialize-eshell-buffer
 
    wg-serialize-term-buffer
 
    wg-serialize-magit-buffer
 
    )
 
  "List of functions providing special buffer serialization/deserialization.
 
An entry should be either a function symbol or a lambda, and should
 
accept a single Emacs buffer object as an argument.
 

	
 
When a buffer is to be serialized, it is passed to each of these
 
functions in turn until one returns non-nil, or the list ends.  A
 
return value of nil indicates that the function can't handle
 
buffers of that type.  A non-nil return value indicates that it
 
can.  The first non-nil return value becomes the buffer's special
 
serialization data.  The return value should be a cons, with a
 
deserialization function (a function symbol or a lambda) as the car,
 
and any other serialization data as the cdr.
 

	
 
When it comes time to deserialize the buffer, the deserialization
 
function (the car of the cons mentioned above) is passed the
 
wg-buf object, from which it should restore the buffer.  The
 
special serialization data itself can be accessed
 
with (cdr (wg-buf-special-data <wg-buf>)).  The deserialization
 
function must return the restored Emacs buffer object.
 

	
 
See the definitions of the functions in this list for examples of
 
how to write your own."
 
  :type 'alist
 
  :group 'workgroups)
 

	
 
(defcustom wg-default-buffer "*scratch*"
 
  "Buffer made visible a window when the window's actual buffer
 
can't be restored.  Also used when a blank workgroup is created."
 
  :type 'string
 
  :group 'workgroups)
 

	
 
;; What to restore:
 

	
 
(defcustom wg-restore-remote-buffers t
 
  "nil means do not restore buffers that get \"t\" with
 
`wg-is-file-remote'"
 
  :type 'boolean
 
  :group 'workgroups)
 

	
 
(defcustom wg-restore-associated-buffers t
 
  "Non-nil means restore all buffers associated with the
 
workgroup on workgroup restore."
 
  :type 'boolean
 
  :group 'workgroups)
 

	
 
(defcustom wg-restore-frame-position nil
 
  "Non-nil means restore frame position on workgroup restore."
 
  :type 'boolean
 
  :group 'workgroups)
 

	
 
(defcustom wg-restore-scroll-bars t
 
  "Non-nil means restore scroll-bar settings on workgroup restore."
 
  :type 'boolean
 
  :group 'workgroups)
 

	
 
(defcustom wg-restore-fringes t
 
  "Non-nil means restore fringe settings on workgroup restore."
 
  :type 'boolean
 
  :group 'workgroups)
 

	
 
(defcustom wg-restore-margins t
 
  "Non-nil means restore margin settings on workgroup restore."
 
  :type 'boolean
 
  :group 'workgroups)
 

	
 
(defcustom wg-restore-point t
 
  "Non-nil means restore `point' on workgroup restore.
 
This is included mainly so point restoration can be suspended
 
during `wg-morph' -- you probably want this non-nil."
 
  :type 'boolean
 
  :group 'workgroups)
 

	
 
(defcustom wg-restore-point-max t
 
  "Controls point restoration when point is at `point-max'.
 
If `point' is at `point-max' when a wconfig is created, put
 
`point' back at `point-max' when the wconfig is restored, even if
 
`point-max' has increased in the meantime.  This is useful in,
 
say, irc buffers where `point-max' is constantly increasing."
 
  :type 'boolean
 
  :group 'workgroups)
 

	
 
(defcustom wg-restore-mark t
 
  "Non-nil means restore mark data on workgroup restore."
 
  :type 'boolean
 
  :group 'workgroups)
 

	
 
(defcustom wg-restore-window-dedicated-p t
 
  "Non-nil means restore `window-dedicated-p' on workgroup restore."
 
  :type 'boolean
 
  :group 'workgroups)
 

	
 

	
 
;; wconfig undo/redo customization
 

	
 
(defcustom wg-wconfig-undo-list-max 20
 
  "Number of past window configs to retain for undo."
 
  :type 'integer
 
  :group 'workgroups)
 

	
 

	
 
;; wconfig kill-ring customization
 

	
 
(defcustom wg-wconfig-kill-ring-max 20
 
  "Maximum length of the `wg-wconfig-kill-ring'."
 
  :type 'integer
 
  :group 'workgroups)
 

	
 

	
 
;; buffer-list filtration customization
 

	
 
(defcustom wg-buffer-list-filtration-on t
 
  "Non-nil means Workgroups' buffer-list filtration feature is on.
 
Nil means ido and iswitchb behave normally.  See
 
`wg-buffer-list-filter-definitions' for more info."
 
  :type 'boolean
 
  :group 'workgroups)
 

	
 
(defcustom wg-buffer-list-filter-definitions
 
  '((all "all" wg-buffer-list-filter-all)
 
    (associated "associated" wg-buffer-list-filter-associated)
 
    (unassociated "unassociated" wg-buffer-list-filter-unassociated)
 
    (fallback "fallback" nil))
 
  "List of buffer list filter definitions.
 
Each entry should be a list containing an identifier symbol, a
 
prompt string, and a function form that's funcall'd to produce
 
the filtered buffer-list.
 

	
 
The prompt string is displayed as part of the minibuffer prompt
 
when its filter is active.
 

	
 
The function form should be either a function-symbol or a lambda, and
 
should take two arguments: a workgroup and a list of live Emacs
 
buffers.  The function should return a new list of live buffers,
 
typically by filtering its second argument in some way.
 

	
 
Default buffer-list-filters include:
 

	
 
`all'           All buffer names
 

	
 
`associated'    Only the names of those live buffers that have
 
                been associated with the current workgroup
 

	
 
`unassociated'  Only the names of those live buffers that are
 
                unassociated with the current workgroup
 

	
 
`fallback'      A special case used to fallback to the
 
                original (non-ido/iswitchb) Emacs command.
 
                `fallback' isn't actually a buffer-list-filter
 
                itself, but can be used in
 
                `wg-buffer-list-filter-order-alist' just the
 
                same.
 

	
 
A few example custom buffer-list filtration functions are
 
included, like `wg-buffer-list-filter-home-dir',
 
`wg-buffer-list-filter-irc' and `wg-buffer-list-filter-elisp'.
 
See their definitions for more info on how they're defined, and
 
the utilities they're built on.
 

	
 
Here's an example of how to add an `elisp' buffer-list-filter
 
definition to `wg-buffer-list-filter-definitions' using the
 
example function `wg-buffer-list-filter-elisp':
 

	
 
(add-to-list
 
 'wg-buffer-list-filter-definitions
 
 '(elisp \"elisp\" wg-buffer-list-filter-elisp))
 

	
 
After this form has been evaluated, `elisp' can be used wherever
 
other buffer-list-filter identifiers are used, like in
 
`wg-buffer-list-filter-order-alist'.
 

	
 
Becomes workgroup-local when set with `wg-set-workgroup-parameter'.
 
Becomes session-local when set with `wg-set-session-parameter'."
 
  :type 'list
 
  :group 'workgroups)
 

	
 
(defcustom wg-buffer-list-filter-order-alist
 
  '((default associated unassociated all fallback))
 
  "Alist defining the order in which filtered buffer-lists are presented.
 

	
 
The car of each entry should be the symbol of the original Emacs
 
command (not the ido or iswitchb remappings) -- i.e. one of
 
`switch-to-buffer', `switch-to-buffer-other-window',
 
`switch-to-buffer-other-frame', `kill-buffer', `next-buffer',
 
`previous-buffer', `display-buffer', `insert-buffer',
 
`read-buffer', or the special symbol `default', which defines the
 
buffer-list-filter order for all commands not present in this
 
alist.
 

	
 
The cdr of each entry should be a list of buffer-list-filter
 
identifiers defining the order in which filtered buffer-lists are
 
presented for the command.  See
 
`wg-buffer-list-filter-definitions'.
 

	
 
Becomes workgroup-local when set with `wg-set-workgroup-parameter'.
 
Becomes session-local when set with `wg-set-session-parameter'."
 
  :type 'alist
 
  :group 'workgroups)
 

	
 
(defcustom wg-center-rotate-buffer-list-display nil
 
  "Non-nil means rotate the buffer list display so that the
 
current buffer is in the center of the list.  This can make it
 
easier to see the where `wg-previous-buffer' will take you, but
 
it doesn't look right if the buffer list display is long enough
 
to wrap in the miniwindow."
 
  :type 'boolean
 
  :group 'workgroups)
 

	
 
(defcustom wg-buffer-auto-association-on t
 
  "Non-nil means buffer auto-association is on.
 
nil means it's off.  See `wg-buffer-auto-association'."
 
  :type 'boolean
 
  :group 'workgroups)
 

	
 
(defcustom wg-buffer-auto-association 'weak
 
  "Specifies the behavior for auto-associating buffers with workgroups.
 

	
 
When a buffer is made visible in a window it can be automatically
 
associated with the current workgroup in the window's frame.
 
This setting determines whether and how that happens.
 

	
 
Allowable values:
 

	
 
`weak' - weakly associate the buffer with the workgroup
 

	
 
`strong' - strongly associate the buffer with the workgroup
 

	
 
A function (a function-symbol or a lambda) - `funcall' the function to
 
determine whether and how to associate the buffer with the
 
workgroup.  The function should accept two arguments -- the
 
buffer and the workgroup -- and should return one of the
 
allowable values for this variable.
0 comments (0 inline, 0 general)