;;; which-func.el --- print current function in mode line
-;; Copyright (C) 1994, 1997, 1998, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
-;; Free Software Foundation, Inc.
+;; Copyright (C) 1994, 1997, 1998, 2001, 2002, 2003, 2004, 2005, 2006
+;; 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
;; Author: Alex Rezinsky <alexr@msil.sps.mot.com>
;; (doesn't seem to be responsive any more)
local-map ,which-func-keymap
face which-func
;;mouse-face highlight ; currently not evaluated :-(
- help-echo "mouse-1: go to beginning, mouse-2: toggle rest visibility, mouse-3: go to end")
+ help-echo "mouse-1: go to beginning\n\
+mouse-2: toggle rest visibility\n\
+mouse-3: go to end")
"]")
"Format for displaying the function in the mode line."
:group 'which-func
:type 'sexp)
;;;###autoload (put 'which-func-format 'risky-local-variable t)
+(defvar which-func-imenu-joiner-function (lambda (x) (car (last x)))
+ "Function to join together multiple levels of imenu nomenclature.
+Called with a single argument, a list of strings giving the names
+of the menus we had to traverse to get to the item. Returns a
+single string, the new name of the item.")
+
(defvar which-func-cleanup-function nil
"Function to transform a string before displaying it in the mode line.
The function is called with one argument, the string to display.
With prefix ARG, turn Which Function mode on if arg is positive,
and off otherwise."
:global t :group 'which-func
+ (when (timerp which-func-update-timer)
+ (cancel-timer which-func-update-timer))
+ (setq which-func-update-timer nil)
(if which-function-mode
;;Turn it on
(progn
(or (eq which-func-modes t)
(member major-mode which-func-modes))))))
;; Turn it off
- (when (timerp which-func-update-timer)
- (cancel-timer which-func-update-timer))
- (setq which-func-update-timer nil)
(dolist (buf (buffer-list))
(with-current-buffer buf (setq which-func-mode nil)))))
(defun which-function ()
"Return current function name based on point.
Uses `which-func-functions', `imenu--index-alist'
-or `add-log-current-defun-function'.
+or `add-log-current-defun'.
If no function name is found, return nil."
(let ((name
;; Try the `which-func-functions' functions first.
(boundp 'imenu--index-alist) imenu--index-alist)
(let ((alist imenu--index-alist)
(minoffset (point-max))
- offset elem pair mark)
- (while alist
- (setq elem (car-safe alist)
- alist (cdr-safe alist))
- ;; Elements of alist are either ("name" . marker), or
- ;; ("submenu" ("name" . marker) ... ).
- (unless (listp (cdr elem))
- (setq elem (list elem)))
- (while elem
- (setq pair (car elem)
- elem (cdr elem))
- (and (consp pair)
- (number-or-marker-p (setq mark (cdr pair)))
- (if (>= (setq offset (- (point) mark)) 0)
- (if (< offset minoffset) ; find the closest item
- (setq minoffset offset
- name (car pair)))
- ;; Entries in order, so can skip all those after point.
- (setq elem nil)))))))
+ offset pair mark imstack namestack)
+ ;; Elements of alist are either ("name" . marker), or
+ ;; ("submenu" ("name" . marker) ... ). The list can be
+ ;; arbitrarily nested.
+ (while (or alist imstack)
+ (if alist
+ (progn
+ (setq pair (car-safe alist)
+ alist (cdr-safe alist))
+
+ (cond ((atom pair)) ; skip anything not a cons
+
+ ((imenu--subalist-p pair)
+ (setq imstack (cons alist imstack)
+ namestack (cons (car pair) namestack)
+ alist (cdr pair)))
+
+ ((number-or-marker-p (setq mark (cdr pair)))
+ (if (>= (setq offset (- (point) mark)) 0)
+ (if (< offset minoffset) ; find the closest item
+ (setq minoffset offset
+ name (funcall
+ which-func-imenu-joiner-function
+ (reverse (cons (car pair)
+ namestack)))))))))
+ (setq alist (car imstack)
+ namestack (cdr namestack)
+ imstack (cdr imstack))))))
+
;; Try using add-log support.
- (when (and (null name) (boundp 'add-log-current-defun-function)
- add-log-current-defun-function)
- (setq name (funcall add-log-current-defun-function)))
+ (when (null name)
+ (setq name (add-log-current-defun)))
;; Filter the name if requested.
(when name
(if which-func-cleanup-function