branch: externals/idlwave
commit b0920b8d8ac275f01cc925ab45364a72c85091f9
Author: JD Smith <jdsm...@rain.mhr.utoledo.edu>
Commit: JD Smith <jdsm...@rain.mhr.utoledo.edu>

    Attempt to deal with "." and "->" Method invocation operator
    
    IDL8 introduced obj.Method syntax.  This shadows structure
    dereference.  Now try both file-local structure tags or
    shell-determined tags (e.g. self tags, or widget_info tags, etc.) and
    if that fails, fall back on method lookup (procedure or function).
    Probably some corner cases that need visiting.
---
 idlw-complete-structtag.el |  9 +++++--
 idlw-complete.el           | 12 ++++++----
 idlw-help.el               | 23 +++++++++---------
 idlw-routine.el            | 59 ++++++++++++++++++++++++++--------------------
 idlw-variables.el          |  2 +-
 idlwave.el                 |  4 ++--
 6 files changed, 62 insertions(+), 47 deletions(-)

diff --git a/idlw-complete-structtag.el b/idlw-complete-structtag.el
index d719060c42..b3699091f9 100644
--- a/idlw-complete-structtag.el
+++ b/idlw-complete-structtag.el
@@ -24,6 +24,11 @@
 
 ;;; Commentary:
 
+;; NOTA BENE!!! As of IDL v8, a method invocation operator of "." was
+;; introduced (in addition to "->").  As a result, it is no longer
+;; clear if you are completing an implicit structure tag, or a
+;; method procedure.
+
 ;; Completion of structure tags can be done automatically in the
 ;; shell, since the list of tags can be determined dynamically through
 ;; interaction with IDL.
@@ -102,7 +107,7 @@
 (defvar idlwave-current-struct-tags nil)
 (defvar idlwave-sint-structtags nil)
 
-;; Create the sintern type for structure talks
+;; Create the sintern type for structure tags
 (add-hook 'idlwave-load-hook
          (lambda () (idlwave-new-sintern-type 'structtag)))
 
@@ -147,7 +152,7 @@ an up-to-date completion list."
          (if (or (not (string= var (or idlwave-current-tags-var "@")))
                  (not (eq (current-buffer) idlwave-current-tags-buffer))
                   (not (equal start idlwave-current-tags-completion-pos)))
-             (idlwave-prepare-structure-tag-completion var ))
+             (idlwave-prepare-structure-tag-completion var))
           (setq idlwave-current-tags-completion-pos start)
          (setq idlwave-completion-help-info 
                (list 'idlwave-complete-structure-tag-help))
diff --git a/idlw-complete.el b/idlw-complete.el
index d512be1028..6db531d9d1 100644
--- a/idlw-complete.el
+++ b/idlw-complete.el
@@ -110,7 +110,7 @@ When we force a method or a method keyword, CLASS can 
specify the class."
              module (substring module (match-end 0))))
 
     (cond
-
+     ;; Just scroll the completions list on repeat commands
      ((and (null arg)
           (eq (car-safe last-command) 'idlwave-display-completion-list)
           (get-buffer-window "*Completions*"))
@@ -124,12 +124,14 @@ When we force a method or a method keyword, CLASS can 
specify the class."
 
      ;; Check for any special completion functions
      ((and idlwave-complete-special
-          (idlwave-call-special idlwave-complete-special)))
-     
+          (condition-case nil
+              (idlwave-call-special idlwave-complete-special)
+            (error nil))))
+
      ((null what)
       (error "Nothing to complete here"))
 
-     ;; Complete a class
+     ;; Complete a class name
      ((eq what 'class)
       (setq idlwave-completion-help-info '(class))
       (idlwave-complete-class))
@@ -182,7 +184,7 @@ When we force a method or a method keyword, CLASS can 
specify the class."
 
      ((and (memq what '(procedure-keyword function-keyword)) ; Special Case
           (equal arg '(4)))
-      (idlwave-complete 3))
+      (idlwave-complete 3))            ;force function completion
 
      ((eq what 'procedure-keyword)
       ;; Complete a procedure keyword
diff --git a/idlw-help.el b/idlw-help.el
index 3fd1dcab8f..4ebf1b713a 100644
--- a/idlw-help.el
+++ b/idlw-help.el
@@ -165,9 +165,8 @@ It collects and prints the diagnostics messages."
           module keyword cw mod1 mod2 mod3)
       (if (or arg 
              (and (not classtag)
-                  (not structtag)
-                  (not (member (string-to-char this-word) '(?! ?.)))))
-         ;; Need the module information
+                  (not (member (string-to-char this-word) '(?!)))))
+         ;; Get the module information
          (progn
            ;; MODULE is (name type class), for this or any inheriting class
            (setq module (idlwave-what-module-find-class)
@@ -251,14 +250,16 @@ It collects and prints the diagnostics messages."
        
        ;; A regular structure tag -- only in text, and if
        ;; `complete-structtag' loaded.
-       (structtag
-       (let ((var (match-string 1 this-word))
-             (tag (substring this-word (match-end 0))))
-         ;; Check if we need to update the "current" structure
-         (idlwave-prepare-structure-tag-completion var)
-         (setq idlwave-help-do-struct-tag
-               idlwave-structtag-struct-location
-               mod1 (list nil nil nil nil tag))))
+       ((and structtag
+            (let ((var (match-string 1 this-word))
+                  (tag (substring this-word (match-end 0))))
+              ;; Check if we need to update the "current" structure
+              (condition-case nil
+                  (idlwave-prepare-structure-tag-completion var)
+                (error nil))))
+       (setq idlwave-help-do-struct-tag
+             idlwave-structtag-struct-location
+             mod1 (list nil nil nil nil tag)))
        
        ;; A routine keyword -- in text or system help
        ((and (memq cw '(function-keyword procedure-keyword))
diff --git a/idlw-routine.el b/idlw-routine.el
index 3ba32f825e..7ea2881862 100644
--- a/idlw-routine.el
+++ b/idlw-routine.el
@@ -45,17 +45,18 @@ this arrow, if any (see `idlwave-store-inquired-class').  
With a prefix
 arg, the class property is cleared out."
   (interactive "P")
   (idlwave-routines)
-  (if (string-match "->" (buffer-substring
-                         (max (point-min) (1- (point)))
-                         (min (+ 2 (point)) (point-max))))
-      ;; Cursor is on an arrow
+  (if (or (string-match "->" (buffer-substring
+                             (max (point-min) (1- (point)))
+                             (min (+ 2 (point)) (point-max))))
+         (looking-at "\\."))
+      ;; Cursor is on an arrow/dot
       (if (get-text-property (point) 'idlwave-class)
          ;; arrow has class property
          (if arg
              ;; Remove property
              (save-excursion
                (backward-char 1)
-               (when (looking-at ".?\\(->\\)")
+               (when (looking-at ".?\\(->\\|\\.\\)")
                  (remove-text-properties (match-beginning 1) (match-end 1)
                                          '(idlwave-class nil face nil))
                  (message "Class property removed from arrow")))
@@ -527,7 +528,7 @@ When TYPE is not specified, both procedures and functions 
will be considered."
   ;; this structure is the class.  When nil, we return nil.  When t,
   ;; try to get the class from text properties at the method call
   ;; arrow.  When the object is "self", we use the class of the
-  ;; current (enclosing) routine.  otherwise prompt the user for a
+  ;; current (enclosing) routine.  Otherwise, we prompt the user for a
   ;; class name.  Also stores the selected class as a text property at
   ;; the arrow.  TYPE is 'fun or 'pro.
   (let* ((class (nth 2 cw-list))
@@ -541,7 +542,13 @@ When TYPE is not specified, both procedures and functions 
will be considered."
         (query (cond (nassoc (cdr nassoc))
                      (dassoc (cdr dassoc))
                      (t t)))
-        (arrow (and apos (string= (buffer-substring apos (+ 2 apos)) "->")))
+        arrow-len
+        (arrow (and apos (or (and (string= (buffer-substring apos (min 
(point-max)
+                                                                       (+ 2 
apos))) "->")
+                                  (setq arrow-len 2))
+                             (and (string= (buffer-substring apos (min 
(point-max)
+                                                                       (+ 1 
apos))) ".")
+                                  (setq arrow-len 1)))))
         (is-self 
          (and arrow
               (save-excursion (goto-char apos)
@@ -599,7 +606,7 @@ When TYPE is not specified, both procedures and functions 
will be considered."
        (when (and store arrow)
          (condition-case ()
              (add-text-properties 
-              apos (+ apos 2) 
+              apos (+ apos arrow-len) 
               `(idlwave-class ,class face ,idlwave-class-arrow-face 
                               rear-nonsticky t))
            (error nil)))
@@ -676,7 +683,7 @@ ARROW:  Location of the arrow for method calls"
            cw-point pro-point
            cw-arrow pro-arrow))
 
-     ;; Complete class inside obj_new statement
+     ;; Complete class name inside obj_new statement
      ((string-match "OBJ_NEW([ \t]*['\"]\\([a-zA-Z0-9$_]*\\)?\\'"
                    match-string)
       (setq cw 'class))
@@ -714,7 +721,7 @@ ARROW:  Location of the arrow for method calls"
      (t
       (setq cw 'function)
       (save-excursion
-       (if (re-search-backward "->[ \t]*\\(\\$[ 
\t]*\\(;.*\\)?\n\\s-*\\)?\\(\\([$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 4)
                               (idlwave-sintern-class (match-string 4))
@@ -751,13 +758,13 @@ ARROW:  Location of the arrow for method calls"
             (incf cnt)
             (when (and (= (following-char) ?\()
                        (re-search-backward 
-                        "\\(::\\|\\<\\)\\([a-zA-Z][a-zA-Z0-9$_]*\\)[ \t]*\\="
+                        "\\(::\\|\\<\\|\\.\\)\\([a-zA-Z][a-zA-Z0-9$_]*\\)[ 
\t]*\\="
                         bound t))
               (setq func (match-string 2)
                     func-point (goto-char (match-beginning 2))
                     pos func-point)
               (if (re-search-backward 
-                   "->[ \t]*\\(\\([a-zA-Z][a-zA-Z0-9$_]*\\)::\\)?\\=" bound t)
+                   "\\(->\\|\\.\\)[ 
\t]*\\(\\([a-zA-Z][a-zA-Z0-9$_]*\\)::\\)?\\=" bound t)
                   (setq arrow-start (copy-marker (match-beginning 0))
                         class (or (match-string 2) t)))
               (throw 
@@ -788,7 +795,7 @@ ARROW:  Location of the arrow for method calls"
        (if (and (idlwave-skip-object)
                 (setq string (buffer-substring (point) pos))
                 (string-match 
-                 "\\`[ \t]*\\(->\\)[ 
\t]*\\(\\([a-zA-Z][a-zA-Z0-9$_]*\\)::\\)?\\([a-zA-Z][a-zA-Z0-9$_]*\\)?[ 
\t]*\\(,\\|\\(\\$\\s *\\(;.*\\)?\\)?$\\)" 
+                 "\\`[ \t]*\\(->\\|\\.\\)[ 
\t]*\\(\\([a-zA-Z][a-zA-Z0-9$_]*\\)::\\)?\\([a-zA-Z][a-zA-Z0-9$_]*\\)?[ 
\t]*\\(,\\|\\(\\$\\s *\\(;.*\\)?\\)?$\\)" 
                  string))
            (setq pro (if (match-beginning 4)
                          (match-string 4 string))
@@ -815,19 +822,19 @@ ARROW:  Location of the arrow for method calls"
             ((eq (following-char) ?\()
              nil)
             (t (throw 'exit nil)))
-           (catch 'endwhile
-             (while t
-               (cond ((eq (following-char) ?.)
-                      (forward-char 1)
-                      (if (not (looking-at idlwave-identifier))
-                          (throw 'exit nil))
-                      (goto-char (match-end 0)))
-                     ((memq (following-char) '(?\( ?\[))
-                      (condition-case nil
-                          (forward-list 1)
-                        (error (throw 'exit nil))))
-                     (t (throw 'endwhile t)))))
-           (if (looking-at "[ \t]*->")
+           ;; (catch 'endwhile ; Can't skip dots anymore, they are used for 
method invocation!
+           ;;   (while t
+           ;;  (cond ((eq (following-char) ?.)
+           ;;         (forward-char 1)
+           ;;         (if (not (looking-at idlwave-identifier))
+           ;;             (throw 'exit nil))
+           ;;         (goto-char (match-end 0)))
+           ;;        ((memq (following-char) '(?\( ?\[))
+           ;;         (condition-case nil
+           ;;             (forward-list 1)
+           ;;           (error (throw 'exit nil))))
+           ;;        (t (throw 'endwhile t)))))
+           (if (looking-at "[ \t]*\\(->\\|\\.\\)")
                (throw 'exit (setq pos (match-beginning 0)))
              (throw 'exit nil))))
        (goto-char pos)
diff --git a/idlw-variables.el b/idlw-variables.el
index d54ac3bbcc..6f6114b27f 100644
--- a/idlw-variables.el
+++ b/idlw-variables.el
@@ -1286,7 +1286,7 @@ blocks starting with a BEGIN statement.  The matches must 
have associations
 (defconst idlwave-label (concat idlwave-identifier ":")
   "Regular expression matching IDL labels.")
 
-(defconst idlwave-method-call (concat idlwave-identifier  "\\s *->"
+(defconst idlwave-method-call (concat idlwave-identifier  "\\s *\\(->\\|\\.\\)"
                                      "\\(\\s *" idlwave-identifier "::\\)?"
 ))
 
diff --git a/idlwave.el b/idlwave.el
index 55e28c637b..face890f91 100644
--- a/idlwave.el
+++ b/idlwave.el
@@ -1336,7 +1336,7 @@ INFO is as returned by `idlwave-what-function' or 
`-procedure'."
   (let ((apos (nth 3 info)))
     (if apos
        (save-excursion (goto-char apos)
-                       (looking-at "->[a-zA-Z][a-zA-Z0-9$_]*::")))))
+                       (looking-at "\\(->|\\.\\)[a-zA-Z][a-zA-Z0-9$_]*::")))))
 
 ;;----------------------------------------------------
 ;; Indent and indent action
@@ -1715,7 +1715,7 @@ routine definitions, and parenthetical groupings, are 
treated separately."
                  ;; A continued Procedure call or definition
                  ((progn
                     (idlwave-look-at "^[ \t]*\\(pro\\|function\\)") ;skip over
-                    (looking-at "[ \t]*\\([a-zA-Z0-9.$_]+[ \t]*->[ 
\t]*\\)?[a-zA-Z][:a-zA-Z0-9$_]*[ \t]*\\(,\\)[ \t]*"))
+                    (looking-at "[ \t]*\\([a-zA-Z0-9.$_]+[ \t]*\\(->|\\.\\)[ 
\t]*\\)?[a-zA-Z][:a-zA-Z0-9$_]*[ \t]*\\(,\\)[ \t]*"))
                   (goto-char (match-end 0))
                   ;; Comment only, or blank line with "$"?  Basic indent.
                   (if (save-match-data (looking-at "[ \t$]*\\(;.*\\)?$"))

Reply via email to