diff lisp/oobr/br-python.el @ 0:376386a54a3c r19-14

Import from CVS: tag r19-14
author cvs
date Mon, 13 Aug 2007 08:45:50 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/oobr/br-python.el	Mon Aug 13 08:45:50 2007 +0200
@@ -0,0 +1,255 @@
+;;!emacs
+;;
+;; FILE:         br-python.el
+;; SUMMARY:      Support routines for Python inheritance browsing.
+;; USAGE:        GNU Emacs Lisp Library
+;; KEYWORDS:     oop, tools, python
+;;
+;; AUTHOR:       Harri Pasanen, based on Smalltalk and C++ browsers 
+;;               by Bob Weiner
+;; ORG:          Tekla Oy
+;;
+;; ORIG-DATE:    5-Apr-96
+;; LAST-MOD:     12-Apr
+;;
+;; Copyright (C) 1990-1995  Free Software Foundation, Inc.
+;; See the file BR-COPY for license information.
+;;
+;; This file is part of the OO-Browser.
+;;
+;; DESCRIPTION:  
+;;
+;;   See 'python-class-def-regexp' for regular expression that matches class
+;;   definitions.
+;;            
+;; DESCRIP-END.
+
+;;; ************************************************************************
+;;; Other required Elisp libraries
+;;; ************************************************************************
+
+(mapcar 'require '(br-lib hypb))
+
+;;; ************************************************************************
+;;; User visible variables
+;;; ************************************************************************
+
+(defvar python-lib-search-dirs nil
+  "List of directories below which Python Library source files are found.
+Subdirectories of Library source are also searched.  A Library is a stable
+group of classes.")
+
+(defvar python-sys-search-dirs nil
+  "List of directories below which Python System source files are found.
+Subdirectories of System source are also searched.  A System class is one
+that is not yet reusable and is likely to change before release.")
+
+(defconst python-narrow-view-to-class nil
+ "*Non-nil means narrow buffer to just the matching class definition when displayed.")
+
+;;; following is reserved for future, currently does not work
+(defconst python-duplicate-classnames-across-modules nil
+ "*Non-nil means that the module name is prepended to class names.")
+
+;;; ************************************************************************
+;;; Internal functions
+;;; ************************************************************************
+
+(defun python-get-classes-from-source (filename &optional skip-tags
+						skip-tags-cleanup)
+  "Scans FILENAME and returns cons of class list with parents-class alist.
+Handles multiple inheritance.  Assumes file existence and readability have
+already been checked."
+  (let ((no-kill (get-file-buffer filename))
+	classes class parents parent-cons)
+    (if no-kill
+	(set-buffer no-kill)
+      (funcall br-view-file-function filename))
+    (save-restriction
+      (save-excursion
+	(widen)
+	(goto-char (point-min))
+	(or skip-tags
+	    (progn (setq signatures (python-scan-features))
+		   (goto-char (point-min))))
+	(while (re-search-forward python-class-def-regexp nil t)
+	  (setq has-parents
+		(= ?\( (char-after (point))))
+	  (setq class (buffer-substring (match-beginning 1) (match-end 1))
+		parent-cons 
+		(cons
+		 ;; Return parents as a list, or nil if no parents
+		 (if has-parents (python-scan-parents))
+		 class))
+	  ;; Assume class name not found within a comment.
+	  (setq classes (cons class classes)
+		parents (cons parent-cons parents))
+	  (or skip-tags
+	      ;; Scan members defined within class
+	      (setq signatures
+		    (append
+		     signatures
+		     (python-scan-features-in-class class (point) 
+						    (python-locate-class-end))
+		     )))))
+      (if skip-tags
+	  nil
+	(python-get-feature-tags buffer-file-name (python-sort-features 
+						 signatures))
+	(or skip-tags-cleanup (br-feature-tags-save)))
+      (or no-kill (kill-buffer (current-buffer)))
+    (cons classes (delq nil parents)))))
+
+
+(defun python-scan-parents ()
+  "Return list of parents names from a Python class definition.
+Point must be after the '(' that begins the parent list and before the
+first parent entry when this function is called."
+  (let ((parent-list) (again t)
+	parent)
+    (while (and again (re-search-forward python-parent-class-name nil t))
+      (setq again (= ?, (char-after (point)))
+	    parent (buffer-substring (match-beginning 3)
+				      (match-end 3))
+	    parent-list (cons parent parent-list)))
+    (nreverse parent-list)))
+
+(defun python-locate-class-end ()
+  "Look up the end of class.  Point is assumed to be in the class definition.
+Do this by looking up the first line that begins with python-identifier-chars."
+  (save-excursion
+    (let ((result-point (point-max)))
+      (if (re-search-forward 
+	   (concat "^[" python-identifier-chars "]") nil t)
+	  (progn
+	    (setq result-point (- (match-beginning 0) 1))
+	    (if (python-within-string-p)
+		(python-locate-class-end)
+	      result-point))
+	result-point))))
+
+(defun python-get-parents-from-source (filename class-name)
+  "Scan source in FILENAME and return list of parents of CLASS-NAME.
+Assume file existence has already been checked."
+    (or (null class-name)
+	(car (car (br-rassoc
+		   class-name
+		   (cdr (python-get-classes-from-source filename)))))))
+
+(defun python-select-path (paths-htable-elt &optional feature-p)
+  "Select proper pathname from PATHS-HTABLE-ELT based upon value of optional FEATURE-P.
+Selection is between path of class definition and path for features associated
+with the class."
+  (cdr paths-htable-elt))
+
+(defun python-set-case (type)
+  "Return string TYPE identifier for use as a class name."
+  type)
+
+(defun python-set-case-type (class-name)
+  "Return string CLASS-NAME for use as a type identifier."
+  class-name)
+
+(defun python-to-comments-begin ()
+  "Skip back from current point past any preceding Python comments. 
+Presently NoOp"
+  )
+
+(defun python-class-definition-regexp (class &optional regexp-flag)
+  "Return regexp to uniquely match the definition of CLASS name.
+Optional REGEXP-FLAG non-nil means CLASS has already been quoted for use in a
+regular expression. (not meaningful for Python)"
+  (concat python-class-name-before class whitespace))
+
+;;; ************************************************************************
+;;; Internal variables
+;;; ************************************************************************
+
+(defconst python-type-tag-separator "@"
+  "String that separates a tag's type from its normalized definition form.
+This should be a single character which is unchanged when quoted for use as a
+literal in a regular expression.")
+
+(defconst python-identifier-chars "a-zA-Z0-9_"
+  "String of chars and char ranges that may be used within a Python identifier.")
+
+(defconst python-identifier (concat "\\([a-zA-Z_][" python-identifier-chars "]*\\)")
+  "Regular expression matching a Python identifier.")
+
+(defconst whitespace "[ \t]*")
+
+(defconst python-parent-class-name 
+  (concat whitespace 
+	  "\\(" python-identifier "\\.\\)*" ; possible module name precedes
+	  python-identifier whitespace)
+  "Regular expression matching optional Python parent class")
+
+(defconst python-class-name-before  "^class[ \t]+"
+  "Regexp preceding the class name in a class definition.  
+Note: this does not allow for nested classes.")
+
+(defconst python-class-name-after
+  (concat whitespace python-parent-class-name whitespace ":")
+  "Regexp following the class name in a class definition.")
+
+(defconst python-class-def-regexp
+  (concat python-class-name-before python-identifier whitespace)
+;  (concat python-class-name-before python-identifier python-class-name-after)
+  "Regular expression used to match to class definitions in source text.
+Class name identifier is grouped expression 1.  Parent identifier is grouped
+expression 2.")
+
+
+(defconst python-lang-prefix "python-"
+ "Prefix string that starts \"br-python.el\" symbol names.")
+
+(defconst python-src-file-regexp ".\\.py$"
+  "Regular expression matching a unique part of Python source file name and no others.")
+
+(defvar python-children-htable nil
+  "Htable whose elements are of the form: (LIST-OF-CHILD-CLASSES . CLASS-NAME).
+Used to traverse Python inheritance graph.  'br-build-children-htable' builds
+this list.")
+(defvar python-parents-htable nil
+  "Htable whose elements are of the form: (LIST-OF-PARENT-CLASSES . CLASS-NAME).
+Used to traverse Python inheritance graph.  'br-build-parents-htable' builds
+this list.")
+(defvar python-paths-htable nil
+  "Htable whose elements are of the form: (LIST-OF-CLASS-NAMES . FILE-PATH).
+FILE-PATH gives the location of classes found in LIST-OF-CLASS-NAMES.
+'br-build-paths-htable' builds this list.")
+
+
+(defvar python-lib-parents-htable nil
+  "Htable whose elements are of the form: (LIST-OF-PARENT-CLASSES . CLASS-NAME).
+Only classes from stable software libraries are used to build the list.")
+(defvar python-lib-paths-htable nil
+  "Htable whose elements are of the form: (LIST-OF-CLASS-NAMES . FILE-PATH).
+FILE-PATH gives the location of classes found in LIST-OF-CLASS-NAMES.
+Only classes from stable software libraries are used to build the list.")
+
+(defvar python-sys-parents-htable nil
+  "Htable whose elements are of the form: (LIST-OF-PARENT-CLASSES . CLASS-NAME).
+Only classes from systems that are likely to change are used to build the list.")
+(defvar python-sys-paths-htable nil
+  "Alist whose elements are of the form: (LIST-OF-CLASS-NAMES . FILE-PATH).
+FILE-PATH gives the location of classes found in LIST-OF-CLASS-NAMES.
+Only classes from systems that are likely to change are used to build the
+list.")
+
+(defvar python-lib-prev-search-dirs nil
+  "Used to check if 'python-lib-classes-htable' must be regenerated.")
+(defvar python-sys-prev-search-dirs nil
+  "Used to check if 'python-sys-classes-htable' must be regenerated.")
+
+(defvar python-env-spec nil
+  "Non-nil value means Environment specification has been given but not yet built.
+Nil means current Environment has been built, though it may still require updating.")
+
+(provide 'br-python)
+
+
+
+
+
+