;;; Support for stack based hacking. (require 'cl) (provide 'recurse) (defvar *recurse-tasklist* '()) (defun recurse-make-entry (note buffer configuration) (vector note buffer configuration)) (defun recurse-note (entry) (aref entry 0)) (defun recurse-buffer (entry) (aref entry 1)) (defun recurse-configuration (entry) (aref entry 2)) (defun recurse (note) "Recurse into some other task. Often, while hacking, I find that I have to do something else first, and start doing that. Then once again, I find that I have to do something else. And so I recurse. But when a task is finished, I have forgotten what task was interrupted. \\[recurse] lets you note what you are doing, and it also remembers the current window configuration. To continue where you left off, use \\[recurse-pop-task]." (interactive "sRecurse from what? ") (setq *recurse-tasklist* (cons (recurse-make-entry note (current-buffer) (current-window-configuration)) *recurse-tasklist*))) (defun recurse-pop-task () "Pop a task that was interrupted earlier. See \\[recurse]." (interactive) (if *recurse-tasklist* (let* ((entry (car *recurse-tasklist*)) (note (recurse-note entry)) (configuration (recurse-configuration entry))) (when (yes-or-no-p (format "Pop task \"%s\"? " note)) (setq *recurse-tasklist* (cdr *recurse-tasklist*)) (set-window-configuration configuration) (message "%s" note))) (error "No task to pop"))) (defun recurse-show-backtrace () "Shows a backtrace of the tasks that have been interrupted." (interactive) (let ((buffer (generate-new-buffer "*recurse*"))) (save-excursion (set-buffer buffer) (setq buffer-read-only nil) (erase-buffer) (insert "Recurse backtrace\n\n") (insert (mapconcat (lambda (entry) (format "%20s: %s" (or (buffer-name (recurse-buffer entry)) "") (recurse-note entry))) (reverse *recurse-tasklist*) "\n")) (setq buffer-read-only t)) (shrink-window-if-larger-than-buffer (display-buffer buffer)))) (defun recurse-forget () "Remove all interrupted tasks from the list." (interactive) (setq *recurse-tasklist* '()))