+ (let (keep-at-top tail)
+ (if (memq imenu--rescan-item menulist)
+ (setq keep-at-top (cons imenu--rescan-item nil)
+ menulist (delq imenu--rescan-item menulist)))
+ (setq tail menulist)
+ (while tail
+ (if (imenu--subalist-p (car tail))
+ (setq keep-at-top (cons (car tail) keep-at-top)
+ menulist (delq (car tail) menulist)))
+ (setq tail (cdr tail)))
+ (if imenu-sort-function
+ (setq menulist
+ (sort
+ (let ((res nil)
+ (oldlist menulist))
+ ;; Copy list method from the cl package `copy-list'
+ (while (consp oldlist) (push (pop oldlist) res))
+ (if res ; in case, e.g. no functions defined
+ (prog1 (nreverse res) (setcdr res oldlist))))
+ imenu-sort-function)))
+ (if (> (length menulist) imenu-max-items)
+ (let ((count 0))
+ (setq menulist
+ (mapcar
+ (function
+ (lambda (menu)
+ (cons (format "From: %s" (caar menu)) menu)))
+ (imenu--split menulist imenu-max-items)))))
+ (cons title
+ (nconc (nreverse keep-at-top) menulist))))
+
+;;; Split up each long alist that are nested within ALIST
+;;; into nested alists.
+(defun imenu--split-submenus (alist)
+ (mapcar (function
+ (lambda (elt)
+ (if (and (consp elt)
+ (stringp (car elt))
+ (listp (cdr elt)))
+ (imenu--split-menu (cdr elt) (car elt))
+ elt)))
+ alist))
+
+;;; Truncate all strings in MENULIST to imenu-max-item-length
+(defun imenu--truncate-items (menulist)
+ (mapcar (function
+ (lambda (item)
+ (cond
+ ((consp (cdr item))
+ (imenu--truncate-items (cdr item)))
+ (t
+ ;; truncate if necessary
+ (if (and (numberp imenu-max-item-length)
+ (> (length (car item)) imenu-max-item-length))
+ (setcar item (substring (car item) 0 imenu-max-item-length)))))))
+ menulist))
+
+
+(defun imenu--make-index-alist (&optional noerror)
+ "Create an index-alist for the definitions in the current buffer.
+
+Report an error if the list is empty unless NOERROR is supplied and
+non-nil.
+
+Simple elements in the alist look like (INDEX-NAME . INDEX-POSITION).
+Special elements look like (INDEX-NAME FUNCTION ARGUMENTS...).
+A nested sub-alist element looks like (INDEX-NAME SUB-ALIST).
+The function `imenu--subalist-p' tests an element and returns t
+if it is a sub-alist.
+
+There is one simple element with negative POSITION; that's intended
+as a way for the user to ask to recalculate the buffer's index alist."
+ (or (and imenu--index-alist
+ (or (not imenu-auto-rescan)
+ (and imenu-auto-rescan
+ (> (buffer-size) imenu-auto-rescan-maxout))))
+ ;; Get the index; truncate if necessary
+ (progn
+ (setq imenu--index-alist
+ (save-excursion
+ (save-restriction
+ (widen)
+ (funcall imenu-create-index-function))))
+ (imenu--truncate-items imenu--index-alist)))
+ (or imenu--index-alist noerror
+ (error "No items suitable for an index found in this buffer"))