imenu parser for emacs delphi-mode

improve the one found on


1. support 'record', 'class' and 'interface' as level 1 menu

2. methods show as submenu of class

3. correctly jump to the impl. part (ignore interface part)


FIXME: currently not work if no 'interface/implementation'


keyword: emacs, delphi, freepascal, imenu


;; based on code from

(defvar imenu--function-name-regexp-delphi
    "^[ \t]*\\(function\\|procedure\\|constructor\\|destructor\\)[ \t]+"
    "\\([_a-zA-Z][_a-zA-Z0-9]*\\.\\)?"   ; class?
  "Re to get function/procedure names in Delphi.")

(defvar imenu--type-name-regexp-delphi
   (concat "^[ \t]*\\([a-zA-Z0-9]*\\)[ \t]*=[ \t]*\\(class\\|record\\|interface\\)"
   "regexp to get class/record namesin Delphi.")

(defun imenu--create-delphi-index-enh (&optional regexp)
  (let ((index-alist '())
        (progress-prev-pos 0)
        (case-fold-search t))
    (goto-char (point-min))
    (imenu-progress-message progress-prev-pos 0)
    ;;first, scan interface part for types
    (if (eq nil (re-search-forward "interface" nil t)) 
        (goto-char (point-min))
      (progn    ;; if we have interface..implementaion
         (while (re-search-forward
                 (or regexp imenu--type-name-regexp-delphi)
                 nil t)
           (imenu-progress-message progress-prev-pos)
           (let ((pos (save-excursion
                        (if imenu-use-markers (point-marker) (point))))
                  (sub-alist '())
                 (type-name (match-string-no-properties 1)))
                (push (cons "(declaration)" pos) sub-alist)
                (push (cons (format "%s." type-name) sub-alist) index-alist))))
    ;;now, scan implementation part for methods (and other functions)
    (goto-char (point-min))
    (if (eq nil (re-search-forward "implementation" nil t)) ;;advance to the interface part
        (goto-char (point-min))    
        (while (re-search-forward
                (or regexp imenu--function-name-regexp-delphi)
                nil t)
          (imenu-progress-message progress-prev-pos)
          (let* ((pos (save-excursion
                        (if imenu-use-markers (point-marker) (point))))
                 (class-name (match-string-no-properties 2))
                 (function-name (match-string-no-properties 3))
                 (sub-menu (assoc class-name index-alist)))
            (if (eq nil sub-menu)
                (push (cons (format "%s%s()"
                                    (if (eq nil class-name) "" class-name)
              (setcdr sub-menu (cons (cons function-name pos) (cdr sub-submenu)))
 (imenu-progress-message progress-prev-pos 100)
 (nreverse index-alist))) 

(add-hook 'delphi-mode-hook
    #'(lambda ()
     (require 'imenu)
     (setq imenu-sort-function 'imenu--sort-by-name)
     (setq imenu-create-index-function
posted @ 2010-04-07 21:49 巴蛮子 阅读(...) 评论(...) 编辑 收藏