Occasionally I save myself a lot of head-scratching by being able to refer to a timestamped history of my work in a particular shell session. You know the feeling, when you say either "I thought I already did that" or "Didn't I do X before Y?" Of course, usually you can piece together a timeline by looking at file modification times or revision control logs. Sometimes you absolutely cannot figure out the history -- a deleted file has no modification time -- and other times it would just be handy to have a transcript telling you when you did what.
Here are the ingredients to keeping a timestamped history:
- Emacs shell buffer: M-x shell.
- Timestamp script running in the background.
- Lisp code to remove shell output, leaving prompts and history.
ssh, and even things like ftp. If you need multiple shell buffers (say, on different hosts), use M-x rename-buffer.
The hitch is that after a few weeks in your emacs session, a shell buffer can grow very large. Here is a Lisp function to put in your .emacs which knocks it back down to size (make sure the emacs shell-prompt-pattern variable matches your shell prompt):
(defun engisneering-clean-shell-buffer ()
(let ((beg (point-min)))
(if (> 10000 (buffer-size)) (buffer-disable-undo))
(while (re-search-forward shell-prompt-pattern nil t)
(if (not (= (point) (line-end-position)))
(forward-line 0) ;; beginning of line, ignore prompt boundary
(if (not (= (point) beg))
(delete-region beg (point)))
(setq beg (point)))))
That will also be useful when you're ready to save your timestamped history. The timestamping is easy -- put this shell script into a file called "timestamp", and give it execute permission:
while ((1)); do
echo -n "timestamp> "
echo -n "prompt> "
There are two things to note about the script. First, when it outputs a timestamp, it will match the prompt pattern, so that it won't get deleted by our Lisp cleaning function. Second, it ends with "prompt> " so that the next time you hit return, emacs doesn't think the output from the timestamp is part of your next command.
So, whenever you start a shell buffer, run "timestamp&", to get the date and time printed out once an hour while you do other things.
Finally, here is a little script to help you save your shell histories. Create a directory to hold your histories; name the history files after the host the shell was on, and date them (including the year). Save them periodically, just like any of your work.
(defun engisneering-save-shell-buffer ()
(let ((name (buffer-name)))
(setq buffer-file-name nil)
(delete-region (point-min) (point-max))