Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
branch: master
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 214 lines (178 sloc) 8.76 kb
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
;; Copyright 2005 Steve Wainstead (swain@panix.com)

;; This file is NOT part of GNU Emacs.

;; This program is free software; you can redistribute it and/or
;; modify it under the terms of the GNU General Public License as
;; published by the Free Software Foundation; either version 2, or (at
;; your option) any later version.

;; This program is distributed in the hope that it will be useful, but
;; WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;; General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see
;; <http://www.gnu.org/licenses/>.


;; ABOUT:

;; desktop-auto-save extends the functionality of Emacs's feature of
;; saving your "desktop" (that is, the list of files you have
;; open). It adds the feature of saving the contents of shell buffers
;; to files whenever the desktop is saved.

;; Additionally if you store all the files in a directory and turn
;; that directory into a git repository, desktop-auto-save commits
;; those files when you quit Emacs.

;; put these in your .emacs file or similar.

;; ;; load the desktop on startup (from ~/)
;; (desktop-load-default)
;; ;; automatically save the desktop on exit.
;; (setq desktop-enable t)
;; (load-file "~swain/.elisp/desktop-auto-save.el")



;; save the desktop every time you auto-save-file
(defun desktop-auto-save ()
  "Added to auto-save-hook so the desktop is not lost."
  (desktop-save "~/")
  (sw-save-shell-buffer-contents)
  ;;(message "Wrote desktop.")
  )

(add-hook 'auto-save-hook 'desktop-auto-save t)



(defvar sw-restore-shell-buffers-flag t
  "If t, shell buffer contents are inserted from the previous session,
if available. (This is the default). If nil, previous shell
buffer contents are not restored. On some systems (or some
versions of systems? Or Emacs?) the shell tries to execute the
contents of the file after insertion, with disasterous
consequences.")


;; For all shell buffers, save their contents to individual files. The
;; idea here is to preserve their contents in case of a crash.
(defun sw-save-shell-buffer-contents ()
  "Find and save all buffers that are in shell-mode"
  (interactive)
  (and (file-accessible-directory-p sw-buffer-file-name-prefix)
       (let ( (bufflist (buffer-list)) )
         (while bufflist
           (setq buff (car bufflist))
           (save-excursion
             (set-buffer buff)
             (when (or (string= major-mode "shell-mode") (string= (buffer-name) "psql"))
               ;;(message (format "it's a shell: %s" (buffer-name buff)))
               ;; if this buffer's contents have not been reloaded...

               ;; thus far, this is just not working out... I want a
               ;; buffer-local variable that indicates whether the buffer
               ;; contents have been inserted. I want to insert them if
               ;; it's nil. What's happening is the variable is "void" and
               ;; desktop-write goes into an infinite loop making system
               ;; beeps.

               ;;(if (and (boundp 'buffer-contents-restored) (not buffer-contents-restored)) (sw-insert-saved-buffer-contents (buffer-name buff)))
               (sw-save-buffer-invisibly buff)
               )
             (setq bufflist (cdr bufflist))
             )
           )
         )
       )
  )

(defvar sw-buffer-file-name-prefix "~swain/.emacs.shellbuffers/"
  "All shell buffers, when their contents are saved, get this string prefixed to the buffer name.")

;; save a shell buffer's contents to ~/.emacs.shellbuffers/buffer-name; doesn't switch
;; buffer on user; hack from desktop.el which showed how to use write-region
;; to save the contents invisibly
(defun sw-save-buffer-invisibly (buffer)
  "Write out shell buffer's contents for preservation behind-the-scenes."
  (set-buffer buffer)
  (let ( (coding-system-for-write 'no-conversion) )
    ;; (write-region (point-min) (point-max) (concat sw-buffer-file-name-prefix (buffer-name buffer) (format-time-string "-%Y-%m-%d"))))
    (write-region (point-min) (point-max) (sw-make-buffer-filename buffer)))
  )

(defun sw-make-buffer-filename (buffer)
  "Make a buffer file name string from the buffer name passed in
by prefixing the string passed in with the contents of the
variable sw-buffer-file-name-prefix. For example: pass in 'cli'
and it returns '~swain/.emacs.shellbuffers/cli'"
  ;;(message (concat sw-buffer-file-name-prefix buffname))
  (concat sw-buffer-file-name-prefix (buffer-name buffer))
  )

;; so far, no go (no va) FIXME
(defun sw-advance-point-log-buffers ()
  "Saving a window config to register also preserves the location of point, which we
don't want. Cycle through the log file buffers and send point to point-max."
  (interactive)
  (let ( (file-alist sw-tail-file-alist) )
    (while (consp file-alist)
      (setq pair (car file-alist))
      (set-buffer (car pair))
      (message (format "in buffer %s" (car pair)))
      (end-of-buffer)
      (insert "\ntest message\n")
      (setq file-alist (cdr file-alist))
      )
    )
  )


;; The idea here is to "restore" a shell buffer's contents. For
;; example: you have a shell buffer named "foo." The contents of the
;; shell buffer "foo" should be saved when you quit Emacs (saving the
;; contents of all shell buffers is the whole point of this Emacs Lisp
;; file). When you again create a new shell buffer named "foo" the
;; contents of the previous incarnation of "foo" should be loaded into
;; the "foo" shell buffer at the top. Unfortunately it just inserts
;; the text from the previous shell buffer; a future hack will be to
;; insert not the text, but the actual Emacs lisp code (see
;; "buffer-string") representing the shell buffer as it existed
;; previously, including the command history.
(defun sw-insert-saved-buffer-contents (sw-buff-name)
  (message "Inserting auto-desktop-save data...")
  (goto-char (point-min))
  (insert-file (concat sw-buffer-file-name-prefix sw-buff-name))
  (goto-char (point-max))
  ;;(setq buffer-contents-restored t) ;; should be buffer local variable, first created in sw-shell
  )


;; Rather than using version control like git or svn, rename the shell
;; buffer contents file with a date (currently unused)
(defun sw-backup-saved-buffer-contents (sw-buff-name)
  "Make a backup copy of the shell buffer auto save file"
  (message (format "Backing up %s shell buffer contents..." sw-buff-name))
  (rename-file
   (concat sw-buffer-file-name-prefix sw-buff-name)
   (concat sw-buffer-file-name-prefix sw-buff-name "." (format-time-string "-%Y-%m-%d")))
)


;; deprecated
;; As of april 2009, here's the way to do it; relies on our ability to
;; svn revert the shellbuffer files. You have "within the hour" to
;; restore the shell buffer contents before the cron job commits them
;; to the local svn repository. After that, you'll have to manually
;; retrieve the version you want.
;; (defun sw-restore-shellbuffers-contents ()
;; "do an svn revert on the shell buffers directory, then for each
;; open buffer, insert its file at point-min"
;; (interactive)
;; (shell-command "svn revert ~swain/.emacs.shellbuffers/*")
;; ;; now recurse, since they are reverted. Don't want to revert every
;; ;; time.
;; (sw-insert-previous-shellbuffer-contents (list "cli" "root" "www" "sql")))

;; deprecated
;; (defun sw-restore-recent-shellbuffers-contents ()
;; "Don't do an svn revert on the shell buffers directory, then for each
;; open buffer, insert its file at point-min"
;; (interactive)
;; (sw-insert-previous-shellbuffer-contents (list "cli" "root" "www" "sql")))

;; recursive function called by sw-restore-shellbuffers-contents
(defun sw-insert-previous-shellbuffer-contents (shell-buffer-list)
  "insert shell buffer contents from a previous session, and
recurse on the list of shellbuffer names to do the same for each
shell buffer so named."
  (if (car shell-buffer-list)
      (progn
        (switch-to-buffer (get-buffer (car shell-buffer-list)))
        (goto-char (point-min))
        (insert-file (format "~swain/.emacs.shellbuffers/%s" (car shell-buffer-list)))
        (goto-char (point-max))
        (sw-insert-previous-shellbuffer-contents (cdr shell-buffer-list))
        )
    )
  )

(defun sw-git-commit-buffers()
  "Save the contents of all shell buffers to their files and then
git-commit those files in ~/.emacs.shellbuffers."
  (interactive)
  (sw-save-shell-buffer-contents)
  (shell-command "cd ~swain/.emacs.shellbuffers; git commit -am \"Committing buffers\"")
)
;; when quiting Emacs save and commit the shell buffers
(add-hook 'kill-emacs-hook 'sw-git-commit-buffers t)

Something went wrong with that request. Please try again.