(imenu-example--python-show-method-args-p,

imenu-example--python-class-regexp,
imenu-example--python-method-regexp,
imenu-example--python-method-no-arg-parens,
imenu-example--python-method-arg-parens,
imenu-example--generic-python-expression,
imenu-example--python-generic-regexp,
imenu-example--python-generic-parens): New variables.

(imenu-example--create-python-index,
imenu-example--create-python-index-engine): New functions.
This commit is contained in:
Barry Warsaw 1996-08-01 19:48:02 +00:00
parent ce60bc7192
commit 8143746750
1 changed files with 210 additions and 0 deletions

View File

@ -229,6 +229,11 @@ the Emacs bell is also rung as a warning.")
))
"Additional expressions to highlight in Python mode.")
(defvar imenu-example--python-show-method-args-p nil
"*Controls echoing of arguments of functions & methods in the imenu buffer.
When non-nil, arguments are printed.")
;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
;; NO USER DEFINABLE VARIABLES BEYOND THIS POINT
@ -413,6 +418,211 @@ Currently-active file is at the head of the list.")
["Describe mode" py-describe-mode t]
)))
;; imenu definitions, courtesy of Perry A. Stoll <stoll@atr-sw.atr.co.jp>
(defvar imenu-example--python-class-regexp
(concat ; <<classes>>
"\\(" ;
"^[ \t]*" ; newline and maybe whitespace
"\\(class[ \t]+[a-zA-Z0-9_]+\\)" ; class name
; possibly multiple superclasses
"\\([ \t]*\\((\\([a-zA-Z0-9_, \t\n]\\)*)\\)?\\)"
"[ \t]*:" ; and the final :
"\\)" ; >>classes<<
)
"Regexp for Python classes for use with the imenu package."
)
(defvar imenu-example--python-method-regexp
(concat ; <<methods and functions>>
"\\(" ;
"^[ \t]*" ; new line and maybe whitespace
"\\(def[ \t]+" ; function definitions start with def
"\\([a-zA-Z0-9_]+\\)" ; name is here
; function arguments...
"[ \t]*(\\([a-zA-Z0-9_=,\* \t\n]*\\))"
"\\)" ; end of def
"[ \t]*:" ; and then the :
"\\)" ; >>methods and functions<<
)
"Regexp for Python methods/functions for use with the imenu package."
)
(defvar imenu-example--python-method-no-arg-parens '(2 8)
"Indicies into groups of the Python regexp for use with imenu.
Using these values will result in smaller imenu lists, as arguments to
functions are not listed.
See the variable `imenu-example--python-show-method-args-p' for more
information.")
(defvar imenu-example--python-method-arg-parens '(2 7)
"Indicies into groups of the Python regexp for use with imenu.
Using these values will result in large imenu lists, as arguments to
functions are listed.
See the variable `imenu-example--python-show-method-args-p' for more
information.")
;; Note that in this format, this variable can still be used with the
;; imenu--generic-function. Otherwise, there is no real reason to have
;; it.
(defvar imenu-example--generic-python-expression
(cons
(concat
imenu-example--python-class-regexp
"\\|" ; or...
imenu-example--python-method-regexp
)
imenu-example--python-method-no-arg-parens)
"Generic Python expression which may be used directly with imenu.
Used by setting the variable `imenu-generic-expression' to this value.
Also, see the function \\[imenu-example--create-python-index] for a
better alternative for finding the index.")
;; These next two variables are used when searching for the python
;; class/definitions. Just saving some time in accessing the
;; generic-python-expression, really.
(defvar imenu-example--python-generic-regexp)
(defvar imenu-example--python-generic-parens)
;;;###autoload
(eval-when-compile
;; Imenu isn't used in XEmacs, so just ignore load errors
(condition-case ()
(progn
(require 'cl)
(require 'imenu))
(error nil)))
(defun imenu-example--create-python-index ()
"Python interface function for imenu package.
Finds all python classes and functions/methods. Calls function
\\[imenu-example--create-python-index-engine]. See that function for
the details of how this works."
(setq imenu-example--python-generic-regexp
(car imenu-example--generic-python-expression))
(setq imenu-example--python-generic-parens
(if imenu-example--python-show-method-args-p
imenu-example--python-method-arg-parens
imenu-example--python-method-no-arg-parens))
(goto-char (point-min))
(imenu-example--create-python-index-engine nil))
(defun imenu-example--create-python-index-engine (&optional start-indent)
"Function for finding imenu definitions in Python.
Finds all definitions (classes, methods, or functions) in a Python
file for the imenu package.
Returns a possibly nested alist of the form
(INDEX-NAME . INDEX-POSITION)
The second element of the alist may be an alist, producing a nested
list as in
(INDEX-NAME . INDEX-ALIST)
This function should not be called directly, as it calls itself
recursively and requires some setup. Rather this is the engine for
the function \\[imenu-example--create-python-index].
It works recursively by looking for all definitions at the current
indention level. When it finds one, it adds it to the alist. If it
finds a definition at a greater indentation level, it removes the
previous definition from the alist. In it's place it adds all
definitions found at the next indentation level. When it finds a
definition that is less indented then the current level, it retuns the
alist it has created thus far.
The optional argument START-INDENT indicates the starting indentation
at which to continue looking for Python classes, methods, or
functions. If this is not supplied, the function uses the indentation
of the first definition found."
(let ((index-alist '())
(sub-method-alist '())
looking-p
def-name prev-name
cur-indent def-pos
(class-paren (first imenu-example--python-generic-parens))
(def-paren (second imenu-example--python-generic-parens)))
(setq looking-p
(re-search-forward imenu-example--python-generic-regexp
(point-max) t))
(while looking-p
(save-excursion
;; used to set def-name to this value but generic-extract-name is
;; new to imenu-1.14. this way it still works with imenu-1.11
;;(imenu--generic-extract-name imenu-example--python-generic-parens))
(let ((cur-paren (if (match-beginning class-paren)
class-paren def-paren)))
(setq def-name
(buffer-substring (match-beginning cur-paren)
(match-end cur-paren))))
(beginning-of-line)
(setq cur-indent (current-indentation)))
;; HACK: want to go to the next correct definition location. we
;; explicitly list them here. would be better to have them in a
;; list.
(setq def-pos
(or (match-beginning class-paren)
(match-beginning def-paren)))
;; if we don't have a starting indent level, take this one
(or start-indent
(setq start-indent cur-indent))
;; if we don't have class name yet, take this one
(or prev-name
(setq prev-name def-name))
;; what level is the next definition on? must be same, deeper
;; or shallower indentation
(cond
;; at the same indent level, add it to the list...
((= start-indent cur-indent)
;; if we don't have push, use the following...
;;(setf index-alist (cons (cons def-name def-pos) index-alist))
(push (cons def-name def-pos) index-alist))
;; deeper indented expression, recur...
((< start-indent cur-indent)
;; the point is currently on the expression we're supposed to
;; start on, so go back to the last expression. The recursive
;; call will find this place again and add it to the correct
;; list
(re-search-backward imenu-example--python-generic-regexp
(point-min) 'move)
(setq sub-method-alist (imenu-example--create-python-index-engine
cur-indent))
(if sub-method-alist
;; we put the last element on the index-alist on the start
;; of the submethod alist so the user can still get to it.
(let ((save-elmt (pop index-alist)))
(push (cons (imenu-create-submenu-name prev-name)
(cons save-elmt sub-method-alist))
index-alist))))
;; found less indented expression, we're done.
(t
(setq looking-p nil)
(re-search-backward imenu-example--python-generic-regexp
(point-min) t)))
(setq prev-name def-name)
(and looking-p
(setq looking-p
(re-search-forward imenu-example--python-generic-regexp
(point-max) 'move))))
(nreverse index-alist)))
;;;###autoload
(defun python-mode ()