Last edit

Summary: Rückgängig gemacht auf den Stand vom 2013-08-24 11:21 UTC


< I am currently developing [


> I am currently developing [


< has a [ manual], and is


> has a [ manual], and is


< (let ((buf-pos (find-function-WikiModes-for-symbol


> (let ((buf-pos (find-function-search-for-symbol


< (let ((case-fold-WikiModes t))


> (let ((case-fold-search t))


< (while (re-WikiModes-forward


> (while (re-search-forward


< (while (WikiModes-backward "/" nil t)


> (while (search-backward "/" nil t)


< '(icicle-WikiModes-context-level-1 ((((background dark)) (:background "gray20" :weight bold))))
< '(icicle-WikiModes-context-level-2 ((((background dark)) (:background "gray15" :weight bold))))
< '(icicle-WikiModes-context-level-3 ((((background dark)) (:background "gray10" :weight bold))))
< '(icicle-WikiModes-context-level-4 ((((background dark)) (:weight bold))))
< '(icicle-WikiModes-context-level-5 ((((background dark)) (:weight bold))))
< '(icicle-WikiModes-context-level-6 ((((background dark)) (:weight bold))))
< '(icicle-WikiModes-context-level-7 ((((background dark)) (:weight bold))))
< '(icicle-WikiModes-context-level-8 ((((background dark)) (:weight bold))))
< '(icicle-WikiModes-current-input ((t (:foreground "green"))))
< '(icicle-WikiModes-main-regexp-current ((((background dark)) (:foreground "DodgerBlue"))))
< '(icicle-WikiModes-main-regexp-others ((((background dark)) (:foreground "SeaGreenk"))))


> '(icicle-search-context-level-1 ((((background dark)) (:background "gray20" :weight bold))))
> '(icicle-search-context-level-2 ((((background dark)) (:background "gray15" :weight bold))))
> '(icicle-search-context-level-3 ((((background dark)) (:background "gray10" :weight bold))))
> '(icicle-search-context-level-4 ((((background dark)) (:weight bold))))
> '(icicle-search-context-level-5 ((((background dark)) (:weight bold))))
> '(icicle-search-context-level-6 ((((background dark)) (:weight bold))))
> '(icicle-search-context-level-7 ((((background dark)) (:weight bold))))
> '(icicle-search-context-level-8 ((((background dark)) (:weight bold))))
> '(icicle-search-current-input ((t (:foreground "green"))))
> '(icicle-search-main-regexp-current ((((background dark)) (:foreground "DodgerBlue"))))
> '(icicle-search-main-regexp-others ((((background dark)) (:foreground "SeaGreenk"))))

I guess I’m an addict – even on a Mac, I write my code, read my mail, keep a diary, and even sometimes browse the web in GnuEmacs. I’ve even been known to control iTunes with a bastard child of Emacs and MySQL.

Here are the functions I use to control iTunes: [1]. There is another library out there to do this, but I didn’t know about it at the time.

I am currently developing Sepia, a set of tools to improve interactive Perl development in Emacs, adding things like an interactive mode, find-function, eldoc, and cross-referencing. It now has a manual, and is mostly ready for public consumption.

Some time ago I wrote SimpleCallTree, trying to find bits of unused code in my Perl script. It uses font-lock-function-name to identify function names, so if you’re writing trivial Perl, it might actually work… I’m interested in your code. :) – AlexSchroeder

Heh – that’s pretty clever. My code is perl-specific, and so probably less interesting, relying on a Perl backend to crawl over the compiled program.

I develop EmacsLispForRuby, talking Emacs with Ruby. I’ll consult Sepia. – rubikitch

I’ve tried el4r, and in most ways, it’s much better than Sepia… though Sepia does have a few of its own tricks. – SeanO

Peeves / Hall of Shame

When you write Emacs extensions, please use the built-in facilities where possible, as reinvented wheels are annoying. Today’s example, which disables iswitchb in w3m buffers:

    (defun w3m-e21-switch-to-buffer (buffer &optional norecord)
      "Run `switch-to-buffer' and redisplay the header-line.
    Redisplaying is done by wobbling the window size."
      (interactive "BSwitch to buffer: ")
          (switch-to-buffer buffer norecord)
        (when (and header-line-format
                   (eq major-mode 'w3m-mode))


A bit of code I’ve had in my init file for awhile to go to the definition of whatever elisp thing is at point:

    (defun find-thing-at-point (&optional always-ask)
      (interactive "P")
      (let* ((at-point (thing-at-point 'symbol))
             (s (and at-point (intern at-point)))
             (v (or (variable-at-point)
                    (and s (boundp s) s)))
             (f (or (function-called-at-point)
                    (and s (fboundp s) s))))
        (push-mark (point) t)
          (always-ask (call-interactively 'find-function))
          ((and v (not (numberp v)))
           (find-variable v))
          ((and f (subrp (symbol-function f)))
           (let ((buf-pos (find-function-search-for-symbol
                           f nil (help-C-file-name (symbol-function f) 'subr))))
             (and (car buf-pos) (pop-to-buffer (car buf-pos)))))
          (f (find-function f))
          (t (call-interactively 'find-function)))))

Good idea. Based on this, I’ve added a similar command (‘find-fn-or-var-nearest-point’) to Lisp:thingatpt+.el. Thanks. -- DrewAdams

Another bit to jump to a function within the buffer using ido and semantic:

    (defun my-semanticdb-minor-mode-p ()
    "Query if the current buffer has Semanticdb mode enabled."
      (condition-case blah
          (and (semanticdb-minor-mode-p)
               (eq imenu-create-index-function
        (error nil)))
    (defun my-icompleting-read (prompt choices)
      (flet ((ido-make-buffer-list (default)
               (setq ido-temp-list choices)))
        (ido-read-buffer prompt)))
    (defun my-jump-to-function ()
    "Jump to a function found by either Semantic or Imenu within the
    current buffer."
        ((my-semanticdb-minor-mode-p) (my-semantic-jump-to-function))
        ((boundp 'imenu-create-index-function) (my-imenu-jump-to-function))))
    (defun my-imenu-jump-to-function ()
    "Jump to a function found by Semantic within the current buffer
    with ido-style completion."
        (setq imenu--index-alist (funcall imenu-create-index-function)))
      (let ((thing (assoc
                       (my-icompleting-read "Go to: "
                                            (mapcar #'car imenu--index-alist))
        (when thing
          (funcall imenu-default-goto-function (car thing) (cdr thing))
    (defun my-semantic-jump-to-function ()
    "Jump to a function found by Semantic within the current buffer
    with ido-style completion."
      (let ((tags
              (lambda (x)
                (or (getf (semantic-tag-attributes x) :prototype-flag)
                    (not (member (cadr x) '(function variable type)))))
              (semanticdb-file-stream (buffer-file-name (current-buffer)))))
            (names (make-hash-table :test 'equal)))
        (dolist (tag tags)
          (let ((sn (semantic-tag-name tag)))
            (when (gethash sn names)
              (setq sn
                    (loop for i = 1 then (1+ i)
                       for name = (format "%s<%d>" sn i)
                       while (gethash name names)
                       finally return name)))
            (puthash sn tag names)))
        (goto-char (semantic-tag-start
                     (my-icompleting-read "Go to: " (hash-table-keys names))

Great, exactly what I was looking for :) Unfortunately this results in “Symbol’s function definition is void: hash-table-keys” on Aquamacs 0.99d - any thoughts? JanR?

Oops! This is one of mine:

    (defun hash-table-keys (hash)
      (let ((ret nil))
        (maphash (lambda (k v) (push k ret)) hash)

Also, IMHO you should switch to the normal Carbon Emacs. Aquamacs is a mutant abomination.

Another bit to use Spotlight as a stand-in for locate on OSX:

    (defun spotlight ()
      (let ((locate-command "mdfind"))
        (call-interactively 'locate nil)))

Useful snippet for Perl hackers:

    (defun w3m-about-perldoc-buffer (url &optional no-decode no-cache &rest args)
      "Handle perldoc in the current buffer."
      (when (string-match "\\`about://perldoc-buffer/" url)
        (let ((buf (get-buffer (w3m-url-decode-string
    			    (substring url (match-end 0)))))
    	  (default-directory w3m-profile-directory)
    	  (process-environment (copy-sequence process-environment)))
          ;; To specify the place in which pod2html generates its cache files.
          (setenv "HOME" (expand-file-name w3m-profile-directory))
          (insert-buffer buf)
          (when (zerop (apply #'call-process-region
    			  (point-min) (point-max)
    			  t '(t nil) nil
    			  (append w3m-perldoc-pod2html-arguments
    	(let ((case-fold-search t))
    	  (goto-char (point-min))
    	  (while (re-search-forward
    		  "<a href=\"about://perldoc\\(-buffer\\)?/\\([^\"]*\\)\\(\\.html\\)\">" nil t)
    	    (delete-region (match-beginning 3) (match-end 3))
    	      (narrow-to-region (match-beginning 2) (match-end 2))
    	      (while (search-backward "/" nil t)
    		(delete-char 1)
    		(insert "::"))
    	      (goto-char (point-max))))
    (defun w3m-view-pod (&optional buffer)
      "View POD for the current buffer."
      (w3m-goto-url (concat "about://perldoc-buffer/"
    			(w3m-url-encode-string (buffer-name buffer)))))
    (defun w3m-pod-file (file)
      "View POD for FILE."
        (insert-file file)
         (concat "about://perldoc-buffer/"
                 (w3m-url-encode-string (buffer-name (current-buffer)))))))

A generic version of ‘X-other-window’ (specific ‘X-other-window’ functions are usually better):

    (defun make-other-window-map (okmap)
      (unless (eq window-system 'ns)
        (let ((kmap (if (consp okmap) (cadr okmap) okmap)))
            ((consp kmap)
             (let ((ret (make-sparse-keymap)))
               (dolist (kv kmap)
                 (define-key ret (car kv) (other-windowize (cdr kv))))
            ((char-table-p kmap)
             (let* ((ret (copy-keymap okmap)))
               (map-char-table (lambda (k v)
                                 (unless (keymapp k)
                                   (aset (cadr ret) k (other-windowize v))))
                               (cadr ret))
               (dolist (kv (cddr ret))
                 (setf (cdr kv) (other-windowize (cdr kv))))
            (t (error "wtf is this: %s" kmap))))))
    (defun other-windowize (fn)
      `(lambda ()
          (save-window-excursion (call-interactively ',fn) (current-buffer)))))

Go to the indicated line with ‘find-file-at-point’:

    (defadvice find-file-at-point (around goto-line compile activate)
      (let ((line (and (looking-at ".*:\\([0-9]+\\)")
                       (parse-integer (match-string 1)))))
        (and line (goto-line line))))

Awesome, thank you! – RyanDavis

A better way to define hooks, particularly when you’re experimenting with them, than “(add-hook ‘blah (lambda () …))”:

    (defmacro defhook (mode &rest body)
      (let ((name (intern (concat "my-" (symbol-name mode) "-hook"))))
          ',(intern (concat (symbol-name mode) "-hook"))
          (defun ,name ()
         (put ',name 'definition-name ',mode))))
    (put 'defhook 'lisp-indent-function 1)

Since it took me so long to figure this one out (hey, it is late), I thought I’d add an example:

    (defhook text-mode ; note not 'text-mode


A function to go to the definition of a function bound to a key; basically, a shortcut for ‘C-h k’, ‘C-x o’, ‘TAB’, ‘RET’:

    (defun my-find-key (k &optional untranslated up-event)
      "Find the definition of a key."
      (interactive "kKey Sequence: \np\nU")
      (if (numberp untranslated)
          (setq untranslated (this-single-command-raw-keys)))
        (let ((modifiers (event-modifiers (aref k 0)))
    	  window position)
          ;; For a mouse button event, go to the button it applies to
          ;; to get the right key bindings.  And go to the right place
          ;; in case the keymap depends on where you clicked.
          (if (or (memq 'click modifiers) (memq 'down modifiers)
    	      (memq 'drag modifiers))
    	  (setq window (posn-window (event-start (aref k 0)))
    		position (posn-point (event-start (aref k 0)))))
          (when (windowp window)
    	    (set-buffer (window-buffer window))
    	(goto-char position))
          (let ((defn (key-binding k)))
            (if (or (null defn) (integerp defn) (equal defn 'undefined))
                (message "%s is undefined" (help-key-description k untranslated))
                (find-function defn))))))

If you’re on a Mac, M-tab switches between applications. Unfortunately if, like any civilized human, you use Command as Meta, it also does useful things in Emacs. This makes S-tab do those things as well:

    (define-key global-map (kbd "<S-tab>")
      (lambda ()
        (call-interactively (key-binding "\M-\t"))))

The GNUstep/Cocoa port doesn’t have ‘do-applescript’, so here’s a cheap replacement:

    (defun do-applescript (str)
      "Synchronously run applescript STR."
        (insert str)
        (shell-command-on-region (point-min) (point-max) "osascript" nil t)

Icicles faces for dark backgrounds:

     '(icicle-complete-input ((((background dark)) nil)))
     '(icicle-completing-mustmatch-prompt-prefix ((((type x w32 mac graphic) (class color)) (:foreground "Cyan"))))
     '(icicle-completing-prompt-prefix ((((type x w32 mac graphic) (class     color)) (:foreground "Red"))))
     '(icicle-current-candidate-highlight ((((background dark)) (:background "gray20"))))
     '(icicle-historical-candidate ((((background dark)) (:foreground "White"))))
     '(icicle-prompt-suffix ((((type x w32 mac graphic) (class color) (background dark)) (:foreground "LightSlateBlue"))))
     '(icicle-search-context-level-1 ((((background dark)) (:background     "gray20" :weight bold))))
     '(icicle-search-context-level-2 ((((background dark)) (:background     "gray15" :weight bold))))
     '(icicle-search-context-level-3 ((((background dark)) (:background     "gray10" :weight bold))))
     '(icicle-search-context-level-4 ((((background dark)) (:weight bold))))
     '(icicle-search-context-level-5 ((((background dark)) (:weight bold))))
     '(icicle-search-context-level-6 ((((background dark)) (:weight bold))))
     '(icicle-search-context-level-7 ((((background dark)) (:weight bold))))
     '(icicle-search-context-level-8 ((((background dark)) (:weight bold))))
     '(icicle-search-current-input ((t (:foreground "green"))))
     '(icicle-search-main-regexp-current ((((background dark)) (:foreground "DodgerBlue"))))
     '(icicle-search-main-regexp-others ((((background dark)) (:foreground     "SeaGreenk"))))
     '(icicle-special-candidate ((((background dark)) (:foreground "yellow"))))
     '(icicle-whitespace-highlight ((t (:background "#300")))))

Current curmudgeon code:

    (blink-cursor-mode		0)
    (tool-bar-mode			0)
    (when (fboundp 'tooltip-mode)
      (tooltip-mode			0))
    (with-current-buffer (get-buffer-create "*scratch*")
      (setq buffer-offer-save nil))
     line-move-visual		nil
     initial-scratch-message	nil)

Prevent the occasional disaster by confirming comint exits:

    (defadvice comint-send-eof (around warn-me-please compile activate)
      "Confirm EOF when called interactively, because accidental EOF sucks."
      (when (or (not (member this-command '(comint-send-eof
                (y-or-n-p "Really exit? "))