branch: externals/idlwave
commit b26590104f38b2a5006b8029c6c5b23c0a11474d
Author: jdsmith <jdsmith>
Commit: jdsmith <jdsmith>

    - Allow inherited structures in class definitions, looking for them in
      the class definition routine.  Scan any structure found in a class
      definition.
    - Use two part help when calling help with source on an inherited
      structure, to direct the help to the correct routine definition
      (assuming it's found-in some other __define procedure than its own).
    - Narrow to region when searching through structures for a big speedup.
    - Remove requirememnt of valid file for class-info: if a buffers
      visiting an unsaved file, that'll work as well.
    - Don't insert/remove char in show-begin: was messing up VIPER mode (and
      not really needed anymore ?).
---
 idlwave.el | 253 ++++++++++++++++++++++++++++++++++++++-----------------------
 1 file changed, 159 insertions(+), 94 deletions(-)

diff --git a/idlwave.el b/idlwave.el
index f725615a4d..851f6ce229 100644
--- a/idlwave.el
+++ b/idlwave.el
@@ -6,7 +6,7 @@
 ;;          Chris Chase <ch...@att.com>
 ;; Maintainer: J.D. Smith <jdsm...@as.arizona.edu>
 ;; Version: VERSIONTAG
-;; Date: $Date: 2004/10/16 01:05:49 $
+;; Date: $Date: 2004/11/17 05:21:40 $
 ;; Keywords: languages
 
 ;; This file is part of GNU Emacs.
@@ -2101,8 +2101,8 @@ An END token must be preceded by whitespace."
 Also checks if the correct end statement has been used."
   ;; All end statements are reserved words
   ;; Re-indent end line
-  (insert-char ?\  1) ;; So indent, etc. work well
-  (backward-char 1)
+  ;;(insert-char ?\  1) ;; So indent, etc. work well
+  ;;(backward-char 1)
   (let* ((pos (point-marker))
         (last-abbrev-marker (copy-marker last-abbrev-location))
         (eol-pos (save-excursion (end-of-line) (point)))
@@ -2145,8 +2145,8 @@ Also checks if the correct end statement has been used."
            (beep)
            (message "Warning: Shouldn't this be \"%s\" instead of \"%s\"?" 
                     end1 end)
-           (sit-for 1)))))))
-  (delete-char 1))
+           (sit-for 1))))))))
+  ;;(delete-char 1))
 
 (defun idlwave-block-master ()
   (let ((case-fold-search t))
@@ -4382,7 +4382,7 @@ will re-read the catalog."
 
 
 (defvar idlwave-load-rinfo-idle-timer)
-(defun idlwave-update-routine-info (&optional arg)
+(defun idlwave-update-routine-info (&optional arg no-concatenate)
   "Update the internal routine-info lists.
 These lists are used by `idlwave-routine-info' (\\[idlwave-routine-info])
 and by `idlwave-complete' (\\[idlwave-complete]) to provide information
@@ -4401,8 +4401,14 @@ for currently compiled routines.
 
 With prefix ARG, also reload the system and library lists.
 With two prefix ARG's, also rescans the chosen user catalog tree.
-With three prefix args, dispatch asynchronous process to do the update."
-  (interactive "P")
+With three prefix args, dispatch asynchronous process to do the update.
+
+If NO-CONCATENATE is non-nil, don't pre-concatenate the routine info
+lists, but instead wait for the shell query to complete and
+asynchronously finish updating routine info.  This is set
+automatically when called interactively.  When you need routine
+information updated immediately, leave NO-CONCATENATE nil."
+  (interactive "P\np")
   ;; Stop any idle processing
   (if (or (and (fboundp 'itimerp)
               (itimerp idlwave-load-rinfo-idle-timer))
@@ -4461,7 +4467,7 @@ With three prefix args, dispatch asynchronous process to 
do the update."
            (idlwave-scan-library-catalogs)))
 
        (if (or (not ask-shell)
-               (not (interactive-p)))
+               (not no-concatenate))
            ;; 1. If we are not going to ask the shell, we need to do the
            ;;    concatenation now.
            ;; 2. When this function is called non-interactively, it
@@ -4626,8 +4632,7 @@ With three prefix args, dispatch asynchronous process to 
do the update."
   "Put the different sources for routine information together."
   ;; The sequence here is important because earlier definitions shadow 
   ;; later ones.  We assume that if things in the buffers are newer
-  ;; then in the shell of the system, it is meant to be different.
-
+  ;; then in the shell of the system, they are meant to be different.
   (setcdr idlwave-last-system-routine-info-cons-cell
          (append idlwave-buffer-routines
                  idlwave-compiled-routines
@@ -5306,7 +5311,7 @@ end
      nil 'hide wait)
 ;    (message "SENDING SAVE") ; ????????????????????????
     (idlwave-shell-send-command
-     (format 
"save,'idlwave_routine_info','idlwave_print_info_entry',FILE='%s',/ROUTINES" 
+     (format 
"save,'idlwave_routine_info','idlwave_print_info_entry','idlwave_get_class_tags','idlwave_get_sysvars',FILE='%s',/ROUTINES"
 
             (idlwave-shell-temp-file 'rinfo))
      nil 'hide wait))
 
@@ -5961,25 +5966,28 @@ ARROW:  Location of the arrow"
         (pro-point (or (nth 3 pro-entry) 0))
         (last-char (idlwave-last-valid-char))
          (case-fold-search t)
+        (match-string (buffer-substring bos (point)))
         cw cw-mod cw-arrow cw-class cw-point)
     (if (< func-point pro-point) (setq func nil))
     (cond
      ((string-match "\\`[ \t]*\\(pro\\|function\\)[ \t]+[a-zA-Z0-9_]*\\'"
-                    (buffer-substring bos (point)))
+                    match-string)
       (setq cw 'class))
      ((string-match 
        "\\`[ \t]*\\([a-zA-Z][a-zA-Z0-9$_]*\\)?\\'" 
-       (buffer-substring (if (> pro-point 0) pro-point bos) (point)))
+       (if (> pro-point 0)
+          (buffer-substring pro-point (point))
+        match-string))
       (setq cw 'procedure cw-class pro-class cw-point pro-point
            cw-arrow pro-arrow))
      ((string-match "\\`[ \t]*\\(pro\\|function\\)\\>"
-                   (buffer-substring bos (point)))
+                   match-string)
       nil)
      ((string-match "OBJ_NEW([ \t]*['\"]\\([a-zA-Z0-9$_]*\\)?\\'"
-                   (buffer-substring bos (point)))
+                   match-string)
       (setq cw 'class))                    
      ((string-match "\\<inherits\\s-+\\([a-zA-Z0-9$_]*\\)?\\'"
-                   (buffer-substring bos (point)))
+                   match-string)
       (setq cw 'class))                    
      ((and func 
           (> func-point pro-point)
@@ -5999,10 +6007,10 @@ ARROW:  Location of the arrow"
      (t
       (setq cw 'function)
       (save-excursion
-       (if (re-search-backward "->[ 
\t]*\\(\\([$a-zA-Z0-9_]+\\)::\\)?[$a-zA-Z0-9_]*\\=" bos t)
+       (if (re-search-backward "->[ \t]*\\(\\$[ 
\t]*\\(;.*\\)?\n\\s-*\\)?\\(\\([$a-zA-Z0-9_]+\\)::\\)?[$a-zA-Z0-9_]*\\=" bos t)
            (setq cw-arrow (copy-marker (match-beginning 0))
-                 cw-class (if (match-end 2)
-                              (idlwave-sintern-class (match-string 2))
+                 cw-class (if (match-end 4)
+                              (idlwave-sintern-class (match-string 4))
                             t))))))
     (list (list pro pro-point pro-class pro-arrow)
           (list func func-point func-class func-arrow)
@@ -6719,6 +6727,13 @@ If these don't exist, a letter in the string is 
automatically selected."
   "Regexp for skipping continued blank or comment-only lines in
 structures")
 
+(defvar idlwave-struct-tag-regexp
+  (concat "[{,]" ;leading comma/brace
+         idlwave-struct-skip ; 4 groups
+         "\\([a-zA-Z][a-zA-Z0-9_]*\\)" ;the tag itself, group 5
+         "[ \t]*:") ; the final colon
+  "Regexp for structure tags.")
+
 (defun idlwave-struct-tags ()
   "Return a list of all tags in the structure defined at point.
 Point is expected just before the opening `{' of the struct definition."
@@ -6728,18 +6743,15 @@ Point is expected just before the opening `{' of the 
struct definition."
           (end (cdr borders))
           tags)
       (goto-char beg)
-      (while (re-search-forward 
-             (concat "[{,]" ;leading comma/brace
-                     idlwave-struct-skip ; 4 groups
-                     "\\([a-zA-Z][a-zA-Z0-9_]*\\)" ;the tag itself, group 5
-                     "[ \t]*:")   ; the final colon
-             end t)
-       ;; Check if we are still on the top level of the structure.
-       (if (and (condition-case nil (progn (up-list -1) t) (error nil))
-                (= (point) beg))
-           (push (match-string-no-properties 5) tags))
-       (goto-char (match-end 0)))
-      (nreverse tags))))
+      (save-restriction
+       (narrow-to-region beg end)
+       (while (re-search-forward idlwave-struct-tag-regexp end t)
+         ;; Check if we are still on the top level of the structure.
+         (if (and (condition-case nil (progn (up-list -1) t) (error nil))
+                  (= (point) beg))
+             (push (match-string-no-properties 5) tags))
+         (goto-char (match-end 0))))
+       (nreverse tags))))
 
 (defun idlwave-find-struct-tag (tag)
   "Find a given TAG in the structure defined at point."
@@ -6760,22 +6772,24 @@ Point is expected just before the opening `{' of the 
struct definition."
           (case-fold-search t)
           names)
       (goto-char beg)
-      (while (re-search-forward 
-             (concat "[{,]"  ;leading comma/brace
-                     idlwave-struct-skip ; 4 groups
-                     "inherits"    ; The INHERITS tag
-                     idlwave-struct-skip ; 4 more
-                     "\\([a-zA-Z][a-zA-Z0-9_]*\\)") ; The super-group, #9
-             end t)
-       ;; Check if we are still on the top level of the structure.
-       (if (and (condition-case nil (progn (up-list -1) t) (error nil))
-                (= (point) beg))
-           (push (match-string-no-properties 9) names))
-       (goto-char (match-end 0)))
+      (save-restriction
+       (narrow-to-region beg end)
+       (while (re-search-forward 
+               (concat "[{,]"  ;leading comma/brace
+                       idlwave-struct-skip ; 4 groups
+                       "inherits"    ; The INHERITS tag
+                       idlwave-struct-skip ; 4 more
+                       "\\([a-zA-Z][a-zA-Z0-9_]*\\)") ; The super-group, #9
+               end t)
+         ;; Check if we are still on the top level of the structure.
+         (if (and (condition-case nil (progn (up-list -1) t) (error nil))
+                  (= (point) beg))
+             (push (match-string-no-properties 9) names))
+         (goto-char (match-end 0))))
       (nreverse names))))
 
 (defun idlwave-in-structure ()
-  "Return t if point is inside an IDL structure."
+  "Return t if point is inside an IDL structure definition."
   (let ((beg (point)))
     (save-excursion
       (if (not (or (idlwave-in-comment) (idlwave-in-quote)))
@@ -6795,12 +6809,13 @@ Point is expected just before the opening `{' of the 
struct definition."
       (cons beg (point)))))
 
 (defun idlwave-find-structure-definition (&optional var name bound)
-  "Search forward for a structure definition.  
-If VAR is non-nil, search for a structure assigned to variable VAR.
-If NAME is non-nil, search for a named structure NAME.  If BOUND is an
-integer, limit the search.  If BOUND is the symbol `all', we search
-first back and then forward through the entire file.  If BOUND is the
-symbol `back' we search only backward."
+  "Search forward for a structure definition.  If VAR is non-nil,
+search for a structure assigned to variable VAR.  If NAME is non-nil,
+search for a named structure NAME, if a string, or a generic named
+structure otherwise.  If BOUND is an integer, limit the search.  If
+BOUND is the symbol `all', we search first back and then forward
+through the entire file.  If BOUND is the symbol `back' we search only
+backward."
   (let* ((ws "[ \t]*\\(\\$.*\n[ \t]*\\)*")
         (case-fold-search t)
         (lim (if (integerp bound) bound nil))
@@ -6809,36 +6824,53 @@ symbol `back' we search only backward."
                  (concat "\\<" (regexp-quote (downcase var)) "\\>" ws)
                "\\(\\)")
              "=" ws "\\({\\)"
-             (if name (concat ws "\\<" (downcase name) "[^a-zA-Z0-9_$]") ""))))
+             (if name 
+                 (if (stringp name)
+                     (concat ws "\\(\\<" (downcase name) "\\)[^a-zA-Z0-9_$]") 
+                   ;; Just a generic name
+                   (concat ws "\\<\\([a-zA-Z_0-9$]+\\)" ws ","))
+               ""))))
     (if (or (and (or (eq bound 'all) (eq bound 'back))
                 (re-search-backward re nil t))
            (and (not (eq bound 'back)) (re-search-forward re lim t)))
-       (goto-char (match-beginning 3)))))
+       (progn
+         (goto-char (match-beginning 3))
+         (match-string-no-properties 5)))))
+
+(defvar idlwave-class-info nil) 
+(defvar idlwave-system-class-info nil) ; Gathered from idlw-rinfo
+(defvar idlwave-class-reset nil) ; to reset buffer-local classes
 
-(defvar idlwave-class-info nil)
-(defvar idlwave-system-class-info nil)
 (add-hook 'idlwave-update-rinfo-hook
-         (lambda () (setq idlwave-class-info nil)))
+         (lambda () (setq idlwave-class-reset t)))
 (add-hook 'idlwave-after-load-rinfo-hook
          (lambda () (setq idlwave-class-info nil)))
 
 (defun idlwave-class-info (class)
   (let (list entry)
-    (unless idlwave-class-info
-      ;; Info is nil, put in the system stuff.
+    (if idlwave-class-info
+       (if idlwave-class-reset
+           (setq           
+            idlwave-class-reset nil
+            idlwave-class-info ; Remove any visited in a buffer
+            (delq nil (mapcar 
+                       (lambda (x) 
+                         (let ((filebuf 
+                                (idlwave-class-file-or-buffer 
+                                 (or (cdr (assq 'found-in x)) (car x)))))
+                           (if (cdr filebuf)
+                               nil
+                             x)))
+                       idlwave-class-info))))
+      ;; Info is nil, put in the system stuff to start.
       (setq idlwave-class-info idlwave-system-class-info)
       (setq list idlwave-class-info)
       (while (setq entry (pop list))
        (idlwave-sintern-class-info entry)))
     (setq class (idlwave-sintern-class class))
-    (setq entry (assq class idlwave-class-info))
-    (unless entry  ;; Find the __define file, parse and include it
-      (setq entry (idlwave-find-class-info class))
-      (when entry
-       ;; Sintern and cache the info
-       (idlwave-sintern-class-info entry)
-       (push entry idlwave-class-info)))
-    entry))
+    (or (assq class idlwave-class-info)
+       (progn (idlwave-scan-class-info class)
+              (assq class idlwave-class-info)))))
 
 (defun idlwave-sintern-class-info (entry)
   "Sintern the class names in a class-info entry."
@@ -6849,28 +6881,50 @@ symbol `back' we search only backward."
        (setcdr inherits (mapcar (lambda (x) (idlwave-sintern-class x 'set))
                                 (cdr inherits))))))
 
-(defun idlwave-find-class-definition (class)
-  (let ((case-fold-search t))
-    (if (re-search-forward
-        (concat "^[ \t]*pro[ \t]+" (downcase class) "__define" "\\>") nil t)
-       ;; FIXME: should we limit to end of pro here?
-       (idlwave-find-structure-definition nil class))))
+(defun idlwave-find-class-definition (class &optional all-hook alt-class)
+  "Find class structure definition(s)
+If ALL-HOOK is set, find all named structure definitions in a given
+class__define routine, on which ALL-HOOK will be run.  If ALT-CLASS is
+set, look for the name__define pro, and inside of it, for the ALT-CLASS
+class/struct definition"
+  (let ((case-fold-search t) end-lim list name)
+    (when (re-search-forward
+          (concat "^[ \t]*pro[ \t]+" (downcase class) "__define" "\\>") nil t)
+      (if all-hook
+         (progn
+           ;; For everything there
+           (setq end-lim (save-excursion (idlwave-end-of-subprogram) (point)))
+           (while (setq name 
+                        (idlwave-find-structure-definition nil t end-lim))
+             (funcall all-hook name)))
+       (idlwave-find-structure-definition nil (or alt-class class))))))
+
 
-(defun idlwave-find-class-info (class)
-  "Find the __define procedure for a class structure and return info entry."
+(defun idlwave-class-file-or-buffer (class)
+  "Find buffer visiting CLASS definition"
   (let* ((pro (concat (downcase class) "__define"))
-        (class (idlwave-sintern-class class))
-        (idlwave-auto-routine-info-updates nil)
         (file (idlwave-routine-source-file
                (nth 3 (idlwave-rinfo-assoc pro 'pro nil
-                                           (idlwave-routines)))))
-        buf)
-    (if (or (not file)
-           (not (file-regular-p file)))
-       nil ; Cannot get info
+                                           (idlwave-routines))))))
+    (cons file (if file (idlwave-get-buffer-visiting file)))))
+
+
+(defun idlwave-scan-class-info (class)
+  "Scan all class and named structure info in the class__define pro"
+  (let* ((idlwave-auto-routine-info-updates nil)
+        (filebuf (idlwave-class-file-or-buffer class))
+        (file (car filebuf))
+        (buf (cdr filebuf))
+        (class (idlwave-sintern-class class)))
+    (if (or
+        (not file)
+        (and ;; neither a regular file nor a visited buffer
+         (not buf)
+         (not (file-regular-p file))))
+       nil ; Cannot find the file/buffer to get any info
       (save-excursion
-       (if (setq buf (idlwave-get-buffer-visiting file))
-           (set-buffer buf)
+       (if buf (set-buffer buf)
+         ;; Read the file in temporarily
          (set-buffer (get-buffer-create " *IDLWAVE-tmp*"))
          (erase-buffer)
          (unless (eq major-mode 'idlwave-mode)
@@ -6878,20 +6932,29 @@ symbol `back' we search only backward."
          (insert-file-contents file))
        (save-excursion
          (goto-char 1)
-         (if (idlwave-find-class-definition class)
-             (list class
-                   (cons 'tags (idlwave-struct-tags))
-                   (cons 'inherits (idlwave-struct-inherits)))))))))
-
+         (idlwave-find-class-definition class 
+          ;; Scan all of the structures found there
+          (lambda (name)
+            (let* ((this-class (idlwave-sintern-class name))
+                   (entry 
+                    (list this-class
+                          (cons 'tags (idlwave-struct-tags))
+                          (cons 'inherits (idlwave-struct-inherits)))))
+              (if (not (eq this-class class))
+                  (setq entry (nconc entry (list (cons 'found-in class)))))
+              (idlwave-sintern-class-info entry)
+              (push entry idlwave-class-info)))))))))
+
+(defun idlwave-class-found-in (class)
+  "Return the FOUND-IN property of the class."
+  (cdr (assq 'found-in (idlwave-class-info class))))
 (defun idlwave-class-tags (class)
   "Return the native tags in CLASS."
   (cdr (assq 'tags (idlwave-class-info class))))
 (defun idlwave-class-inherits (class)
   "Return the direct superclasses of CLASS."
   (cdr (assq 'inherits (idlwave-class-info class))))
-(defun idlwave-class-file (class)
-  "Return the HTML help file (if any) for CLASS."
-  (cdr (assq 'file (idlwave-class-info class))))
+
 
 (defun idlwave-all-class-tags (class)
   "Return a list of native and inherited tags in CLASS."
@@ -7132,7 +7195,7 @@ Gets set in `idlw-rinfo.el'.")
       link)))
 
 ;; Fake help in the source buffer for class structure tags.
-;; kwd and name are global-variables here.
+;; KWD AND NAME ARE GLOBAL-VARIABLES HERE.
 (defvar name) 
 (defvar kwd)
 (defvar idlwave-help-do-class-struct-tag nil)
@@ -7141,7 +7204,7 @@ Gets set in `idlw-rinfo.el'.")
    ((eq mode 'test) ; nothing gets fontified for class tags
     nil)
    ((eq mode 'set)
-    (let (class-with)
+    (let (class-with found-in)
       (when (setq class-with 
                (idlwave-class-or-superclass-with-tag 
                 idlwave-current-tags-class
@@ -7149,7 +7212,9 @@ Gets set in `idlw-rinfo.el'.")
        (if (assq (idlwave-sintern-class class-with) 
                  idlwave-system-class-info)
            (error "No help available for system class tags."))
-       (setq name (concat class-with "__define"))))
+       (if (setq found-in (idlwave-class-found-in class-with))
+           (setq name (cons (concat found-in "__define") class-with))
+         (setq name (concat class-with "__define")))))
     (setq kwd word
          idlwave-help-do-class-struct-tag t))
    (t (error "This should not happen"))))

Reply via email to