Dan McKinley
Math, Programming, and Minority Reports

August 3rd, 2008

Well, if you use emacs long enough, eventually you realize that you have tens of thousands of lines of elisp lying around. I’m making a modest effort to dig myself out of this mess and what useful tidbits there are I will share with the world. Here is a very basic module that helps you get yourself in a predicament similar to my own.

;; elisp-ext.el
;; Utilities for writing and debugging Emacs lisp. The
;; interactive functions are:
;;   elisp:goto-definition - Jumps to the source for a
;;                           defun, defvar, etc.
;;   elisp:edebug-at-point - Enable edebug for the symbol
;;                           nearest the cursor.
;; When this is loaded, the sequence C-c C-g is bound to
;; elisp:goto-definition and C-c C-d is bound to
;; elisp:edebug-at-point in ielm and elisp-mode.
;; by Dan McKinley, 2008
;; http://mcfunley.com
;; 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 3 of the License, 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
;; 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/>.
(eval-when-compile (require 'cl))

(defun* elisp:read-symbol (default &amp;optional
                (prompt "Symbol")
                (test 'intern-soft))
  (let (val)
    (setq val (completing-read
           (if default (format "%s (default %s): " prompt default)
             (concat prompt ": "))
           obarray test t nil nil
           (and default (symbol-name default))))
    (if (equal val "")
      (intern val))))

(defun elisp:goto-definition (sym)
  "Extends find-func.el to find any symbol (defaulting
to the one at point)."
  (interactive (list (elisp:read-symbol (symbol-at-point))))
  (cond ((fboundp sym) (find-function sym))
    ((facep sym) (find-face-definition sym))
    (t (find-variable sym))))

(defun elisp:edebug-function (fun)
  "Enables edebug on a function given its symbol.
This necessarily leaves the file containing `fun' open, since
edebug will not open files on its own."
  (when (subrp fun)
    (error "Can't edebug a C function, sorry."))
    (let ((library (symbol-file fun nil)))
      (destructuring-bind (buf . pos)
      (find-function-search-for-symbol fun nil library)
    (set-buffer buf)
    (goto-char pos)

(defun elisp:edebug-at-point (fun)
  "Enables edebug on a function, defaulting to the
     (function-called-at-point) "Debug function" 'fboundp)))
  (message "Enabled debugging on %s." (elisp:edebug-function fun)))

(defun elisp:local-keys ()
  (local-set-key "\C-c\C-g" 'elisp:goto-definition)
  (local-set-key "\C-c\C-d" 'elisp:edebug-at-point))
(add-hook 'emacs-lisp-mode-hook 'elisp:local-keys)
(add-hook 'ielm-mode-hook 'elisp:local-keys)

(provide 'elisp-ext)
Back home