Hello All,

> Is there any existing way of sorting the Classes imenu,
> (I thought that setting the imenu-sort-function may do this but
> apparently not)
> or would this require a modification to the jde-create-imenu-index
> function?

Attached file jde-parse-imenu.el contains enhanced versions of the
jde-parse.el imenu functions to add customizable sort facilities to the
JDE Classes index menu.

Your feedback will be welcome.

Sincerely,

David <[EMAIL PROTECTED]>
;;;
;;; Load this file after the JDE or replace `jde-create-imenu-index',
;;; `jde-imenu-index-class' and `jde-imenu-index-class-parts'
;;; functions by the above code in jde-parse.el to add customizable
;;; sort facilities to the JDE Classes imenu.
;;;
;;; David Ponce <[EMAIL PROTECTED]>
;;;

(defcustom jde-imenu-index-sort nil
  "If non-nil sorts items in the classes index menu.
You can choose:

- - 'asc   to sort by token name ascending (ignoring case).
- - 'desc  to sort by token name descending (ignoring case).

Use *Rescan* to rebuild the imenu when you have changed this option."
  :group 'jde-project
  :type '(choice (const :tag "No sort"    nil )
                 (const :tag "Ascending"  asc )
                 (const :tag "Descending" desc)))

(defun jde-sort-tokens (tokens)
  "Sorts the token list TOKENS depending on `jde-imenu-index-sort' value."
  (cond ((eq jde-imenu-index-sort 'asc)
         (sort tokens
               (function
                (lambda (token1 token2)
                  (string-lessp (upcase (semantic-token-name token1))
                                (upcase (semantic-token-name token2)))))))
        ((eq jde-imenu-index-sort 'desc)
         (sort tokens
               (function
                (lambda (token1 token2)
                  (string-lessp (upcase (semantic-token-name token2))
                                (upcase (semantic-token-name token1)))))))
        (t
         tokens)))

(defun jde-imenu-index-class  (class-token)
  "Creates an imenu index for a class in CLASS-TOKEN."
  (let* ((class-name  (semantic-token-name       class-token))
         (class-type  (semantic-token-type       class-token))
         (class-start (semantic-token-start      class-token))
         (class-parts (semantic-token-type-parts class-token))
         (class-index (jde-imenu-index-class-parts class-parts)))

    (if jde-imenu-include-classdef
        ;; If requested adds a *class def* item to go to the class def.
        (setq class-index (cons (cons "*class def*" class-start)
                                class-index))
      ;; Else adds an *empty* item to go to the class def. only
      ;; when there is not parts
      (or class-index
          (setq class-index
                (list (cons "*empty*"
                            class-start)))))

    (list (cons (format "%s %s" class-type class-name)
                class-index))))

(defun jde-imenu-index-class-parts (tokens)
  "Creates an imenu index for class parts in TOKENS.
When`jde-imenu-include-signature' is non-nil the
index menu displays full method signatures and field types."
  (let ((methods (semantic-find-nonterminal-by-token 'function tokens))
        (fields  (semantic-find-nonterminal-by-token 'variable tokens))
        (classes (semantic-find-nonterminal-by-token 'type     tokens))
        index)

    (setq methods (jde-sort-tokens methods))
    (while methods
      (let* ((method-token (car methods))
             (method-name  (semantic-token-name method-token))
             (method-pos   (semantic-token-start method-token))
             method-sig)
        (if jde-imenu-include-signature
            (let ((method-type  (semantic-token-type method-token))
                  (method-args  (semantic-token-function-args method-token)))
              (setq method-sig (if method-type
                                   (format "%s %s(" method-type method-name)
                                 (format "%s(" method-name)))
              (while method-args
                (let ((method-arg-token (car method-args))
                      method-arg-type)
                  (when method-arg-token
                    (setq method-arg-type (semantic-token-type method-arg-token))
                    (setq method-sig (concat method-sig method-arg-type))))
                (setq method-args (cdr method-args))
                (if method-args (setq method-sig (concat method-sig ","))))
              (setq method-sig (concat method-sig ")")))
          (setq method-sig (format "%s()" method-name)))
        (setq index
              (append
               index (list (cons method-sig method-pos)))))
      (setq methods (cdr methods)))

    ;; Add a separator between method and field index
    (if fields
        (setq index (append index '(("-"))))) 
    
    (setq fields (jde-sort-tokens fields))
    (while fields
      (let* ((field-token (car fields))
             (field-name  (semantic-token-name  field-token))
             (field-pos   (semantic-token-start field-token)))
        (if jde-imenu-include-signature
            (setq field-name (concat (semantic-token-type field-token)
                                     " " field-name)))
        (setq index 
              (append 
               index (list (cons field-name field-pos)))))
      (setq fields (cdr fields)))

    (setq classes (jde-sort-tokens classes))
    (while classes
      (let* ((class-token  (car classes))
             (class-index  (jde-imenu-index-class class-token)))
        (setq index (append index class-index)))
      (setq classes (cdr classes)))
    index))

(defun jde-create-imenu-index ()
  "Creates an imenu index for a Java source buffer.
This function uses the semantic bovinator to index the buffer."

  ;; The following clears the toplevel bovine cache for the current
  ;; buffer and forces *rescan* to work even if the current buffer has
  ;; not been modifified. This is needed to rebuild the "Classes"
  ;; imenu when customization has been changed.
  (semantic-clear-toplevel-cache)
  
  (let* ((tokens   (semantic-bovinate-toplevel))
         (packages (semantic-find-nonterminal-by-token 'package tokens))
         (depends  (semantic-find-nonterminal-by-token 'include tokens))
         (classes  (semantic-find-nonterminal-by-token 'type tokens))
         depend-index
         index)

    (setq classes (jde-sort-tokens classes))
    (while classes
      (let* ((class-token  (car classes))
             (class-index  (jde-imenu-index-class class-token)))
        (setq index (append index class-index)))
      (setq classes (cdr classes)))

    (setq depends (jde-sort-tokens depends))
    (while depends
      (let* ((depend-token (car depends))
             (depend-name  (semantic-token-name  depend-token))
             (depend-pos   (semantic-token-start depend-token)))
        (setq depend-index (append depend-index (list (cons depend-name depend-pos)))))
      (setq depends (cdr depends)))
    (if depend-index
        (setq index (append index (list (cons "imports" depend-index)))))

    (setq packages (jde-sort-tokens packages))
    (while packages
      (let* ((package-token (car packages))
             (package-name  (semantic-token-name  package-token))
             (package-pos   (semantic-token-start package-token)))
        (setq index 
              (append 
               index 
               (list (cons (concat "package " package-name) package-pos)))))
      (setq packages (cdr packages)))
    index))

;;; jde-parse-imenu.el ends here

Reply via email to