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

            * idlwave.el (idlwave-popup-select): Moved this and auxiliary
            functions from idlw-help.el, to support super examine popup.
            * idlwave.el (idlwave-fix-keywords): Oops, special obj_new fix not
            respecting downcase or other cased routine preferences.
            * idlwave.el (idlwave-calculate-cont-indent): Wrote to use
            idlwave-max-extra-continuation-indent, for testing special
            vs. fixed continuation indentation.
            (idlwave-calculate-cont-indent): Added test to add to basic-indent
            to respect any already-established fancy indentations.
            * idlwave.el (idlwave-calculate-indent): Look for end-block-reg
            only on current line, to move it over.
            * idlwave.el (idlwave-last-valid-char): Updated continuation line
            regexp to avoid scanning over several lines: fixes idlwave-where
            type on function continuations which close and is then continued
            itself.
            (idlwave-calculate-cont-indent): Line continued assignment lines
            up after the equal sign, if no enclosing parens match.
            * idlwave.el (idlwave-beginning-of-statement): Added in-structure
            test, for blank lines which can count as continuation lines.
            (idlwave-is-continuation-line): Changed to test for blank or
            continuation lines following a regular cont-line (with `$')
            everywhere (e.g. function calls, etc.)
            (idlwave-in-structure): Wrote, but realized didn't need.  Still
            useful.
            * idlwave.el (idlwave-what-procedure): Fixed regexp to accomodate
            procedures on multiple statement lines.
            * idlwave.el (idlwave-define-abbrev): Created, to accomodate Emacs
            21 additional define-abbrev argument specifying system-abbrev.
            * idlwave.el (idlwave-split-line): Moved character forward when
            splitting strings.
            * idlwave.el (idlwave-what-procedure): Changed string match to
            deal with multiple commands on one line (via &).
            * idlwave.el (idlwave-explicit-class-listed): Fixed ugly
            non-method completion bug.
---
 idlwave.el | 464 +++++++++++++++++++++++++++++++++++++++++++------------------
 1 file changed, 329 insertions(+), 135 deletions(-)

diff --git a/idlwave.el b/idlwave.el
index 68a86773ef..60205ddadf 100644
--- a/idlwave.el
+++ b/idlwave.el
@@ -1,11 +1,11 @@
 ;;; idlwave.el --- IDL and WAVE CL editing mode for GNU Emacs
-;; Copyright (c) 1999, 2000, 2001 Free Software Foundation
+;; Copyright (c) 1999, 2000, 2001,2002 Free Software Foundation
 
 ;; Author: Carsten Dominik <domi...@astro.uva.nl>
 ;;         Chris Chase <ch...@att.com>
 ;; Maintainer: J.D. Smith <jdsm...@as.arizona.edu>
 ;; Version: VERSIONTAG
-;; Date: $Date: 2002/04/23 20:53:54 $
+;; Date: $Date: 2002/05/13 21:53:45 $
 ;; Keywords: languages
 
 ;; This file is part of GNU Emacs.
@@ -187,29 +187,46 @@ line up with the block BEGIN lines."
 (defcustom idlwave-continuation-indent 2
   "*Extra indentation applied to continuation lines.
 This extra offset applies to the first of a set of continuation lines.
-The following lines receive the same indentation as the first.
-Also, the value of this variable applies to continuation lines inside
-parenthesis.  When the current line contains an open unmatched ([{,
-the next line is indented to that parenthesis plus the value of this variable."
+The following lines receive the same indentation as the first."
   :group 'idlwave-code-formatting
   :type 'integer)
 
-(defcustom idlwave-indent-to-open-paren t
-  "*Non-nil means, indent continuation lines to innermost open parenthesis.
-This is done in a way so that matching parens are lined up.
-Example:
+(defcustom idlwave-max-extra-continuation-indent 20
+  "*Maximum additional indentation for special continuation indent.
+Several special indentations are tried to help line up continuation
+lines in routine calls or definitions, other statements with
+parentheses, or assigment statements.  This variable specifies a
+maximum amount by which this special indentation can exceed the
+standard continuation indentation, otherwise defaulting to a fixed
+offset.  Set to 0 to effectively disable all special continuation
+indentation, or to a large number (like 100) to enable it in all
+cases.  See also `idlwave-indent-top-open-paren', which can override
+this variable."
+  :group 'idlwave-code-formatting
+  :type 'integer)
 
-  x = function_a(function_b(function_c( a, b, $
+(defcustom idlwave-indent-to-open-paren t
+  "*Non-nil means, indent continuation lines to innermost open
+parenthesis.  This indentation occurs even if otherwise disallowed by
+`idlwave-max-extra-continuation-indent'.  Matching parens and the
+interleaving args are lined up.  Example:
+
+  x = function_a(function_b(function_c( a, b, [1,2,3, $
+                                               4,5,6 $
+                                              ], $
                                         c, d $
                                       )))
 
-When this variable is nil, such lines only receive the normal
-`idlwave-continuation-indent'.  Example:
+When this variable is nil, paren alignment may still occur, based on
+the value of `max-extra-continuation-indent', which, if zero, would
+yield:
 
-  x = function_a(function_b(function_c( a, b, $
-    c, d $
-    )))"
-  :group 'idlwave-code-formatting
+  x = function_a(function_b(function_c( a, b, [1,2,3, $
+     4,5,6 $
+     ], $
+     c, d $
+     )))"
+ :group 'idlwave-code-formatting
   :type 'boolean)
 
 (defcustom idlwave-hanging-indent t
@@ -1573,6 +1590,7 @@ Capitalize system variables - action only
 (define-key idlwave-mode-map "\C-c\C-n" 'idlwave-next-statement)
 ;; (define-key idlwave-mode-map "\r"       'idlwave-newline)
 ;; (define-key idlwave-mode-map "\t"       'idlwave-indent-line)
+(define-key idlwave-mode-map (kbd "S-<iso-lefttab>") 'idlwave-indent-statement)
 (define-key idlwave-mode-map "\C-c\C-a" 'idlwave-auto-fill-mode)
 (define-key idlwave-mode-map "\M-q"     'idlwave-fill-paragraph)
 (define-key idlwave-mode-map "\M-s"     'idlwave-edit-in-idlde)
@@ -1647,11 +1665,14 @@ Capitalize system variables - action only
   "Abbreviation table used for IDLWAVE mode")
 (define-abbrev-table 'idlwave-mode-abbrev-table ())
 
-(defun idlwave-define-abbrev (name expansion hook &optional table)
-  "Define-abbrev with backward compatibility."
+(defun idlwave-define-abbrev (name expansion hook &optional noprefix table)
+  "Define-abbrev with backward compatibility.
+
+If NOPREFIX is non-nil, don't prepend prefix character.  Installs into
+idlwave-mode-abbrev-table unless TABLE is non-nil."
   (let ((abbrevs-changed nil)  ;; mask the current value to avoid save
        (args (list (or table idlwave-mode-abbrev-table)
-                   (concat idlwave-abbrev-start-char name)
+                   (if noprefix name (concat idlwave-abbrev-start-char name))
                    expansion
                    hook)))
     (condition-case nil
@@ -1724,7 +1745,7 @@ Capitalize system variables - action only
 (idlwave-define-abbrev "t"  "then"         (idlwave-keyword-abbrev 0 t))
 (idlwave-define-abbrev "u"  "until"        (idlwave-keyword-abbrev 0 t))
 (idlwave-define-abbrev "wu" "writeu,"      (idlwave-keyword-abbrev 0))
-(idlwave-define-abbrev "iap" "if arg_present()"     (idlwave-keyword-abbrev 1))
+(idlwave-define-abbrev "iap" "if arg_present() then"     
(idlwave-keyword-abbrev 6))
 (idlwave-define-abbrev "ik" "if keyword_set() then" (idlwave-keyword-abbrev 6))
 (idlwave-define-abbrev "ine" "if n_elements() eq 0 then" 
(idlwave-keyword-abbrev 11))
 (idlwave-define-abbrev "inn" "if n_elements() ne 0 then" 
(idlwave-keyword-abbrev 11))
@@ -1735,45 +1756,45 @@ Capitalize system variables - action only
   
 ;; This section is reserved words only. (From IDL user manual)
 ;;
-(idlwave-define-abbrev "and"        "and"        (idlwave-keyword-abbrev 0 t))
-(idlwave-define-abbrev "begin"      "begin"      (idlwave-keyword-abbrev 0 t))
-(idlwave-define-abbrev "break"      "break"      (idlwave-keyword-abbrev 0 t))
-(idlwave-define-abbrev "case"       "case"       (idlwave-keyword-abbrev 0 t))
-(idlwave-define-abbrev "common"     "common"     (idlwave-keyword-abbrev 0 t))
-(idlwave-define-abbrev "continue"   "continue"   (idlwave-keyword-abbrev 0 t))
-(idlwave-define-abbrev "do"         "do"         (idlwave-keyword-abbrev 0 t))
-(idlwave-define-abbrev "else"       "else"       (idlwave-keyword-abbrev 0 t))
-(idlwave-define-abbrev "end"        "end"        'idlwave-show-begin-check)
-(idlwave-define-abbrev "endcase"    "endcase"    'idlwave-show-begin-check)
-(idlwave-define-abbrev "endelse"    "endelse"    'idlwave-show-begin-check)
-(idlwave-define-abbrev "endfor"     "endfor"     'idlwave-show-begin-check)
-(idlwave-define-abbrev "endif"      "endif"      'idlwave-show-begin-check)
-(idlwave-define-abbrev "endrep"     "endrep"     'idlwave-show-begin-check)
-(idlwave-define-abbrev "endswitch"  "endswitch"  'idlwave-show-begin-check)
-(idlwave-define-abbrev "endwhi"     "endwhi"     'idlwave-show-begin-check)
-(idlwave-define-abbrev "endwhile"   "endwhile"   'idlwave-show-begin-check)
-(idlwave-define-abbrev "eq"         "eq"         (idlwave-keyword-abbrev 0 t))
-(idlwave-define-abbrev "for"        "for"        (idlwave-keyword-abbrev 0 t))
-(idlwave-define-abbrev "function"   "function"   (idlwave-keyword-abbrev 0 t))
-(idlwave-define-abbrev "ge"         "ge"         (idlwave-keyword-abbrev 0 t))
-(idlwave-define-abbrev "goto"       "goto"       (idlwave-keyword-abbrev 0 t))
-(idlwave-define-abbrev "gt"         "gt"         (idlwave-keyword-abbrev 0 t))
-(idlwave-define-abbrev "if"         "if"         (idlwave-keyword-abbrev 0 t))
-(idlwave-define-abbrev "le"         "le"         (idlwave-keyword-abbrev 0 t))
-(idlwave-define-abbrev "lt"         "lt"         (idlwave-keyword-abbrev 0 t))
-(idlwave-define-abbrev "mod"        "mod"        (idlwave-keyword-abbrev 0 t))
-(idlwave-define-abbrev "ne"         "ne"         (idlwave-keyword-abbrev 0 t))
-(idlwave-define-abbrev "not"        "not"        (idlwave-keyword-abbrev 0 t))
-(idlwave-define-abbrev "of"         "of"         (idlwave-keyword-abbrev 0 t))
-(idlwave-define-abbrev "on_ioerror" "on_ioerror" (idlwave-keyword-abbrev 0 t))
-(idlwave-define-abbrev "or"         "or"         (idlwave-keyword-abbrev 0 t))
-(idlwave-define-abbrev "pro"        "pro"        (idlwave-keyword-abbrev 0 t))
-(idlwave-define-abbrev "repeat"     "repeat"     (idlwave-keyword-abbrev 0 t))
-(idlwave-define-abbrev "switch"     "switch"     (idlwave-keyword-abbrev 0 t))
-(idlwave-define-abbrev "then"       "then"       (idlwave-keyword-abbrev 0 t))
-(idlwave-define-abbrev "until"      "until"      (idlwave-keyword-abbrev 0 t))
-(idlwave-define-abbrev "while"      "while"      (idlwave-keyword-abbrev 0 t))
-(idlwave-define-abbrev "xor"        "xor"        (idlwave-keyword-abbrev 0 t))
+(idlwave-define-abbrev "and"        "and"       (idlwave-keyword-abbrev 0 t) t)
+(idlwave-define-abbrev "begin"      "begin"     (idlwave-keyword-abbrev 0 t) t)
+(idlwave-define-abbrev "break"      "break"     (idlwave-keyword-abbrev 0 t) t)
+(idlwave-define-abbrev "case"       "case"      (idlwave-keyword-abbrev 0 t) t)
+(idlwave-define-abbrev "common"     "common"    (idlwave-keyword-abbrev 0 t) t)
+(idlwave-define-abbrev "continue"   "continue"  (idlwave-keyword-abbrev 0 t) t)
+(idlwave-define-abbrev "do"         "do"        (idlwave-keyword-abbrev 0 t) t)
+(idlwave-define-abbrev "else"       "else"      (idlwave-keyword-abbrev 0 t) t)
+(idlwave-define-abbrev "end"        "end"       'idlwave-show-begin-check t)
+(idlwave-define-abbrev "endcase"    "endcase"   'idlwave-show-begin-check t)
+(idlwave-define-abbrev "endelse"    "endelse"   'idlwave-show-begin-check t)
+(idlwave-define-abbrev "endfor"     "endfor"    'idlwave-show-begin-check t)
+(idlwave-define-abbrev "endif"      "endif"     'idlwave-show-begin-check t)
+(idlwave-define-abbrev "endrep"     "endrep"    'idlwave-show-begin-check t)
+(idlwave-define-abbrev "endswitch"  "endswitch" 'idlwave-show-begin-check t)
+(idlwave-define-abbrev "endwhi"     "endwhi"    'idlwave-show-begin-check t)
+(idlwave-define-abbrev "endwhile"   "endwhile"  'idlwave-show-begin-check t)
+(idlwave-define-abbrev "eq"         "eq"        (idlwave-keyword-abbrev 0 t) t)
+(idlwave-define-abbrev "for"        "for"       (idlwave-keyword-abbrev 0 t) t)
+(idlwave-define-abbrev "function"   "function"  (idlwave-keyword-abbrev 0 t) t)
+(idlwave-define-abbrev "ge"         "ge"        (idlwave-keyword-abbrev 0 t) t)
+(idlwave-define-abbrev "goto"       "goto"      (idlwave-keyword-abbrev 0 t) t)
+(idlwave-define-abbrev "gt"         "gt"        (idlwave-keyword-abbrev 0 t) t)
+(idlwave-define-abbrev "if"         "if"        (idlwave-keyword-abbrev 0 t) t)
+(idlwave-define-abbrev "le"         "le"        (idlwave-keyword-abbrev 0 t) t)
+(idlwave-define-abbrev "lt"         "lt"        (idlwave-keyword-abbrev 0 t) t)
+(idlwave-define-abbrev "mod"        "mod"       (idlwave-keyword-abbrev 0 t) t)
+(idlwave-define-abbrev "ne"         "ne"        (idlwave-keyword-abbrev 0 t) t)
+(idlwave-define-abbrev "not"        "not"       (idlwave-keyword-abbrev 0 t) t)
+(idlwave-define-abbrev "of"         "of"        (idlwave-keyword-abbrev 0 t) t)
+(idlwave-define-abbrev "on_ioerror" "on_ioerror" (idlwave-keyword-abbrev 0 t) 
t)
+(idlwave-define-abbrev "or"         "or"        (idlwave-keyword-abbrev 0 t) t)
+(idlwave-define-abbrev "pro"        "pro"       (idlwave-keyword-abbrev 0 t) t)
+(idlwave-define-abbrev "repeat"     "repeat"    (idlwave-keyword-abbrev 0 t) t)
+(idlwave-define-abbrev "switch"     "switch"    (idlwave-keyword-abbrev 0 t) t)
+(idlwave-define-abbrev "then"       "then"      (idlwave-keyword-abbrev 0 t) t)
+(idlwave-define-abbrev "until"      "until"     (idlwave-keyword-abbrev 0 t) t)
+(idlwave-define-abbrev "while"      "while"     (idlwave-keyword-abbrev 0 t) t)
+(idlwave-define-abbrev "xor"        "xor"       (idlwave-keyword-abbrev 0 t) t)
 
 (defvar imenu-create-index-function)
 (defvar extract-index-name-function)
@@ -2670,9 +2691,10 @@ See `idlwave-surround'. "
               (idlwave-surround 0 0))
              (t)))))          
 
-(defun idlwave-indent-and-action ()
-  "Call `idlwave-indent-line' and do expand actions."
-  (interactive)
+(defun idlwave-indent-and-action (&optional arg)
+  "Call `idlwave-indent-line' and do expand actions.
+With prefix ARG non-nil, indent the entire sub-statement."
+  (interactive "p")
   (save-excursion
     (if        (and idlwave-expand-generic-end 
             (re-search-backward "\\<\\(end\\)\\s-*\\=" 
@@ -2682,7 +2704,9 @@ See `idlwave-surround'. "
               ;;Expand the END abbreviation, just as RET or Space would have.
               (if abbrev-mode (expand-abbrev)
                 (idlwave-show-begin)))))
-  (idlwave-indent-line t))
+  (if arg 
+      (idlwave-indent-statement)
+    (idlwave-indent-line t)))
 
 (defun idlwave-indent-line (&optional expand)
   "Indents current IDL line as code or as a comment.
@@ -2780,6 +2804,15 @@ Inserts spaces before markers at point."
       (indent-region beg (point) nil))
     (message "Indenting subprogram...done.")))
 
+(defun idlwave-indent-statement ()
+  "Indent current statement, including all continuation lines."
+  (interactive)
+  (save-excursion
+    (idlwave-beginning-of-statement)
+    (let ((beg (point)))
+      (idlwave-end-of-statement)
+      (indent-region beg (point) nil))))
+
 (defun idlwave-calculate-indent ()
   "Return appropriate indentation for current line as IDL code."
   (save-excursion
@@ -2798,7 +2831,7 @@ Inserts spaces before markers at point."
      (t (let ((the-indent
                ;; calculate indent based on previous statement
                (save-excursion
-                 (cond
+                (cond
                   ((idlwave-previous-statement)
                    0)
                   ;; Main block
@@ -2817,78 +2850,137 @@ Inserts spaces before markers at point."
           ;; adjust the indentation based on the current statement
           (cond
            ;; End block
-           ((idlwave-look-at idlwave-end-block-reg t)
-            (+ the-indent idlwave-end-offset))
+           ((idlwave-look-at idlwave-end-block-reg)
+           (+ the-indent idlwave-end-offset))
            (the-indent)))))))
 
 ;;
-;; Parenthesses balacing/indent
+;; Parentheses balacing/indent
 ;;
 
+(defun idlwave-calculate-paren-indent (beg-reg end-reg close-exp)
+  "Calculate the continuation indent inside a paren group.
+Returns a cons-cell with (open . indent), where open is the 
+location of the open paren"
+  (let ((open (nth 1 (parse-partial-sexp beg-reg end-reg))))
+    ;; Found an innermost open paren.
+    (when open
+      (goto-char open)
+      ;; Line up with next word unless this is a closing paren.
+      (cons open
+           (cond
+            ;; This is a closed paren - line up under open paren.
+            (close-exp
+             (current-column))
+            ;; Empty (or just comment) - just line up next to paren
+            ((progn
+               ;; Skip paren
+               (forward-char 1)
+               (looking-at "[ \t$]*\\(;.*\\)?$"))
+             (current-column))
+            ;; Line up with first word after blank space
+            ((progn
+               (skip-chars-forward " \t")
+               (current-column))))))))
+
 (defun idlwave-calculate-cont-indent ()
   "Calculates the IDL continuation indent column from the previous statement.
 Note that here previous statement means the beginning of the current
-statement if this statement is a continuation of the previous line.
-Intervening comments or comments within the previous statement can
-screw things up if the comments contain parentheses characters."
+statement if this statement is a continuation of the previous line."
   (save-excursion
     (let* (open
            (case-fold-search t)
            (end-reg (progn (beginning-of-line) (point)))
            (close-exp (progn (skip-chars-forward " \t") (looking-at "\\s)")))
-           (beg-reg (progn (idlwave-previous-statement) (point))))
-      ;;
-      ;; If PRO or FUNCTION declaration indent after name, and first comma.
-      ;;
-      (if (idlwave-look-at "\\<\\(pro\\|function\\)[ \t]+[a-zA-Z0-9$_:]+\\>")
-          (progn
-            (goto-char (match-end 0))
-            (if (looking-at "[ \t]*,[ \t]*")
-                (goto-char (match-end 0)))
-            (current-column))
-        ;;
-        ;; Not a PRO or FUNCTION
-        ;;
-        ;; Look for innermost unmatched open paren
-        ;;
-        (if (and idlwave-indent-to-open-paren
-                (setq open (car (cdr (parse-partial-sexp beg-reg end-reg)))))
-                
-            ;; Found innermost open paren.
-            (progn
-              (goto-char open)
-             ;; Line up with next word unless this is a closing paren.
-              (cond
-               ;; This is a closed paren - line up under open paren.
-               (close-exp
-                (current-column))
-               ;; Empty - just add regular indent. Take into account
-               ;; the forward-char
-               ((progn
-                  ;; Skip paren
-                  (forward-char 1)
-                  (looking-at "[ \t$]*$"))
-                (+ (current-column) idlwave-continuation-indent -1))
-               ;; Line up with first word
-               ((progn
-                  (skip-chars-forward " \t")
-                  (current-column)))))
-          ;; No unmatched open paren (or the user asked us to ignore them...)
-         ;; So we just do a simple continuation.
-          (goto-char beg-reg)
-         ;; Handle some special cases
-         (cond
-          ;; Procedure call (objects ignored)
-          ((looking-at "[ \t]*[a-zA-Z][a-zA-Z0-9$_]*[ \t]*,[ \t]*")
-           (goto-char (match-end 0))
-           (current-column))
-          (t
+           (beg-reg (progn (idlwave-previous-statement) (point)))
+          (basic-indent           ;; The basic, non-fancy indent
            (+ (idlwave-current-indent)
-              ;; Make adjustments based on current line
+              ;; Move else statement back over
               (if (and (goto-char end-reg)
                        (looking-at "[ \t]*else"))
                   0
-                idlwave-continuation-indent)))))))))
+                idlwave-continuation-indent)))
+          (fancy-nonparen-indent  ;; A smarter indent for routine/assignments
+           ;; Try without parens first:
+           (progn
+             (goto-char beg-reg)
+             (cond
+              ;; A continued Procedure call or definition
+              ((looking-at "\\(\\<pro\\|function\\)?[ 
\t]*\\([a-zA-Z0-9$_]+\\(->\\|::\\)\\)?[a-zA-Z][a-zA-Z0-9$_]*[ \t]*\\(,\\)[ 
\t]*")
+               (goto-char (match-end 0))
+               ;; Comment only, or blank line with "$"?  Align with ,
+               (if (save-match-data (looking-at "[ \t$]*\\(;.*\\)?$"))
+                   (goto-char (match-end 4)))
+               (current-column))
+              ;; Continued assignment (with =), 
+              ;; or label/struct member (with :)
+              ((looking-at "[ \t]*[a-zA-Z0-9$_]+[ \t]*\\([=:]\\)[ \t]*")
+               (goto-char (match-end 0))
+               ;; Comment only?  Align with =
+               (if (save-match-data (looking-at "[ \t$]*\\(;.*\\)?$"))
+                   (goto-char (match-end 1)))
+               (current-column)))))
+          (fancy-nonparen-indent-allowed
+           (and fancy-nonparen-indent
+                (< (- fancy-nonparen-indent basic-indent)
+                   idlwave-max-extra-continuation-indent)))
+          (fancy-paren-indent-cons     ;; A smarter indent for paren groups
+           ;; Look for any enclosing parens
+           (idlwave-calculate-paren-indent beg-reg end-reg close-exp))
+          (fancy-paren-open (car fancy-paren-indent-cons))
+          (fancy-paren-indent (cdr fancy-paren-indent-cons))
+          (fancy-paren-indent-allowed
+           (and fancy-paren-indent
+                (or idlwave-indent-to-open-paren ;; override
+                    (< (- fancy-paren-indent basic-indent)
+                       idlwave-max-extra-continuation-indent))))
+           fancy-enclosing-parent-indent)
+      (cond 
+       ;; an allowed paren indent
+       (fancy-paren-indent-allowed 
+;      (message "allowed paren indent")
+       fancy-paren-indent)
+
+       ;; a disallowed paren indent nested inside one or more other
+       ;; parens: indent relative to the first allowed enclosing paren
+       ;; set, if any... if it's actually a greater indent, just use
+       ;; the fancy-paren-indent anyway.
+       ((and fancy-paren-indent
+            (not fancy-paren-indent-allowed)
+            (setq fancy-enclosing-paren-indent
+                  (let ((enclose-open fancy-paren-open)
+                        enclose-indent-cons
+                        enclose-indent)
+                    (catch 'loop
+                      (while (setq enclose-indent-cons
+                                   (idlwave-calculate-paren-indent 
+                                    beg-reg (max (1- enclose-open) beg-reg)
+                                    nil)
+                                   enclose-open   (car enclose-indent-cons)
+                                   enclose-indent (cdr enclose-indent-cons))
+                        (if (< (- enclose-indent basic-indent)
+                               idlwave-max-extra-continuation-indent)
+                            (throw 'loop enclose-indent)))))))
+;      (message "non-allowed paren, relative to nested paren indent")
+       (min fancy-paren-indent
+            (+ fancy-enclosing-paren-indent idlwave-continuation-indent)))
+               
+       ;; a disallowed paren indent inside another type: indent relative
+       ((and fancy-paren-indent        
+            (not fancy-paren-indent-allowed)
+            fancy-nonparen-indent-allowed )
+;      (message "non-allowed paren-ident, relative to non-paren")
+       (+ fancy-nonparen-indent idlwave-continuation-indent))
+
+       ;; an allowed nonparen-only indent
+       (fancy-nonparen-indent-allowed
+;      (message "non-paren-indent")
+       fancy-nonparen-indent)
+
+       ;; everything else
+       (t 
+;      (message "basic indent") 
+       basic-indent)))))
 
 (defun idlwave-find-key (key-re &optional dir nomark limit)
   "Move to next match of the regular expression KEY-RE.
@@ -2970,9 +3062,16 @@ Skips any whitespace. Returns 0 if the end-of-line 
follows the whitespace."
           ((current-column)))))
 
 (defun idlwave-is-continuation-line ()
-  "Tests if current line is continuation line."
+  "Tests if current line is continuation line.
+Blank or comment-only lines following regular continuation lines (with
+`$') count as continuations too."
   (save-excursion
-    (idlwave-look-at "\\<\\$")))
+    (or 
+     (idlwave-look-at "\\<\\$")
+     (catch 'loop
+       (while (and (looking-at "^[ \t]*\\(;.*\\)?$") 
+                  (eq (forward-line -1) 0))
+        (if (idlwave-look-at "\\<\\$") (throw 'loop t)))))))
 
 (defun idlwave-is-comment-line ()
   "Tests if the current line is a comment line."
@@ -4919,10 +5018,10 @@ end
   ;; the user may have killed or redefined it.  In particular,
   ;; .RESET_SESSION will kill all user procedures.
   (unless (and idlwave-idlwave_routine_info-compiled
-              (file-readable-p idlwave-shell-temp-rinfo-save-file))
+              (file-readable-p (idlwave-shell-temp-file 'rinfo)))
     (save-excursion
       (set-buffer (idlwave-find-file-noselect
-                  idlwave-shell-temp-pro-file))
+                  (idlwave-shell-temp-file 'pro)))
       (erase-buffer)
       (insert idlwave-routine-info.pro)
       (save-buffer 0))
@@ -4932,7 +5031,7 @@ end
 ;    (message "SENDING SAVE") ; ????????????????????????
     (idlwave-shell-send-command
      (format 
"save,'idlwave_routine_info','idlwave_print_info_entry',FILE='%s',/ROUTINES" 
-            idlwave-shell-temp-rinfo-save-file)
+            (idlwave-shell-temp-file 'rinfo))
      nil 'hide))
 
   ;; Restore and execute the procedure, analyze the output
@@ -5718,7 +5817,7 @@ This function is not general, can only be used for 
completion stuff."
         ((memq (preceding-char) '(?\; ?\$)) (throw 'exit nil))
         ((eq (preceding-char) ?\n)
          (beginning-of-line 0)
-         (if (looking-at "\\([^;]\\)*\\$[ \t]*\\(;.*\\)?\n")
+         (if (looking-at "\\([^;\n]*\\)\\$[ \t]*\\(;[^\n]*\\)?\n")
              ;; continuation line
              (goto-char (match-end 1))
            (throw 'exit nil)))
@@ -5906,6 +6005,93 @@ Show PROMPT in echo area.  TYPE is one of 'function, 
'procedure or 'keyword."
 ;;----------------------------------------------------------------------
 ;;----------------------------------------------------------------------
 ;;----------------------------------------------------------------------
+(defvar rtn)
+(defun idlwave-pset (item)
+  (set 'rtn item))
+
+(defun idlwave-popup-select (ev list title &optional sort)
+  "Select an item in LIST with a popup menu.
+TITLE is the title to put atop the popup.  If SORT is non-nil,
+sort the list before displaying"
+  (let ((maxpopup idlwave-max-popup-menu-items)
+       rtn menu resp)
+    (cond ((null list))
+         ((= 1 (length list))
+          (setq rtn (car list)))
+         ((featurep 'xemacs)
+          (if sort (setq list (sort list (lambda (a b) 
+                                           (string< (upcase a) (upcase b))))))
+          (setq menu
+                (append (list title)
+                        (mapcar (lambda (x) (vector x (list 'idlwave-pset
+                                                            x)))
+                                list)))
+          (setq menu (idlwave-split-menu-xemacs menu maxpopup))
+          (setq resp (get-popup-menu-response menu))
+          (funcall (event-function resp) (event-object resp)))
+         (t
+          (if sort (setq list (sort list (lambda (a b) 
+                                           (string< (upcase a) (upcase b))))))
+          (setq menu (cons title
+                           (list
+                            (append (list "")
+                                    (mapcar (lambda(x) (cons x x)) list)))))
+          (setq menu (idlwave-split-menu-emacs menu maxpopup))
+          (setq rtn (x-popup-menu ev menu))))
+    rtn))
+
+(defun idlwave-split-menu-xemacs (menu N)
+  "Split the MENU into submenus of maximum length N."
+  (if (<= (length menu) (1+ N))
+      ;; No splitting needed
+      menu
+    (let* ((title (car menu))
+          (entries (cdr menu))
+          (menu (list title))
+          (cnt 0)
+          (nextmenu nil))
+      (while entries
+       (while (and entries (< cnt N))
+         (setq cnt (1+ cnt)
+               nextmenu (cons (car entries) nextmenu)
+               entries (cdr entries)))
+       (setq nextmenu (nreverse nextmenu))
+       (setq nextmenu (cons (format "%s...%s"
+                                    (aref (car nextmenu) 0)
+                                    (aref (nth (1- cnt) nextmenu) 0))
+                            nextmenu))
+       (setq menu (cons nextmenu menu)
+             nextmenu nil
+             cnt 0))
+      (nreverse menu))))
+
+(defun idlwave-split-menu-emacs (menu N)
+  "Split the MENU into submenus of maximum length N."
+  (if (<= (length (nth 1 menu)) (1+ N))
+      ;; No splitting needed
+      menu
+    (let* ((title (car menu))
+          (entries (cdr (nth 1 menu)))
+          (menu nil)
+          (cnt 0)
+          (nextmenu nil))
+      (while entries
+       (while (and entries (< cnt N))
+         (setq cnt (1+ cnt)
+               nextmenu (cons (car entries) nextmenu)
+               entries (cdr entries)))
+       (setq nextmenu (nreverse nextmenu))
+       (prin1 nextmenu)
+       (setq nextmenu (cons (format "%s...%s"
+                                    (car (car nextmenu))
+                                    (car (nth (1- cnt) nextmenu)))
+                            nextmenu))
+       (setq menu (cons nextmenu menu)
+             nextmenu nil
+             cnt 0))
+      (setq menu (nreverse menu))
+      (setq menu (cons title menu))
+      menu)))
 
 (defvar idlwave-completion-setup-hook nil)
 
@@ -6105,6 +6291,15 @@ Point is expected just before the opening `{' of the 
struct definition."
        (goto-char (match-end 0)))
       (nreverse names))))
 
+(defun idlwave-in-structure ()
+  "Return t if point is inside an IDL structure."
+  (let ((beg (point)))
+    (save-excursion
+      (if (not (or (idlwave-in-comment) (idlwave-in-quote)))
+         (if (idlwave-find-structure-definition nil nil 'back)
+             (let ((borders (idlwave-struct-borders)))
+               (or (= (car borders) (cdr borders)) ;; struct not yet closed...
+                   (and (> beg (car borders)) (< beg (cdr borders))))))))))
 
 (defun idlwave-struct-borders ()
   "Return the borders of the {...} after point as a cons cell."
@@ -6117,12 +6312,12 @@ 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.
+  "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 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."
   (let* ((ws "[ \t]*\\(\\$.*\n[ \t]*\\)?")
         (case-fold-search t)
         (lim (if (integerp bound) bound nil))
@@ -6132,9 +6327,9 @@ through the entire file."
                "\\(\\)")
              "=" ws "\\({\\)"
              (if name (concat ws "\\<" (downcase name) "[^a-zA-Z0-9_$]") ""))))
-    (if (or (and (eq bound 'all)
+    (if (or (and (or (eq bound 'all) (eq bound 'back))
                 (re-search-backward re nil t))
-           (re-search-forward re lim t))
+           (and (not (eq bound 'back)) (re-search-forward re lim t)))
        (goto-char (match-beginning 3)))))
 
 (defvar idlwave-class-info nil)
@@ -6491,7 +6686,6 @@ Works for system routines and keywords only."
   ;; work.
   (setq this-command last-command)
   (idlwave-do-mouse-completion-help ev))
-  
 
 (defvar idlwave-help-is-loaded nil
   "Is online help avaiable?")
@@ -6807,7 +7001,7 @@ keyword region, change to the appropriate Init method."
 
     ;; If this is the OBJ_NEW function, try to figure out the class and use
     ;; the keywords from the corresponding INIT method.
-    (if (and (equal name "OBJ_NEW")
+    (if (and (equal (upcase name) "OBJ_NEW")
             (or (eq major-mode 'idlwave-mode)
                 (eq major-mode 'idlwave-shell-mode)))
        (let* ((bos (save-excursion (idlwave-beginning-of-statement) (point)))

Reply via email to