/[emacs]/emacs/lisp/progmodes/idlwave.el
ViewVC logotype

Diff of /emacs/lisp/progmodes/idlwave.el

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 3.17 by lektu, Thu May 16 11:59:29 2002 UTC revision 3.17.2.1 by miles, Fri Apr 4 06:20:35 2003 UTC
# Line 1  Line 1 
1  ;;; idlwave.el --- IDL and WAVE CL editing mode for GNU Emacs  ;;; idlwave.el --- IDL editing mode for GNU Emacs
2  ;; Copyright (c) 1999, 2000 Free Software Foundation  ;; Copyright (c) 1999, 2000, 2001,2002 Free Software Foundation
3    
4  ;; Author: Chris Chase <chase@att.com>  ;; Author: Carsten Dominik <dominik@astro.uva.nl>
5  ;; Maintainer: John-David Smith <jdsmith@astro.cornell.edu>  ;;         Chris Chase <chase@att.com>
6  ;; Version: 4.7  ;; Maintainer: J.D. Smith <jdsmith@as.arizona.edu>
7    ;; Version: 4.15
8  ;; Date: $Date$  ;; Date: $Date$
9  ;; Keywords: languages  ;; Keywords: languages
10    
# Line 37  Line 38 
38  ;; for features, key bindings, and info.  ;; for features, key bindings, and info.
39  ;; Also, Info format documentation is available with `M-x idlwave-info'  ;; Also, Info format documentation is available with `M-x idlwave-info'
40  ;;  ;;
41    ;; New versions of IDLWAVE, documentation, and more information
42    ;; available from:
43    ;;                 http://idlwave.org
44  ;;  ;;
45  ;; INSTALLATION  ;; INSTALLATION
46  ;; ============  ;; ============
# Line 53  Line 57 
57  ;; SOURCE  ;; SOURCE
58  ;; ======  ;; ======
59  ;;  ;;
60  ;; The newest version of this file is available from the maintainers  ;; The newest version of this file is available from the maintainer's
61  ;; Webpage.  ;; Webpage.
62  ;;  ;;
63  ;;   http://www.strw.leidenuniv.el/~dominik/Tools/idlwave  ;;   http://idlwave.org
64  ;;  ;;
65  ;; DOCUMENTATION  ;; DOCUMENTATION
66  ;; =============  ;; =============
# Line 65  Line 69 
69  ;; A printable version of the documentation is available from the  ;; A printable version of the documentation is available from the
70  ;; maintainers webpage (see under SOURCE)  ;; maintainers webpage (see under SOURCE)
71  ;;  ;;
72  ;;  ;;
73  ;; ACKNOWLEDGMENTS  ;; ACKNOWLEDGMENTS
74  ;; ===============  ;; ===============
75  ;;  ;;
# Line 80  Line 84 
84  ;;    Simon Marshall <Simon.Marshall@esrin.esa.it>  ;;    Simon Marshall <Simon.Marshall@esrin.esa.it>
85  ;;    Laurent Mugnier <mugnier@onera.fr>  ;;    Laurent Mugnier <mugnier@onera.fr>
86  ;;    Lubos Pochman <lubos@rsinc.com>  ;;    Lubos Pochman <lubos@rsinc.com>
87    ;;    Bob Portmann <portmann@al.noaa.gov>
88  ;;    Patrick M. Ryan <pat@jaameri.gsfc.nasa.gov>  ;;    Patrick M. Ryan <pat@jaameri.gsfc.nasa.gov>
89  ;;    Marty Ryba <ryba@ll.mit.edu>  ;;    Marty Ryba <ryba@ll.mit.edu>
90  ;;    Phil Williams <williams@irc.chmcc.org>  ;;    Phil Williams <williams@irc.chmcc.org>
 ;;    J.D. Smith <jdsmith@astrosun.tn.cornell.edu>  
91  ;;    Phil Sterne <sterne@dublin.llnl.gov>  ;;    Phil Sterne <sterne@dublin.llnl.gov>
92  ;;  ;;
93  ;; CUSTOMIZATION:  ;; CUSTOMIZATION:
94  ;; =============  ;; =============
95  ;;  ;;
96  ;; IDLWAVE has customize support - so if you want to learn about the  ;; IDLWAVE has extensive customize support - so if you want to learn
97  ;;  variables which control the behavior of the mode, use  ;; about the variables which control the behavior of the mode, use
98  ;; `M-x idlwave-customize'.  ;; `M-x idlwave-customize'.
99  ;;  ;;
100  ;; You can set your own preferred values with Customize, or with Lisp  ;; You can set your own preferred values with Customize, or with Lisp
101  ;; code in .emacs.  For an example of what to put into .emacs, check  ;; code in .emacs.  For an example of what to put into .emacs, check
102  ;; the TexInfo documentation.  ;; the TexInfo documentation or see a complete .emacs at
103    ;; http://idlwave.org.
104  ;;  ;;
105  ;; KNOWN PROBLEMS:  ;; KNOWN PROBLEMS:
106  ;; ==============  ;; ==============
107  ;;  ;;
108    ;;   IDLWAVE support for the IDL-derived PV-WAVE CL language of Visual
109    ;;   Numerics, Inc. is growing less and less complete as the two
110    ;;   languages grow increasingly apart.  The mode probably shouldn't
111    ;;   even have "WAVE" in it's title, but it's catchy, and required to
112    ;;   avoid conflict with the CORBA idl.el mode.  Caveat WAVEor.
113    ;;
114  ;;   Moving the point backwards in conjunction with abbrev expansion  ;;   Moving the point backwards in conjunction with abbrev expansion
115  ;;   does not work as I would like it, but this is a problem with  ;;   does not work as I would like it, but this is a problem with
116  ;;   emacs abbrev expansion done by the self-insert-command.  It ends  ;;   emacs abbrev expansion done by the self-insert-command.  It ends
117  ;;   up inserting the character that expanded the abbrev after moving  ;;   up inserting the character that expanded the abbrev after moving
118  ;;   point backward, e.g., "\cl" expanded with a space becomes  ;;   point backward, e.g., "\cl" expanded with a space becomes
119  ;;   "LONG( )" with point before the close paren.  This is solved by  ;;   "LONG( )" with point before the close paren.  This is solved by
120  ;;   using a temporary function in `post-command-hook' - not pretty,  ;;   using a temporary function in `post-command-hook' - not pretty,
121  ;;   but it works.  ;;   but it works.
122  ;;  ;;
123  ;;   Tabs and spaces are treated equally as whitespace when filling a  ;;   Tabs and spaces are treated equally as whitespace when filling a
# Line 116  Line 127 
127  ;;   limited to comments only and occurs only when a comment  ;;   limited to comments only and occurs only when a comment
128  ;;   paragraph is filled via `idlwave-fill-paragraph'.  ;;   paragraph is filled via `idlwave-fill-paragraph'.
129  ;;  ;;
 ;;   "&" is ignored when parsing statements.  
130  ;;   Avoid muti-statement lines (using "&") on block begin and end  ;;   Avoid muti-statement lines (using "&") on block begin and end
131  ;;   lines.  Multi-statement lines can mess up the formatting, for  ;;   lines.  Multi-statement lines can mess up the formatting, for
132  ;;   example, multiple end statements on a line: endif & endif.  ;;   example, multiple end statements on a line: endif & endif.
133  ;;   Using "&" outside of block begin/end lines should be okay.  ;;   Using "&" outside of block begin/end lines should be okay.
134  ;;  ;;
135  ;;   It is possible that the parser which decides what to complete has  ;;   Determining the expression at point for printing and other
136  ;;   problems with pointer dereferencing statements.  I don't use  ;;   examination commands is somewhat rough: currently only fairly
137  ;;   pointers often enough to find out - please report any problems.  ;;   simple entities are found.  You can always drag-select or examine
138  ;;  ;;   a region.
 ;;   Completion and Routine Info do not know about inheritance.  Thus,  
 ;;   Keywords inherited from superclasses are not displayed and cannot  
 ;;   completed.  
139  ;;  ;;
140  ;;   When forcing completion of method keywords, the initial  ;;   When forcing completion of method keywords, the initial
141  ;;   query for a method has multiple entries for some methods.  Would  ;;   query for a method has multiple entries for some methods.  Would
# Line 140  Line 147 
147  (eval-when-compile (require 'cl))  (eval-when-compile (require 'cl))
148    
149  (eval-and-compile  (eval-and-compile
150   ;; Kludge to allow `defcustom' for Emacs 19.    ;; Kludge to allow `defcustom' for Emacs 19.
151   (condition-case () (require 'custom) (error nil))    (condition-case () (require 'custom) (error nil))
152   (if (and (featurep 'custom) (fboundp 'custom-declare-variable))    (if (and (featurep 'custom) (fboundp 'custom-declare-variable))
153       nil ;; We've got what we needed        nil ;; We've got what we needed
154       ;; We have the old or no custom-library, hack around it!      ;; We have the old or no custom-library, hack around it!
155       (defmacro defgroup (&rest args) nil)      (defmacro defgroup (&rest args) nil)
156       (defmacro defcustom (var value doc &rest args)      (defmacro defcustom (var value doc &rest args)
157         `(defvar ,var ,value ,doc))))        `(defvar ,var ,value ,doc))))
158    
159  (defgroup idlwave nil  (defgroup idlwave nil
160    "Major mode for editing IDL/WAVE CL .pro files"    "Major mode for editing IDL .pro files"
161    :tag "IDLWAVE"    :tag "IDLWAVE"
162    :link '(url-link :tag "Home Page"    :link '(url-link :tag "Home Page"
163                     "http://strw.leidenuniv.nl/~dominik/Tools/idlwave")                     "http://idlwave.org")
164    :link '(emacs-commentary-link :tag "Commentary in idlw-shell.el"    :link '(emacs-commentary-link :tag "Commentary in idlw-shell.el"
165                                  "idlw-shell.el")                                  "idlw-shell.el")
166    :link '(emacs-commentary-link :tag "Commentary in idlwave.el" "idlwave.el")    :link '(emacs-commentary-link :tag "Commentary in idlwave.el" "idlwave.el")
# Line 190  line up with the block BEGIN lines." Line 197  line up with the block BEGIN lines."
197  (defcustom idlwave-continuation-indent 2  (defcustom idlwave-continuation-indent 2
198    "*Extra indentation applied to continuation lines.    "*Extra indentation applied to continuation lines.
199  This extra offset applies to the first of a set of continuation lines.  This extra offset applies to the first of a set of continuation lines.
200  The following lines receive the same indentation as the first.  The following lines receive the same indentation as the first."
201  Also, the value of this variable applies to continuation lines inside    :group 'idlwave-code-formatting
202  parenthesis.  When the current line contains an open unmatched ([{,    :type 'integer)
203  the next line is indented to that parenthesis plus the value of this variable."  
204    (defcustom idlwave-max-extra-continuation-indent 20
205      "*Maximum additional indentation for special continuation indent.
206    Several special indentations are tried to help line up continuation
207    lines in routine calls or definitions, other statements with
208    parentheses, or assignment statements.  This variable specifies a
209    maximum amount by which this special indentation can exceed the
210    standard continuation indentation, otherwise defaulting to a fixed
211    offset.  Set to 0 to effectively disable all special continuation
212    indentation, or to a large number (like 100) to enable it in all
213    cases.  See also `idlwave-indent-top-open-paren', which can override
214    this variable."
215    :group 'idlwave-code-formatting    :group 'idlwave-code-formatting
216    :type 'integer)    :type 'integer)
217    
218    (defcustom idlwave-indent-to-open-paren t
219      "*Non-nil means, indent continuation lines to innermost open
220    parenthesis.  This indentation occurs even if otherwise disallowed by
221    `idlwave-max-extra-continuation-indent'.  Matching parens and the
222    interleaving args are lined up.  Example:
223    
224      x = function_a(function_b(function_c( a, b, [1,2,3, $
225                                                   4,5,6 $
226                                                  ], $
227                                            c, d $
228                                          )))
229    
230    When this variable is nil, paren alignment may still occur, based on
231    the value of `max-extra-continuation-indent', which, if zero, would
232    yield:
233    
234      x = function_a(function_b(function_c( a, b, [1,2,3, $
235         4,5,6 $
236         ], $
237         c, d $
238         )))"
239     :group 'idlwave-code-formatting
240      :type 'boolean)
241    
242  (defcustom idlwave-hanging-indent t  (defcustom idlwave-hanging-indent t
243    "*If set non-nil then comment paragraphs are indented under the    "*If set non-nil then comment paragraphs are indented under the
244  hanging indent given by `idlwave-hang-indent-regexp' match in the first line  hanging indent given by `idlwave-hang-indent-regexp' match in the first line
# Line 223  extends to the end of the match for the Line 265  extends to the end of the match for the
265    
266  (defcustom idlwave-auto-fill-split-string t  (defcustom idlwave-auto-fill-split-string t
267    "*If non-nil then auto fill will split strings with the IDL `+' operator.    "*If non-nil then auto fill will split strings with the IDL `+' operator.
268  When the line end falls within a string, string concatenation with the  When the line end falls within a string, string concatenation with the
269  '+' operator will be used to distribute a long string over lines.    '+' operator will be used to distribute a long string over lines.
270  If nil and a string is split then a terminal beep and warning are issued.  If nil and a string is split then a terminal beep and warning are issued.
271    
272  This variable is ignored when `idlwave-fill-comment-line-only' is  This variable is ignored when `idlwave-fill-comment-line-only' is
# Line 274  the comment is not preceded by whitespac Line 316  the comment is not preceded by whitespac
316    "Routine Info options for IDLWAVE mode."    "Routine Info options for IDLWAVE mode."
317    :group 'idlwave)    :group 'idlwave)
318    
319    
320    (defcustom idlwave-init-rinfo-when-idle-after 10
321      "*Seconds of idle time before routine info is automatically initialized.
322    Initializing the routine info can take long, in particular if a large
323    library catalog is involved.  When Emacs is idle for more than the number
324    of seconds specified by this variable, it starts the initialization.
325    The process is split into five steps, in order to keep possible work
326    interruption as short as possible.  If one of the steps finishes, and no
327    user input has arrived in the mean time, initialization proceeds immediately
328    to the next step.
329    A good value for this variable is about 1/3 of the time initialization
330    take in you setup.  So if you have a fast machine and no problems with a slow network connection, don't hesitate to set this to 2 seconds.
331    A Value of 0 means, don't initialize automatically."
332      :group 'idlwave-routine-info
333      :type 'number)
334    
335  (defcustom idlwave-scan-all-buffers-for-routine-info t  (defcustom idlwave-scan-all-buffers-for-routine-info t
336    "*Non-nil means, scan buffers for IDL programs when updating info.    "*Non-nil means, scan buffers for IDL programs when updating info.
337  The scanning is done by the command `idlwave-update-routine-info'.  The scanning is done by the command `idlwave-update-routine-info'.
# Line 302  scan, this is not necessary." Line 360  scan, this is not necessary."
360  Possible values:  Possible values:
361  nil       Never  nil       Never
362  t         All available  t         All available
363  (...)     A list of circumstances. Allowed members are:  \(...)     A list of circumstances. Allowed members are:
364             find-file       Add info for new IDLWAVE buffers.             find-file       Add info for new IDLWAVE buffers.
365             save-buffer     Update buffer info when buffer is saved             save-buffer     Update buffer info when buffer is saved
366             kill-buffer     Remove buffer info when buffer gets killed             kill-buffer     Remove buffer info when buffer gets killed
# Line 316  t         All available Line 374  t         All available
374                 (const :tag "When saving a buffer" save-buffer)                 (const :tag "When saving a buffer" save-buffer)
375                 (const :tag "After a buffer was killed" kill-buffer)                 (const :tag "After a buffer was killed" kill-buffer)
376                 (const :tag "After a buffer was compiled successfully, update shell info" compile-buffer))))                 (const :tag "After a buffer was compiled successfully, update shell info" compile-buffer))))
377                  
378  (defcustom idlwave-rinfo-max-source-lines 5  (defcustom idlwave-rinfo-max-source-lines 5
379    "*Maximum number of source files displayed in the Routine Info window.    "*Maximum number of source files displayed in the Routine Info window.
380  When an integer, it is the maximum number of source files displayed.  When an integer, it is the maximum number of source files displayed.
# Line 361  will be used to store the result." Line 419  will be used to store the result."
419  (defcustom idlwave-special-lib-alist nil  (defcustom idlwave-special-lib-alist nil
420    "Alist of regular expressions matching special library directories.    "Alist of regular expressions matching special library directories.
421  When listing routine source locations, IDLWAVE gives a short hint where  When listing routine source locations, IDLWAVE gives a short hint where
422  the file defining the routine is located.  By default it lists `SystemLib'  the file defining the routine is located.  By default it lists `SystemLib'
423  for routines in the system library `!DIR/lib' and `Library' for anything  for routines in the system library `!DIR/lib' and `Library' for anything
424  else.  This variable can define additional types.  The car of each entry  else.  This variable can define additional types.  The car of each entry
425  is a regular expression matching the file name (they normally will match  is a regular expression matching the file name (they normally will match
# Line 449  definition is displayed instead." Line 507  definition is displayed instead."
507    "Face for highlighting links into IDLWAVE online help."    "Face for highlighting links into IDLWAVE online help."
508    :group 'idlwave-online-help)    :group 'idlwave-online-help)
509    
510  (defcustom idlwave-help-activate-links-agressively t  (defcustom idlwave-help-activate-links-aggressively t
511    "*Non-nil means, make all possible links in help active.    "*Non-nil means, make all possible links in help active.
512  This just activates all words which are also a help topic - some links may  This just activates all words which are also a help topic - some links may
513  be misleading."  be misleading."
514    :group 'idlwave-online-help    :group 'idlwave-online-help
515    :type 'boolean)    :type 'boolean)
516      
517    
518  (defgroup idlwave-completion nil  (defgroup idlwave-completion nil
519    "Completion options for IDLWAVE mode."    "Completion options for IDLWAVE mode."
# Line 480  be misleading." Line 538  be misleading."
538  This variable determines the case (UPPER/lower/Capitalized...) of  This variable determines the case (UPPER/lower/Capitalized...) of
539  words inserted into the buffer by completion.  The preferred case can  words inserted into the buffer by completion.  The preferred case can
540  be specified separately for routine names, keywords, classes and  be specified separately for routine names, keywords, classes and
541  methods.  methods.
542  This alist should therefore have entries for `routine' (normal  This alist should therefore have entries for `routine' (normal
543  functions and procedures, i.e. non-methods), `keyword', `class', and  functions and procedures, i.e. non-methods), `keyword', `class', and
544  `method'.  Plausible values are  `method'.  Plausible values are
# Line 553  This option is only effective when the o Line 611  This option is only effective when the o
611    
612  (defcustom idlwave-support-inheritance t  (defcustom idlwave-support-inheritance t
613    "Non-nil means, treat inheritance with completion, online help etc.    "Non-nil means, treat inheritance with completion, online help etc.
614  When nil,  IDLWAVE only knows about the native methods and tags of a class,  When nil, IDLWAVE only knows about the native methods and tags of a class,
615  not about inherited ones."  not about inherited ones."
616    :group 'idlwave-routine-info    :group 'idlwave-routine-info
617    :type 'boolean)    :type 'boolean)
618    
619    (defcustom idlwave-keyword-class-inheritance '("^[gs]etproperty$" "^init$")
620      "List of regular expressions for class-driven keyword inheritance.
621    Keyword inheritance is often tied to class inheritance by \"chaining\"
622    up the class tree.  While it cannot be assumed that the presence of an
623    _EXTRA or _REF_EXTRA symbol guarantees such chaining will occur, for
624    certain methods this assumption is almost always true.  The methods
625    for which to assume this can be set here."
626      :group 'idlwave-routine-info
627      :type '(repeat (regexp :tag "Match method:")))
628    
629    
630  (defcustom idlwave-completion-show-classes 1  (defcustom idlwave-completion-show-classes 1
631    "*Number of classes to show when completing object methods and keywords.    "*Number of classes to show when completing object methods and keywords.
632  When completing methods or keywords for an object with unknown class,  When completing methods or keywords for an object with unknown class,
# Line 588  class info listed.  See `idlwave-complet Line 657  class info listed.  See `idlwave-complet
657                                   (keyword-default . nil))                                   (keyword-default . nil))
658    "Association list governing specification of object classes for completion.    "Association list governing specification of object classes for completion.
659    
660  When IDLWAVE is trying to complete items which belong to the object  When IDLWAVE tries to complete object-oriented methods, it usually
661  oriented part of IDL, it usually cannot determine the class of a given  cannot determine the class of a given object from context.  In order
662  object from context.  In order to provide the user with a correct list  to provide the user with a correct list of methods or keywords, it
663  of methods or keywords, it would have to determine the appropriate  needs to determine the appropriate class.  IDLWAVE has two ways of
664  class.  IDLWAVE has two ways to deal with this problem.  doing this (well, three ways if you count the shell... see
665    `idlwave-shell-query-for-class'):
666  1. One possibility is to combine the items of all available  
667     classes for the purpose of completion.  So when completing a  1. Combine the items of all available classes which contain this
668     method, all methods of all classes are available, and when     method for the purpose of completion.  So when completing a method,
669     completing a keyword, all keywords allowed for this method in any     all methods of all known classes are available, and when completing
670     class will be possible completions.  This behavior is very much     a keyword, all keywords allowed for this method in any class are
671     like normal completion and is therefore the default.  It works much     shown.  This behavior is very much like normal completion and is
672     better than one might think - only for the INIT, GETPROPERTY and     therefore the default.  It works much better than one might think -
673     SETPROPERTY the keyword lists become uncomfortably long.     only for the INIT, GETPROPERTY and SETPROPERTY the keyword lists
674     See also `idlwave-completion-show-classes'.     become uncomfortably long.  See also
675       `idlwave-completion-show-classes'.
676    
677  2. The second possibility is to ask the user on each occasion.  To  2. The second possibility is to ask the user on each occasion.  To
678     make this less interruptive, IDLWAVE can store the class as a text     make this less interruptive, IDLWAVE can store the class as a text
# Line 613  class.  IDLWAVE has two ways to deal wit Line 683  class.  IDLWAVE has two ways to deal wit
683     You will have to turn on the storage of the selected class     You will have to turn on the storage of the selected class
684     explicitly with the variable `idlwave-store-inquired-class'.     explicitly with the variable `idlwave-store-inquired-class'.
685    
686  This variable allows to configure IDLWAVE's behavior during  This variable allows you to configure IDLWAVE's method and
687  completion.  Its value is an alist, which should contain at least two  method-keyword completion behavior.  Its value is an alist, which
688  elements: (method-default . VALUE) and (keyword-default . VALUE),  should contain at least two elements: (method-default . VALUE) and
689  where VALUE is either t or nil.  These specify if the class should be  \(keyword-default . VALUE), where VALUE is either t or nil.  These
690  determined during method and keyword completion, respectively.  specify if the class should be found during method and keyword
691    completion, respectively.
692    
693  The alist may have additional entries specifying exceptions from the  The alist may have additional entries specifying exceptions from the
694  keyword completion rule for specific methods, like INIT or  keyword completion rule for specific methods, like INIT or
695  GETPROPERTY.  In order to turn on class specification for the INIT  GETPROPERTY.  In order to turn on class specification for the INIT
696  method, add an entry (\"INIT\" . t).  The method name must be ALL-CAPS."  method, add an entry (\"INIT\" . t).  The method name must be ALL-CAPS."
# Line 643  particular object method call.  This hap Line 714  particular object method call.  This hap
714  value of the variable `idlwave-query-class'.  value of the variable `idlwave-query-class'.
715    
716  When you specify a class, this information can be stored as a text  When you specify a class, this information can be stored as a text
717  property on the `->' arrow in the source code, so that during the same  property on the `->' arrow in the source code, so that during the same
718  editing session, IDLWAVE will not have to ask again.  When this  editing session, IDLWAVE will not have to ask again.  When this
719  variable is non-nil, IDLWAVE will store and reuse the class information.  variable is non-nil, IDLWAVE will store and reuse the class information.
720  The class stored can be checked and removed with `\\[idlwave-routine-info]'  The class stored can be checked and removed with `\\[idlwave-routine-info]'
# Line 663  at point." Line 734  at point."
734  (defcustom idlwave-class-arrow-face 'bold  (defcustom idlwave-class-arrow-face 'bold
735    "*Face to highlight object operator arrows `->' which carry a class property.    "*Face to highlight object operator arrows `->' which carry a class property.
736  When IDLWAVE stores a class name as text property on an object arrow  When IDLWAVE stores a class name as text property on an object arrow
737  (see variable `idlwave-store-inquired-class', it highlights the arrow  \(see variable `idlwave-store-inquired-class', it highlights the arrow
738  with this font in order to remind the user that this arrow is special."  with this font in order to remind the user that this arrow is special."
739    :group 'idlwave-completion    :group 'idlwave-completion
740    :type 'symbol)    :type 'symbol)
# Line 917  Otherwise STRING is used. If nil, the fi Line 988  Otherwise STRING is used. If nil, the fi
988  For example you might set PATHNAME to the path for the  For example you might set PATHNAME to the path for the
989  lib_template.pro file included in the IDL distribution.")  lib_template.pro file included in the IDL distribution.")
990    
991    (defcustom idlwave-header-to-beginning-of-file nil
992      "*Non-nil means, the documentation header will always be at start of file.
993    When nil, the header is positioned between the PRO/FUNCTION line of
994    the current routine and the code, allowing several routine headers in
995    a file."
996      :group 'idlwave-documentation
997      :type 'boolean)
998    
999  (defcustom idlwave-timestamp-hook 'idlwave-default-insert-timestamp  (defcustom idlwave-timestamp-hook 'idlwave-default-insert-timestamp
1000    "*The hook function used to update the timestamp of a function."    "*The hook function used to update the timestamp of a function."
1001    :group 'idlwave-documentation    :group 'idlwave-documentation
# Line 951  If nil it will not be inserted." Line 1030  If nil it will not be inserted."
1030  ;; anything.  ;; anything.
1031    
1032  (defcustom idlwave-shell-explicit-file-name "idl"  (defcustom idlwave-shell-explicit-file-name "idl"
1033    "*If non-nil, is the command to run IDL.    "*If non-nil, this is the command to run IDL.
1034  Should be an absolute file path or path relative to the current environment  Should be an absolute file path or path relative to the current environment
1035  execution search path."  execution search path.  If you want to specify command line switches
1036    for the idl program, use `idlwave-shell-command-line-options'.
1037    
1038    I know the name of this variable is badly chosen, but I cannot change
1039    it without compromizing backwards-compatibility."
1040    :group 'idlwave-external-programs    :group 'idlwave-external-programs
1041    :type 'string)    :type 'string)
1042    
 ;; FIXME: Document a case when is this needed.  
1043  (defcustom idlwave-shell-command-line-options nil  (defcustom idlwave-shell-command-line-options nil
1044    "*A list of command line options for calling the IDL program."    "*A list of command line options for calling the IDL program.
1045    :type '(repeat (string :value ""))  Since IDL is executed directly without going through a shell like /bin/sh,
1046    this should be a list of strings like '(\"-rt=file\" \"-nw\") with a separate
1047    string for each argument.  But you may also give a single string which
1048    contains the options whitespace-separated.  Emacs will be kind enough to
1049    split it for you."
1050      :type '(choice
1051              string
1052              (repeat (string :value "")))
1053    :group 'idlwave-external-programs)    :group 'idlwave-external-programs)
1054    
1055  (defcustom idlwave-help-application "idlhelp"  (defcustom idlwave-help-application "idlhelp"
# Line 1005  IDL process is made." Line 1094  IDL process is made."
1094    :group 'idlwave-misc    :group 'idlwave-misc
1095    :type 'boolean)    :type 'boolean)
1096    
1097  (defcustom idlwave-default-font-lock-items  (defcustom idlwave-default-font-lock-items
1098    '(pros-and-functions batch-files idl-keywords label goto    '(pros-and-functions batch-files idlwave-idl-keywords label goto
1099                         common-blocks class-arrows)                         common-blocks class-arrows)
1100    "Items which should be fontified on the default fontification level 2.    "Items which should be fontified on the default fontification level 2.
1101  IDLWAVE defines 3 levels of fontification.  Level 1 is very little, level 3  IDLWAVE defines 3 levels of fontification.  Level 1 is very little, level 3
# Line 1016  a list of symbols, the following symbols Line 1105  a list of symbols, the following symbols
1105    
1106  pros-and-functions   Procedure and Function definitions  pros-and-functions   Procedure and Function definitions
1107  batch-files          Batch Files  batch-files          Batch Files
1108  idl-keywords         IDL Keywords  idlwave-idl-keywords IDL Keywords
1109  label                Statement Labels  label                Statement Labels
1110  goto                 Goto Statements  goto                 Goto Statements
1111  common-blocks        Common Blocks  common-blocks        Common Blocks
# Line 1028  class-arrows         Object Arrows with Line 1117  class-arrows         Object Arrows with
1117    :type '(set    :type '(set
1118            :inline t :greedy t            :inline t :greedy t
1119            (const :tag "Procedure and Function definitions" pros-and-functions)            (const :tag "Procedure and Function definitions" pros-and-functions)
1120            (const :tag "Batch Files"                        batch-files)            (const :tag "Batch Files"                       batch-files)
1121            (const :tag "IDL Keywords (reserved words)"      idl-keywords)            (const :tag "IDL Keywords (reserved words)"     idlwave-idl-keywords)
1122            (const :tag "Statement Labels"                   label)            (const :tag "Statement Labels"                  label)
1123            (const :tag "Goto Statements"                    goto)            (const :tag "Goto Statements"                   goto)
1124            (const :tag "Tags in Structure Definition"       structtag)            (const :tag "Tags in Structure Definition"      structtag)
1125            (const :tag "Structure Name"                     structname)            (const :tag "Structure Name"                    structname)
1126            (const :tag "Common Blocks"                      common-blocks)            (const :tag "Common Blocks"                     common-blocks)
1127            (const :tag "Keyword Parameters"                 keyword-parameters)            (const :tag "Keyword Parameters"                keyword-parameters)
1128            (const :tag "System Variables"                   system-variables)            (const :tag "System Variables"                  system-variables)
1129            (const :tag "FIXME: Warning"                     fixme)            (const :tag "FIXME: Warning"                    fixme)
1130            (const :tag "Object Arrows with class property " class-arrows)))            (const :tag "Object Arrows with class property " class-arrows)))
1131    
1132  (defcustom idlwave-mode-hook nil  (defcustom idlwave-mode-hook nil
# Line 1066  As a user, you should not set this to t. Line 1155  As a user, you should not set this to t.
1155  ;;; Simon Marshall <simon@gnu.ai.mit.edu>  ;;; Simon Marshall <simon@gnu.ai.mit.edu>
1156  ;;; and Carsten Dominik...  ;;; and Carsten Dominik...
1157    
1158  (defconst idlwave-font-lock-keywords-1 nil  ;; The following are the reserved words in IDL.  Maybe we should
1159    "Subdued level highlighting for IDLWAVE mode.")  ;; highlight some more stuff as well?
1160    ;; Procedure declarations.  Fontify keyword plus procedure name.
1161  (defconst idlwave-font-lock-keywords-2 nil  (defvar idlwave-idl-keywords
1162    "Medium level highlighting for IDLWAVE mode.")    ;; To update this regexp, update the list of keywords and
1163      ;; evaluate the form.
1164  (defconst idlwave-font-lock-keywords-3 nil    ;;    (insert
1165    "Gaudy level highlighting for IDLWAVE mode.")    ;;     (prin1-to-string
1166      ;;      (concat
1167  (let* ((oldp (or (string-match "Lucid" emacs-version)    ;;       "\\<\\("
1168                   (not (boundp 'emacs-minor-version))    ;;       (regexp-opt
1169                   (and (<= emacs-major-version 19)    ;;        '("and" "or" "xor" "not"
1170                        (<= emacs-minor-version 29))))    ;;          "eq" "ge" "gt" "le" "lt" "ne"
1171      ;;          "for" "do" "endfor"
1172         ;; The following are the reserved words in IDL.  Maybe we should    ;;          "if" "then" "endif" "else" "endelse"
1173         ;; highlight some more stuff as well?          ;;          "case" "of" "endcase"
1174         (idl-keywords    ;;          "switch" "break" "continue" "endswitch"
1175          ;; To update this regexp, update the list of keywords and    ;;          "begin" "end"
1176          ;; evaluate the form.    ;;          "repeat" "until" "endrep"
1177  ;       (insert    ;;          "while" "endwhile"
1178  ;        (prin1-to-string    ;;          "goto" "return"
1179  ;         (concat    ;;          "inherits" "mod"
1180  ;          "\\<\\("    ;;          "compile_opt" "forward_function"
1181  ;          (regexp-opt    ;;          "on_error" "on_ioerror"))  ; on_error is not officially reserved
1182  ;           '("and" "or" "xor" "not"    ;;       "\\)\\>")))
1183  ;             "eq" "ge" "gt" "le" "lt" "ne"    "\\<\\(and\\|b\\(egin\\|reak\\)\\|c\\(ase\\|o\\(mpile_opt\\|ntinue\\)\\)\\|do\\|e\\(lse\\|nd\\(case\\|else\\|for\\|if\\|rep\\|switch\\|while\\)?\\|q\\)\\|for\\(ward_function\\)?\\|g\\(oto\\|[et]\\)\\|i\\(f\\|nherits\\)\\|l[et]\\|mod\\|n\\(e\\|ot\\)\\|o\\(n_\\(error\\|ioerror\\)\\|[fr]\\)\\|re\\(peat\\|turn\\)\\|switch\\|then\\|until\\|while\\|xor\\)\\>")
 ;             "for" "do" "endfor"  
 ;             "if" "then" "endif" "else" "endelse"  
 ;             "case" "of" "endcase"  
 ;             "switch" "break" "continue" "endswitch"  
 ;             "begin" "end"  
 ;             "repeat" "until" "endrep"  
 ;             "while" "endwhile"  
 ;             "goto" "return"  
 ;             "inherits" "mod"  
 ;             "compile_opt" "forward_function"  
 ;             "on_error" "on_ioerror"))  ; on_error is not officially reserved  
 ;          "\\)\\>")))  
   
         "\\<\\(and\\|b\\(egin\\|reak\\)\\|c\\(ase\\|o\\(mpile_opt\\|ntinue\\)\\)\\|do\\|e\\(lse\\|nd\\(case\\|else\\|for\\|if\\|rep\\|switch\\|while\\)?\\|q\\)\\|for\\(ward_function\\)?\\|g\\(oto\\|[et]\\)\\|i\\(f\\|nherits\\)\\|l[et]\\|mod\\|n\\(e\\|ot\\)\\|o\\(n_\\(error\\|ioerror\\)\\|[fr]\\)\\|re\\(peat\\|turn\\)\\|switch\\|then\\|until\\|while\\|xor\\)\\>")  
1184    
1185         ;; Procedure declarations.  Fontify keyword plus procedure name.  (let* (;; Procedure declarations.  Fontify keyword plus procedure name.
1186         ;; Function  declarations.  Fontify keyword plus function  name.         ;; Function  declarations.  Fontify keyword plus function  name.
1187         (pros-and-functions         (pros-and-functions
1188          '("\\<\\(function\\|pro\\)\\>[ \t]+\\(\\sw+\\(::\\sw+\\)?\\)"          '("\\<\\(function\\|pro\\)\\>[ \t]+\\(\\sw+\\(::\\sw+\\)?\\)"
# Line 1121  As a user, you should not set this to t. Line 1196  As a user, you should not set this to t.
1196            (2 font-lock-reference-face nil t)      ; block name            (2 font-lock-reference-face nil t)      ; block name
1197            (font-lock-match-c++-style-declaration-item-and-skip-to-next            (font-lock-match-c++-style-declaration-item-and-skip-to-next
1198             ;; Start with point after block name and comma             ;; Start with point after block name and comma
1199             (goto-char (match-end 0))  ; needed for XEmacs, could be nil             (goto-char (match-end 0))  ; needed for XEmacs, could be nil
1200             nil             nil
1201             (1 font-lock-variable-name-face)       ; variable names             (1 font-lock-variable-name-face)       ; variable names
1202             )))             )))
# Line 1174  As a user, you should not set this to t. Line 1249  As a user, you should not set this to t.
1249         ;; All operators (not used because too noisy)         ;; All operators (not used because too noisy)
1250         (all-operators         (all-operators
1251          '("[-*^#+<>/]" (0 font-lock-keyword-face)))          '("[-*^#+<>/]" (0 font-lock-keyword-face)))
1252            
1253         ;; Arrows with text property `idlwave-class'         ;; Arrows with text property `idlwave-class'
1254         (class-arrows         (class-arrows
1255          (list 'idlwave-match-class-arrows          '(idlwave-match-class-arrows (0 idlwave-class-arrow-face))))
               (list 0 (if (featurep 'xemacs)  
                           idlwave-class-arrow-face  
                         'idlwave-class-arrow-face))))  
   
        )  
   
   ;; The following lines are just a dummy to make the compiler shut up  
   ;; about variables bound but not used.  
   (setq oldp oldp  
         idl-keywords idl-keywords  
         pros-and-functions pros-and-functions  
         common-blocks common-blocks  
         batch-files batch-files  
         fixme fixme  
         label label  
         goto goto  
         structtag structtag  
         structname structname  
         keyword-parameters keyword-parameters  
         system-variables system-variables  
         special-operators special-operators  
         all-operators all-operators  
         class-arrows class-arrows)  
1256    
1257    (setq idlwave-font-lock-keywords-1    (defconst idlwave-font-lock-keywords-1
1258          (list pros-and-functions      (list pros-and-functions batch-files)
1259                batch-files      "Subdued level highlighting for IDLWAVE mode.")
               ))  
1260    
1261    (setq idlwave-font-lock-keywords-2    (defconst idlwave-font-lock-keywords-2
1262          (mapcar 'symbol-value idlwave-default-font-lock-items))      (mapcar 'symbol-value idlwave-default-font-lock-items)
1263        "Medium level highlighting for IDLWAVE mode.")
1264    
1265    (setq idlwave-font-lock-keywords-3    (defconst idlwave-font-lock-keywords-3
1266          (list pros-and-functions          (list pros-and-functions
1267                batch-files                batch-files
1268                idl-keywords                idlwave-idl-keywords
1269                label goto                label goto
1270                structtag                structtag
1271                structname                structname
1272                common-blocks                common-blocks
1273                keyword-parameters                keyword-parameters
1274                system-variables                system-variables
1275                class-arrows            class-arrows)
1276                ))      "Gaudy level highlighting for IDLWAVE mode."))
   )  
1277    
1278  (defun idlwave-match-class-arrows (limit)  (defun idlwave-match-class-arrows (limit)
1279    ;; Match an object arrow with class property    ;; Match an object arrow with class property
# Line 1235  As a user, you should not set this to t. Line 1286  As a user, you should not set this to t.
1286    
1287  (defvar idlwave-font-lock-defaults  (defvar idlwave-font-lock-defaults
1288    '((idlwave-font-lock-keywords    '((idlwave-font-lock-keywords
1289       idlwave-font-lock-keywords-1       idlwave-font-lock-keywords-1
1290       idlwave-font-lock-keywords-2       idlwave-font-lock-keywords-2
1291       idlwave-font-lock-keywords-3)       idlwave-font-lock-keywords-3)
1292      nil t      nil t
1293      ((?$ . "w") (?_ . "w") (?. . "w"))      ((?$ . "w") (?_ . "w") (?. . "w"))
1294      beginning-of-line))      beginning-of-line))
1295    
1296  (put 'idlwave-mode 'font-lock-defaults  (put 'idlwave-mode 'font-lock-defaults
1297       idlwave-font-lock-defaults) ; XEmacs       idlwave-font-lock-defaults) ; XEmacs
1298    
1299  (defconst idlwave-comment-line-start-skip "^[ \t]*;"  (defconst idlwave-comment-line-start-skip "^[ \t]*;"
# Line 1250  As a user, you should not set this to t. Line 1301  As a user, you should not set this to t.
1301  That is the _beginning_ of a line containing a comment delimiter `;' preceded  That is the _beginning_ of a line containing a comment delimiter `;' preceded
1302  only by whitespace.")  only by whitespace.")
1303    
1304  (defconst idlwave-begin-block-reg  (defconst idlwave-begin-block-reg
1305    "\\<\\(pro\\|function\\|begin\\|case\\|switch\\)\\>"    "\\<\\(pro\\|function\\|begin\\|case\\|switch\\)\\>"
1306    "Regular expression to find the beginning of a block. The case does    "Regular expression to find the beginning of a block. The case does
1307  not matter. The search skips matches in comments.")  not matter. The search skips matches in comments.")
# Line 1325  blocks starting with a BEGIN statement. Line 1376  blocks starting with a BEGIN statement.
1376     '(switch . ("switch\\>" nil))     '(switch . ("switch\\>" nil))
1377     (cons 'call (list (concat idlwave-identifier "\\(\\s *$\\|\\s *,\\)") nil))     (cons 'call (list (concat idlwave-identifier "\\(\\s *$\\|\\s *,\\)") nil))
1378     '(assign . ("[^=>\n]*=" nil)))     '(assign . ("[^=>\n]*=" nil)))
1379      
1380    "Associated list of statement matching regular expressions.    "Associated list of statement matching regular expressions.
1381  Each regular expression matches the start of an IDL statement.  The  Each regular expression matches the start of an IDL statement.  The
1382  first element of each association is a symbol giving the statement  first element of each association is a symbol giving the statement
# Line 1348  the leftover unidentified statements con Line 1399  the leftover unidentified statements con
1399  ;; Note that this is documented in the v18 manuals as being a string  ;; Note that this is documented in the v18 manuals as being a string
1400  ;; of length one rather than a single character.  ;; of length one rather than a single character.
1401  ;; The code in this file accepts either format for compatibility.  ;; The code in this file accepts either format for compatibility.
1402  (defvar idlwave-comment-indent-char ?\  (defvar idlwave-comment-indent-char ?\
1403    "Character to be inserted for IDL comment indentation.    "Character to be inserted for IDL comment indentation.
1404  Normally a space.")  Normally a space.")
1405    
# Line 1356  Normally a space.") Line 1407  Normally a space.")
1407    "Character which is inserted as a last character on previous line by    "Character which is inserted as a last character on previous line by
1408     \\[idlwave-split-line] to begin a continuation line.  Normally $.")     \\[idlwave-split-line] to begin a continuation line.  Normally $.")
1409    
1410  (defconst idlwave-mode-version " 4.7")  (defconst idlwave-mode-version " 4.15")
1411    
1412  (defmacro idlwave-keyword-abbrev (&rest args)  (defmacro idlwave-keyword-abbrev (&rest args)
1413    "Creates a function for abbrev hooks to call `idlwave-check-abbrev' with args."    "Creates a function for abbrev hooks to call `idlwave-check-abbrev' with args."
1414    `(quote (lambda ()    `(quote (lambda ()
1415              ,(append '(idlwave-check-abbrev) args))))              ,(append '(idlwave-check-abbrev) args))))
1416    
1417  ;; If I take the time I can replace idlwave-keyword-abbrev with  ;; If I take the time I can replace idlwave-keyword-abbrev with
1418  ;; idlwave-code-abbrev and remove the quoted abbrev check from  ;; idlwave-code-abbrev and remove the quoted abbrev check from
# Line 1374  Normally a space.") Line 1425  Normally a space.")
1425  Specifically, if the abbrev is in a comment or string it is unexpanded.  Specifically, if the abbrev is in a comment or string it is unexpanded.
1426  Otherwise ARGS forms a list that is evaluated."  Otherwise ARGS forms a list that is evaluated."
1427    `(quote (lambda ()    `(quote (lambda ()
1428              ,(prin1-to-string args) ;; Puts the code in the doc string              ,(prin1-to-string args)  ;; Puts the code in the doc string
1429              (if (idlwave-quoted)              (if (idlwave-quoted)
1430                  (progn (unexpand-abbrev) nil)                  (progn (unexpand-abbrev) nil)
1431                  ,(append args)))))                ,(append args)))))
1432    
1433  (defvar idlwave-mode-map (make-sparse-keymap)  (defvar idlwave-mode-map (make-sparse-keymap)
1434    "Keymap used in IDL mode.")    "Keymap used in IDL mode.")
# Line 1413  Otherwise ARGS forms a list that is eval Line 1464  Otherwise ARGS forms a list that is eval
1464    
1465  (modify-syntax-entry ?$   "w"  idlwave-find-symbol-syntax-table)  (modify-syntax-entry ?$   "w"  idlwave-find-symbol-syntax-table)
1466  (modify-syntax-entry ?_   "w"  idlwave-find-symbol-syntax-table)  (modify-syntax-entry ?_   "w"  idlwave-find-symbol-syntax-table)
   
 (defmacro idlwave-with-special-syntax (&rest body)  
   "Execute BODY with a different systax table."  
   `(let ((saved-syntax (syntax-table)))  
      (unwind-protect  
          (progn  
            (set-syntax-table idlwave-find-symbol-syntax-table)  
            ,@body)  
        (set-syntax-table saved-syntax))))  
   
 (defvar idlwave-print-symbol-syntax-table  
   (copy-syntax-table idlwave-mode-syntax-table)  
   "Syntax table that treats symbol characters as word characters.")  
   
 (modify-syntax-entry ?$   "w"  idlwave-find-symbol-syntax-table)  
 (modify-syntax-entry ?_   "w"  idlwave-find-symbol-syntax-table)  
1467  (modify-syntax-entry ?!   "w"  idlwave-find-symbol-syntax-table)  (modify-syntax-entry ?!   "w"  idlwave-find-symbol-syntax-table)
1468  (modify-syntax-entry ?.   "w"  idlwave-find-symbol-syntax-table)  (modify-syntax-entry ?.   "w"  idlwave-find-symbol-syntax-table)
1469    
1470  (defmacro idlwave-with-special-syntax1 (&rest body)  (defmacro idlwave-with-special-syntax (&rest body)
1471    "Execute BODY with a different systax table."    "Execute BODY with a different syntax table."
1472    `(let ((saved-syntax (syntax-table)))    `(let ((saved-syntax (syntax-table)))
1473       (unwind-protect       (unwind-protect
1474           (progn           (progn
# Line 1441  Otherwise ARGS forms a list that is eval Line 1476  Otherwise ARGS forms a list that is eval
1476             ,@body)             ,@body)
1477         (set-syntax-table saved-syntax))))         (set-syntax-table saved-syntax))))
1478    
1479    ;(defmacro idlwave-with-special-syntax1 (&rest body)
1480    ;  "Execute BODY with a different syntax table."
1481    ;  `(let ((saved-syntax (syntax-table)))
1482    ;     (unwind-protect
1483    ;         (progn
1484    ;           (set-syntax-table idlwave-find-symbol-syntax-table)
1485    ;           ,@body)
1486    ;       (set-syntax-table saved-syntax))))
1487    
1488  (defun idlwave-action-and-binding (key cmd &optional select)  (defun idlwave-action-and-binding (key cmd &optional select)
1489    "KEY and CMD are made into a key binding and an indent action.    "KEY and CMD are made into a key binding and an indent action.
1490  KEY is a string - same as for the `define-key' function.  CMD is a  KEY is a string - same as for the `define-key' function.  CMD is a
# Line 1449  KEY in `idlwave-mode-map' by defining an Line 1493  KEY in `idlwave-mode-map' by defining an
1493  `self-insert-command' followed by CMD.  If KEY contains more than one  `self-insert-command' followed by CMD.  If KEY contains more than one
1494  character a binding will only be set if SELECT is 'both.  character a binding will only be set if SELECT is 'both.
1495    
1496  (KEY . CMD\ is also placed in the `idlwave-indent-expand-table',  \(KEY . CMD\) is also placed in the `idlwave-indent-expand-table',
1497  replacing any previous value for KEY.  If a binding is not set then it  replacing any previous value for KEY.  If a binding is not set then it
1498  will instead be placed in `idlwave-indent-action-table'.  will instead be placed in `idlwave-indent-action-table'.
1499    
# Line 1495  Capitalize system variables - action onl Line 1539  Capitalize system variables - action onl
1539  ;(define-key idlwave-mode-map "\C-c\C- " 'idlwave-hard-tab)  ;(define-key idlwave-mode-map "\C-c\C- " 'idlwave-hard-tab)
1540  (define-key idlwave-mode-map "'"        'idlwave-show-matching-quote)  (define-key idlwave-mode-map "'"        'idlwave-show-matching-quote)
1541  (define-key idlwave-mode-map "\""       'idlwave-show-matching-quote)  (define-key idlwave-mode-map "\""       'idlwave-show-matching-quote)
1542    (define-key idlwave-mode-map "\C-g"     'idlwave-keyboard-quit)
1543  (define-key idlwave-mode-map "\C-c;"    'idlwave-toggle-comment-region)  (define-key idlwave-mode-map "\C-c;"    'idlwave-toggle-comment-region)
1544  (define-key idlwave-mode-map "\C-\M-a"  'idlwave-beginning-of-subprogram)  (define-key idlwave-mode-map "\C-\M-a"  'idlwave-beginning-of-subprogram)
1545  (define-key idlwave-mode-map "\C-\M-e"  'idlwave-end-of-subprogram)  (define-key idlwave-mode-map "\C-\M-e"  'idlwave-end-of-subprogram)
# Line 1512  Capitalize system variables - action onl Line 1557  Capitalize system variables - action onl
1557  (define-key idlwave-mode-map "\C-c\C-n" 'idlwave-next-statement)  (define-key idlwave-mode-map "\C-c\C-n" 'idlwave-next-statement)
1558  ;; (define-key idlwave-mode-map "\r"       'idlwave-newline)  ;; (define-key idlwave-mode-map "\r"       'idlwave-newline)
1559  ;; (define-key idlwave-mode-map "\t"       'idlwave-indent-line)  ;; (define-key idlwave-mode-map "\t"       'idlwave-indent-line)
1560    (define-key idlwave-mode-map [(shift tab)] 'idlwave-indent-statement)
1561  (define-key idlwave-mode-map "\C-c\C-a" 'idlwave-auto-fill-mode)  (define-key idlwave-mode-map "\C-c\C-a" 'idlwave-auto-fill-mode)
1562  (define-key idlwave-mode-map "\M-q"     'idlwave-fill-paragraph)  (define-key idlwave-mode-map "\M-q"     'idlwave-fill-paragraph)
1563  (define-key idlwave-mode-map "\M-s"     'idlwave-edit-in-idlde)  (define-key idlwave-mode-map "\M-s"     'idlwave-edit-in-idlde)
# Line 1526  Capitalize system variables - action onl Line 1572  Capitalize system variables - action onl
1572           (not (equal idlwave-shell-debug-modifiers '())))           (not (equal idlwave-shell-debug-modifiers '())))
1573    ;; Bind the debug commands also with the special modifiers.    ;; Bind the debug commands also with the special modifiers.
1574    (let ((shift (memq 'shift idlwave-shell-debug-modifiers))    (let ((shift (memq 'shift idlwave-shell-debug-modifiers))
1575          (mods-noshift (delq 'shift          (mods-noshift (delq 'shift
1576                              (copy-sequence idlwave-shell-debug-modifiers))))                              (copy-sequence idlwave-shell-debug-modifiers))))
1577      (define-key idlwave-mode-map      (define-key idlwave-mode-map
1578        (vector (append mods-noshift (list (if shift ?C ?c))))        (vector (append mods-noshift (list (if shift ?C ?c))))
1579        'idlwave-shell-save-and-run)        'idlwave-shell-save-and-run)
1580      (define-key idlwave-mode-map      (define-key idlwave-mode-map
1581        (vector (append mods-noshift (list (if shift ?B ?b))))        (vector (append mods-noshift (list (if shift ?B ?b))))
1582        'idlwave-shell-break-here)))        'idlwave-shell-break-here)))
1583  (define-key idlwave-mode-map "\C-c\C-f" 'idlwave-for)  (define-key idlwave-mode-map "\C-c\C-f" 'idlwave-for)
# Line 1555  Capitalize system variables - action onl Line 1601  Capitalize system variables - action onl
1601  (define-key idlwave-mode-map "\C-c\C-v"   'idlwave-find-module)  (define-key idlwave-mode-map "\C-c\C-v"   'idlwave-find-module)
1602  (define-key idlwave-mode-map "\C-c?"      'idlwave-routine-info)  (define-key idlwave-mode-map "\C-c?"      'idlwave-routine-info)
1603  (define-key idlwave-mode-map "\M-?"       'idlwave-context-help)  (define-key idlwave-mode-map "\M-?"       'idlwave-context-help)
1604    (define-key idlwave-mode-map [(control meta ?\?)] 'idlwave-online-help)
1605  (define-key idlwave-mode-map [(meta tab)] 'idlwave-complete)  (define-key idlwave-mode-map [(meta tab)] 'idlwave-complete)
1606  (define-key idlwave-mode-map "\C-c\C-i"   'idlwave-update-routine-info)  (define-key idlwave-mode-map "\C-c\C-i"   'idlwave-update-routine-info)
1607  (define-key idlwave-mode-map "\C-c="      'idlwave-resolve)  (define-key idlwave-mode-map "\C-c="      'idlwave-resolve)
1608  (define-key idlwave-mode-map  (define-key idlwave-mode-map
1609    (if (featurep 'xemacs) [(shift button3)] [(shift mouse-3)])    (if (featurep 'xemacs) [(shift button3)] [(shift mouse-3)])
1610    'idlwave-mouse-context-help)    'idlwave-mouse-context-help)
1611    
# Line 1567  Capitalize system variables - action onl Line 1614  Capitalize system variables - action onl
1614  ;; Automatically add spaces for the following characters  ;; Automatically add spaces for the following characters
1615  (idlwave-action-and-binding "&"  '(idlwave-surround -1 -1))  (idlwave-action-and-binding "&"  '(idlwave-surround -1 -1))
1616  (idlwave-action-and-binding "<"  '(idlwave-surround -1 -1))  (idlwave-action-and-binding "<"  '(idlwave-surround -1 -1))
1617  (idlwave-action-and-binding ">"  '(idlwave-surround -1 -1 '(?-)))  ;; Binding works for both > and ->, by changing the length of the token.
1618  (idlwave-action-and-binding "->" '(idlwave-surround -1 -1 nil 2))  (idlwave-action-and-binding ">"  '(idlwave-surround -1 -1 '(?-) 1
1619                                                        'idlwave-gtr-pad-hook))
1620    (idlwave-action-and-binding "->" '(idlwave-surround -1 -1 nil 2) t)
1621  (idlwave-action-and-binding ","  '(idlwave-surround 0 -1))  (idlwave-action-and-binding ","  '(idlwave-surround 0 -1))
1622  ;; Automatically add spaces to equal sign if not keyword  ;; Automatically add spaces to equal sign if not keyword
1623  (idlwave-action-and-binding "="  '(idlwave-expand-equal -1 -1))  (idlwave-action-and-binding "="  '(idlwave-expand-equal -1 -1))
# Line 1580  Capitalize system variables - action onl Line 1629  Capitalize system variables - action onl
1629  ;;; space is inserted (this is the space typed by the user to expanded  ;;; space is inserted (this is the space typed by the user to expanded
1630  ;;; the abbrev).  ;;; the abbrev).
1631  ;;;  ;;;
1632    (defvar idlwave-mode-abbrev-table nil
1633      "Abbreviation table used for IDLWAVE mode")
1634    (define-abbrev-table 'idlwave-mode-abbrev-table ())
1635    
1636    (defun idlwave-define-abbrev (name expansion hook &optional noprefix table)
1637      "Define-abbrev with backward compatibility.
1638    
1639    If NOPREFIX is non-nil, don't prepend prefix character.  Installs into
1640    idlwave-mode-abbrev-table unless TABLE is non-nil."
1641      (let ((abbrevs-changed nil)  ;; mask the current value to avoid save
1642            (args (list (or table idlwave-mode-abbrev-table)
1643                        (if noprefix name (concat idlwave-abbrev-start-char name))
1644                        expansion
1645                        hook)))
1646        (condition-case nil
1647            (apply 'define-abbrev (append args '(0 t)))
1648          (error (apply 'define-abbrev args)))))
1649    
1650  (condition-case nil  (condition-case nil
1651      (modify-syntax-entry (string-to-char idlwave-abbrev-start-char)      (modify-syntax-entry (string-to-char idlwave-abbrev-start-char)
1652                           "w" idlwave-mode-syntax-table)                           "w" idlwave-mode-syntax-table)
1653    (error nil))    (error nil))
1654    
1655  (defvar idlwave-mode-abbrev-table nil  ;;
1656    "Abbreviation table used for IDLWAVE mode")  ;; Templates
1657  (define-abbrev-table 'idlwave-mode-abbrev-table ())  ;;
1658  (let ((abbrevs-changed nil)          ;; mask the current value to avoid save  (idlwave-define-abbrev "c"   "" (idlwave-code-abbrev idlwave-case))
1659        (tb idlwave-mode-abbrev-table)  (idlwave-define-abbrev "sw"  "" (idlwave-code-abbrev idlwave-switch))
1660        (c idlwave-abbrev-start-char))  (idlwave-define-abbrev "f"   "" (idlwave-code-abbrev idlwave-for))
1661    ;;  (idlwave-define-abbrev "fu"  "" (idlwave-code-abbrev idlwave-function))
1662    ;; Templates  (idlwave-define-abbrev "pr"  "" (idlwave-code-abbrev idlwave-procedure))
1663    ;;  (idlwave-define-abbrev "r"   "" (idlwave-code-abbrev idlwave-repeat))
1664    (define-abbrev tb (concat c "c")   "" (idlwave-code-abbrev idlwave-case) 0 t)  (idlwave-define-abbrev "w"   "" (idlwave-code-abbrev idlwave-while))
1665    (define-abbrev tb (concat c "sw")  "" (idlwave-code-abbrev idlwave-switch) 0 t)  (idlwave-define-abbrev "i"   "" (idlwave-code-abbrev idlwave-if))
1666    (define-abbrev tb (concat c "f")   "" (idlwave-code-abbrev idlwave-for) 0 t)  (idlwave-define-abbrev "elif" "" (idlwave-code-abbrev idlwave-elif))
1667    (define-abbrev tb (concat c "fu")  "" (idlwave-code-abbrev idlwave-function) 0 t)  ;;
1668    (define-abbrev tb (concat c "pr")  "" (idlwave-code-abbrev idlwave-procedure) 0 t)  ;; Keywords, system functions, conversion routines
1669    (define-abbrev tb (concat c "r")   "" (idlwave-code-abbrev idlwave-repeat) 0 t)  ;;
1670    (define-abbrev tb (concat c "w")   "" (idlwave-code-abbrev idlwave-while) 0 t)  (idlwave-define-abbrev "ap" "arg_present()" (idlwave-keyword-abbrev 1))
1671    (define-abbrev tb (concat c "i")   "" (idlwave-code-abbrev idlwave-if) 0 t)  (idlwave-define-abbrev "b"  "begin"        (idlwave-keyword-abbrev 0 t))
1672    (define-abbrev tb (concat c "elif") "" (idlwave-code-abbrev idlwave-elif) 0 t)  (idlwave-define-abbrev "co" "common"       (idlwave-keyword-abbrev 0 t))
1673    ;;  (idlwave-define-abbrev "cb" "byte()"       (idlwave-keyword-abbrev 1))
1674    ;; Keywords, system functions, conversion routines  (idlwave-define-abbrev "cx" "fix()"        (idlwave-keyword-abbrev 1))
1675    ;;  (idlwave-define-abbrev "cl" "long()"       (idlwave-keyword-abbrev 1))
1676    (define-abbrev tb (concat c "b")  "begin"        (idlwave-keyword-abbrev 0 t)  0 t)  (idlwave-define-abbrev "cf" "float()"      (idlwave-keyword-abbrev 1))
1677    (define-abbrev tb (concat c "co") "common"       (idlwave-keyword-abbrev 0 t) 0 t)  (idlwave-define-abbrev "cs" "string()"     (idlwave-keyword-abbrev 1))
1678    (define-abbrev tb (concat c "cb") "byte()"       (idlwave-keyword-abbrev 1) 0 t)  (idlwave-define-abbrev "cc" "complex()"    (idlwave-keyword-abbrev 1))
1679    (define-abbrev tb (concat c "cx") "fix()"        (idlwave-keyword-abbrev 1) 0 t)  (idlwave-define-abbrev "cd" "double()"     (idlwave-keyword-abbrev 1))
1680    (define-abbrev tb (concat c "cl") "long()"       (idlwave-keyword-abbrev 1) 0 t)  (idlwave-define-abbrev "e"  "else"         (idlwave-keyword-abbrev 0 t))
1681    (define-abbrev tb (concat c "cf") "float()"      (idlwave-keyword-abbrev 1) 0 t)  (idlwave-define-abbrev "ec" "endcase"      'idlwave-show-begin)
1682    (define-abbrev tb (concat c "cs") "string()"     (idlwave-keyword-abbrev 1) 0 t)  (idlwave-define-abbrev "es" "endswitch"    'idlwave-show-begin)
1683    (define-abbrev tb (concat c "cc") "complex()"    (idlwave-keyword-abbrev 1) 0 t)  (idlwave-define-abbrev "ee" "endelse"      'idlwave-show-begin)
1684    (define-abbrev tb (concat c "cd") "double()"     (idlwave-keyword-abbrev 1) 0 t)  (idlwave-define-abbrev "ef" "endfor"       'idlwave-show-begin)
1685    (define-abbrev tb (concat c "e")  "else"         (idlwave-keyword-abbrev 0 t) 0 t)  (idlwave-define-abbrev "ei" "endif else if" 'idlwave-show-begin)
1686    (define-abbrev tb (concat c "ec") "endcase"      'idlwave-show-begin  0 t)  (idlwave-define-abbrev "el" "endif else"   'idlwave-show-begin)
1687    (define-abbrev tb (concat c "es") "endswitch"    'idlwave-show-begin 0 t)  (idlwave-define-abbrev "en" "endif"        'idlwave-show-begin)
1688    (define-abbrev tb (concat c "ee") "endelse"      'idlwave-show-begin 0 t)  (idlwave-define-abbrev "er" "endrep"       'idlwave-show-begin)
1689    (define-abbrev tb (concat c "ef") "endfor"       'idlwave-show-begin 0 t)  (idlwave-define-abbrev "ew" "endwhile"     'idlwave-show-begin)
1690    (define-abbrev tb (concat c "ei") "endif else if" 'idlwave-show-begin 0 t)  (idlwave-define-abbrev "g"  "goto,"        (idlwave-keyword-abbrev 0 t))
1691    (define-abbrev tb (concat c "el") "endif else"   'idlwave-show-begin 0 t)  (idlwave-define-abbrev "h"  "help,"        (idlwave-keyword-abbrev 0))
1692    (define-abbrev tb (concat c "en") "endif"        'idlwave-show-begin 0 t)  (idlwave-define-abbrev "k"  "keyword_set()" (idlwave-keyword-abbrev 1))
1693    (define-abbrev tb (concat c "er") "endrep"       'idlwave-show-begin 0 t)  (idlwave-define-abbrev "n"  "n_elements()" (idlwave-keyword-abbrev 1))
1694    (define-abbrev tb (concat c "ew") "endwhile"     'idlwave-show-begin 0 t)  (idlwave-define-abbrev "on" "on_error,"    (idlwave-keyword-abbrev 0))
1695    (define-abbrev tb (concat c "g")  "goto,"        (idlwave-keyword-abbrev 0 t) 0 t)  (idlwave-define-abbrev "oi" "on_ioerror,"  (idlwave-keyword-abbrev 0 1))
1696    (define-abbrev tb (concat c "h")  "help,"        (idlwave-keyword-abbrev 0) 0 t)  (idlwave-define-abbrev "ow" "openw,"       (idlwave-keyword-abbrev 0))
1697    (define-abbrev tb (concat c "k")  "keyword_set()" (idlwave-keyword-abbrev 1) 0 t)  (idlwave-define-abbrev "or" "openr,"       (idlwave-keyword-abbrev 0))
1698    (define-abbrev tb (concat c "n")  "n_elements()" (idlwave-keyword-abbrev 1) 0 t)  (idlwave-define-abbrev "ou" "openu,"       (idlwave-keyword-abbrev 0))
1699    (define-abbrev tb (concat c "on") "on_error,"    (idlwave-keyword-abbrev 0) 0 t)  (idlwave-define-abbrev "p"  "print,"       (idlwave-keyword-abbrev 0))
1700    (define-abbrev tb (concat c "oi") "on_ioerror,"  (idlwave-keyword-abbrev 0 1) 0 t)  (idlwave-define-abbrev "pt" "plot,"        (idlwave-keyword-abbrev 0))
1701    (define-abbrev tb (concat c "ow") "openw,"       (idlwave-keyword-abbrev 0) 0 t)  (idlwave-define-abbrev "re" "read,"        (idlwave-keyword-abbrev 0))
1702    (define-abbrev tb (concat c "or") "openr,"       (idlwave-keyword-abbrev 0) 0 t)  (idlwave-define-abbrev "rf" "readf,"       (idlwave-keyword-abbrev 0))
1703    (define-abbrev tb (concat c "ou") "openu,"       (idlwave-keyword-abbrev 0) 0 t)  (idlwave-define-abbrev "ru" "readu,"       (idlwave-keyword-abbrev 0))
1704    (define-abbrev tb (concat c "p")  "print,"       (idlwave-keyword-abbrev 0) 0 t)  (idlwave-define-abbrev "rt" "return"       (idlwave-keyword-abbrev 0))
1705    (define-abbrev tb (concat c "pt") "plot,"        (idlwave-keyword-abbrev 0) 0 t)  (idlwave-define-abbrev "sc" "strcompress()" (idlwave-keyword-abbrev 1))
1706    (define-abbrev tb (concat c "re") "read,"        (idlwave-keyword-abbrev 0) 0 t)  (idlwave-define-abbrev "sn" "strlen()"     (idlwave-keyword-abbrev 1))
1707    (define-abbrev tb (concat c "rf") "readf,"       (idlwave-keyword-abbrev 0) 0 t)  (idlwave-define-abbrev "sl" "strlowcase()" (idlwave-keyword-abbrev 1))
1708    (define-abbrev tb (concat c "ru") "readu,"       (idlwave-keyword-abbrev 0) 0 t)  (idlwave-define-abbrev "su" "strupcase()"  (idlwave-keyword-abbrev 1))
1709    (define-abbrev tb (concat c "rt") "return"       (idlwave-keyword-abbrev 0) 0 t)  (idlwave-define-abbrev "sm" "strmid()"     (idlwave-keyword-abbrev 1))
1710    (define-abbrev tb (concat c "sc") "strcompress()" (idlwave-keyword-abbrev 1) 0 t)  (idlwave-define-abbrev "sp" "strpos()"     (idlwave-keyword-abbrev 1))
1711    (define-abbrev tb (concat c "sn") "strlen()"     (idlwave-keyword-abbrev 1) 0 t)  (idlwave-define-abbrev "st" "strput()"     (idlwave-keyword-abbrev 1))
1712    (define-abbrev tb (concat c "sl") "strlowcase()" (idlwave-keyword-abbrev 1) 0 t)  (idlwave-define-abbrev "sr" "strtrim()"    (idlwave-keyword-abbrev 1))
1713    (define-abbrev tb (concat c "su") "strupcase()"  (idlwave-keyword-abbrev 1) 0 t)  (idlwave-define-abbrev "t"  "then"         (idlwave-keyword-abbrev 0 t))
1714    (define-abbrev tb (concat c "sm") "strmid()"     (idlwave-keyword-abbrev 1) 0 t)  (idlwave-define-abbrev "u"  "until"        (idlwave-keyword-abbrev 0 t))
1715    (define-abbrev tb (concat c "sp") "strpos()"     (idlwave-keyword-abbrev 1) 0 t)  (idlwave-define-abbrev "wu" "writeu,"      (idlwave-keyword-abbrev 0))
1716    (define-abbrev tb (concat c "st") "strput()"     (idlwave-keyword-abbrev 1) 0 t)  (idlwave-define-abbrev "iap" "if arg_present() then"     (idlwave-keyword-abbrev 6))
1717    (define-abbrev tb (concat c "sr") "strtrim()"    (idlwave-keyword-abbrev 1) 0 t)  (idlwave-define-abbrev "ik" "if keyword_set() then" (idlwave-keyword-abbrev 6))
1718    (define-abbrev tb (concat c "t")  "then"         (idlwave-keyword-abbrev 0 t) 0 t)  (idlwave-define-abbrev "ine" "if n_elements() eq 0 then" (idlwave-keyword-abbrev 11))
1719    (define-abbrev tb (concat c "u")  "until"        (idlwave-keyword-abbrev 0 t) 0 t)  (idlwave-define-abbrev "inn" "if n_elements() ne 0 then" (idlwave-keyword-abbrev 11))
1720    (define-abbrev tb (concat c "wu") "writeu,"      (idlwave-keyword-abbrev 0) 0 t)  (idlwave-define-abbrev "np" "n_params()"   (idlwave-keyword-abbrev 0))
1721    (define-abbrev tb (concat c "ine") "if n_elements() eq 0 then"  (idlwave-define-abbrev "s"  "size()"       (idlwave-keyword-abbrev 1))
1722      (idlwave-keyword-abbrev 11) 0 t)  (idlwave-define-abbrev "wi" "widget_info()" (idlwave-keyword-abbrev 1))
1723    (define-abbrev tb (concat c "inn") "if n_elements() ne 0 then"  (idlwave-define-abbrev "wc" "widget_control," (idlwave-keyword-abbrev 0))
1724      (idlwave-keyword-abbrev 11) 0 t)  
1725    (define-abbrev tb (concat c "np") "n_params()"   (idlwave-keyword-abbrev 0) 0 t)  ;; This section is reserved words only. (From IDL user manual)
1726    (define-abbrev tb (concat c "s")  "size()"       (idlwave-keyword-abbrev 1) 0 t)  ;;
1727    (define-abbrev tb (concat c "wi") "widget_info()" (idlwave-keyword-abbrev 1) 0 t)  (idlwave-define-abbrev "and"        "and"       (idlwave-keyword-abbrev 0 t) t)
1728    (define-abbrev tb (concat c "wc") "widget_control," (idlwave-keyword-abbrev 0) 0 t)  (idlwave-define-abbrev "begin"      "begin"     (idlwave-keyword-abbrev 0 t) t)
1729      (idlwave-define-abbrev "break"      "break"     (idlwave-keyword-abbrev 0 t) t)
1730    ;; This section is reserved words only. (From IDL user manual)  (idlwave-define-abbrev "case"       "case"      (idlwave-keyword-abbrev 0 t) t)
1731    ;;  (idlwave-define-abbrev "common"     "common"    (idlwave-keyword-abbrev 0 t) t)
1732    (define-abbrev tb "and"        "and"        (idlwave-keyword-abbrev 0 t) 0 t)  (idlwave-define-abbrev "continue"   "continue"  (idlwave-keyword-abbrev 0 t) t)
1733    (define-abbrev tb "begin"      "begin"      (idlwave-keyword-abbrev 0 t) 0 t)  (idlwave-define-abbrev "do"         "do"        (idlwave-keyword-abbrev 0 t) t)
1734    (define-abbrev tb "break"      "break"      (idlwave-keyword-abbrev 0 t) 0 t)  (idlwave-define-abbrev "else"       "else"      (idlwave-keyword-abbrev 0 t) t)
1735    (define-abbrev tb "case"       "case"       (idlwave-keyword-abbrev 0 t) 0 t)  (idlwave-define-abbrev "end"        "end"       'idlwave-show-begin-check t)
1736    (define-abbrev tb "common"     "common"     (idlwave-keyword-abbrev 0 t) 0 t)  (idlwave-define-abbrev "endcase"    "endcase"   'idlwave-show-begin-check t)
1737    (define-abbrev tb "continue"   "continue"   (idlwave-keyword-abbrev 0 t) 0 t)  (idlwave-define-abbrev "endelse"    "endelse"   'idlwave-show-begin-check t)
1738    (define-abbrev tb "do"         "do"         (idlwave-keyword-abbrev 0 t) 0 t)  (idlwave-define-abbrev "endfor"     "endfor"    'idlwave-show-begin-check t)
1739    (define-abbrev tb "else"       "else"       (idlwave-keyword-abbrev 0 t) 0 t)  (idlwave-define-abbrev "endif"      "endif"     'idlwave-show-begin-check t)
1740    (define-abbrev tb "end"        "end"        'idlwave-show-begin-check 0 t)  (idlwave-define-abbrev "endrep"     "endrep"    'idlwave-show-begin-check t)
1741    (define-abbrev tb "endcase"    "endcase"    'idlwave-show-begin-check 0 t)  (idlwave-define-abbrev "endswitch"  "endswitch" 'idlwave-show-begin-check t)
1742    (define-abbrev tb "endelse"    "endelse"    'idlwave-show-begin-check 0 t)  (idlwave-define-abbrev "endwhi"     "endwhi"    'idlwave-show-begin-check t)
1743    (define-abbrev tb "endfor"     "endfor"     'idlwave-show-begin-check 0 t)  (idlwave-define-abbrev "endwhile"   "endwhile"  'idlwave-show-begin-check t)
1744    (define-abbrev tb "endif"      "endif"      'idlwave-show-begin-check 0 t)  (idlwave-define-abbrev "eq"         "eq"        (idlwave-keyword-abbrev 0 t) t)
1745    (define-abbrev tb "endrep"     "endrep"     'idlwave-show-begin-check 0 t)  (idlwave-define-abbrev "for"        "for"       (idlwave-keyword-abbrev 0 t) t)
1746    (define-abbrev tb "endswitch"  "endswitch"  'idlwave-show-begin-check 0 t)  (idlwave-define-abbrev "function"   "function"  (idlwave-keyword-abbrev 0 t) t)
1747    (define-abbrev tb "endwhi"     "endwhi"     'idlwave-show-begin-check 0 t)  (idlwave-define-abbrev "ge"         "ge"        (idlwave-keyword-abbrev 0 t) t)
1748    (define-abbrev tb "endwhile"   "endwhile"   'idlwave-show-begin-check 0 t)  (idlwave-define-abbrev "goto"       "goto"      (idlwave-keyword-abbrev 0 t) t)
1749    (define-abbrev tb "eq"         "eq"         (idlwave-keyword-abbrev 0 t) 0 t)  (idlwave-define-abbrev "gt"         "gt"        (idlwave-keyword-abbrev 0 t) t)
1750    (define-abbrev tb "for"        "for"        (idlwave-keyword-abbrev 0 t) 0 t)  (idlwave-define-abbrev "if"         "if"        (idlwave-keyword-abbrev 0 t) t)
1751    (define-abbrev tb "function"   "function"   (idlwave-keyword-abbrev 0 t) 0 t)  (idlwave-define-abbrev "le"         "le"        (idlwave-keyword-abbrev 0 t) t)
1752    (define-abbrev tb "ge"         "ge"         (idlwave-keyword-abbrev 0 t) 0 t)  (idlwave-define-abbrev "lt"         "lt"        (idlwave-keyword-abbrev 0 t) t)
1753    (define-abbrev tb "goto"       "goto"       (idlwave-keyword-abbrev 0 t) 0 t)  (idlwave-define-abbrev "mod"        "mod"       (idlwave-keyword-abbrev 0 t) t)
1754    (define-abbrev tb "gt"         "gt"         (idlwave-keyword-abbrev 0 t) 0 t)  (idlwave-define-abbrev "ne"         "ne"        (idlwave-keyword-abbrev 0 t) t)
1755    (define-abbrev tb "if"         "if"         (idlwave-keyword-abbrev 0 t) 0 t)  (idlwave-define-abbrev "not"        "not"       (idlwave-keyword-abbrev 0 t) t)
1756    (define-abbrev tb "le"         "le"         (idlwave-keyword-abbrev 0 t) 0 t)  (idlwave-define-abbrev "of"         "of"        (idlwave-keyword-abbrev 0 t) t)
1757    (define-abbrev tb "lt"         "lt"         (idlwave-keyword-abbrev 0 t) 0 t)  (idlwave-define-abbrev "on_ioerror" "on_ioerror" (idlwave-keyword-abbrev 0 t) t)
1758    (define-abbrev tb "mod"        "mod"        (idlwave-keyword-abbrev 0 t) 0 t)  (idlwave-define-abbrev "or"         "or"        (idlwave-keyword-abbrev 0 t) t)
1759    (define-abbrev tb "ne"         "ne"         (idlwave-keyword-abbrev 0 t) 0 t)  (idlwave-define-abbrev "pro"        "pro"       (idlwave-keyword-abbrev 0 t) t)
1760    (define-abbrev tb "not"        "not"        (idlwave-keyword-abbrev 0 t 0 t))  (idlwave-define-abbrev "repeat"     "repeat"    (idlwave-keyword-abbrev 0 t) t)
1761    (define-abbrev tb "of"         "of"         (idlwave-keyword-abbrev 0 t) 0 t)  (idlwave-define-abbrev "switch"     "switch"    (idlwave-keyword-abbrev 0 t) t)
1762    (define-abbrev tb "on_ioerror" "on_ioerror" (idlwave-keyword-abbrev 0 t) 0 t)  (idlwave-define-abbrev "then"       "then"      (idlwave-keyword-abbrev 0 t) t)
1763    (define-abbrev tb "or"         "or"         (idlwave-keyword-abbrev 0 t) 0 t)  (idlwave-define-abbrev "until"      "until"     (idlwave-keyword-abbrev 0 t) t)
1764    (define-abbrev tb "pro"        "pro"        (idlwave-keyword-abbrev 0 t) 0 t)  (idlwave-define-abbrev "while"      "while"     (idlwave-keyword-abbrev 0 t) t)
1765    (define-abbrev tb "repeat"     "repeat"     (idlwave-keyword-abbrev 0 t) 0 t)  (idlwave-define-abbrev "xor"        "xor"       (idlwave-keyword-abbrev 0 t) t)
   (define-abbrev tb "switch"     "switch"     (idlwave-keyword-abbrev 0 t 0 t))  
   (define-abbrev tb "then"       "then"       (idlwave-keyword-abbrev 0 t) 0 t)  
   (define-abbrev tb "until"      "until"      (idlwave-keyword-abbrev 0 t) 0 t)  
   (define-abbrev tb "while"      "while"      (idlwave-keyword-abbrev 0 t) 0 t)  
   (define-abbrev tb "xor"        "xor"        (idlwave-keyword-abbrev 0 t) 0 t))  
1766    
1767  (defvar imenu-create-index-function)  (defvar imenu-create-index-function)
1768  (defvar extract-index-name-function)  (defvar extract-index-name-function)
1769  (defvar prev-index-position-function)  (defvar prev-index-position-function)
1770  (defvar imenu-extract-index-name-function)  (defvar imenu-extract-index-name-function)
1771  (defvar imenu-prev-index-position-function)  (defvar imenu-prev-index-position-function)
1772  ;; defined later - so just make the compiler shut up  ;; defined later - so just make the compiler hush
1773  (defvar idlwave-mode-menu)    (defvar idlwave-mode-menu)
1774  (defvar idlwave-mode-debug-menu)  (defvar idlwave-mode-debug-menu)
1775    
1776  ;;;###autoload  ;;;###autoload
# Line 1723  The main features of this mode are Line 1784  The main features of this mode are
1784     Like other Emacs programming modes, C-j inserts a newline and indents.     Like other Emacs programming modes, C-j inserts a newline and indents.
1785     TAB is used for explicit indentation of the current line.     TAB is used for explicit indentation of the current line.
1786    
1787     To start a continuation line, use \\[idlwave-split-line].  This function can also     To start a continuation line, use \\[idlwave-split-line].  This
1788     be used in the middle of a line to split the line at that point.     function can also be used in the middle of a line to split the line
1789     When used inside a long constant string, the string is split at     at that point.  When used inside a long constant string, the string
1790     that point with the `+' concatenation operator.     is split at that point with the `+' concatenation operator.
1791    
1792     Comments are indented as follows:     Comments are indented as follows:
1793    
# Line 1736  The main features of this mode are Line 1797  The main features of this mode are
1797    
1798     The indentation of comments starting in column 0 is never changed.     The indentation of comments starting in column 0 is never changed.
1799    
1800     Use \\[idlwave-fill-paragraph] to refill a paragraph inside a comment.  The indentation     Use \\[idlwave-fill-paragraph] to refill a paragraph inside a
1801     of the second line of the paragraph relative to the first will be     comment.  The indentation of the second line of the paragraph
1802     retained.  Use \\[idlwave-auto-fill-mode] to toggle auto-fill mode for these comments.     relative to the first will be retained.  Use
1803     When the variable `idlwave-fill-comment-line-only' is nil, code     \\[idlwave-auto-fill-mode] to toggle auto-fill mode for these
1804     can also be auto-filled and auto-indented (not recommended).     comments.  When the variable `idlwave-fill-comment-line-only' is
1805       nil, code can also be auto-filled and auto-indented (not
1806       recommended).
1807    
1808     To convert pre-existing IDL code to your formatting style, mark the     To convert pre-existing IDL code to your formatting style, mark the
1809     entire buffer with \\[mark-whole-buffer] and execute \\[idlwave-expand-region-abbrevs].     entire buffer with \\[mark-whole-buffer] and execute
1810     Then mark the entire buffer again followed by \\[indent-region] (`indent-region').     \\[idlwave-expand-region-abbrevs].  Then mark the entire buffer
1811       again followed by \\[indent-region] (`indent-region').
1812    
1813  2. Routine Info  2. Routine Info
1814     ------------     ------------
1815     IDLWAVE displays information about the calling sequence and the accepted     IDLWAVE displays information about the calling sequence and the
1816     keyword parameters of a procedure or function with \\[idlwave-routine-info].     accepted keyword parameters of a procedure or function with
1817     \\[idlwave-find-module] jumps to the source file of a module.     \\[idlwave-routine-info].  \\[idlwave-find-module] jumps to the
1818     These commands know about system routines, all routines in idlwave-mode     source file of a module.  These commands know about system
1819     buffers and (when the idlwave-shell is active) about all modules     routines, all routines in idlwave-mode buffers and (when the
1820     currently compiled under this shell.  Use \\[idlwave-update-routine-info] to update this     idlwave-shell is active) about all modules currently compiled under
1821       this shell.  Use \\[idlwave-update-routine-info] to update this
1822     information, which is also used for completion (see item 4).     information, which is also used for completion (see item 4).
1823    
1824  3. Online IDL Help  3. Online IDL Help
# Line 1787  The main features of this mode are Line 1852  The main features of this mode are
1852     \\i         IF statement template     \\i         IF statement template
1853     \\elif      IF-ELSE statement template     \\elif      IF-ELSE statement template
1854     \\b         BEGIN     \\b         BEGIN
1855      
1856     For a full list, use \\[idlwave-list-abbrevs].  Some templates also have     For a full list, use \\[idlwave-list-abbrevs].  Some templates also have
1857     direct keybindings - see the list of keybindings below.     direct keybindings - see the list of keybindings below.
1858    
# Line 1812  The main features of this mode are Line 1877  The main features of this mode are
1877    
1878  9. Documentation and Customization  9. Documentation and Customization
1879     -------------------------------     -------------------------------
1880     Info documentation for this package is available.  Use \\[idlwave-info]     Info documentation for this package is available.  Use
1881     to display (complain to your sysadmin if that does not work).     \\[idlwave-info] to display (complain to your sysadmin if that does
1882     For Postscript and HTML versions of the documentation, check IDLWAVE's     not work).  For Postscript, PDF, and HTML versions of the
1883     homepage at `http://www.strw.leidenuniv.nl/~dominik/Tools/idlwave'.     documentation, check IDLWAVE's homepage at `http://idlwave.org'.
1884     IDLWAVE has customize support - see the group `idlwave'.     IDLWAVE has customize support - see the group `idlwave'.
1885    
1886  10.Keybindings  10.Keybindings
# Line 1828  The main features of this mode are Line 1893  The main features of this mode are
1893    
1894    (interactive)    (interactive)
1895    (kill-all-local-variables)    (kill-all-local-variables)
1896      
1897    (if idlwave-startup-message    (if idlwave-startup-message
1898        (message "Emacs IDLWAVE mode version %s." idlwave-mode-version))        (message "Emacs IDLWAVE mode version %s." idlwave-mode-version))
1899    (setq idlwave-startup-message nil)    (setq idlwave-startup-message nil)
1900      
1901    (setq local-abbrev-table idlwave-mode-abbrev-table)    (setq local-abbrev-table idlwave-mode-abbrev-table)
1902    (set-syntax-table idlwave-mode-syntax-table)    (set-syntax-table idlwave-mode-syntax-table)
1903      
1904    (set (make-local-variable 'indent-line-function) 'idlwave-indent-and-action)    (set (make-local-variable 'indent-line-function) 'idlwave-indent-and-action)
1905      
1906    (make-local-variable idlwave-comment-indent-function)    (make-local-variable idlwave-comment-indent-function)
1907    (set idlwave-comment-indent-function 'idlwave-comment-hook)    (set idlwave-comment-indent-function 'idlwave-comment-hook)
1908      
1909    (set (make-local-variable 'comment-start-skip) ";+[ \t]*")    (set (make-local-variable 'comment-start-skip) ";+[ \t]*")
1910    (set (make-local-variable 'comment-start) ";")    (set (make-local-variable 'comment-start) ";")
1911    (set (make-local-variable 'require-final-newline) t)    (set (make-local-variable 'require-final-newline) t)
1912    (set (make-local-variable 'abbrev-all-caps) t)    (set (make-local-variable 'abbrev-all-caps) t)
1913    (set (make-local-variable 'indent-tabs-mode) nil)    (set (make-local-variable 'indent-tabs-mode) nil)
1914    (set (make-local-variable 'completion-ignore-case) t)    (set (make-local-variable 'completion-ignore-case) t)
1915      
1916    (use-local-map idlwave-mode-map)    (use-local-map idlwave-mode-map)
1917    
1918    (when (featurep 'easymenu)    (when (featurep 'easymenu)
# Line 1857  The main features of this mode are Line 1922  The main features of this mode are
1922    (setq mode-name "IDLWAVE")    (setq mode-name "IDLWAVE")
1923    (setq major-mode 'idlwave-mode)    (setq major-mode 'idlwave-mode)
1924    (setq abbrev-mode t)    (setq abbrev-mode t)
1925      
1926    (set (make-local-variable idlwave-fill-function) 'idlwave-auto-fill)    (set (make-local-variable idlwave-fill-function) 'idlwave-auto-fill)
1927    (setq comment-end "")    (setq comment-end "")
1928    (set (make-local-variable 'comment-multi-line) nil)    (set (make-local-variable 'comment-multi-line) nil)
1929    (set (make-local-variable 'paragraph-separate) "[ \t\f]*$\\|[ \t]*;+[ \t]*$")    (set (make-local-variable 'paragraph-separate)
1930           "[ \t\f]*$\\|[ \t]*;+[ \t]*$\\|;+[+=-_*]+$")
1931    (set (make-local-variable 'paragraph-start) "[ \t\f]\\|[ \t]*;+[ \t]")    (set (make-local-variable 'paragraph-start) "[ \t\f]\\|[ \t]*;+[ \t]")
1932    (set (make-local-variable 'paragraph-ignore-fill-prefix) nil)    (set (make-local-variable 'paragraph-ignore-fill-prefix) nil)
1933    (set (make-local-variable 'parse-sexp-ignore-comments) nil)    (set (make-local-variable 'parse-sexp-ignore-comments) t)
1934      
1935    ;; Set tag table list to use IDLTAGS as file name.    ;; Set tag table list to use IDLTAGS as file name.
1936    (if (boundp 'tag-table-alist)    (if (boundp 'tag-table-alist)
1937        (add-to-list 'tag-table-alist '("\\.pro$" . "IDLTAGS")))        (add-to-list 'tag-table-alist '("\\.pro$" . "IDLTAGS")))
1938      
1939    ;; Font-lock additions - originally Phil Williams, then Ulrik Dickow    ;; Font-lock additions - originally Phil Williams, then Ulrik Dickow
1940    ;; Following line is for Emacs - XEmacs uses the corresponding porperty    ;; Following line is for Emacs - XEmacs uses the corresponding porperty
1941    ;; on the `idlwave-mode' symbol.    ;; on the `idlwave-mode' symbol.
# Line 1884  The main features of this mode are Line 1950  The main features of this mode are
1950         'idlwave-prev-index-position)         'idlwave-prev-index-position)
1951    
1952    ;; Make a local post-command-hook and add our hook to it    ;; Make a local post-command-hook and add our hook to it
1953      ;; NB: `make-local-hook' needed for older/alternative Emacs compatibility
1954      (make-local-hook 'post-command-hook)
1955    (add-hook 'post-command-hook 'idlwave-command-hook nil 'local)    (add-hook 'post-command-hook 'idlwave-command-hook nil 'local)
1956    
1957    ;; Make local hooks for buffer updates    ;; Make local hooks for buffer updates
1958      ;; NB: `make-local-hook' needed for older/alternative Emacs compatibility
1959      (make-local-hook 'kill-buffer-hook)
1960    (add-hook 'kill-buffer-hook 'idlwave-kill-buffer-update nil 'local)    (add-hook 'kill-buffer-hook 'idlwave-kill-buffer-update nil 'local)
1961      (make-local-hook 'after-save-hook)
1962    (add-hook 'after-save-hook 'idlwave-save-buffer-update nil 'local)    (add-hook 'after-save-hook 'idlwave-save-buffer-update nil 'local)
1963    (add-hook 'after-save-hook 'idlwave-revoke-license-to-kill nil 'local)    (add-hook 'after-save-hook 'idlwave-revoke-license-to-kill nil 'local)
1964    
# Line 1988  Returns point if comment found and nil o Line 2059  Returns point if comment found and nil o
2059             (backward-char 1)             (backward-char 1)
2060             (point)))))             (point)))))
2061    
2062    (defvar transient-mark-mode)
2063    (defvar zmacs-regions)
2064    (defvar mark-active)
2065    (defun idlwave-region-active-p ()
2066      "Is transien-mark-mode on and the region active?
2067    Works on both Emacs and XEmacs."
2068      (if (featurep 'xemacs)
2069          (and zmacs-regions (region-active-p))
2070        (and transient-mark-mode mark-active)))
2071    
2072  (defun idlwave-show-matching-quote ()  (defun idlwave-show-matching-quote ()
2073    "Insert quote and show matching quote if this is end of a string."    "Insert quote and show matching quote if this is end of a string."
2074    (interactive)    (interactive)
# Line 2006  Returns point if comment found and nil o Line 2087  Returns point if comment found and nil o
2087  (defun idlwave-show-begin-check ()  (defun idlwave-show-begin-check ()
2088    "Ensure that the previous word was a token before `idlwave-show-begin'.    "Ensure that the previous word was a token before `idlwave-show-begin'.
2089  An END token must be preceded by whitespace."  An END token must be preceded by whitespace."
2090    (if    (if (not (idlwave-quoted))
2091        (save-excursion        (if
2092          (backward-word 1)            (save-excursion
2093          (backward-char 1)              (backward-word 1)
2094          (looking-at "[ \t\n\f]"))              (backward-char 1)
2095        (idlwave-show-begin)))              (looking-at "[ \t\n\f]"))
2096              (idlwave-show-begin))))
2097    
2098  (defun idlwave-show-begin ()  (defun idlwave-show-begin ()
2099    "Finds the start of current block and blinks to it for a second.    "Finds the start of current block and blinks to it for a second.
2100  Also checks if the correct end statement has been used."  Also checks if the correct end statement has been used."
   ;; Re-indent end line  
   (if idlwave-reindent-end  
       (idlwave-indent-line))  
2101    ;; All end statements are reserved words    ;; All end statements are reserved words
2102    (let* ((pos (point))    ;; Re-indent end line
2103           end end1)    (insert-char ?\  1) ;; So indent, etc. work well
2104      (backward-char 1)
2105      (let* ((pos (point-marker))
2106             (last-abbrev-marker (copy-marker last-abbrev-location))
2107             (eol-pos (save-excursion (end-of-line) (point)))
2108             begin-pos end-pos end end1 )
2109        (if idlwave-reindent-end  (idlwave-indent-line))
2110    
2111      (when (and (idlwave-check-abbrev 0 t)      (when (and (idlwave-check-abbrev 0 t)
2112                 idlwave-show-block)                 idlwave-show-block)
2113        (save-excursion        (save-excursion
2114          ;; Move inside current block          ;; Move inside current block
2115          (setq end (buffer-substring          (goto-char last-abbrev-marker)
                    (save-excursion (skip-chars-backward "a-zA-Z")  
                                    (point))  
                    (point)))  
         (idlwave-beginning-of-statement)  
2116          (idlwave-block-jump-out -1 'nomark)          (idlwave-block-jump-out -1 'nomark)
2117            (setq begin-pos (point))
2118            (idlwave-block-jump-out 1 'nomark)
2119            (setq end-pos (point))
2120            (if (> end-pos eol-pos)
2121                (setq end-pos pos))
2122            (goto-char end-pos)
2123            (setq end (buffer-substring
2124                       (progn
2125                         (skip-chars-backward "a-zA-Z")
2126                         (point))
2127                       end-pos))
2128            (goto-char begin-pos)
2129          (when (setq end1 (cdr (idlwave-block-master)))          (when (setq end1 (cdr (idlwave-block-master)))
2130            (cond            (cond
2131             ((null end1)) ; no-opeartion             ((null end1)) ; no-operation
2132             ((string= (downcase end) (downcase end1))             ((string= (downcase end) (downcase end1))
2133              (sit-for 1))              (sit-for 1))
2134             ((string= (downcase end) "end")             ((string= (downcase end) "end")
# Line 2048  Also checks if the correct end statement Line 2142  Also checks if the correct end statement
2142              (sit-for 1))              (sit-for 1))
2143             (t             (t
2144              (beep)              (beep)
2145              (message "Warning: Shouldn't this be \"%s\" instead of \"%s\"?"              (message "Warning: Shouldn't this be \"%s\" instead of \"%s\"?"
2146                       end1 end)                       end1 end)
2147              (sit-for 1))))))))              (sit-for 1)))))))
2148      (delete-char 1))
2149    
2150  (defun idlwave-block-master ()  (defun idlwave-block-master ()
2151    (let ((case-fold-search t))    (let ((case-fold-search t))
# Line 2059  Also checks if the correct end statement Line 2154  Also checks if the correct end statement
2154         ((looking-at "pro\\|case\\|switch\\|function\\>")         ((looking-at "pro\\|case\\|switch\\|function\\>")
2155          (assoc (downcase (match-string 0)) idlwave-block-matches))          (assoc (downcase (match-string 0)) idlwave-block-matches))
2156         ((looking-at "begin\\>")         ((looking-at "begin\\>")
2157          (let ((limit (save-excursion          (let ((limit (save-excursion
2158                         (idlwave-beginning-of-statement)                         (idlwave-beginning-of-statement)
2159                         (point))))                         (point))))
2160            (cond            (cond
2161             ((re-search-backward idlwave-block-match-regexp limit t)             ((re-search-backward idlwave-block-match-regexp limit t)
# Line 2084  Also checks if the correct end statement Line 2179  Also checks if the correct end statement
2179              (bolp))              (bolp))
2180      (let ((idlwave-show-block nil))      (let ((idlwave-show-block nil))
2181        (newline-and-indent)))        (newline-and-indent)))
2182    (insert "end")    (let ((last-abbrev-location (point)))  ; for upcasing
2183    (idlwave-show-begin))      (insert "end")
2184        (idlwave-show-begin)))
2185    
2186    (defun idlwave-gtr-pad-hook (char)
2187      "Let the > symbol expand around -> if present.  The new token length
2188    is returned."
2189      2)
2190    
2191  (defun idlwave-surround (&optional before after escape-chars length)  (defun idlwave-surround (&optional before after escape-chars length ec-hook)
2192    "Surround the LENGTH characters before point with blanks.    "Surround the LENGTH characters before point with blanks.
2193  LENGTH defaults to 1.  LENGTH defaults to 1.
2194  Optional arguments BEFORE and AFTER affect the behavior before and  Optional arguments BEFORE and AFTER affect the behavior before and
# Line 2103  The function does nothing if any of the Line 2204  The function does nothing if any of the
2204  - the character before point is inside a string or comment  - the character before point is inside a string or comment
2205  - the char preceeding the string to be surrounded is a member of ESCAPE-CHARS.  - the char preceeding the string to be surrounded is a member of ESCAPE-CHARS.
2206    This hack is used to avoid padding of `>' when it is part of    This hack is used to avoid padding of `>' when it is part of
2207    the '->' operator.  In this case, ESCAPE-CHARS would be '(?-)."    the '->' operator.  In this case, ESCAPE-CHARS would be '(?-).
   
   (setq length (or length 1))   ; establish a default for LENGTH  
2208    
2209    (when (and idlwave-surround-by-blank  If a function is passed in EC-HOOK, and an ESCAPE-CHARS match occurs,
2210               (not (idlwave-quoted))  the named function will be called with a single argument of the
2211               (not (memq (char-after (- (point) (1+ length))) escape-chars)))  preceeding character.  Then idlwave-surround will run as usual if
2212      (backward-char length)  EC-HOOK returns non-nil, and a new length will be taken from the
2213      (save-restriction  return value."
2214        (let ((here (point)))    (when (and idlwave-surround-by-blank (not (idlwave-quoted)))
2215          (skip-chars-backward " \t")      (let* ((length (or length 1)) ; establish a default for LENGTH
2216          (if (bolp)             (prev-char (char-after (- (point) (1+ length)))))
2217              ;; avoid clobbering indent        (when (or (not (memq prev-char escape-chars))
2218              (progn                  (and (fboundp ec-hook)
2219                (move-to-column (idlwave-calculate-indent))                       (setq length
2220                (if (<= (point) here)                             (save-excursion (funcall ec-hook prev-char)))))
2221                    (narrow-to-region (point) here))          (backward-char length)
2222                (goto-char here)))          (save-restriction
2223          (idlwave-make-space before))            (let ((here (point)))
2224        (skip-chars-forward " \t"))              (skip-chars-backward " \t")
2225      (forward-char length)              (if (bolp)
2226      (idlwave-make-space after)                  ;; avoid clobbering indent
2227      ;; Check to see if the line should auto wrap                  (progn
2228      (if (and (equal (char-after (1- (point))) ?\ )                    (move-to-column (idlwave-calculate-indent))
2229               (> (current-column) fill-column))                    (if (<= (point) here)
2230          (funcall auto-fill-function))))                        (narrow-to-region (point) here))
2231                      (goto-char here)))
2232                (idlwave-make-space before))
2233              (skip-chars-forward " \t"))
2234            (forward-char length)
2235            (idlwave-make-space after)
2236            ;; Check to see if the line should auto wrap
2237            (if (and (equal (char-after (1- (point))) ?\ )
2238                     (> (current-column) fill-column))
2239                (funcall auto-fill-function))))))
2240    
2241  (defun idlwave-make-space (n)  (defun idlwave-make-space (n)
2242    "Make space at point.    "Make space at point.
# Line 2226  non-nil." Line 2334  non-nil."
2334                    ;; Split the string.                    ;; Split the string.
2335                    (progn (insert (setq beg (char-after beg)) " + "                    (progn (insert (setq beg (char-after beg)) " + "
2336                                   idlwave-continuation-char beg)                                   idlwave-continuation-char beg)
2337                           (backward-char 1))                           (backward-char 1)
2338                             (newline-and-indent)
2339                             (forward-char 1))
2340                  ;; Do not split the string.                  ;; Do not split the string.
2341                  (beep)                  (beep)
2342                  (message "Warning: continuation inside string!!")                  (message "Warning: continuation inside string!!")
# Line 2234  non-nil." Line 2344  non-nil."
2344              ;; Not splitting a string.              ;; Not splitting a string.
2345              (if (not (member (char-before) '(?\  ?\t)))              (if (not (member (char-before) '(?\  ?\t)))
2346                  (insert " "))                  (insert " "))
2347              (insert idlwave-continuation-char))              (insert idlwave-continuation-char)
2348            (newline-and-indent))              (newline-and-indent)))
2349        (indent-new-comment-line))        (indent-new-comment-line))
2350      ;; Indent previous line      ;; Indent previous line
2351      (setq beg (- (point-max) (point)))      (setq beg (- (point-max) (point)))
# Line 2328  Returns non-nil if successfull." Line 2438  Returns non-nil if successfull."
2438          (let ((eos (save-excursion          (let ((eos (save-excursion
2439                       (idlwave-block-jump-out -1 'nomark)                       (idlwave-block-jump-out -1 'nomark)
2440                       (point))))                       (point))))
2441            (if (setq status (idlwave-find-key            (if (setq status (idlwave-find-key
2442                              idlwave-end-block-reg -1 'nomark eos))                              idlwave-end-block-reg -1 'nomark eos))
2443                (idlwave-beginning-of-statement)                (idlwave-beginning-of-statement)
2444              (message "No nested block before beginning of containing block.")))              (message "No nested block before beginning of containing block.")))
# Line 2336  Returns non-nil if successfull." Line 2446  Returns non-nil if successfull."
2446        (let ((eos (save-excursion        (let ((eos (save-excursion
2447                     (idlwave-block-jump-out 1 'nomark)                     (idlwave-block-jump-out 1 'nomark)
2448                     (point))))                     (point))))
2449          (if (setq status (idlwave-find-key          (if (setq status (idlwave-find-key
2450                            idlwave-begin-block-reg 1 'nomark eos))                            idlwave-begin-block-reg 1 'nomark eos))
2451              (idlwave-end-of-statement)              (idlwave-end-of-statement)
2452            (message "No nested block before end of containing block."))))            (message "No nested block before end of containing block."))))
# Line 2350  The marks are pushed." Line 2460  The marks are pushed."
2460          (here (point)))          (here (point)))
2461      (goto-char (point-max))      (goto-char (point-max))
2462      (if (re-search-backward idlwave-doclib-start nil t)      (if (re-search-backward idlwave-doclib-start nil t)
2463          (progn          (progn
2464            (setq beg (progn (beginning-of-line) (point)))            (setq beg (progn (beginning-of-line) (point)))
2465            (if (re-search-forward idlwave-doclib-end nil t)            (if (re-search-forward idlwave-doclib-end nil t)
2466                (progn                (progn
# Line 2384  actual statement." Line 2494  actual statement."
2494     ((eq major-mode 'idlwave-shell-mode)     ((eq major-mode 'idlwave-shell-mode)
2495      (if (re-search-backward idlwave-shell-prompt-pattern nil t)      (if (re-search-backward idlwave-shell-prompt-pattern nil t)
2496          (goto-char (match-end 0))))          (goto-char (match-end 0))))
2497     (t       (t
2498      (if (save-excursion (forward-line -1) (idlwave-is-continuation-line))      (if (save-excursion (forward-line -1) (idlwave-is-continuation-line))
2499          (idlwave-previous-statement)          (idlwave-previous-statement)
2500        (beginning-of-line)))))        (beginning-of-line)))))
# Line 2456  If not in a statement just moves to end Line 2566  If not in a statement just moves to end
2566                         (looking-at "^@")))))                         (looking-at "^@")))))
2567      last-statement))      last-statement))
2568    
2569    (defun idlwave-skip-multi-commands (&optional lim)
2570      "Skip past multiple commands on a line (with `&')."
2571      (let ((save-point (point)))
2572        (when (re-search-forward ".*&" lim t)
2573          (goto-char (match-end 0))
2574          (if (idlwave-in-quote) (goto-char save-point)))
2575        (point)))
2576    
2577  (defun idlwave-skip-label-or-case ()  (defun idlwave-skip-label-or-case ()
2578    "Skip label or case statement element.    "Skip label or case statement element.
2579  Returns position after label.  Returns position after label.
# Line 2466  If there is no label point is not moved Line 2584  If there is no label point is not moved
2584    ;; - it is not in a comment    ;; - it is not in a comment
2585    ;; - not in a string constant    ;; - not in a string constant
2586    ;; - not in parenthesis (like a[0:3])    ;; - not in parenthesis (like a[0:3])
2587      ;; - not followed by another ":" in explicit class, ala a->b::c
2588    ;; As many in this mode, this function is heuristic and not an exact    ;; As many in this mode, this function is heuristic and not an exact
2589    ;; parser.    ;; parser.
2590    (let ((start (point))    (let* ((start (point))
2591          (end (idlwave-find-key ":" 1 'nomark           (eos (save-excursion (idlwave-end-of-statement) (point)))
2592                                 (save-excursion           (end (idlwave-find-key ":" 1 'nomark eos)))
                                  (idlwave-end-of-statement) (point)))))  
2593      (if (and end      (if (and end
2594               (= (nth 0 (parse-partial-sexp start end)) 0)               (= (nth 0 (parse-partial-sexp start end)) 0)
2595               (not (string-match "\\?" (buffer-substring start end))))               (not (string-match "\\?" (buffer-substring start end)))
2596                 (not (string-match "^::" (buffer-substring end eos))))
2597          (progn          (progn
2598            (forward-char)            (forward-char)
2599            (point))            (point))
# Line 2494  substatement." Line 2613  substatement."
2613          st nst last)          st nst last)
2614      (idlwave-beginning-of-statement)      (idlwave-beginning-of-statement)
2615      (idlwave-skip-label-or-case)      (idlwave-skip-label-or-case)
2616        (idlwave-skip-multi-commands orig)
2617      (setq last (point))      (setq last (point))
2618      ;; Continue looking for substatements until we are past orig      ;; Continue looking for substatements until we are past orig
2619      (while (and (<= (point) orig) (not (eobp)))      (while (and (<= (point) orig) (not (eobp)))
# Line 2523  list not just the type symbol. Returns n Line 2643  list not just the type symbol. Returns n
2643  statement."  statement."
2644    (save-excursion    (save-excursion
2645      ;; Skip whitespace within a statement which is spaces, tabs, continuations      ;; Skip whitespace within a statement which is spaces, tabs, continuations
2646      (while (looking-at "[ \t]*\\<\\$")      ;; and possibly comments
2647        (while (looking-at "[ \t]*\\$")
2648        (forward-line 1))        (forward-line 1))
2649      (skip-chars-forward " \t")      (skip-chars-forward " \t")
2650      (let ((st idlwave-statement-match)      (let ((st idlwave-statement-match)
# Line 2559  See `idlwave-surround'. " Line 2680  See `idlwave-surround'. "
2680                ((null idlwave-pad-keyword)                ((null idlwave-pad-keyword)
2681                 ;; Spaces should be removed at a keyword                 ;; Spaces should be removed at a keyword
2682                 (idlwave-surround 0 0))                 (idlwave-surround 0 0))
2683                (t)))))                          (t)))))
2684    
2685  (defun idlwave-indent-and-action ()  (defun idlwave-indent-and-action (&optional arg)
2686    "Call `idlwave-indent-line' and do expand actions."    "Call `idlwave-indent-line' and do expand actions.
2687    (interactive)  With prefix ARG non-nil, indent the entire sub-statement."
2688      (interactive "p")
2689    (save-excursion    (save-excursion
2690      (if (and idlwave-expand-generic-end      (if (and idlwave-expand-generic-end
2691               (re-search-backward "\\<\\(end\\)\\s-*\\="               (re-search-backward "\\<\\(end\\)\\s-*\\="
2692                                   (max 0 (- (point) 10)) t)                                   (max 0 (- (point) 10)) t)
2693               (looking-at "\\(end\\)\\([ \n\t]\\|\\'\\)"))               (looking-at "\\(end\\)\\([ \n\t]\\|\\'\\)"))
2694          (progn (goto-char (match-end 1))          (progn (goto-char (match-end 1))
2695                 (idlwave-show-begin))))                 ;;Expand the END abbreviation, just as RET or Space would have.
2696    (idlwave-indent-line t)                 (if abbrev-mode (expand-abbrev)
2697    )                   (idlwave-show-begin)))))
2698      (if arg
2699          (idlwave-indent-statement)
2700        (idlwave-indent-line t)))
2701    
2702  (defun idlwave-indent-line (&optional expand)  (defun idlwave-indent-line (&optional expand)
2703    "Indents current IDL line as code or as a comment.    "Indents current IDL line as code or as a comment.
# Line 2620  If the optional argument EXPAND is non-n Line 2745  If the optional argument EXPAND is non-n
2745            ;; indent the line            ;; indent the line
2746            (idlwave-indent-left-margin (idlwave-calculate-indent)))            (idlwave-indent-left-margin (idlwave-calculate-indent)))
2747          ;; Adjust parallel comment          ;; Adjust parallel comment
2748          (end-of-line)          (end-of-line)
2749          (if (idlwave-in-comment)          (if (idlwave-in-comment)
2750              (indent-for-comment))))              ;; Emacs 21 is too smart with fill-column on comment indent
2751                (let ((fill-column (if (fboundp 'comment-indent-new-line)
2752                                       (1- (frame-width))
2753                                     fill-column)))
2754                  (indent-for-comment)))))
2755      (goto-char mloc)      (goto-char mloc)
2756      ;; Get rid of marker      ;; Get rid of marker
2757      (set-marker mloc nil)      (set-marker mloc nil)))
     ))  
2758    
2759  (defun idlwave-do-action (action)  (defun idlwave-do-action (action)
2760    "Perform an action repeatedly on a line.    "Perform an action repeatedly on a line.
# Line 2670  Inserts spaces before markers at point." Line 2798  Inserts spaces before markers at point."
2798        (indent-region beg (point) nil))        (indent-region beg (point) nil))
2799      (message "Indenting subprogram...done.")))      (message "Indenting subprogram...done.")))
2800    
2801    (defun idlwave-indent-statement ()
2802      "Indent current statement, including all continuation lines."
2803      (interactive)
2804      (save-excursion
2805        (idlwave-beginning-of-statement)
2806        (let ((beg (point)))
2807          (idlwave-end-of-statement)
2808          (indent-region beg (point) nil))))
2809    
2810  (defun idlwave-calculate-indent ()  (defun idlwave-calculate-indent ()
2811    "Return appropriate indentation for current line as IDL code."    "Return appropriate indentation for current line as IDL code."
2812    (save-excursion    (save-excursion
# Line 2688  Inserts spaces before markers at point." Line 2825  Inserts spaces before markers at point."
2825       (t (let ((the-indent       (t (let ((the-indent
2826                 ;; calculate indent based on previous statement                 ;; calculate indent based on previous statement
2827                 (save-excursion                 (save-excursion
2828                   (cond                   (cond
2829                    ((idlwave-previous-statement)                    ((idlwave-previous-statement)
2830                     0)                     0)
2831                    ;; Main block                    ;; Main block
# Line 2707  Inserts spaces before markers at point." Line 2844  Inserts spaces before markers at point."
2844            ;; adjust the indentation based on the current statement            ;; adjust the indentation based on the current statement
2845            (cond            (cond
2846             ;; End block             ;; End block
2847             ((idlwave-look-at idlwave-end-block-reg t)             ((idlwave-look-at idlwave-end-block-reg)
2848              (+ the-indent idlwave-end-offset))              (+ the-indent idlwave-end-offset))
2849             (the-indent)))))))             (the-indent)))))))
2850    
2851  ;;  ;;
2852  ;; Parenthesses balacing/indent  ;; Parentheses balacing/indent
2853  ;;  ;;
2854    
2855    (defun idlwave-calculate-paren-indent (beg-reg end-reg close-exp)
2856      "Calculate the continuation indent inside a paren group.
2857    Returns a cons-cell with (open . indent), where open is the
2858    location of the open paren"
2859      (let ((open (nth 1 (parse-partial-sexp beg-reg end-reg))))
2860        ;; Found an innermost open paren.
2861        (when open
2862          (goto-char open)
2863          ;; Line up with next word unless this is a closing paren.
2864          (cons open
2865                (cond
2866                 ;; This is a closed paren - line up under open paren.
2867                 (close-exp
2868                  (current-column))
2869                 ;; Empty (or just comment) - just line up next to paren
2870                 ((progn
2871                    ;; Skip paren
2872                    (forward-char 1)
2873                    (looking-at "[ \t$]*\\(;.*\\)?$"))
2874                  (current-column))
2875                 ;; Line up with first word after blank space
2876                 ((progn
2877                    (skip-chars-forward " \t")
2878                    (current-column))))))))
2879    
2880  (defun idlwave-calculate-cont-indent ()  (defun idlwave-calculate-cont-indent ()
2881    "Calculates the IDL continuation indent column from the previous statement.    "Calculates the IDL continuation indent column from the previous statement.
2882  Note that here previous statement means the beginning of the current  Note that here previous statement means the beginning of the current
2883  statement if this statement is a continuation of the previous line.  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."  
2884    (save-excursion    (save-excursion
2885      (let* (open      (let* (open
2886             (case-fold-search t)             (case-fold-search t)
2887             (end-reg (progn (beginning-of-line) (point)))             (end-reg (progn (beginning-of-line) (point)))
2888             (close-exp (progn (skip-chars-forward " \t") (looking-at "\\s)")))             (close-exp (progn (skip-chars-forward " \t") (looking-at "\\s)")))
2889             (beg-reg (progn (idlwave-previous-statement) (point))))  ;           (beg-reg (progn (idlwave-previous-statement) (point)))
2890        ;;             (beg-reg (progn ;; Use substatement indent unless it's this line
2891        ;; If PRO or FUNCTION declaration indent after name, and first comma.                        (idlwave-start-of-substatement 'pre)
2892        ;;                        (if (eq (line-beginning-position) end-reg)
2893        (if (idlwave-look-at "\\<\\(pro\\|function\\)\\>")                            (idlwave-previous-statement))
2894            (progn                        (point)))
2895              (forward-sexp 1)             (cur-indent (idlwave-current-indent))
2896              (if (looking-at "[ \t]*,[ \t]*")             (else-cont (and (goto-char end-reg) (looking-at "[ \t]*else")))
2897                  (goto-char (match-end 0)))             (basic-indent           ;; The basic, non-fancy indent
2898              (current-column))              (+ cur-indent idlwave-continuation-indent))
2899          ;;             (fancy-nonparen-indent  ;; A smarter indent for routine/assignments
2900          ;; Not a PRO or FUNCTION              ;; Try without parens first:
2901          ;;              (progn
2902          ;; Look for innermost unmatched open paren                (goto-char beg-reg)
2903          ;;                (while (idlwave-look-at "&"))  ; skip over continued statements
2904          (if (setq open (car (cdr (parse-partial-sexp beg-reg end-reg))))                (cond
2905              ;; Found innermost open paren.                 ;; A continued Procedure call or definition
2906              (progn                 ((progn
2907                (goto-char open)                    (idlwave-look-at "^[ \t]*\\(pro\\|function\\)") ;skip over
2908                ;; Line up with next word unless this is a closing paren.                    (looking-at "[ \t]*\\([a-zA-Z0-9$_]+[ \t]*->[ \t]*\\)?[a-zA-Z][:a-zA-Z0-9$_]*[ \t]*\\(,\\)[ \t]*"))
2909                (cond                  (goto-char (match-end 0))
2910                 ;; This is a closed paren - line up under open paren.                  ;; Comment only, or blank line with "$"?  Align with ,
2911                 (close-exp                  (if (save-match-data (looking-at "[ \t$]*\\(;.*\\)?$"))
2912                  (current-column))                      (goto-char (match-end 2)))
2913                 ;; Empty - just add regular indent. Take into account                  (current-column))
2914                 ;; the forward-char  
2915                 ((progn                 ;; Continued assignment (with =),
2916                    ;; Skip paren                 ((looking-at "[ \t]*[][().a-zA-Z0-9$_]+[ \t]*\\(=\\)[ \t]*")
2917                    (forward-char 1)                  (goto-char (match-end 0))
2918                    (looking-at "[ \t$]*$"))                  ;; Comment only?  Align with =
2919                  (+ (current-column) idlwave-continuation-indent -1))                  (if (save-match-data (looking-at "[ \t$]*\\(;.*\\)?$"))
2920                 ;; Line up with first word                      (progn
2921                 ((progn                        (goto-char (match-end 1))
2922                    (skip-chars-forward " \t")                        (if idlwave-surround-by-blank
2923                    (current-column)))))                            (1+ (current-column))
2924            ;; No unmatched open paren. Just a simple continuation.                          (current-column)))
2925            (goto-char beg-reg)                    (current-column))))))
2926            (+ (idlwave-current-indent)             (fancy-nonparen-indent-allowed
2927               ;; Make adjustments based on current line              (and fancy-nonparen-indent
2928               (cond                   (< (- fancy-nonparen-indent basic-indent)
2929                ;; Else statement                      idlwave-max-extra-continuation-indent)))
2930                ((progn             (fancy-paren-indent-cons     ;; A smarter indent for paren groups
2931                   (goto-char end-reg)              ;; Look for any enclosing parens
2932                   (skip-chars-forward " \t")              (idlwave-calculate-paren-indent beg-reg end-reg close-exp))
2933                   (looking-at "else"))             (fancy-paren-open (car fancy-paren-indent-cons))
2934                 0)             (fancy-paren-indent (cdr fancy-paren-indent-cons))
2935                ;; Ordinary continuation             (fancy-paren-indent-allowed
2936                (idlwave-continuation-indent))))))))              (and fancy-paren-indent
2937                     (or idlwave-indent-to-open-paren ;; override
2938                         (< (- fancy-paren-indent basic-indent)
2939                            idlwave-max-extra-continuation-indent))))
2940                fancy-enclosing-paren-indent)
2941          (cond
2942           ;; else continuations are always standard
2943           (else-cont
2944            cur-indent)
2945    
2946           ;; an allowed parenthesis-indent
2947           (fancy-paren-indent-allowed
2948            fancy-paren-indent)
2949    
2950           ;; a disallowed paren indent nested inside one or more other
2951           ;; parens: indent relative to the first allowed enclosing paren
2952           ;; set, if any... if it's actually a greater indent, just use
2953           ;; the fancy-paren-indent anyway.
2954           ((and fancy-paren-indent
2955                 (not fancy-paren-indent-allowed)
2956                 (setq fancy-enclosing-paren-indent
2957                       (let ((enclose-open fancy-paren-open)
2958                             enclose-indent-cons
2959                             enclose-indent)
2960                         (catch 'loop
2961                           (while (setq enclose-indent-cons
2962                                        (idlwave-calculate-paren-indent
2963                                         beg-reg (max (1- enclose-open) beg-reg)
2964                                         nil)
2965                                        enclose-open   (car enclose-indent-cons)
2966                                        enclose-indent (cdr enclose-indent-cons))
2967                             (if (< (- enclose-indent basic-indent)
2968                                    idlwave-max-extra-continuation-indent)
2969                                 (throw 'loop enclose-indent)))))))
2970            (min fancy-paren-indent
2971                 (+ fancy-enclosing-paren-indent idlwave-continuation-indent)))
2972    
2973           ;; a disallowed paren indent inside another type: indent relative
2974           ((and fancy-paren-indent
2975                 (not fancy-paren-indent-allowed)
2976                 fancy-nonparen-indent-allowed )
2977            (+ fancy-nonparen-indent idlwave-continuation-indent))
2978    
2979           ;; an allowed nonparen-only indent
2980           (fancy-nonparen-indent-allowed
2981            fancy-nonparen-indent)
2982    
2983           ;; everything else
2984           (t
2985            basic-indent)))))
2986    
2987  (defun idlwave-find-key (key-re &optional dir nomark limit)  (defun idlwave-find-key (key-re &optional dir nomark limit)
2988    "Move to next match of the regular expression KEY-RE.    "Move to next match of the regular expression KEY-RE.
# Line 2814  possibility of unbalanced blocks." Line 3023  possibility of unbalanced blocks."
3023    (let* ((here (point))    (let* ((here (point))
3024           (case-fold-search t)           (case-fold-search t)
3025           (limit (if (>= dir 0) (point-max) (point-min)))           (limit (if (>= dir 0) (point-max) (point-min)))
3026           (block-limit (if (>= dir 0)           (block-limit (if (>= dir 0)
3027                            idlwave-begin-block-reg                            idlwave-begin-block-reg
3028                          idlwave-end-block-reg))                          idlwave-end-block-reg))
3029           found           found
# Line 2825  possibility of unbalanced blocks." Line 3034  possibility of unbalanced blocks."
3034                                 (idlwave-find-key                                 (idlwave-find-key
3035                                  idlwave-begin-unit-reg dir t limit)                                  idlwave-begin-unit-reg dir t limit)
3036                               (end-of-line)                               (end-of-line)
3037                               (idlwave-find-key                               (idlwave-find-key
3038                                idlwave-end-unit-reg dir t limit)))                                idlwave-end-unit-reg dir t limit)))
3039                           limit)))                           limit)))
3040      (if (>= dir 0) (end-of-line)) ;Make sure we are in current block      (if (>= dir 0) (end-of-line)) ;Make sure we are in current block
# Line 2855  Skips any whitespace. Returns 0 if the e Line 3064  Skips any whitespace. Returns 0 if the e
3064            ((current-column)))))            ((current-column)))))
3065    
3066  (defun idlwave-is-continuation-line ()  (defun idlwave-is-continuation-line ()
3067    "Tests if current line is continuation line."    "Tests if current line is continuation line.
3068    Blank or comment-only lines following regular continuation lines (with
3069    `$') count as continuations too."
3070    (save-excursion    (save-excursion
3071      (idlwave-look-at "\\<\\$")))      (or
3072         (idlwave-look-at "\\<\\$")
3073         (catch 'loop
3074           (while (and (looking-at "^[ \t]*\\(;.*\\)?$")
3075                       (eq (forward-line -1) 0))
3076             (if (idlwave-look-at "\\<\\$") (throw 'loop t)))))))
3077    
3078  (defun idlwave-is-comment-line ()  (defun idlwave-is-comment-line ()
3079    "Tests if the current line is a comment line."    "Tests if the current line is a comment line."
# Line 2953  ignored." Line 3169  ignored."
3169                                            (beginning-of-line) (point))                                            (beginning-of-line) (point))
3170                                          (point))))                                          (point))))
3171                 "[^;]"))                 "[^;]"))
3172            
3173          ;; Mark the beginning and end of the paragraph          ;; Mark the beginning and end of the paragraph
3174          (goto-char bcl)          (goto-char bcl)
3175          (while (and (looking-at fill-prefix-reg)          (while (and (looking-at fill-prefix-reg)
# Line 3017  ignored." Line 3233  ignored."
3233                        (insert (make-string diff ?\ ))))                        (insert (make-string diff ?\ ))))
3234                  (forward-line -1))                  (forward-line -1))
3235                )                )
3236              
3237            ;; No hang. Instead find minimum indentation of paragraph            ;; No hang. Instead find minimum indentation of paragraph
3238            ;; after first line.            ;; after first line.
3239            ;; For the following while statement, since START is at the            ;; For the following while statement, since START is at the
# Line 3049  ignored." Line 3265  ignored."
3265                    t)                    t)
3266                   (current-column))                   (current-column))
3267                 indent))                 indent))
3268            
3269          ;; try to keep point at its original place          ;; try to keep point at its original place
3270          (goto-char here)          (goto-char here)
3271    
# Line 3215  is non-nil." Line 3431  is non-nil."
3431    (interactive "P")    (interactive "P")
3432    (or nomark (push-mark))    (or nomark (push-mark))
3433    ;; make sure we catch the current line if it begins the unit    ;; make sure we catch the current line if it begins the unit
3434    (end-of-line)    (if idlwave-header-to-beginning-of-file
3435    (idlwave-beginning-of-subprogram)        (goto-char (point-min))
3436    (beginning-of-line)      (end-of-line)
3437    ;; skip function or procedure line      (idlwave-beginning-of-subprogram)
3438    (if (idlwave-look-at "\\<\\(pro\\|function\\)\\>")      (beginning-of-line)
3439        (progn      ;; skip function or procedure line
3440          (idlwave-end-of-statement)      (if (idlwave-look-at "\\<\\(pro\\|function\\)\\>")
3441          (if (> (forward-line 1) 0) (insert "\n"))))          (progn
3442    (if idlwave-file-header            (idlwave-end-of-statement)
3443        (cond ((car idlwave-file-header)            (if (> (forward-line 1) 0) (insert "\n")))))
3444               (insert-file (car idlwave-file-header)))    (let ((pos (point)))
3445              ((stringp (car (cdr idlwave-file-header)))      (if idlwave-file-header
3446               (insert (car (cdr idlwave-file-header)))))))          (cond ((car idlwave-file-header)
3447                   (insert-file (car idlwave-file-header)))
3448                  ((stringp (car (cdr idlwave-file-header)))
3449                   (insert (car (cdr idlwave-file-header))))))
3450        (goto-char pos)))
3451    
3452  (defun idlwave-default-insert-timestamp ()  (defun idlwave-default-insert-timestamp ()
3453    "Default timestamp insertion function"    "Default timestamp insertion function"
3454    (insert (current-time-string))    (insert (current-time-string))
3455    (insert ", " (user-full-name))    (insert ", " (user-full-name))
3456    (insert " <" (user-login-name) "@" (system-name) ">")    (if (boundp 'user-mail-address)
3457          (insert " <" user-mail-address ">")
3458        (insert " <" (user-login-name) "@" (system-name) ">"))
3459    ;; Remove extra spaces from line    ;; Remove extra spaces from line
3460    (idlwave-fill-paragraph)    (idlwave-fill-paragraph)
3461    ;; Insert a blank line comment to separate from the date entry -    ;; Insert a blank line comment to separate from the date entry -
3462    ;; will keep the entry from flowing onto date line if re-filled.    ;; will keep the entry from flowing onto date line if re-filled.
3463    (insert "\n;\n;\t\t"))t    (insert "\n;\n;\t\t"))
3464    
3465  (defun idlwave-doc-modification ()  (defun idlwave-doc-modification ()
3466    "Insert a brief modification log at the beginning of the current program.    "Insert a brief modification log at the beginning of the current program.
# Line 3259  location on mark ring so that the user c Line 3480  location on mark ring so that the user c
3480               (setq end (match-end 0)))               (setq end (match-end 0)))
3481          (progn          (progn
3482            (goto-char beg)            (goto-char beg)
3483            (if (re-search-forward            (if (re-search-forward
3484                 (concat idlwave-doc-modifications-keyword ":")                 (concat idlwave-doc-modifications-keyword ":")
3485                 end t)                 end t)
3486                (end-of-line)                (end-of-line)
# Line 3349  constants - a double quote followed by a Line 3570  constants - a double quote followed by a
3570        ;; return string beginning position or nil        ;; return string beginning position or nil
3571        (if (> start bq) bq))))        (if (> start bq) bq))))
3572    
3573    (defun idlwave-is-pointer-dereference (&optional limit)
3574      "Determines if the character after point is a pointer dereference *."
3575      (let ((pos (point)))
3576        (and
3577         (eq (char-after) ?\*)
3578         (not (idlwave-in-quote))
3579         (save-excursion
3580           (forward-char)
3581           (re-search-backward (concat "\\(" idlwave-idl-keywords
3582                                       "\\|[[(*+-/=,^><]\\)\\s-*\\*") limit t)))))
3583    
3584    
3585  ;; Statement templates  ;; Statement templates
3586    
3587  ;; Replace these with a general template function, something like  ;; Replace these with a general template function, something like
# Line 3391  unless the optional second argument NOIN Line 3624  unless the optional second argument NOIN
3624            (indent-region beg end nil))            (indent-region beg end nil))
3625        (if (stringp prompt)        (if (stringp prompt)
3626            (message prompt)))))            (message prompt)))))
3627      
3628  (defun idlwave-rw-case (string)  (defun idlwave-rw-case (string)
3629    "Make STRING have the case required by `idlwave-reserved-word-upcase'."    "Make STRING have the case required by `idlwave-reserved-word-upcase'."
3630    (if idlwave-reserved-word-upcase    (if idlwave-reserved-word-upcase
# Line 3409  unless the optional second argument NOIN Line 3642  unless the optional second argument NOIN
3642  (defun idlwave-case ()  (defun idlwave-case ()
3643    "Build skeleton IDL case statement."    "Build skeleton IDL case statement."
3644    (interactive)    (interactive)
3645    (idlwave-template    (idlwave-template
3646     (idlwave-rw-case "case")     (idlwave-rw-case "case")
3647     (idlwave-rw-case " of\n\nendcase")     (idlwave-rw-case " of\n\nendcase")
3648     "Selector expression"))     "Selector expression"))
# Line 3417  unless the optional second argument NOIN Line 3650  unless the optional second argument NOIN
3650  (defun idlwave-switch ()  (defun idlwave-switch ()
3651    "Build skeleton IDL switch statement."    "Build skeleton IDL switch statement."
3652    (interactive)    (interactive)
3653    (idlwave-template    (idlwave-template
3654     (idlwave-rw-case "switch")     (idlwave-rw-case "switch")
3655     (idlwave-rw-case " of\n\nendswitch")     (idlwave-rw-case " of\n\nendswitch")
3656     "Selector expression"))     "Selector expression"))
# Line 3425  unless the optional second argument NOIN Line 3658  unless the optional second argument NOIN
3658  (defun idlwave-for ()  (defun idlwave-for ()
3659    "Build skeleton for loop statment."    "Build skeleton for loop statment."
3660    (interactive)    (interactive)
3661    (idlwave-template    (idlwave-template
3662     (idlwave-rw-case "for")     (idlwave-rw-case "for")
3663     (idlwave-rw-case " do begin\n\nendfor")     (idlwave-rw-case " do begin\n\nendfor")
3664     "Loop expression"))     "Loop expression"))
# Line 3440  unless the optional second argument NOIN Line 3673  unless the optional second argument NOIN
3673    
3674  (defun idlwave-procedure ()  (defun idlwave-procedure ()
3675    (interactive)    (interactive)
3676    (idlwave-template    (idlwave-template
3677     (idlwave-rw-case "pro")     (idlwave-rw-case "pro")
3678     (idlwave-rw-case "\n\nreturn\nend")     (idlwave-rw-case "\n\nreturn\nend")
3679     "Procedure name"))     "Procedure name"))
3680    
3681  (defun idlwave-function ()  (defun idlwave-function ()
3682    (interactive)    (interactive)
3683    (idlwave-template    (idlwave-template
3684     (idlwave-rw-case "function")     (idlwave-rw-case "function")
3685     (idlwave-rw-case "\n\nreturn\nend")     (idlwave-rw-case "\n\nreturn\nend")
3686     "Function name"))     "Function name"))
# Line 3461  unless the optional second argument NOIN Line 3694  unless the optional second argument NOIN
3694    
3695  (defun idlwave-while ()  (defun idlwave-while ()
3696    (interactive)    (interactive)
3697    (idlwave-template    (idlwave-template
3698     (idlwave-rw-case "while")     (idlwave-rw-case "while")
3699     (idlwave-rw-case " do begin\n\nendwhile")     (idlwave-rw-case " do begin\n\nendwhile")
3700     "Entry condition"))     "Entry condition"))
# Line 3540  Buffer containing unsaved changes requir Line 3773  Buffer containing unsaved changes requir
3773  (defun idlwave-count-outlawed-buffers (tag)  (defun idlwave-count-outlawed-buffers (tag)
3774    "How many outlawed buffers have tag TAG?"    "How many outlawed buffers have tag TAG?"
3775    (length (delq nil    (length (delq nil
3776                  (mapcar                  (mapcar
3777                   (lambda (x) (eq (cdr x) tag))                   (lambda (x) (eq (cdr x) tag))
3778                   idlwave-outlawed-buffers))))                   idlwave-outlawed-buffers))))
3779    
3780  (defun idlwave-do-kill-autoloaded-buffers (&rest reasons)  (defun idlwave-do-kill-autoloaded-buffers (&rest reasons)
# Line 3555  Buffer containing unsaved changes requir Line 3788  Buffer containing unsaved changes requir
3788                     (memq (cdr entry) reasons))                     (memq (cdr entry) reasons))
3789                 (kill-buffer (car entry))                 (kill-buffer (car entry))
3790                 (incf cnt)                 (incf cnt)
3791                 (setq idlwave-outlawed-buffers                 (setq idlwave-outlawed-buffers
3792                       (delq entry idlwave-outlawed-buffers)))                       (delq entry idlwave-outlawed-buffers)))
3793          (setq idlwave-outlawed-buffers          (setq idlwave-outlawed-buffers
3794                (delq entry idlwave-outlawed-buffers))))                (delq entry idlwave-outlawed-buffers))))
3795      (message "%d buffer%s killed" cnt (if (= cnt 1) "" "s"))))      (message "%d buffer%s killed" cnt (if (= cnt 1) "" "s"))))
3796    
# Line 3569  Intended for `after-save-hook'." Line 3802  Intended for `after-save-hook'."
3802           (entry (assq buf idlwave-outlawed-buffers)))           (entry (assq buf idlwave-outlawed-buffers)))
3803      ;; Revoke license      ;; Revoke license
3804      (if entry      (if entry
3805          (setq idlwave-outlawed-buffers          (setq idlwave-outlawed-buffers
3806                (delq entry idlwave-outlawed-buffers)))                (delq entry idlwave-outlawed-buffers)))
3807      ;; Remove this function from the hook.      ;; Remove this function from the hook.
3808      (remove-hook 'after-save-hook 'idlwave-revoke-license-to-kill 'local)))      (remove-hook 'after-save-hook 'idlwave-revoke-license-to-kill 'local)))
# Line 3586  Intended for `after-save-hook'." Line 3819  Intended for `after-save-hook'."
3819              (throw 'exit efile))))))              (throw 'exit efile))))))
3820  (defun idlwave-expand-lib-file-name (file)  (defun idlwave-expand-lib-file-name (file)
3821    ;; Find FILE on the scanned lib path and return a buffer visiting it    ;; Find FILE on the scanned lib path and return a buffer visiting it
3822    (cond    (cond
3823     ((null file) nil)     ((null file) nil)
3824     ((string-match "\\`\\({\\([0-9]+\\)}/\\)\\(.*\\)" file)     ((string-match "\\`\\({\\([0-9]+\\)}/\\)\\(.*\\)" file)
3825      (expand-file-name (match-string 3 file)      (expand-file-name (match-string 3 file)
# Line 3605  you specify /." Line 3838  you specify /."
3838    (interactive)    (interactive)
3839    (let (directory directories cmd append status numdirs dir getsubdirs    (let (directory directories cmd append status numdirs dir getsubdirs
3840                    buffer save_buffer files numfiles item errbuf)                    buffer save_buffer files numfiles item errbuf)
3841        
3842      ;;      ;;
3843      ;; Read list of directories      ;; Read list of directories
3844      (setq directory (read-string "Tag Directories: " "."))      (setq directory (read-string "Tag Directories: " "."))
# Line 3668  you specify /." Line 3901  you specify /."
3901                    (setq numfiles (1+ numfiles))                    (setq numfiles (1+ numfiles))
3902                    (setq item (nth numfiles files))                    (setq item (nth numfiles files))
3903                    )))                    )))
3904                
3905              (setq numdirs (1+ numdirs))              (setq numdirs (1+ numdirs))
3906              (setq dir (nth numdirs directories)))              (setq dir (nth numdirs directories)))
3907          (progn          (progn
3908            (setq numdirs (1+ numdirs))            (setq numdirs (1+ numdirs))
3909            (setq dir (nth numdirs directories)))))            (setq dir (nth numdirs directories)))))
3910        
3911      (setq errbuf (get-buffer-create "*idltags-error*"))      (setq errbuf (get-buffer-create "*idltags-error*"))
3912      (if (= status 0)      (if (= status 0)
3913          (kill-buffer errbuf))          (kill-buffer errbuf))
# Line 3725  blank lines." Line 3958  blank lines."
3958  ;; substrings.  So most of the code can simply assume to deal with  ;; substrings.  So most of the code can simply assume to deal with
3959  ;; "sinterned" strings.  The only exception is that the functions  ;; "sinterned" strings.  The only exception is that the functions
3960  ;; which scan whole buffers for routine information do not intern the  ;; which scan whole buffers for routine information do not intern the
3961  ;; grabbed strings.  This is only done afterwards.  Therefore in these  ;; grabbed strings.  This is only done afterwards.  Therefore in these
3962  ;; functions it is *not* save to assume the strings can be compared  ;; functions it is *not* safe to assume the strings can be compared
3963  ;; with `eq' and be fed into the routine assq functions.  ;; with `eq' and be fed into the routine assq functions.
3964    
3965  ;; Here we define the hashing functions.  ;; Here we define the hashing functions.
# Line 3743  blank lines." Line 3976  blank lines."
3976    ;; Make sure the hash functions are accessible.    ;; Make sure the hash functions are accessible.
3977    (if (or (not (fboundp 'gethash))    (if (or (not (fboundp 'gethash))
3978            (not (fboundp 'puthash)))            (not (fboundp 'puthash)))
3979        (progn        (progn
3980          (require 'cl)          (require 'cl)
3981          (or (fboundp 'puthash)          (or (fboundp 'puthash)
3982              (defalias 'puthash 'cl-puthash))))              (defalias 'puthash 'cl-puthash))))
# Line 3762  blank lines." Line 3995  blank lines."
3995        ;; Reset the system & library hash        ;; Reset the system & library hash
3996        (loop for entry in entries        (loop for entry in entries
3997          for var = (car entry) for size = (nth 1 entry)          for var = (car entry) for size = (nth 1 entry)
3998          do (setcdr (symbol-value var)          do (setcdr (symbol-value var)
3999                     (make-hash-table ':size size ':test 'equal)))                     (make-hash-table ':size size ':test 'equal)))
4000        (setq idlwave-sint-files nil))        (setq idlwave-sint-files nil))
4001    
# Line 3771  blank lines." Line 4004  blank lines."
4004        ;; Reset the buffer & shell hash        ;; Reset the buffer & shell hash
4005        (loop for entry in entries        (loop for entry in entries
4006          for var = (car entry) for size = (nth 1 entry)          for var = (car entry) for size = (nth 1 entry)
4007          do (setcar (symbol-value var)          do (setcar (symbol-value var)
4008                     (make-hash-table ':size size ':test 'equal))))))                     (make-hash-table ':size size ':test 'equal))))))
4009    
4010  (defun idlwave-sintern-routine-or-method (name &optional class set)  (defun idlwave-sintern-routine-or-method (name &optional class set)
# Line 3915  This defines the function `idlwave-sinte Line 4148  This defines the function `idlwave-sinte
4148  ;; The code to get routine info from different sources.  ;; The code to get routine info from different sources.
4149    
4150  (defvar idlwave-system-routines)  (defvar idlwave-system-routines)
4151    (defvar idlwave-catalog-process nil
4152      "The background process currently updating the catalog.")
4153    
4154  (defun idlwave-routines ()  (defun idlwave-routines ()
4155    "Provide a list of IDL routines.    "Provide a list of IDL routines.
4156  This routine loads the builtin routines on the first call.  Later it  This routine loads the builtin routines on the first call.  Later it
4157  only returns the value of the variable."  only returns the value of the variable."
4158      (if (and idlwave-catalog-process
4159               (processp idlwave-catalog-process))
4160          (progn
4161            (cond
4162             ((equal (process-status idlwave-catalog-process) 'exit)
4163              (message "updating........")
4164              (setq idlwave-catalog-process nil)
4165              (idlwave-update-routine-info '(4)))
4166             ((equal (process-status idlwave-catalog-process) 'run)
4167              ;; Keep it running...
4168              )
4169             (t
4170              ;; Something is wrong, get rid of the process
4171              (message "Problem with catalog process") (beep)
4172              (condition-case nil
4173                  (kill-process idlwave-catalog-process)
4174                (error nil))
4175              (setq idlwave-catalog-process nil)))))
4176    (or idlwave-routines    (or idlwave-routines
4177        (progn        (progn
4178          (idlwave-update-routine-info)          (idlwave-update-routine-info)
# Line 3929  only returns the value of the variable." Line 4183  only returns the value of the variable."
4183    "List of functions which should run after a global rinfo update.    "List of functions which should run after a global rinfo update.
4184  Does not run after automatic updates of buffer or the shell.")  Does not run after automatic updates of buffer or the shell.")
4185    
4186    (defun idlwave-rescan-catalog-directories ()
4187      "Rescan the previously selected directories. For batch processing."
4188      (idlwave-update-routine-info '(16)))
4189    
4190    (defun idlwave-rescan-asynchronously ()
4191      "Dispatch another emacs instance to update the idlwave catalog.
4192    After the process finishes normally, the first access to routine info
4193    will re-read the catalog."
4194      (interactive)
4195      (if (processp idlwave-catalog-process)
4196          (if (eq (process-status idlwave-catalog-process) 'run)
4197              (if (yes-or-no-p "A catalog-updating process is running.  Kill it? ")
4198                  (progn
4199                    (condition-case nil
4200                        (kill-process idlwave-catalog-process)
4201                      (error nil))
4202                    (error "Process killed, no new process started"))
4203                (error "Quit"))
4204            (condition-case nil
4205                (kill-process idlwave-catalog-process)
4206              (error nil))))
4207      (if (or (not idlwave-libinfo-file)
4208              (not (stringp idlwave-libinfo-file))
4209              (not (file-regular-p idlwave-libinfo-file)))
4210          (error "No catalog has been produced yet"))
4211      (let* ((emacs (expand-file-name (invocation-name) (invocation-directory)))
4212             (args (list "-batch"
4213                         "-l" (expand-file-name "~/.emacs")
4214                         "-l" "idlwave"
4215                         "-f" "idlwave-rescan-catalog-directories"))
4216             (process (apply 'start-process "idlcat"
4217                             nil emacs args)))
4218        (setq idlwave-catalog-process process)
4219        (set-process-sentinel
4220         process
4221         (lambda (pro why)
4222           (when (string-match "finished" why)
4223             (setq idlwave-routines nil
4224                   idlwave-system-routines nil
4225                   idlwave-catalog-process nil)
4226             (or (idlwave-start-load-rinfo-timer)
4227                 (idlwave-update-routine-info '(4))))))
4228        (message "Background job started to update catalog file")))
4229    
4230    
4231    (defvar idlwave-load-rinfo-idle-timer)
4232  (defun idlwave-update-routine-info (&optional arg)  (defun idlwave-update-routine-info (&optional arg)
4233    "Update the internal routine-info lists.    "Update the internal routine-info lists.
4234  These lists are used by `idlwave-routine-info' (\\[idlwave-routine-info])  These lists are used by `idlwave-routine-info' (\\[idlwave-routine-info])
# Line 3947  When an IDL shell is running, this comma Line 4247  When an IDL shell is running, this comma
4247  for currently compiled routines.  for currently compiled routines.
4248    
4249  With prefix ARG, also reload the system and library lists.  With prefix ARG, also reload the system and library lists.
4250  With two prefix ARG's, also rescans the library tree."  With two prefix ARG's, also rescans the library tree.
4251    With three prefix args, dispatch asynchronous process to do the update."
4252    (interactive "P")    (interactive "P")
4253    (if (equal arg '(16))    ;; Stop any idle processing
4254        (idlwave-create-libinfo-file t)    (if (or (and (fboundp 'itimerp)
4255      (let* ((reload (or arg                 (itimerp idlwave-load-rinfo-idle-timer))
4256                         idlwave-buffer-case-takes-precedence            (and (fboundp 'timerp)
4257                         (null idlwave-system-routines))))                 (timerp idlwave-load-rinfo-idle-timer)))
4258                (cancel-timer idlwave-load-rinfo-idle-timer))
4259      (cond
4260       ((equal arg '(64))
4261        ;; Start a background process which updates the catalog.
4262        (idlwave-rescan-asynchronously))
4263       ((equal arg '(16))
4264        ;; Update the catalog now, and wait for it.
4265        (idlwave-create-libinfo-file t))
4266       (t
4267        (let* ((load (or arg
4268                         idlwave-buffer-case-takes-precedence
4269                         (null idlwave-routines)))
4270               ;; The override-idle means, even if the idle timer has done some
4271               ;; preparing work, load and renormalize everything anyway.
4272               (override-idle (or arg idlwave-buffer-case-takes-precedence)))
4273    
4274        (setq idlwave-buffer-routines nil        (setq idlwave-buffer-routines nil
4275              idlwave-compiled-routines nil              idlwave-compiled-routines nil
4276              idlwave-unresolved-routines nil)              idlwave-unresolved-routines nil)
4277        ;; Reset the appropriate hashes        ;; Reset the appropriate hashes
4278        (idlwave-reset-sintern (cond (reload t)        (if (get 'idlwave-reset-sintern 'done-by-idle)
4279                                     ((null idlwave-system-routines) t)            ;; reset was already done in idle time, so skip this step now once
4280                                     (t 'bufsh)))            (put 'idlwave-reset-sintern 'done-by-idle nil)
4281                  (idlwave-reset-sintern (cond (load t)
4282                                         ((null idlwave-system-routines) t)
4283                                         (t 'bufsh))))
4284    
4285        (if idlwave-buffer-case-takes-precedence        (if idlwave-buffer-case-takes-precedence
4286            ;; We can safely scan the buffer stuff first            ;; We can safely scan the buffer stuff first
4287            (progn            (progn
4288              (idlwave-update-buffer-routine-info)              (idlwave-update-buffer-routine-info)
4289              (and reload (idlwave-load-system-rinfo)))              (and load (idlwave-load-system-rinfo override-idle)))
4290          ;; We first do the system info, and then the buffers          ;; We first do the system info, and then the buffers
4291          (and reload (idlwave-load-system-rinfo))          (and load (idlwave-load-system-rinfo override-idle))
4292          (idlwave-update-buffer-routine-info))          (idlwave-update-buffer-routine-info))
4293    
4294        ;; Let's see if there is a shell        ;; Let's see if there is a shell
# Line 3977  With two prefix ARG's, also rescans the Line 4296  With two prefix ARG's, also rescans the
4296                                      (idlwave-shell-is-running)))                                      (idlwave-shell-is-running)))
4297               (ask-shell (and shell-is-running               (ask-shell (and shell-is-running
4298                               idlwave-query-shell-for-routine-info)))                               idlwave-query-shell-for-routine-info)))
4299          
4300          (if (or (not ask-shell)          (if (or (not ask-shell)
4301                  (not (interactive-p)))                  (not (interactive-p)))
4302              ;; 1. If we are not going to ask the shell, we need to do the              ;; 1. If we are not going to ask the shell, we need to do the
# Line 3988  With two prefix ARG's, also rescans the Line 4307  With two prefix ARG's, also rescans the
4307              ;;    the current command.  Therefore, we do a concatenation              ;;    the current command.  Therefore, we do a concatenation
4308              ;;    now, even though the shell might do it again.              ;;    now, even though the shell might do it again.
4309              (idlwave-concatenate-rinfo-lists nil t))              (idlwave-concatenate-rinfo-lists nil t))
4310          
4311          (when ask-shell          (when ask-shell
4312            ;; Ask the shell about the routines it knows.            ;; Ask the shell about the routines it knows.
4313            (message "Querying the shell")            (message "Querying the shell")
4314            (idlwave-shell-update-routine-info nil t))))))            (idlwave-shell-update-routine-info nil t)))))))
4315    
4316  (defun idlwave-load-system-rinfo ()  (defvar idlwave-load-rinfo-steps-done (make-vector 5 nil))
4317    (defvar idlwave-load-rinfo-idle-timer nil)
4318    (defun idlwave-start-load-rinfo-timer ()
4319      (if (or (and (fboundp 'itimerp)
4320                   (itimerp idlwave-load-rinfo-idle-timer))
4321              (and (fboundp 'timerp)
4322                   (timerp idlwave-load-rinfo-idle-timer)))
4323          (cancel-timer idlwave-load-rinfo-idle-timer))
4324      (setq idlwave-load-rinfo-steps-done (make-vector 5 nil))
4325      (setq idlwave-load-rinfo-idle-timer nil)
4326      (if (and idlwave-init-rinfo-when-idle-after
4327               (numberp idlwave-init-rinfo-when-idle-after)
4328               (not (equal 0 idlwave-init-rinfo-when-idle-after))
4329               (not idlwave-routines))
4330          (condition-case nil
4331              (progn
4332                (setq idlwave-load-rinfo-idle-timer
4333                      (run-with-idle-timer
4334                       idlwave-init-rinfo-when-idle-after
4335                       nil 'idlwave-load-rinfo-next-step)))
4336            (error nil))))
4337    
4338    
4339    
4340    (defun idlwave-load-rinfo-next-step ()
4341      (let ((inhibit-quit t)
4342            (arr idlwave-load-rinfo-steps-done))
4343        (if (catch 'exit
4344              (when (not (aref arr 0))
4345                (message "Loading idlw-rinfo.el in idle time...")
4346                (load "idlw-rinfo" 'noerror 'nomessage)
4347                (message "Loading idlw-rinfo.el in idle time...done")
4348                (aset arr 0 t)
4349                (throw 'exit t))
4350              (when (not (aref arr 1))
4351                (message "Normalizing idlwave-system-routines in idle time...")
4352                (idlwave-reset-sintern t)
4353                (put 'idlwave-reset-sintern 'done-by-idle t)
4354                (setq idlwave-system-routines
4355                      (idlwave-sintern-rinfo-list idlwave-system-routines 'sys))
4356                (message "Normalizing idlwave-system-routines in idle time...done")
4357                (aset arr 1 t)
4358                (throw 'exit t))
4359              (when (not (aref arr 2))
4360                (when (and (stringp idlwave-libinfo-file)
4361                           (file-regular-p idlwave-libinfo-file))
4362                  (condition-case nil
4363                      (progn
4364                        (message "Loading library catalog in idle time...")
4365                        (load-file idlwave-libinfo-file)
4366                        (message "Loading library catalog in idle time...done")
4367                        (aset arr 2 t)
4368                        (throw 'exit t))
4369                    (error (throw 'exit nil)))))
4370              (when (not (aref arr 3))
4371                (when idlwave-library-routines
4372                  (message "Normalizing idlwave-library-routines in idle time...")
4373                  (setq idlwave-library-routines (idlwave-sintern-rinfo-list
4374                                                  idlwave-library-routines 'sys))
4375                  (message "Normalizing idlwave-library-routines in idle time...done"))
4376                (aset arr 3 t)
4377                (throw 'exit t))
4378              (when (not (aref arr 4))
4379                (message "Finishing initialization in idle time...")
4380                (idlwave-routines)
4381                (message "Finishing initialization in idle time...done")
4382                (throw 'exit nil)))
4383            (progn
4384              ;; restart the timer
4385              (if (sit-for 1)
4386                  (idlwave-load-rinfo-next-step)
4387                (setq idlwave-load-rinfo-idle-timer
4388                      (run-with-idle-timer
4389                       idlwave-init-rinfo-when-idle-after
4390                       nil 'idlwave-load-rinfo-next-step)))
4391              ))))
4392    
4393    (defun idlwave-load-system-rinfo (&optional force)
4394    ;; Load and case-treat the system and lib info files.    ;; Load and case-treat the system and lib info files.
4395    (load "idlw-rinfo" t)    (when (or force (not (aref idlwave-load-rinfo-steps-done 0)))
4396    (message "Normalizing idlwave-system-routines...")      (load "idlw-rinfo" 'noerror 'nomessage))
4397    (setq idlwave-system-routines    (when (or force (not (aref idlwave-load-rinfo-steps-done 1)))
4398          (idlwave-sintern-rinfo-list idlwave-system-routines 'sys))      (message "Normalizing idlwave-system-routines...")
4399    (message "Normalizing idlwave-system-routines...done")      (setq idlwave-system-routines
4400              (idlwave-sintern-rinfo-list idlwave-system-routines 'sys))
4401        (message "Normalizing idlwave-system-routines...done"))
4402    (setq idlwave-routines (copy-sequence idlwave-system-routines))    (setq idlwave-routines (copy-sequence idlwave-system-routines))
4403    (setq idlwave-last-system-routine-info-cons-cell    (setq idlwave-last-system-routine-info-cons-cell
4404          (nthcdr (1- (length idlwave-routines)) idlwave-routines))          (nthcdr (1- (length idlwave-routines)) idlwave-routines))
# Line 4008  With two prefix ARG's, also rescans the Line 4406  With two prefix ARG's, also rescans the
4406               (file-regular-p idlwave-libinfo-file))               (file-regular-p idlwave-libinfo-file))
4407      (condition-case nil      (condition-case nil
4408          (progn          (progn
4409            (load-file idlwave-libinfo-file)            (when (or force (not (aref idlwave-load-rinfo-steps-done 2)))
4410                (load-file idlwave-libinfo-file))
4411            (setq idlwave-true-path-alist nil)            (setq idlwave-true-path-alist nil)
4412            (message "Normalizing idlwave-library-routines...")            (when (or force (not (aref idlwave-load-rinfo-steps-done 3)))
4413            (setq idlwave-library-routines (idlwave-sintern-rinfo-list              (message "Normalizing idlwave-library-routines...")
4414                                            idlwave-library-routines 'sys))              (setq idlwave-library-routines (idlwave-sintern-rinfo-list
4415            (message "Normalizing idlwave-library-routines...done"))                                              idlwave-library-routines 'sys))
4416                (message "Normalizing idlwave-library-routines...done")))
4417        (error nil)))        (error nil)))
4418    
4419    (run-hooks 'idlwave-after-load-rinfo-hook))    (run-hooks 'idlwave-after-load-rinfo-hook))
4420    
4421    
4422  (defun idlwave-update-buffer-routine-info ()  (defun idlwave-update-buffer-routine-info ()
4423    (let (res)    (let (res)
4424      (cond      (cond
4425       ((eq idlwave-scan-all-buffers-for-routine-info t)       ((eq idlwave-scan-all-buffers-for-routine-info t)
4426        ;; Scan all buffers, current buffer last        ;; Scan all buffers, current buffer last
4427        (message "Scanning all buffers...")        (message "Scanning all buffers...")
4428        (setq res (idlwave-get-routine-info-from-buffers        (setq res (idlwave-get-routine-info-from-buffers
4429                   (reverse (buffer-list)))))                   (reverse (buffer-list)))))
4430       ((null idlwave-scan-all-buffers-for-routine-info)       ((null idlwave-scan-all-buffers-for-routine-info)
4431        ;; Don't scan any buffers        ;; Don't scan any buffers
# Line 4037  With two prefix ARG's, also rescans the Line 4438  With two prefix ARG's, also rescans the
4438              (setq res (idlwave-get-routine-info-from-buffers              (setq res (idlwave-get-routine-info-from-buffers
4439                         (list (current-buffer))))))))                         (list (current-buffer))))))))
4440      ;; Put the result into the correct variable      ;; Put the result into the correct variable
4441      (setq idlwave-buffer-routines      (setq idlwave-buffer-routines
4442            (idlwave-sintern-rinfo-list res t))))            (idlwave-sintern-rinfo-list res t))))
4443    
4444  (defun idlwave-concatenate-rinfo-lists (&optional quiet run-hook)  (defun idlwave-concatenate-rinfo-lists (&optional quiet run-hook)
4445    "Put the different sources for routine information together."    "Put the different sources for routine information together."
4446    ;; The sequence here is important because earlier definitions shadow    ;; The sequence here is important because earlier definitions shadow
4447    ;; later ones.  We assume that if things in the buffers are newer    ;; later ones.  We assume that if things in the buffers are newer
4448    ;; then in the shell of the system, it is meant to be different.    ;; then in the shell of the system, it is meant to be different.
4449    
# Line 4054  With two prefix ARG's, also rescans the Line 4455  With two prefix ARG's, also rescans the
4455    
4456    ;; Give a message with information about the number of routines we have.    ;; Give a message with information about the number of routines we have.
4457    (unless quiet    (unless quiet
4458      (message      (message
4459       "Routine info updated:  buffer(%d)  compiled(%d)  catalog(%d)  system(%d)"       "Routine info updated:  buffer(%d)  compiled(%d)  catalog(%d)  system(%d)"
4460       (length idlwave-buffer-routines)       (length idlwave-buffer-routines)
4461       (length idlwave-compiled-routines)       (length idlwave-compiled-routines)
# Line 4071  With two prefix ARG's, also rescans the Line 4472  With two prefix ARG's, also rescans the
4472            (when (and (setq class (nth 2 x))            (when (and (setq class (nth 2 x))
4473                       (not (assq class idlwave-class-alist)))                       (not (assq class idlwave-class-alist)))
4474              (push (list class) idlwave-class-alist)))              (push (list class) idlwave-class-alist)))
4475          idlwave-class-alist)))                idlwave-class-alist)))
4476    
4477  ;; Three functions for the hooks  ;; Three functions for the hooks
4478  (defun idlwave-save-buffer-update ()  (defun idlwave-save-buffer-update ()
# Line 4104  With two prefix ARG's, also rescans the Line 4505  With two prefix ARG's, also rescans the
4505    
4506  (defun idlwave-replace-buffer-routine-info (file new)  (defun idlwave-replace-buffer-routine-info (file new)
4507    "Cut the part from FILE out of `idlwave-buffer-routines' and add NEW."    "Cut the part from FILE out of `idlwave-buffer-routines' and add NEW."
4508    (let ((list idlwave-buffer-routines)    (let ((list idlwave-buffer-routines)
4509          found)          found)
4510      (while list      (while list
4511        ;; The following test uses eq to make sure it works correctly        ;; The following test uses eq to make sure it works correctly
# Line 4115  With two prefix ARG's, also rescans the Line 4516  With two prefix ARG's, also rescans the
4516              (setcar list nil)              (setcar list nil)
4517              (setq found t))              (setq found t))
4518          (if found          (if found
4519              ;; End of that section reached. Jump.              ;; End of that section reached. Jump.
4520              (setq list nil)))              (setq list nil)))
4521        (setq list (cdr list)))        (setq list (cdr list)))
4522      (setq idlwave-buffer-routines      (setq idlwave-buffer-routines
# Line 4147  With two prefix ARG's, also rescans the Line 4548  With two prefix ARG's, also rescans the
4548        (save-restriction        (save-restriction
4549          (widen)          (widen)
4550          (goto-char (point-min))          (goto-char (point-min))
4551          (while (re-search-forward          (while (re-search-forward
4552                  "^[ \t]*\\(pro\\|function\\)[ \t]" nil t)                  "^[ \t]*\\(pro\\|function\\)[ \t]" nil t)
4553            (setq string (buffer-substring            (setq string (buffer-substring-no-properties
4554                          (match-beginning 0)                          (match-beginning 0)
4555                          (progn                          (progn
4556                            (idlwave-end-of-statement)                            (idlwave-end-of-statement)
4557                            (point))))                            (point))))
4558            (setq entry (idlwave-parse-definition string))            (setq entry (idlwave-parse-definition string))
# Line 4189  With two prefix ARG's, also rescans the Line 4590  With two prefix ARG's, also rescans the
4590          (push (match-string 1 string) args)))          (push (match-string 1 string) args)))
4591      ;; Normalize and sort.      ;; Normalize and sort.
4592      (setq args (nreverse args))      (setq args (nreverse args))
4593      (setq keywords (sort keywords (lambda (a b)      (setq keywords (sort keywords (lambda (a b)
4594                                      (string< (downcase a) (downcase b)))))                                      (string< (downcase a) (downcase b)))))
4595      ;; Make and return the entry      ;; Make and return the entry
4596      ;; We don't know which argument are optional, so this information      ;; We don't know which argument are optional, so this information
# Line 4199  With two prefix ARG's, also rescans the Line 4600  With two prefix ARG's, also rescans the
4600            class            class
4601            (cond ((not (boundp 'idlwave-scanning-lib))            (cond ((not (boundp 'idlwave-scanning-lib))
4602                   (cons 'buffer (buffer-file-name)))                   (cons 'buffer (buffer-file-name)))
4603  ;               ((string= (downcase  ;               ((string= (downcase
4604  ;                          (file-name-sans-extension  ;                          (file-name-sans-extension
4605  ;                           (file-name-nondirectory (buffer-file-name))))  ;                           (file-name-nondirectory (buffer-file-name))))
4606  ;                         (downcase name))  ;                         (downcase name))
# Line 4207  With two prefix ARG's, also rescans the Line 4608  With two prefix ARG's, also rescans the
4608  ;               (t (cons 'lib (file-name-nondirectory (buffer-file-name))))  ;               (t (cons 'lib (file-name-nondirectory (buffer-file-name))))
4609                  (t (cons 'lib (concat idlwave-scanning-lib-dir                  (t (cons 'lib (concat idlwave-scanning-lib-dir
4610                                        (file-name-nondirectory (buffer-file-name))))))                                        (file-name-nondirectory (buffer-file-name))))))
4611            (concat            (concat
4612             (if (string= type "function") "Result = " "")             (if (string= type "function") "Result = " "")
4613             (if class "Obj ->[%s::]" "")             (if class "Obj ->[%s::]" "")
4614             "%s"             "%s"
# Line 4251  will pop up." Line 4652  will pop up."
4652                 (> (length idlwave-libinfo-file) 0)                 (> (length idlwave-libinfo-file) 0)
4653                 (file-accessible-directory-p                 (file-accessible-directory-p
4654                  (file-name-directory idlwave-libinfo-file))                  (file-name-directory idlwave-libinfo-file))
4655                 (not (string= "" (file-name-nondirectory                 (not (string= "" (file-name-nondirectory
4656                                   idlwave-libinfo-file))))                                   idlwave-libinfo-file))))
4657      (error "`idlwave-libinfo-file' does not point to file in accessible directory"))      (error "`idlwave-libinfo-file' does not point to file in accessible directory"))
4658      
4659    (cond    (cond
4660     ((and arg idlwave-path-alist     ((and arg idlwave-path-alist
4661           (consp (car idlwave-path-alist))           (consp (car idlwave-path-alist))
# Line 4289  will pop up." Line 4690  will pop up."
4690      (let* ((rpl (idlwave-shell-path-filter))      (let* ((rpl (idlwave-shell-path-filter))
4691             (sysdir (car rpl))             (sysdir (car rpl))
4692             (dirs (cdr rpl)))             (dirs (cdr rpl)))
4693        (idlwave-display-libinfo-widget        (idlwave-display-libinfo-widget
4694         sysdir dirs         sysdir dirs
4695         (delq nil (mapcar (lambda (x) (if (cdr x) (car x) nil))         (delq nil (mapcar (lambda (x) (if (cdr x) (car x) nil))
4696                           idlwave-path-alist))))))                           idlwave-path-alist))))))
4697    
4698  (defconst idlwave-libinfo-widget-help-string  (defconst idlwave-libinfo-widget-help-string
4699    "This is the front-end to the creation of IDLWAVE library catalog.    "This is the front-end to the creation of IDLWAVE library catalog.
4700  Please select below the directories on IDL's search path from which you  Please select below the directories on IDL's search path from which you
4701  would like to extract routine information, which will be stored in the file  would like to extract routine information, which will be stored in the file
# Line 4332  directories and save the routine info. Line 4733  directories and save the routine info.
4733    (make-local-variable 'idlwave-widget)    (make-local-variable 'idlwave-widget)
4734    (widget-insert (format idlwave-libinfo-widget-help-string    (widget-insert (format idlwave-libinfo-widget-help-string
4735                           idlwave-libinfo-file))                           idlwave-libinfo-file))
4736      
4737    (widget-create 'push-button    (widget-create 'push-button
4738                   :notify 'idlwave-widget-scan-lib-files                   :notify 'idlwave-widget-scan-lib-files
4739                   "Scan & Save")                   "Scan & Save")
# Line 4364  directories and save the routine info. Line 4765  directories and save the routine info.
4765    (widget-insert "\n\n")    (widget-insert "\n\n")
4766    
4767    (widget-insert "Select Directories\n")    (widget-insert "Select Directories\n")
4768      
4769    (setq idlwave-widget    (setq idlwave-widget
4770          (apply 'widget-create          (apply 'widget-create
4771                 'checklist                 'checklist
# Line 4379  directories and save the routine info. Line 4780  directories and save the routine info.
4780    (widget-setup)    (widget-setup)
4781    (goto-char (point-min))    (goto-char (point-min))
4782    (delete-other-windows))    (delete-other-windows))
4783      
4784  (defun idlwave-delete-libinfo-file (&rest ignore)  (defun idlwave-delete-libinfo-file (&rest ignore)
4785    (if (yes-or-no-p    (if (yes-or-no-p
4786         (format "Delete file %s " idlwave-libinfo-file))         (format "Delete file %s " idlwave-libinfo-file))
# Line 4438  directories and save the routine info. Line 4839  directories and save the routine info.
4839      ;; is used.  So we don't do it here - the catalog file looks nicer      ;; is used.  So we don't do it here - the catalog file looks nicer
4840      ;; when it is unsorted.      ;; when it is unsorted.
4841      ;;(message "Sorting...")      ;;(message "Sorting...")
4842      ;;(setq idlwave-library-routines      ;;(setq idlwave-library-routines
4843      ;;(sort idlwave-library-routines 'idlwave-routine-entry-compare))      ;;(sort idlwave-library-routines 'idlwave-routine-entry-compare))
4844      ;;(message "Sorting...done")      ;;(message "Sorting...done")
4845      (message "Creating libinfo file...")      (message "Creating libinfo file...")
# Line 4467  directories and save the routine info. Line 4868  directories and save the routine info.
4868    
4869      ;; Define the routine info list      ;; Define the routine info list
4870      (insert "\n(setq idlwave-library-routines\n    '(")      (insert "\n(setq idlwave-library-routines\n    '(")
4871      (mapcar (lambda (x)      (let ((standard-output (current-buffer)))
4872                (insert "\n    ")        (mapcar (lambda (x)
4873                (insert (with-output-to-string (prin1 x))))                  (insert "\n    ")
4874              idlwave-library-routines)                  (prin1 x)
4875                    (goto-char (point-max)))
4876    ;               (insert (with-output-to-string (prin1 x))))
4877                  idlwave-library-routines))
4878      (insert (format "))\n\n;;; %s ends here\n"      (insert (format "))\n\n;;; %s ends here\n"
4879                      (file-name-nondirectory idlwave-libinfo-file)))                      (file-name-nondirectory idlwave-libinfo-file)))
4880      (goto-char (point-min))      (goto-char (point-min))
# Line 4510  directories and save the routine info. Line 4914  directories and save the routine info.
4914        (when (file-directory-p dir)        (when (file-directory-p dir)
4915          (setq files (nreverse (directory-files dir t "[^.]")))          (setq files (nreverse (directory-files dir t "[^.]")))
4916          (while (setq file (pop files))          (while (setq file (pop files))
4917            (if (file-directory-p file)            (if (file-directory-p file)
4918                (push (file-name-as-directory file) path)))                (push (file-name-as-directory file) path)))
4919          (push dir path1)))          (push dir path1)))
4920      path1))      path1))
# Line 4518  directories and save the routine info. Line 4922  directories and save the routine info.
4922  ;;----- Asking the shell -------------------  ;;----- Asking the shell -------------------
4923    
4924  ;; First, here is the idl program which can be used to query IDL for  ;; First, here is the idl program which can be used to query IDL for
4925  ;; defined routines.  ;; defined routines.
4926  (defconst idlwave-routine-info.pro  (defconst idlwave-routine-info.pro
4927    "    "
4928  ;; START OF IDLWAVE SUPPORT ROUTINES  ;; START OF IDLWAVE SUPPORT ROUTINES
4929  pro idlwave_print_info_entry,name,func=func,separator=sep  pro idlwave_print_info_entry,name,func=func,separator=sep
4930    ;; See if it's an object method    ;; See if it's an object method
4931    if name eq '' then return    if name eq '' then return
4932    func    = keyword_set(func)    func    = keyword_set(func)
4933    methsep = strpos(name,'::')    methsep = strpos(name,'::')
4934    meth    = methsep ne -1    meth    = methsep ne -1
4935      
4936    ;; Get routine info    ;; Get routine info
4937    pars   = routine_info(name,/parameters,functions=func)    pars   = routine_info(name,/parameters,functions=func)
4938    source = routine_info(name,/source,functions=func)    source = routine_info(name,/source,functions=func)
# Line 4536  pro idlwave_print_info_entry,name,func=f Line 4940  pro idlwave_print_info_entry,name,func=f
4940    nkw    = pars.num_kw_args    nkw    = pars.num_kw_args
4941    if nargs gt 0 then args = pars.args    if nargs gt 0 then args = pars.args
4942    if nkw   gt 0 then kwargs = pars.kw_args    if nkw   gt 0 then kwargs = pars.kw_args
4943      
4944    ;; Trim the class, and make the name    ;; Trim the class, and make the name
4945    if meth then begin    if meth then begin
4946        class = strmid(name,0,methsep)        class = strmid(name,0,methsep)
4947        name  = strmid(name,methsep+2,strlen(name)-1)        name  = strmid(name,methsep+2,strlen(name)-1)
4948        if nargs gt 0 then begin        if nargs gt 0 then begin
4949            ;; remove the self argument            ;; remove the self argument
4950            wh = where(args ne 'SELF',nargs)            wh = where(args ne 'SELF',nargs)
4951            if nargs gt 0 then args = args(wh)            if nargs gt 0 then args = args(wh)
# Line 4550  pro idlwave_print_info_entry,name,func=f Line 4954  pro idlwave_print_info_entry,name,func=f
4954        ;; No class, just a normal routine.        ;; No class, just a normal routine.
4955        class = \"\"        class = \"\"
4956    endelse    endelse
4957      
4958    ;; Calling sequence    ;; Calling sequence
4959    cs = \"\"    cs = \"\"
4960    if func then cs = 'Result = '    if func then cs = 'Result = '
# Line 4571  pro idlwave_print_info_entry,name,func=f Line 4975  pro idlwave_print_info_entry,name,func=f
4975            kwstring = kwstring + ' ' + kwargs(j)            kwstring = kwstring + ' ' + kwargs(j)
4976        endfor        endfor
4977    endif    endif
4978      
4979    ret=(['IDLWAVE-PRO','IDLWAVE-FUN'])(func)    ret=(['IDLWAVE-PRO','IDLWAVE-FUN'])(func)
4980      
4981    print,ret + ': ' + name + sep + class + sep + source(0).path  $    print,ret + ': ' + name + sep + class + sep + source(0).path  $
4982      + sep + cs + sep + kwstring      + sep + cs + sep + kwstring
4983  end  end
# Line 4609  end Line 5013  end
5013    
5014  pro idlwave_get_class_tags, class  pro idlwave_get_class_tags, class
5015    res = execute('tags=tag_names({'+class+'})')    res = execute('tags=tag_names({'+class+'})')
5016    if res then print,'IDLWAVE-CLASS-TAGS: '+class+string(format='(1000(\" \",A))',tags)    if res then print,'IDLWAVE-CLASS-TAGS: '+class+' '+strjoin(tags,' ',/single)
5017  end  end
5018  ;; END OF IDLWAVE SUPPORT ROUTINES  ;; END OF IDLWAVE SUPPORT ROUTINES
5019  "  "
5020    "The idl programs to get info from the shell.")    "The idl programs to get info from the shell.")
5021    
5022  (defvar idlwave-idlwave_routine_info-compiled nil  (defvar idlwave-idlwave_routine_info-compiled nil
# Line 4620  end Line 5024  end
5024    
5025  (defvar idlwave-shell-temp-pro-file)  (defvar idlwave-shell-temp-pro-file)
5026  (defvar idlwave-shell-temp-rinfo-save-file)  (defvar idlwave-shell-temp-rinfo-save-file)
5027  (defun idlwave-shell-update-routine-info (&optional quiet run-hooks)  (defun idlwave-shell-update-routine-info (&optional quiet run-hooks preempt)
5028    "Query the shell for routine_info of compiled modules and update the lists."    "Query the shell for routine_info of compiled modules and update the lists."
5029    ;; Save and compile the procedure.  The compiled procedure is then    ;; Save and compile the procedure.  The compiled procedure is then
5030    ;; saved into an IDL SAVE file, to allow for fast RESTORE.    ;; saved into an IDL SAVE file, to allow for fast RESTORE.
5031    ;; We need to RESTORE the procedure each time we use it, since    ;; We need to RESTORE the procedure each time we use it, since
5032    ;; the user may have killed or redefined it.  In particluar,    ;; the user may have killed or redefined it.  In particular,
5033    ;; .RESET_SESSION will kill all user procedures.    ;; .RESET_SESSION will kill all user procedures.
5034    (unless (and idlwave-idlwave_routine_info-compiled    (unless (and idlwave-idlwave_routine_info-compiled
5035                 (file-readable-p idlwave-shell-temp-rinfo-save-file))                 (file-readable-p (idlwave-shell-temp-file 'rinfo)))
5036      (save-excursion      (save-excursion
5037        (set-buffer (idlwave-find-file-noselect        (set-buffer (idlwave-find-file-noselect
5038                     idlwave-shell-temp-pro-file))                     (idlwave-shell-temp-file 'pro)))
5039        (erase-buffer)        (erase-buffer)
5040        (insert idlwave-routine-info.pro)        (insert idlwave-routine-info.pro)
5041        (save-buffer 0))        (save-buffer 0))
5042      (idlwave-shell-send-command      (idlwave-shell-send-command
5043       (concat ".run " idlwave-shell-temp-pro-file)       (concat ".run " idlwave-shell-temp-pro-file)
5044       nil 'hide)       nil 'hide)
5045    ;    (message "SENDING SAVE") ; ????????????????????????
5046      (idlwave-shell-send-command      (idlwave-shell-send-command
5047       (format "save,'idlwave_routine_info','idlwave_print_info_entry',FILE='%s',/ROUTINES"       (format "save,'idlwave_routine_info','idlwave_print_info_entry',FILE='%s',/ROUTINES"
5048               idlwave-shell-temp-rinfo-save-file)               (idlwave-shell-temp-file 'rinfo))
5049       nil 'hide))       nil 'hide))
5050    
5051    ;; Restore and execute the procedure, analyze the output    ;; Restore and execute the procedure, analyze the output
5052    ;  (message "SENDING RESTORE & EXECUTE") ; ????????????????????????
5053    (idlwave-shell-send-command    (idlwave-shell-send-command
5054     (format "RESTORE, '%s' & idlwave_routine_info"     (format "RESTORE, '%s' & idlwave_routine_info"
5055             idlwave-shell-temp-rinfo-save-file)             idlwave-shell-temp-rinfo-save-file)
5056     `(progn     `(progn
5057        (idlwave-shell-routine-info-filter)        (idlwave-shell-routine-info-filter)
5058        (idlwave-concatenate-rinfo-lists ,quiet ,run-hooks))        (idlwave-concatenate-rinfo-lists ,quiet ,run-hooks))
5059     'hide))     'hide preempt))
5060    
5061  ;; ---------------------------------------------------------------------------  ;; ---------------------------------------------------------------------------
5062  ;;  ;;
# Line 4670  at this point. Line 5076  at this point.
5076    it completes a keyword of the relevant function or procedure.    it completes a keyword of the relevant function or procedure.
5077  - In the first arg of `OBJ_NEW', it completes a class name.  - In the first arg of `OBJ_NEW', it completes a class name.
5078    
5079  When several completions are possible, a list will be displayed in the  When several completions are possible, a list will be displayed in the
5080  *Completions* buffer.  If this list is too long to fit into the  *Completions* buffer.  If this list is too long to fit into the
5081  window, scrolling can be achieved by repeatedly pressing \\[idlwave-complete].  window, scrolling can be achieved by repeatedly pressing
5082    \\[idlwave-complete].
5083    
5084  The function also knows about object methods.  When it needs a class  The function also knows about object methods.  When it needs a class
5085  name, the action depends upon `idlwave-query-class', which see.  You  name, the action depends upon `idlwave-query-class', which see.  You
5086  can force IDLWAVE to ask you for a class name with a \\[universal-argument] prefix  can force IDLWAVE to ask you for a class name with a
5087  argument to this command.  \\[universal-argument] prefix argument to this command.
5088    
5089  See also the variables `idlwave-keyword-completion-adds-equal' and  See also the variables `idlwave-keyword-completion-adds-equal' and
5090  `idlwave-function-completion-adds-paren'.  `idlwave-function-completion-adds-paren'.
# Line 4697  Possible values are: Line 5104  Possible values are:
5104  8  <=>  'function-method-keyword  8  <=>  'function-method-keyword
5105  9  <=>  'class  9  <=>  'class
5106    
5107    As a special case, the universal argument C-u forces completion of
5108    function names in places where the default would be a keyword.
5109    
5110  For Lisp programmers only:  For Lisp programmers only:
5111  When we force a keyword, optional argument MODULE can contain the module name.  When we force a keyword, optional argument MODULE can contain the module name.
5112  When we force a method or a method keyword, CLASS can specify the class."  When we force a method or a method keyword, CLASS can specify the class."
# Line 4725  When we force a method or a method keywo Line 5135  When we force a method or a method keywo
5135    
5136       ;; Check for any special completion functions       ;; Check for any special completion functions
5137       ((and idlwave-complete-special       ((and idlwave-complete-special
5138             (idlwave-complete-special)))             (idlwave-call-special idlwave-complete-special)))
5139    
5140       ((and (idlwave-in-quote)       ((and (idlwave-in-quote)
5141             (not (eq what 'class)))             (not (eq what 'class)))
# Line 4740  When we force a method or a method keywo Line 5150  When we force a method or a method keywo
5150    
5151       ((eq what 'procedure)       ((eq what 'procedure)
5152        ;; Complete a procedure name        ;; Complete a procedure name
5153        (let* ((class-selector (idlwave-determine-class (nth 3 where-list) 'pro))        (let* ((cw-list (nth 3 where-list))
5154               (super-classes (idlwave-all-class-inherits class-selector))               (class-selector (idlwave-determine-class cw-list 'pro))
5155                 (super-classes (unless (idlwave-explicit-class-listed cw-list)
5156                                  (idlwave-all-class-inherits class-selector)))
5157               (isa (concat "procedure" (if class-selector "-method" "")))               (isa (concat "procedure" (if class-selector "-method" "")))
5158               (type-selector 'pro))               (type-selector 'pro))
5159          (setq idlwave-completion-help-info          (setq idlwave-completion-help-info
5160                (list 'routine nil type-selector class-selector nil super-classes))                (list 'routine nil type-selector class-selector nil super-classes))
5161          (idlwave-complete-in-buffer          (idlwave-complete-in-buffer
5162           'procedure (if class-selector 'method 'routine)           'procedure (if class-selector 'method 'routine)
# Line 4752  When we force a method or a method keywo Line 5164  When we force a method or a method keywo
5164           (format "Select a %s name%s"           (format "Select a %s name%s"
5165                   isa                   isa
5166                   (if class-selector                   (if class-selector
5167                       (format " (class is %s)" class-selector)                       (format " (class is %s)"
5168                                 (if (eq class-selector t)
5169                                     "unknown" class-selector))
5170                     ""))                     ""))
5171           isa           isa
5172           'idlwave-attach-method-classes)))           'idlwave-attach-method-classes)))
5173    
5174       ((eq what 'function)       ((eq what 'function)
5175        ;; Complete a function name        ;; Complete a function name
5176        (let* ((class-selector (idlwave-determine-class (nth 3 where-list) 'fun))        (let* ((cw-list (nth 3 where-list))
5177               (super-classes (idlwave-all-class-inherits class-selector))               (class-selector (idlwave-determine-class cw-list 'fun))
5178                 (super-classes (unless (idlwave-explicit-class-listed cw-list)
5179                                  (idlwave-all-class-inherits class-selector)))
5180               (isa (concat "function" (if class-selector "-method" "")))               (isa (concat "function" (if class-selector "-method" "")))
5181               (type-selector 'fun))               (type-selector 'fun))
5182          (setq idlwave-completion-help-info          (setq idlwave-completion-help-info
5183                (list 'routine nil type-selector class-selector nil super-classes))                (list 'routine nil type-selector class-selector nil super-classes))
5184          (idlwave-complete-in-buffer          (idlwave-complete-in-buffer
5185           'function (if class-selector 'method 'routine)           'function (if class-selector 'method 'routine)
# Line 4771  When we force a method or a method keywo Line 5187  When we force a method or a method keywo
5187           (format "Select a %s name%s"           (format "Select a %s name%s"
5188                   isa                   isa
5189                   (if class-selector                   (if class-selector
5190                       (format " (class is %s)" class-selector)                       (format " (class is %s)"
5191                                 (if (eq class-selector t)
5192                                     "unknown" class-selector))
5193                     ""))                     ""))
5194           isa           isa
5195           'idlwave-attach-method-classes)))           'idlwave-attach-method-classes)))
5196    
5197         ((and (memq what '(procedure-keyword function-keyword))
5198               (equal arg '(4)))
5199          (idlwave-complete 3))
5200    
5201       ((eq what 'procedure-keyword)       ((eq what 'procedure-keyword)
5202        ;; Complete a procedure keyword        ;; Complete a procedure keyword
5203        (let* ((where (nth 3 where-list))        (let* ((where (nth 3 where-list))
# Line 4795  When we force a method or a method keywo Line 5217  When we force a method or a method keywo
5217          (setq list (idlwave-fix-keywords name 'pro class list))          (setq list (idlwave-fix-keywords name 'pro class list))
5218          (unless list (error (format "No keywords available for procedure %s"          (unless list (error (format "No keywords available for procedure %s"
5219                                      (idlwave-make-full-name class name))))                                      (idlwave-make-full-name class name))))
5220          (setq idlwave-completion-help-info          (setq idlwave-completion-help-info
5221                (list 'keyword name type-selector class-selector nil super-classes))                (list 'keyword name type-selector class-selector nil super-classes))
5222          (idlwave-complete-in-buffer          (idlwave-complete-in-buffer
5223           'keyword 'keyword list nil           'keyword 'keyword list nil
5224           (format "Select keyword for procedure %s%s"           (format "Select keyword for procedure %s%s"
5225                   (idlwave-make-full-name class name)                   (idlwave-make-full-name class name)
5226                   (if (or (member '("_EXTRA") list)                   (if (or (member '("_EXTRA") list)
5227                           (member '("_REF_EXTRA") list))                                             (member '("_REF_EXTRA") list))
5228                       " (note _EXTRA)" ""))                       " (note _EXTRA)" ""))
5229           isa           isa
5230           'idlwave-attach-keyword-classes)))           'idlwave-attach-keyword-classes)))
# Line 4833  When we force a method or a method keywo Line 5255  When we force a method or a method keywo
5255                           (idlwave-make-full-name class name)))                           (idlwave-make-full-name class name)))
5256          (unless list (error (format "No keywords available for function %s"          (unless list (error (format "No keywords available for function %s"
5257                                      msg-name)))                                      msg-name)))
5258          (setq idlwave-completion-help-info          (setq idlwave-completion-help-info
5259                (list 'keyword name type-selector class-selector nil super-classes))                (list 'keyword name type-selector class-selector nil super-classes))
5260          (idlwave-complete-in-buffer          (idlwave-complete-in-buffer
5261           'keyword 'keyword list nil           'keyword 'keyword list nil
5262           (format "Select keyword for function %s%s" msg-name           (format "Select keyword for function %s%s" msg-name
5263                   (if (or (member '("_EXTRA") list)                   (if (or (member '("_EXTRA") list)
5264                           (member '("_REF_EXTRA") list))                                             (member '("_REF_EXTRA") list))
5265                       " (note _EXTRA)" ""))                       " (note _EXTRA)" ""))
5266           isa           isa
5267           'idlwave-attach-keyword-classes)))           'idlwave-attach-keyword-classes)))
# Line 4854  use `idlwave-complete-in-buffer' to do s Line 5276  use `idlwave-complete-in-buffer' to do s
5276  If such a function returns `t', *no further* attempts to complete  If such a function returns `t', *no further* attempts to complete
5277  other contexts will be done.  If the function returns `nil', other completions  other contexts will be done.  If the function returns `nil', other completions
5278  will be tried.")  will be tried.")
5279  (defun idlwave-complete-special ()  
5280    (let ((functions idlwave-complete-special)  (defun idlwave-call-special (functions &rest args)
5281          fun)    (let ((funcs functions)
5282            fun ret)
5283      (catch 'exit      (catch 'exit
5284        (while (setq fun (pop functions))        (while (setq fun (pop funcs))
5285          (if (funcall fun)          (if (setq ret (apply fun args))
5286              (throw 'exit t)))              (throw 'exit ret)))
5287        nil)))        nil)))
5288    
5289  (defun idlwave-make-force-complete-where-list (what &optional module class)  (defun idlwave-make-force-complete-where-list (what &optional module class)
# Line 4876  will be tried.") Line 5299  will be tried.")
5299                        ("class")))                        ("class")))
5300           (module (idlwave-sintern-routine-or-method module class))           (module (idlwave-sintern-routine-or-method module class))
5301           (class (idlwave-sintern-class class))           (class (idlwave-sintern-class class))
5302           (what (cond           (what (cond
5303                  ((equal what 0)                  ((equal what 0)
5304                   (setq what                   (setq what
5305                         (intern (completing-read                         (intern (completing-read
5306                                  "Complete what? " what-list nil t))))                                  "Complete what? " what-list nil t))))
5307                  ((integerp what)                  ((integerp what)
5308                   (setq what (intern (car (nth (1- what) what-list)))))                   (setq what (intern (car (nth (1- what) what-list)))))
# Line 4901  will be tried.") Line 5324  will be tried.")
5324               (super-classes nil)               (super-classes nil)
5325               (type-selector 'pro)               (type-selector 'pro)
5326               (pro (or module               (pro (or module
5327                        (idlwave-completing-read                        (idlwave-completing-read
5328                         "Procedure: " (idlwave-routines) 'idlwave-selector))))                         "Procedure: " (idlwave-routines) 'idlwave-selector))))
5329          (setq pro (idlwave-sintern-routine pro))          (setq pro (idlwave-sintern-routine pro))
5330          (list nil-list nil-list 'procedure-keyword          (list nil-list nil-list 'procedure-keyword
# Line 4915  will be tried.") Line 5338  will be tried.")
5338               (super-classes nil)               (super-classes nil)
5339               (type-selector 'fun)               (type-selector 'fun)
5340               (func (or module               (func (or module
5341                         (idlwave-completing-read                         (idlwave-completing-read
5342                          "Function: " (idlwave-routines) 'idlwave-selector))))                          "Function: " (idlwave-routines) 'idlwave-selector))))
5343          (setq func (idlwave-sintern-routine func))          (setq func (idlwave-sintern-routine func))
5344          (list nil-list nil-list 'function-keyword          (list nil-list nil-list 'function-keyword
# Line 4955  will be tried.") Line 5378  will be tried.")
5378    
5379       ((eq what 'class)       ((eq what 'class)
5380        (list nil-list nil-list 'class nil-list nil))        (list nil-list nil-list 'class nil-list nil))
5381        
5382       (t (error "Illegal value for WHAT")))))       (t (error "Illegal value for WHAT")))))
5383    
5384  (defun idlwave-completing-read (&rest args)  (defun idlwave-completing-read (&rest args)
# Line 4978  will be tried.") Line 5401  will be tried.")
5401                      (stringp idlwave-shell-default-directory)                      (stringp idlwave-shell-default-directory)
5402                      (file-directory-p idlwave-shell-default-directory))                      (file-directory-p idlwave-shell-default-directory))
5403                 idlwave-shell-default-directory                 idlwave-shell-default-directory
5404               default-directory)))                         default-directory)))
5405      (comint-dynamic-complete-filename)))      (comint-dynamic-complete-filename)))
5406    
5407  (defun idlwave-make-full-name (class name)  (defun idlwave-make-full-name (class name)
# Line 4987  will be tried.") Line 5410  will be tried.")
5410    
5411  (defun idlwave-rinfo-assoc (name type class list)  (defun idlwave-rinfo-assoc (name type class list)
5412    "Like `idlwave-rinfo-assq', but sintern strings first."    "Like `idlwave-rinfo-assq', but sintern strings first."
5413    (idlwave-rinfo-assq    (idlwave-rinfo-assq
5414     (idlwave-sintern-routine-or-method name class)     (idlwave-sintern-routine-or-method name class)
5415     type (idlwave-sintern-class class) list))     type (idlwave-sintern-class class) list))
5416    
# Line 5104  When TYPE is not specified, both procedu Line 5527  When TYPE is not specified, both procedu
5527        (setq list (cdr list)))        (setq list (cdr list)))
5528      (nreverse rtn)))      (nreverse rtn)))
5529    
5530    (defun idlwave-explicit-class-listed (info)
5531      "Return whether or not the class is listed explicitly, ala a->b::c.
5532    INFO is as returned by idlwave-what-function or -procedure."
5533      (let ((apos (nth 3 info)))
5534        (if apos
5535            (save-excursion (goto-char apos)
5536                            (looking-at "->[a-zA-Z][a-zA-Z0-9$_]*::")))))
5537    
5538    (defvar idlwave-determine-class-special nil
5539      "List of special functions for determining class.
5540    Must accept two arguments: `apos' and `info'")
5541    
5542  (defun idlwave-determine-class (info type)  (defun idlwave-determine-class (info type)
5543    ;; Determine the class of a routine call.  INFO is the structure returned    ;; Determine the class of a routine call.
5544    ;; `idlwave-what-function' or `idlwave-what-procedure'.    ;; INFO is the `cw-list' structure as returned by idlwave-where.
5545    ;; The third element in this structure is the class.  When nil, we return nil.    ;; The second element in this structure is the class.  When nil, we
5546    ;; When t, try to get the class from text properties at the arrow.  When    ;; return nil.  When t, try to get the class from text properties at
5547    ;; the object is "self", we use the class of the current routine.    ;; the arrow.  When the object is "self", we use the class of the
5548    ;; otherwise prompt the user for a class name.  Also stores the selected    ;; current routine.  otherwise prompt the user for a class name.
5549    ;; class as a text property at the arrow.    ;; Also stores the selected class as a text property at the arrow.
5550    ;; TYPE is 'fun or 'pro.    ;; TYPE is 'fun or 'pro.
5551    (let* ((class (nth 2 info))    (let* ((class (nth 2 info))
5552           (apos (nth 3 info))           (apos (nth 3 info))
# Line 5125  When TYPE is not specified, both procedu Line 5560  When TYPE is not specified, both procedu
5560                        (dassoc (cdr dassoc))                        (dassoc (cdr dassoc))
5561                        (t t)))                        (t t)))
5562           (arrow (and apos (string= (buffer-substring apos (+ 2 apos)) "->")))           (arrow (and apos (string= (buffer-substring apos (+ 2 apos)) "->")))
5563           (is-self           (is-self
5564            (and arrow            (and arrow
5565                 (save-excursion (goto-char apos)                 (save-excursion (goto-char apos)
5566                                 (forward-word -1)                                 (forward-word -1)
5567                                 (let ((case-fold-search t))                                 (let ((case-fold-search t))
5568                                   (looking-at "self\\>")))))                                   (looking-at "self\\>")))))
5569           (force-query idlwave-force-class-query)           (force-query idlwave-force-class-query)
5570           store class-alist)           store special-class class-alist)
5571      (cond      (cond
5572       ((null class) nil)       ((null class) nil)
5573       ((eq t class)       ((eq t class)
# Line 5142  When TYPE is not specified, both procedu Line 5577  When TYPE is not specified, both procedu
5577                 (not force-query))                 (not force-query))
5578            (setq class (get-text-property apos 'idlwave-class)            (setq class (get-text-property apos 'idlwave-class)
5579                  class (idlwave-sintern-class class)))                  class (idlwave-sintern-class class)))
5580          (if (and (eq t class) is-self)
5581              (setq class (or (nth 2 (idlwave-current-routine)) class)))
5582    
5583          ;; Before prompting, try any special class determination routines
5584        (when (and (eq t class)        (when (and (eq t class)
5585                   is-self)                   idlwave-determine-class-special
5586          (setq class (or (nth 2 (idlwave-current-routine)) class)))                   (not force-query))
5587            (setq special-class
5588                  (idlwave-call-special idlwave-determine-class-special apos))
5589            (if special-class
5590                (setq class (idlwave-sintern-class special-class)
5591                      store idlwave-store-inquired-class)))
5592    
5593          ;; Prompt for a class, if we need to
5594        (when (and (eq class t)        (when (and (eq class t)
5595                   (or force-query query))                   (or force-query query))
5596          (setq class-alist          (setq class-alist
5597                (mapcar 'list (idlwave-all-method-classes (car info) type)))                (mapcar 'list (idlwave-all-method-classes (car info) type)))
5598          (setq class          (setq class
5599                (idlwave-sintern-class                (idlwave-sintern-class
# Line 5156  When TYPE is not specified, both procedu Line 5602  When TYPE is not specified, both procedu
5602                   (error "No classes available with method %s" (car info)))                   (error "No classes available with method %s" (car info)))
5603                  ((and (= (length class-alist) 1) (not force-query))                  ((and (= (length class-alist) 1) (not force-query))
5604                   (car (car class-alist)))                   (car (car class-alist)))
5605                  (t                  (t
5606                   (setq store idlwave-store-inquired-class)                   (setq store idlwave-store-inquired-class)
5607                   (idlwave-completing-read                   (idlwave-completing-read
5608                    (format "Class%s: " (if (stringp (car info))                    (format "Class%s: " (if (stringp (car info))
5609                                            (format " for %s method %s"                                            (format " for %s method %s"
5610                                                    type (car info))                                                    type (car info))
5611                                          ""))                                          ""))
5612                    class-alist nil nil nil 'idlwave-class-history))))))                    class-alist nil nil nil 'idlwave-class-history))))))
5613    
5614          ;; Store it, if requested
5615        (when (and class (not (eq t class)))        (when (and class (not (eq t class)))
5616          ;; We have a real class here          ;; We have a real class here
5617          (when (and store arrow)          (when (and store arrow)
5618            (put-text-property apos (+ apos 2) 'idlwave-class class)            (condition-case ()
5619            (put-text-property apos (+ apos 2) 'face idlwave-class-arrow-face))                (add-text-properties
5620                   apos (+ apos 2)
5621                   `(idlwave-class ,class face ,idlwave-class-arrow-face
5622                                   rear-nonsticky t))
5623                (error nil)))
5624          (setf (nth 2 info) class))          (setf (nth 2 info) class))
5625        ;; Return the class        ;; Return the class
5626        class)        class)
# Line 5189  When TYPE is not specified, both procedu Line 5641  When TYPE is not specified, both procedu
5641  (defun idlwave-where ()  (defun idlwave-where ()
5642    "Find out where we are.    "Find out where we are.
5643  The return value is a list with the following stuff:  The return value is a list with the following stuff:
5644  (PRO-LIST FUNC-LIST COMPLETE-WHAT CW-LIST LAST-CHAR)  \(PRO-LIST FUNC-LIST COMPLETE-WHAT CW-LIST LAST-CHAR)
5645    
5646  PRO-LIST       (PRO POINT CLASS ARROW)  PRO-LIST       (PRO POINT CLASS ARROW)
5647  FUNC-LIST      (FUNC POINT CLASS ARROW)  FUNC-LIST      (FUNC POINT CLASS ARROW)
5648  COMPLETE-WHAT  a symbol indicating what kind of completion makes sense here  COMPLETE-WHAT  a symbol indicating what kind of completion makes sense here
5649  CW-LIST        Like PRO-LIST, for what can be copmpleted here.  CW-LIST        (PRO-OR-FUNC POINT CLASS ARROW)  Like PRO-LIST, for what can
5650                   be completed here.
5651  LAST-CHAR      last relevant character before point (non-white non-comment,  LAST-CHAR      last relevant character before point (non-white non-comment,
5652                 not part of current identifier or leading slash).                 not part of current identifier or leading slash).
5653    
# Line 5203  PRO:    Procedure name Line 5656  PRO:    Procedure name
5656  FUNC:   Function name  FUNC:   Function name
5657  POINT:  Where is this  POINT:  Where is this
5658  CLASS:  What class has the routine (nil=no, t=is method, but class unknown)  CLASS:  What class has the routine (nil=no, t=is method, but class unknown)
5659  ARROW:  Where is the arrow?"  ARROW:  Location of the arrow"
5660    (idlwave-routines)    (idlwave-routines)
5661    (let* (;(bos (save-excursion (idlwave-beginning-of-statement) (point)))    (let* (;(bos (save-excursion (idlwave-beginning-of-statement) (point)))
5662           (bos (save-excursion (idlwave-start-of-substatement 'pre) (point)))           (bos (save-excursion (idlwave-start-of-substatement 'pre) (point)))
# Line 5226  ARROW:  Where is the arrow?" Line 5679  ARROW:  Where is the arrow?"
5679       ((string-match "\\`[ \t]*\\(pro\\|function\\)[ \t]+[a-zA-Z0-9_]*\\'"       ((string-match "\\`[ \t]*\\(pro\\|function\\)[ \t]+[a-zA-Z0-9_]*\\'"
5680                      (buffer-substring bos (point)))                      (buffer-substring bos (point)))
5681        (setq cw 'class))        (setq cw 'class))
5682       ((string-match       ((string-match
5683         "\\`[ \t]*\\([a-zA-Z][a-zA-Z0-9$_]*\\)?\\'"         "\\`[ \t]*\\([a-zA-Z][a-zA-Z0-9$_]*\\)?\\'"
5684         (buffer-substring (if (> pro-point 0) pro-point bos) (point)))         (buffer-substring (if (> pro-point 0) pro-point bos) (point)))
5685        (setq cw 'procedure cw-class pro-class cw-point pro-point        (setq cw 'procedure cw-class pro-class cw-point pro-point
5686              cw-arrow pro-arrow))              cw-arrow pro-arrow))
# Line 5236  ARROW:  Where is the arrow?" Line 5689  ARROW:  Where is the arrow?"
5689        nil)        nil)
5690       ((string-match "OBJ_NEW([ \t]*['\"]\\([a-zA-Z0-9$_]*\\)?\\'"       ((string-match "OBJ_NEW([ \t]*['\"]\\([a-zA-Z0-9$_]*\\)?\\'"
5691                      (buffer-substring bos (point)))                      (buffer-substring bos (point)))
5692        (setq cw 'class))                            (setq cw 'class))
5693       ((string-match "\\<inherits\\s-+\\([a-zA-Z0-9$_]*\\)?\\'"       ((string-match "\\<inherits\\s-+\\([a-zA-Z0-9$_]*\\)?\\'"
5694                      (buffer-substring bos (point)))                      (buffer-substring bos (point)))
5695        (setq cw 'class))                            (setq cw 'class))
5696       ((and func       ((and func
5697             (> func-point pro-point)             (> func-point pro-point)
5698             (= func-level 1)             (= func-level 1)
5699             (memq last-char '(?\( ?,)))             (memq last-char '(?\( ?,)))
# Line 5259  ARROW:  Where is the arrow?" Line 5712  ARROW:  Where is the arrow?"
5712        (setq cw 'function)        (setq cw 'function)
5713        (save-excursion        (save-excursion
5714          (if (re-search-backward "->[ \t]*\\(\\([$a-zA-Z0-9_]+\\)::\\)?[$a-zA-Z0-9_]*\\=" bos t)          (if (re-search-backward "->[ \t]*\\(\\([$a-zA-Z0-9_]+\\)::\\)?[$a-zA-Z0-9_]*\\=" bos t)
5715              (setq cw-arrow (match-beginning 0)              (setq cw-arrow (copy-marker (match-beginning 0))
5716                    cw-class (if (match-end 2)                    cw-class (if (match-end 2)
5717                                 (idlwave-sintern-class (match-string 2))                                 (idlwave-sintern-class (match-string 2))
5718                                t))))))                               t))))))
5719      (list (list pro pro-point pro-class pro-arrow)      (list (list pro pro-point pro-class pro-arrow)
5720            (list func func-point func-class func-arrow)            (list func func-point func-class func-arrow)
5721            cw            cw
# Line 5279  ARROW:  Where is the arrow?" Line 5732  ARROW:  Where is the arrow?"
5732    
5733  (defun idlwave-what-function (&optional bound)  (defun idlwave-what-function (&optional bound)
5734    ;; Find out if point is within the argument list of a function.    ;; Find out if point is within the argument list of a function.
5735    ;; The return value is ("function-name" (point) level).    ;; The return value is ("function-name" class arrow-start (point) level).
5736    ;; Level is 1 on the to level parenthesis, higher further down.    ;; Level is 1 on the top level parentheses, higher further down.
5737    
5738    ;; If the optional BOUND is an integer, bound backwards directed    ;; If the optional BOUND is an integer, bound backwards directed
5739    ;;    searches to this point.    ;;    searches to this point.
5740    
5741    (catch 'exit    (catch 'exit
5742      (let (pos      (let (pos
5743            func-point            func-point
5744            (cnt 0)            (cnt 0)
5745            func arrow-start class)            func arrow-start class)
# Line 5301  ARROW:  Where is the arrow?" Line 5754  ARROW:  Where is the arrow?"
5754               (setq pos (point))               (setq pos (point))
5755               (incf cnt)               (incf cnt)
5756               (when (and (= (following-char) ?\()               (when (and (= (following-char) ?\()
5757                          (re-search-backward                          (re-search-backward
5758                           "\\(::\\|\\<\\)\\([a-zA-Z][a-zA-Z0-9$_]*\\)[ \t]*\\="                           "\\(::\\|\\<\\)\\([a-zA-Z][a-zA-Z0-9$_]*\\)[ \t]*\\="
5759                           bound t))                           bound t))
5760                 (setq func (match-string 2)                 (setq func (match-string 2)
5761                       func-point (goto-char (match-beginning 2))                       func-point (goto-char (match-beginning 2))
5762                       pos func-point)                       pos func-point)
5763                 (if (re-search-backward                 (if (re-search-backward
5764                      "->[ \t]*\\(\\([a-zA-Z][a-zA-Z0-9$_]*\\)::\\)?\\=" bound t)                      "->[ \t]*\\(\\([a-zA-Z][a-zA-Z0-9$_]*\\)::\\)?\\=" bound t)
5765                     (setq arrow-start (match-beginning 0)                     (setq arrow-start (copy-marker (match-beginning 0))
5766                           class (or (match-string 2) t)))                           class (or (match-string 2) t)))
5767                 (throw                 (throw
5768                  'exit                  'exit
5769                  (list                  (list
5770                   (idlwave-sintern-routine-or-method func class)                   (idlwave-sintern-routine-or-method func class)
5771                   (idlwave-sintern-class class)                   (idlwave-sintern-class class)
# Line 5328  ARROW:  Where is the arrow?" Line 5781  ARROW:  Where is the arrow?"
5781    ;;    searches to this point.    ;;    searches to this point.
5782    (let ((pos (point)) pro-point    (let ((pos (point)) pro-point
5783          pro class arrow-start string)          pro class arrow-start string)
5784      (save-excursion      (save-excursion
5785        ;;(idlwave-beginning-of-statement)        ;;(idlwave-beginning-of-statement)
5786        (idlwave-start-of-substatement 'pre)        (idlwave-start-of-substatement 'pre)
5787        (setq string (buffer-substring (point) pos))        (setq string (buffer-substring (point) pos))
5788        (if (string-match        (if (string-match
5789             "\\`[ \t]*\\([a-zA-Z][a-zA-Z0-9$_]*\\)[ \t]*\\(,\\|\\'\\)" string)             "\\`[ \t]*\\([a-zA-Z][a-zA-Z0-9$_]*\\)[ \t]*\\(,\\|\\'\\)" string)
5790            (setq pro (match-string 1 string)            (setq pro (match-string 1 string)
5791                  pro-point (+ (point) (match-beginning 1)))                  pro-point (+ (point) (match-beginning 1)))
5792          (if (and (idlwave-skip-object)          (if (and (idlwave-skip-object)
5793                   (setq string (buffer-substring (point) pos))                   (setq string (buffer-substring (point) pos))
5794                   (string-match                   (string-match
5795                    "\\`[ \t]*\\(->\\)[ \t]*\\(\\([a-zA-Z][a-zA-Z0-9$_]*\\)::\\)?\\([a-zA-Z][a-zA-Z0-9$_]*\\)?[ \t]*\\(,\\|\\'\\)" string))                    "\\`[ \t]*\\(->\\)[ \t]*\\(\\([a-zA-Z][a-zA-Z0-9$_]*\\)::\\)?\\([a-zA-Z][a-zA-Z0-9$_]*\\)?[ \t]*\\(,\\|\\'\\)" string))
5796              (setq pro (if (match-beginning 4)              (setq pro (if (match-beginning 4)
5797                            (match-string 4 string))                            (match-string 4 string))
5798                    pro-point (if (match-beginning 4)                    pro-point (if (match-beginning 4)
5799                                  (+ (point) (match-beginning 4))                                  (+ (point) (match-beginning 4))
5800                          pos)                          pos)
5801                    arrow-start (+ (point) (match-beginning 1))                    arrow-start (copy-marker (+ (point) (match-beginning 1)))
5802                    class (or (match-string 3 string) t)))))                    class (or (match-string 3 string) t)))))
5803      (list (idlwave-sintern-routine-or-method pro class)      (list (idlwave-sintern-routine-or-method pro class)
5804            (idlwave-sintern-class class)            (idlwave-sintern-class class)
# Line 5382  ARROW:  Where is the arrow?" Line 5835  ARROW:  Where is the arrow?"
5835                (throw 'exit nil))))                (throw 'exit nil))))
5836          (goto-char pos)          (goto-char pos)
5837        nil)))        nil)))
     
5838    
5839  (defun idlwave-last-valid-char ()  (defun idlwave-last-valid-char ()
5840    "Return the last character before point which is not white or a comment    "Return the last character before point which is not white or a comment
# Line 5404  This function is not general, can only b Line 5856  This function is not general, can only b
5856           ((memq (preceding-char) '(?\; ?\$)) (throw 'exit nil))           ((memq (preceding-char) '(?\; ?\$)) (throw 'exit nil))
5857           ((eq (preceding-char) ?\n)           ((eq (preceding-char) ?\n)
5858            (beginning-of-line 0)            (beginning-of-line 0)
5859            (if (looking-at "\\([^;]\\)*\\$[ \t]*\\(;.*\\)?\n")            (if (looking-at "\\([^;\n]*\\)\\$[ \t]*\\(;[^\n]*\\)?\n")
5860                ;; continuation line                ;; continuation line
5861                (goto-char (match-end 1))                (goto-char (match-end 1))
5862              (throw 'exit nil)))              (throw 'exit nil)))
# Line 5420  This function is not general, can only b Line 5872  This function is not general, can only b
5872  (defun idlwave-complete-in-buffer (type stype list selector prompt isa  (defun idlwave-complete-in-buffer (type stype list selector prompt isa
5873                                          &optional prepare-display-function)                                          &optional prepare-display-function)
5874    "Perform TYPE completion of word before point against LIST.    "Perform TYPE completion of word before point against LIST.
5875  SELECTOR is the PREDICATE argument for the completion function.  SELECTOR is the PREDICATE argument for the completion function.  Show
5876  Show PROMPT in echo area.  TYPE is one of 'function, 'procedure or 'keyword."  PROMPT in echo area.  TYPE is one of 'function, 'procedure,
5877    'class-tag, or 'keyword."
5878    (let* ((completion-ignore-case t)    (let* ((completion-ignore-case t)
5879           beg (end (point)) slash part spart completion all-completions           beg (end (point)) slash part spart completion all-completions
5880           dpart dcompletion)           dpart dcompletion)
# Line 5450  Show PROMPT in echo area.  TYPE is one o Line 5903  Show PROMPT in echo area.  TYPE is one o
5903      (cond      (cond
5904       ((null completion)       ((null completion)
5905        ;; nothing available.        ;; nothing available.
5906        (error "Can't find %s completion for \"%s\"" isa part))        (error (concat prompt ": no completion for \"%s\"") part))
5907       ((and (not (equal dpart dcompletion))       ((and (not (equal dpart dcompletion))
5908             (not (eq t completion)))             (not (eq t completion)))
5909        ;; We can add something        ;; We can add something
# Line 5493  Show PROMPT in echo area.  TYPE is one o Line 5946  Show PROMPT in echo area.  TYPE is one o
5946                       idlwave-complete-empty-string-as-lower-case)                       idlwave-complete-empty-string-as-lower-case)
5947                   (not idlwave-completion-force-default-case))                   (not idlwave-completion-force-default-case))
5948              (setq list (mapcar (lambda (x)              (setq list (mapcar (lambda (x)
5949                                   (if (listp x)                                   (if (listp x)
5950                                       (setcar x (downcase (car x)))                                       (setcar x (downcase (car x)))
5951                                     (setq x (downcase x)))                                     (setq x (downcase x)))
5952                                   x)                                   x)
# Line 5513  Show PROMPT in echo area.  TYPE is one o Line 5966  Show PROMPT in echo area.  TYPE is one o
5966             (re-search-backward "\\<\\(pro\\|function\\)[ \t]+\\="             (re-search-backward "\\<\\(pro\\|function\\)[ \t]+\\="
5967                                 (- (point) 15) t)                                 (- (point) 15) t)
5968             (goto-char (point-min))             (goto-char (point-min))
5969             (re-search-forward             (re-search-forward
5970              "^[ \t]*\\(pro\\|function\\)[ \t]+\\([a-zA-Z0-9_]+::\\)" nil t))))              "^[ \t]*\\(pro\\|function\\)[ \t]+\\([a-zA-Z0-9_]+::\\)" nil t))))
5971        ;; Yank the full class specification        ;; Yank the full class specification
5972        (insert (match-string 2))        (insert (match-string 2))
5973      ;; Do the completion      ;; Do the completion
5974      (idlwave-complete-in-buffer 'class 'class (idlwave-class-alist) nil      (idlwave-complete-in-buffer 'class 'class (idlwave-class-alist) nil
5975                                  "Select a class" "class")))                                  "Select a class" "class")))
5976    
5977  (defun idlwave-attach-classes (list is-kwd show-classes)  (defun idlwave-attach-classes (list type show-classes)
5978    ;; Attach the proper class list to a LIST of completion items.    ;; Attach the proper class list to a LIST of completion items.
5979    ;; IS-KWD, when non-nil, shows its keywords - otherwise its methods    ;; TYPE, when 'kwd, shows classes for method keywords, when
5980      ;; 'class-tag, for class tags, and otherwise for methods.
5981    ;; SHOW-CLASSES is the value of `idlwave-completion-show-classes'.    ;; SHOW-CLASSES is the value of `idlwave-completion-show-classes'.
5982    (catch 'exit    (if (or (null show-classes)           ; don't want to see classes
5983      (if (or (null show-classes)           ; don't want to see classes            (null class-selector)         ; not a method call
5984              (null class-selector)         ; not a method call            (and
5985              (and (stringp class-selector) ; the class is already known             (stringp class-selector) ; the class is already known
5986                   (not super-classes)))    ; no possibilities for inheritance             (not super-classes)))    ; no possibilities for inheritance
5987          ;; In these cases, we do not have to do anything        ;; In these cases, we do not have to do anything
5988          (throw 'exit list))        list
       
5989      (let* ((do-prop (and (>= show-classes 0)      (let* ((do-prop (and (>= show-classes 0)
5990                           (>= emacs-major-version 21)))                           (>= emacs-major-version 21)))
5991             (do-buf (not (= show-classes 0)))             (do-buf (not (= show-classes 0)))
5992             ; (do-dots (featurep 'xemacs))             ;; (do-dots (featurep 'xemacs))
5993             (do-dots t)             (do-dots t)
5994             (inherit (if super-classes             (inherit (if (and (not (eq type 'class-tag)) super-classes)
5995                          (cons class-selector super-classes)))                          (cons class-selector super-classes)))
5996             (max (abs show-classes))             (max (abs show-classes))
5997             (lmax (if do-dots (apply 'max (mapcar 'length list))))             (lmax (if do-dots (apply 'max (mapcar 'length list))))
5998            classes nclasses class-info space)            classes nclasses class-info space)
5999        (mapcar        (mapcar
6000         (lambda (x)         (lambda (x)
6001           ;; get the classes           ;; get the classes
6002           (setq classes           (if (eq type 'class-tag)
6003                 (if is-kwd               ;; Just one class for tags
6004                     (idlwave-all-method-keyword-classes               (setq classes
6005                      method-selector x type-selector)                     (list
6006                   (idlwave-all-method-classes x type-selector)))                      (idlwave-class-or-superclass-with-tag class-selector x)))
6007           (if inherit             ;; Multiple classes for method of method-keyword
6008               (setq classes             (setq classes
6009                     (delq nil                   (if (eq type 'kwd)
6010                           (mapcar (lambda (x) (if (memq x inherit) x nil))                       (idlwave-all-method-keyword-classes
6011                                   classes))))                        method-selector x type-selector)
6012                       (idlwave-all-method-classes x type-selector)))
6013               (if inherit
6014                   (setq classes
6015                         (delq nil
6016                               (mapcar (lambda (x) (if (memq x inherit) x nil))
6017                                       classes)))))
6018           (setq nclasses (length classes))           (setq nclasses (length classes))
6019           ;; Make the separator between item and class-info           ;; Make the separator between item and class-info
6020           (if do-dots           (if do-dots
# Line 5582  Show PROMPT in echo area.  TYPE is one o Line 6041  Show PROMPT in echo area.  TYPE is one o
6041    
6042  (defun idlwave-attach-method-classes (list)  (defun idlwave-attach-method-classes (list)
6043    ;; Call idlwave-attach-classes with method parameters    ;; Call idlwave-attach-classes with method parameters
6044    (idlwave-attach-classes list nil idlwave-completion-show-classes))    (idlwave-attach-classes list 'method idlwave-completion-show-classes))
6045  (defun idlwave-attach-keyword-classes (list)  (defun idlwave-attach-keyword-classes (list)
6046    ;; Call idlwave-attach-classes with keyword parameters    ;; Call idlwave-attach-classes with keyword parameters
6047    (idlwave-attach-classes list t idlwave-completion-show-classes))    (idlwave-attach-classes list 'kwd idlwave-completion-show-classes))
6048    (defun idlwave-attach-class-tag-classes (list)
6049      ;; Call idlwave-attach-classes with class structure tags
6050      (idlwave-attach-classes list 'class-tag idlwave-completion-show-classes))
6051    
6052    
6053  ;;----------------------------------------------------------------------  ;;----------------------------------------------------------------------
6054  ;;----------------------------------------------------------------------  ;;----------------------------------------------------------------------
6055  ;;----------------------------------------------------------------------  ;;----------------------------------------------------------------------
6056  ;;----------------------------------------------------------------------  ;;----------------------------------------------------------------------
6057  ;;----------------------------------------------------------------------  ;;----------------------------------------------------------------------
6058    (defvar rtn)
6059    (defun idlwave-pset (item)
6060      (set 'rtn item))
6061    
6062    (defun idlwave-popup-select (ev list title &optional sort)
6063      "Select an item in LIST with a popup menu.
6064    TITLE is the title to put atop the popup.  If SORT is non-nil,
6065    sort the list before displaying"
6066      (let ((maxpopup idlwave-max-popup-menu-items)
6067            rtn menu resp)
6068        (cond ((null list))
6069              ((= 1 (length list))
6070               (setq rtn (car list)))
6071              ((featurep 'xemacs)
6072               (if sort (setq list (sort list (lambda (a b)
6073                                                (string< (upcase a) (upcase b))))))
6074               (setq menu
6075                     (append (list title)
6076                             (mapcar (lambda (x) (vector x (list 'idlwave-pset
6077                                                                 x)))
6078                                     list)))
6079               (setq menu (idlwave-split-menu-xemacs menu maxpopup))
6080               (setq resp (get-popup-menu-response menu))
6081               (funcall (event-function resp) (event-object resp)))
6082              (t
6083               (if sort (setq list (sort list (lambda (a b)
6084                                                (string< (upcase a) (upcase b))))))
6085               (setq menu (cons title
6086                                (list
6087                                 (append (list "")
6088                                         (mapcar (lambda(x) (cons x x)) list)))))
6089               (setq menu (idlwave-split-menu-emacs menu maxpopup))
6090               (setq rtn (x-popup-menu ev menu))))
6091        rtn))
6092    
6093    (defun idlwave-split-menu-xemacs (menu N)
6094      "Split the MENU into submenus of maximum length N."
6095      (if (<= (length menu) (1+ N))
6096          ;; No splitting needed
6097          menu
6098        (let* ((title (car menu))
6099               (entries (cdr menu))
6100               (menu (list title))
6101               (cnt 0)
6102               (nextmenu nil))
6103          (while entries
6104            (while (and entries (< cnt N))
6105              (setq cnt (1+ cnt)
6106                    nextmenu (cons (car entries) nextmenu)
6107                    entries (cdr entries)))
6108            (setq nextmenu (nreverse nextmenu))
6109            (setq nextmenu (cons (format "%s...%s"
6110                                         (aref (car nextmenu) 0)
6111                                         (aref (nth (1- cnt) nextmenu) 0))
6112                                 nextmenu))
6113            (setq menu (cons nextmenu menu)
6114                  nextmenu nil
6115                  cnt 0))
6116          (nreverse menu))))
6117    
6118    (defun idlwave-split-menu-emacs (menu N)
6119      "Split the MENU into submenus of maximum length N."
6120      (if (<= (length (nth 1 menu)) (1+ N))
6121          ;; No splitting needed
6122          menu
6123        (let* ((title (car menu))
6124               (entries (cdr (nth 1 menu)))
6125               (menu nil)
6126               (cnt 0)
6127               (nextmenu nil))
6128          (while entries
6129            (while (and entries (< cnt N))
6130              (setq cnt (1+ cnt)
6131                    nextmenu (cons (car entries) nextmenu)
6132                    entries (cdr entries)))
6133            (setq nextmenu (nreverse nextmenu))
6134            (prin1 nextmenu)
6135            (setq nextmenu (cons (format "%s...%s"
6136                                         (car (car nextmenu))
6137                                         (car (nth (1- cnt) nextmenu)))
6138                                 nextmenu))
6139            (setq menu (cons nextmenu menu)
6140                  nextmenu nil
6141                  cnt 0))
6142          (setq menu (nreverse menu))
6143          (setq menu (cons title menu))
6144          menu)))
6145    
6146  (defvar idlwave-completion-setup-hook nil)  (defvar idlwave-completion-setup-hook nil)
6147    
# Line 5621  Show PROMPT in echo area.  TYPE is one o Line 6171  Show PROMPT in echo area.  TYPE is one o
6171      (setq idlwave-before-completion-wconf (current-window-configuration)))      (setq idlwave-before-completion-wconf (current-window-configuration)))
6172    
6173    (if (featurep 'xemacs)    (if (featurep 'xemacs)
6174        (idlwave-display-completion-list-xemacs        (idlwave-display-completion-list-xemacs
6175         list)         list)
6176      (idlwave-display-completion-list-emacs list))      (idlwave-display-completion-list-emacs list))
6177    
# Line 5657  Show PROMPT in echo area.  TYPE is one o Line 6207  Show PROMPT in echo area.  TYPE is one o
6207          (remove-text-properties beg (point) '(face nil))))          (remove-text-properties beg (point) '(face nil))))
6208    (eval idlwave-complete-after-success-form-force))    (eval idlwave-complete-after-success-form-force))
6209    
6210    (defun idlwave-keyboard-quit ()
6211      (interactive)
6212      (unwind-protect
6213          (if (eq (car-safe last-command) 'idlwave-display-completion-list)
6214              (idlwave-restore-wconf-after-completion))
6215        (keyboard-quit)))
6216    
6217  (defun idlwave-restore-wconf-after-completion ()  (defun idlwave-restore-wconf-after-completion ()
6218    "Restore the old (before completion) window configuration."    "Restore the old (before completion) window configuration."
6219    (and idlwave-completion-restore-window-configuration    (and idlwave-completion-restore-window-configuration
# Line 5709  Show PROMPT in echo area.  TYPE is one o Line 6266  Show PROMPT in echo area.  TYPE is one o
6266                                      (setq this-command last-command)))                                      (setq this-command last-command)))
6267      new-map))      new-map))
6268    
6269  ;; In Emacs we also to replace choose keybindings in the completion  ;; In Emacs we also replace keybindings in the completion
6270  ;; map in order to install our wrappers.  ;; map in order to install our wrappers.
6271    
6272  (defun idlwave-display-completion-list-emacs (list)  (defun idlwave-display-completion-list-emacs (list)
# Line 5727  Show PROMPT in echo area.  TYPE is one o Line 6284  Show PROMPT in echo area.  TYPE is one o
6284  (defun idlwave-make-modified-completion-map-emacs (old-map)  (defun idlwave-make-modified-completion-map-emacs (old-map)
6285    "Replace `choose-completion' and `mouse-choose-completion' in OLD-MAP."    "Replace `choose-completion' and `mouse-choose-completion' in OLD-MAP."
6286    (let ((new-map (copy-keymap old-map)))    (let ((new-map (copy-keymap old-map)))
6287      (substitute-key-definition      (substitute-key-definition
6288       'choose-completion 'idlwave-choose-completion new-map)       'choose-completion 'idlwave-choose-completion new-map)
6289      (substitute-key-definition      (substitute-key-definition
6290       'mouse-choose-completion 'idlwave-mouse-choose-completion new-map)       'mouse-choose-completion 'idlwave-mouse-choose-completion new-map)
# Line 5753  Show PROMPT in echo area.  TYPE is one o Line 6310  Show PROMPT in echo area.  TYPE is one o
6310  ;;  ;;
6311  ;; - Go again over the documentation how to write a completion  ;; - Go again over the documentation how to write a completion
6312  ;;   plugin.  It is in self.el, but currently still very bad.  ;;   plugin.  It is in self.el, but currently still very bad.
6313  ;;   This could be in a separate file in the distribution, or  ;;   This could be in a separate file in the distribution, or
6314  ;;   in an appendix for the manual.    ;;   in an appendix for the manual.
6315    
6316  (defun idlwave-struct-tags ()  (defun idlwave-struct-tags ()
6317    "Return a list of all tags in the structure defined at point.    "Return a list of all tags in the structure defined at point.
# Line 5765  Point is expected just before the openin Line 6322  Point is expected just before the openin
6322             (end (cdr borders))             (end (cdr borders))
6323             tags)             tags)
6324        (goto-char beg)        (goto-char beg)
6325        (while (re-search-forward "[{,][ \t]*\\(\\$.*\n[ \t]*\\)?\\([a-zA-Z][a-zA-Z0-9_]*\\)[ \t]*:" end t)        (while (re-search-forward "[{,][ \t]*\\(\\$.*\n\\(^[ \t]*\\(\\$[ \t]*\\)?\\(;.*\\)?\n\\)*[ \t]*\\)?\\([a-zA-Z][a-zA-Z0-9_]*\\)[ \t]*:" end t)
6326          ;; Check if we are still on the top level of the structure.          ;; Check if we are still on the top level of the structure.
6327          (if (and (condition-case nil (progn (up-list -1) t) (error nil))          (if (and (condition-case nil (progn (up-list -1) t) (error nil))
6328                   (= (point) beg))                   (= (point) beg))
6329              (push (match-string 2) tags))              (push (match-string 5) tags))
6330          (goto-char (match-end 0)))          (goto-char (match-end 0)))
6331        (nreverse tags))))        (nreverse tags))))
6332    
6333    (defun idlwave-find-struct-tag (tag)
6334      "Find a given TAG in the structure defined at point."
6335      (let* ((borders (idlwave-struct-borders))
6336             (beg (car borders))
6337             (end (cdr borders))
6338             (case-fold-search t))
6339        (re-search-forward (concat "\\(^[ \t]*\\|[,{][ \t]*\\)" tag "[ \t]*:")
6340                           end t)))
6341    
6342  (defun idlwave-struct-inherits ()  (defun idlwave-struct-inherits ()
6343    "Return a list of all `inherits' names in the struct at point.    "Return a list of all `inherits' names in the struct at point.
6344  Point is expected just before the opening `{' of the struct definition."  Point is expected just before the opening `{' of the struct definition."
# Line 5791  Point is expected just before the openin Line 6357  Point is expected just before the openin
6357          (goto-char (match-end 0)))          (goto-char (match-end 0)))
6358        (nreverse names))))        (nreverse names))))
6359    
6360    (defun idlwave-in-structure ()
6361      "Return t if point is inside an IDL structure."
6362      (let ((beg (point)))
6363        (save-excursion
6364          (if (not (or (idlwave-in-comment) (idlwave-in-quote)))
6365              (if (idlwave-find-structure-definition nil nil 'back)
6366                  (let ((borders (idlwave-struct-borders)))
6367                    (or (= (car borders) (cdr borders)) ;; struct not yet closed...
6368                        (and (> beg (car borders)) (< beg (cdr borders))))))))))
6369    
6370  (defun idlwave-struct-borders ()  (defun idlwave-struct-borders ()
6371    "Return the borders of the {...} after point as a cons cell."    "Return the borders of the {...} after point as a cons cell."
# Line 5805  Point is expected just before the openin Line 6380  Point is expected just before the openin
6380  (defun idlwave-find-structure-definition (&optional var name bound)  (defun idlwave-find-structure-definition (&optional var name bound)
6381    "Search forward for a structure definition.    "Search forward for a structure definition.
6382  If VAR is non-nil, search for a structure assigned to variable VAR.  If VAR is non-nil, search for a structure assigned to variable VAR.
6383  If NAME is non-nil, search for a named structure NAME.  If NAME is non-nil, search for a named structure NAME.  If BOUND is an
6384  If BOUND is an integer, limit the search.  integer, limit the search.  If BOUND is the symbol `all', we search
6385  If BOUND is the symbol `all', we search first back and then forward  first back and then forward through the entire file.  If BOUND is the
6386  through the entire file."  symbol `back' we search only backward."
6387    (let* ((ws "[ \t]*\\(\\$.*\n[ \t]*\\)?")    (let* ((ws "[ \t]*\\(\\$.*\n[ \t]*\\)*")
6388           (case-fold-search t)           (case-fold-search t)
6389           (lim (if (integerp bound) bound nil))           (lim (if (integerp bound) bound nil))
6390           (re (concat           (re (concat
# Line 5818  through the entire file." Line 6393  through the entire file."
6393                  "\\(\\)")                  "\\(\\)")
6394                "=" ws "\\({\\)"                "=" ws "\\({\\)"
6395                (if name (concat ws "\\<" (downcase name) "[^a-zA-Z0-9_$]") ""))))                (if name (concat ws "\\<" (downcase name) "[^a-zA-Z0-9_$]") ""))))
6396      (if (or (and (eq bound 'all)      (if (or (and (or (eq bound 'all) (eq bound 'back))
6397                   (re-search-backward re nil t))                   (re-search-backward re nil t))
6398              (re-search-forward re lim t))              (and (not (eq bound 'back)) (re-search-forward re lim t)))
6399          (goto-char (match-beginning 3)))))          (goto-char (match-beginning 3)))))
6400    
6401  (defvar idlwave-class-info nil)  (defvar idlwave-class-info nil)
# Line 5857  through the entire file." Line 6432  through the entire file."
6432          (setcdr inherits (mapcar (lambda (x) (idlwave-sintern-class x 'set))          (setcdr inherits (mapcar (lambda (x) (idlwave-sintern-class x 'set))
6433                                   (cdr inherits))))))                                   (cdr inherits))))))
6434    
6435    (defun idlwave-find-class-definition (class)
6436      (let ((case-fold-search t))
6437        (if (re-search-forward
6438             (concat "^[ \t]*pro[ \t]+" (downcase class) "__define" "\\>") nil t)
6439            ;; FIXME: should we limit to end of pro here?
6440            (idlwave-find-structure-definition nil class))))
6441    
6442  (defun idlwave-find-class-info (class)  (defun idlwave-find-class-info (class)
6443    "Find the __define procedure for a class structure and return info entry."    "Find the __define procedure for a class structure and return info entry."
6444    (let* ((pro (concat (downcase class) "__define"))    (let* ((pro (concat (downcase class) "__define"))
6445           (class (idlwave-sintern-class class))           (class (idlwave-sintern-class class))
6446           (idlwave-auto-routine-info-updates nil)           (idlwave-auto-routine-info-updates nil)
6447           (file (cdr (nth 3 (idlwave-rinfo-assoc pro 'pro nil           (file (cdr (nth 3 (idlwave-rinfo-assoc pro 'pro nil
6448                                                  (idlwave-routines)))))                                                  (idlwave-routines)))))
6449           buf)           buf)
6450      (if (or (not file)      (if (or (not file)
6451              (not (file-regular-p              (not (file-regular-p
6452                    (setq file (idlwave-expand-lib-file-name file)))))                    (setq file (idlwave-expand-lib-file-name file)))))
6453          nil ; Cannot get info          nil ; Cannot get info
6454        (save-excursion        (save-excursion
# Line 5879  through the entire file." Line 6461  through the entire file."
6461            (insert-file-contents file))            (insert-file-contents file))
6462          (save-excursion          (save-excursion
6463            (goto-char 1)            (goto-char 1)
6464            (setq case-fold-search t)            (if (idlwave-find-class-definition class)
6465            (when (and (re-search-forward                (list class
6466                        (concat "^[ \t]*pro[ \t]+" pro "\\>") nil t)                      (cons 'tags (idlwave-struct-tags))
6467                       ;; FIXME: should we limit to end of pro here?                      (cons 'inherits (idlwave-struct-inherits)))))))))
                      (idlwave-find-structure-definition nil class))  
             (list class  
                   (cons 'tags (idlwave-struct-tags))  
                   (cons 'inherits (idlwave-struct-inherits)))))))))  
6468    
6469  (defun idlwave-class-tags (class)  (defun idlwave-class-tags (class)
6470    "Return the native tags in CLASS."    "Return the native tags in CLASS."
# Line 5897  through the entire file." Line 6475  through the entire file."
6475    
6476  (defun idlwave-all-class-tags (class)  (defun idlwave-all-class-tags (class)
6477    "Return a list of native and inherited tags in CLASS."    "Return a list of native and inherited tags in CLASS."
6478    (apply 'append (mapcar 'idlwave-class-tags    (condition-case err
6479                           (cons class (idlwave-all-class-inherits class)))))        (apply 'append (mapcar 'idlwave-class-tags
6480                                 (cons class (idlwave-all-class-inherits class))))
6481        (error
6482         (idlwave-class-tag-reset)
6483         (error "%s" (error-message-string err)))))
6484    
6485    
6486  (defun idlwave-all-class-inherits (class)  (defun idlwave-all-class-inherits (class)
6487    "Return a list of all superclasses of CLASS (recursively expanded).    "Return a list of all superclasses of CLASS (recursively expanded).
6488  The list is cashed in `idlwave-class-info' for faster access."  The list is cached in `idlwave-class-info' for faster access."
6489    (cond    (cond
6490     ((not idlwave-support-inheritance) nil)     ((not idlwave-support-inheritance) nil)
6491     ((eq class nil) nil)     ((eq class nil) nil)
# Line 5912  The list is cashed in `idlwave-class-inf Line 6495  The list is cashed in `idlwave-class-inf
6495            entry)            entry)
6496        (if (setq entry (assq 'all-inherits info))        (if (setq entry (assq 'all-inherits info))
6497            (cdr entry)            (cdr entry)
6498          (let ((inherits (idlwave-class-inherits class))          ;; Save the depth of inheritance scan to check for circular references
6499            (let ((inherits (mapcar (lambda (x) (cons x 0))
6500                                    (idlwave-class-inherits class)))
6501                rtn all-inherits cl)                rtn all-inherits cl)
6502            (while inherits            (while inherits
6503              (setq cl (pop inherits)              (setq cl (pop inherits)
6504                    rtn (cons cl rtn)                    rtn (cons (car cl) rtn)
6505                    inherits (append inherits (idlwave-class-inherits cl))))                    inherits (append (mapcar (lambda (x)
6506                                                 (cons x (1+ (cdr cl))))
6507                                               (idlwave-class-inherits (car cl)))
6508                                       inherits))
6509                (if (> (cdr cl) 999)
6510                  (error
6511                   "Class scan: inheritance depth exceeded. Circular inheritance?")
6512                  ))
6513            (setq all-inherits (nreverse rtn))            (setq all-inherits (nreverse rtn))
6514            (nconc info (list (cons 'all-inherits all-inherits)))            (nconc info (list (cons 'all-inherits all-inherits)))
6515            all-inherits))))))            all-inherits))))))
# Line 5931  The list is cashed in `idlwave-class-inf Line 6523  The list is cashed in `idlwave-class-inf
6523  (defvar idlwave-current-tags-class nil)  (defvar idlwave-current-tags-class nil)
6524  (defvar idlwave-current-class-tags nil)  (defvar idlwave-current-class-tags nil)
6525  (defvar idlwave-current-native-class-tags nil)  (defvar idlwave-current-native-class-tags nil)
6526  (defvar idlwave-sint-classtags nil)  (defvar idlwave-sint-class-tags nil)
6527  (idlwave-new-sintern-type 'classtag)  (idlwave-new-sintern-type 'class-tag)
6528  (add-to-list 'idlwave-complete-special 'idlwave-complete-class-structure-tag)  (add-to-list 'idlwave-complete-special 'idlwave-complete-class-structure-tag)
6529  (add-hook 'idlwave-update-rinfo-hook 'idlwave-classtag-reset)  (add-hook 'idlwave-update-rinfo-hook 'idlwave-class-tag-reset)
6530    
6531  (defun idlwave-complete-class-structure-tag ()  (defun idlwave-complete-class-structure-tag ()
6532    "Complete a structure tag on a `self' argument in an object method."    "Complete a structure tag on a `self' argument in an object method."
# Line 5946  The list is cashed in `idlwave-class-inf Line 6538  The list is cashed in `idlwave-class-inf
6538            (skip-chars-backward "[a-zA-Z0-9._$]")            (skip-chars-backward "[a-zA-Z0-9._$]")
6539            (and (< (point) (- pos 4))            (and (< (point) (- pos 4))
6540                 (looking-at "self\\.")))                 (looking-at "self\\.")))
6541          (let* ((class (nth 2 (idlwave-current-routine))))          (let* ((class-selector (nth 2 (idlwave-current-routine)))
6542                   (super-classes (idlwave-all-class-inherits class-selector)))
6543            ;; Check if we are in a class routine            ;; Check if we are in a class routine
6544            (unless class            (unless class-selector
6545              (error "Not in a method procedure or function"))              (error "Not in a method procedure or function"))
6546            ;; Check if we need to update the "current" class            ;; Check if we need to update the "current" class
6547            (if (not (equal class idlwave-current-tags-class))            (if (not (equal class-selector idlwave-current-tags-class))
6548                (idlwave-prepare-class-tag-completion class))                (idlwave-prepare-class-tag-completion class-selector))
6549            (setq idlwave-completion-help-info nil)            (setq idlwave-completion-help-info
6550                    (list 'idlwave-complete-class-structure-tag-help
6551                          (idlwave-sintern-routine
6552                           (concat class-selector "__define"))
6553                          nil))
6554            (let  ((idlwave-cpl-bold idlwave-current-native-class-tags))            (let  ((idlwave-cpl-bold idlwave-current-native-class-tags))
6555              (idlwave-complete-in-buffer              (idlwave-complete-in-buffer
6556               'classtag 'classtag               'class-tag 'class-tag
6557               idlwave-current-class-tags nil               idlwave-current-class-tags nil
6558               (format "Select a tag of class %s" class)               (format "Select a tag of class %s" class-selector)
6559               "class tag"))               "class tag"
6560                 'idlwave-attach-class-tag-classes))
6561            t) ; return t to skip other completions            t) ; return t to skip other completions
6562        nil)))        nil)))
6563    
6564  (defun idlwave-classtag-reset ()  (defun idlwave-class-tag-reset ()
6565    (setq idlwave-current-tags-class nil))    (setq idlwave-current-tags-class nil))
6566    
6567  (defun idlwave-prepare-class-tag-completion (class)  (defun idlwave-prepare-class-tag-completion (class)
6568    "Find and parse the necessary class definitions for class structure tags."    "Find and parse the necessary class definitions for class structure tags."
6569    (setq idlwave-sint-classtags nil)    (setq idlwave-sint-class-tags nil)
6570    (setq idlwave-current-tags-class class)    (setq idlwave-current-tags-class class)
6571    (setq idlwave-current-class-tags    (setq idlwave-current-class-tags
6572          (mapcar (lambda (x)          (mapcar (lambda (x)
6573                    (list (idlwave-sintern-classtag x 'set)))                    (list (idlwave-sintern-class-tag x 'set)))
6574                  (idlwave-all-class-tags class)))                  (idlwave-all-class-tags class)))
6575    (setq idlwave-current-native-class-tags    (setq idlwave-current-native-class-tags
6576          (mapcar 'downcase (idlwave-class-tags class))))          (mapcar 'downcase (idlwave-class-tags class))))
# Line 5982  The list is cashed in `idlwave-class-inf Line 6580  The list is cashed in `idlwave-class-inf
6580  ;; Completing system variables and their structure fields  ;; Completing system variables and their structure fields
6581  ;; This is also a plugin.  It is a bit bigger since we support loading  ;; This is also a plugin.  It is a bit bigger since we support loading
6582  ;; current system variables from the shell and highlighting in the  ;; current system variables from the shell and highlighting in the
6583  ;; completions buffer.  ;; completions buffer.
6584    
6585  (defvar idlwave-sint-sysvars nil)  (defvar idlwave-sint-sysvars nil)
6586  (defvar idlwave-sint-sysvartags nil)  (defvar idlwave-sint-sysvartags nil)
# Line 6008  Gets set in `idlw-rinfo.el'.") Line 6606  Gets set in `idlw-rinfo.el'.")
6606               (skip-chars-backward "[a-zA-Z0-9_$]")               (skip-chars-backward "[a-zA-Z0-9_$]")
6607               (equal (char-before) ?!))               (equal (char-before) ?!))
6608             (setq idlwave-completion-help-info '(idlwave-complete-sysvar-help))             (setq idlwave-completion-help-info '(idlwave-complete-sysvar-help))
6609             (idlwave-complete-in-buffer 'sysvar 'sysvar             (idlwave-complete-in-buffer 'sysvar 'sysvar
6610                                         idlwave-system-variables-alist nil                                         idlwave-system-variables-alist nil
6611                                         "Select a system variable"                                         "Select a system variable"
6612                                         "system variable")                                         "system variable")
# Line 6027  Gets set in `idlw-rinfo.el'.") Line 6625  Gets set in `idlw-rinfo.el'.")
6625               (or tags (error "System variable !%s is not a structure" var))               (or tags (error "System variable !%s is not a structure" var))
6626               (setq idlwave-completion-help-info               (setq idlwave-completion-help-info
6627                     (list 'idlwave-complete-sysvar-help var))                     (list 'idlwave-complete-sysvar-help var))
6628               (idlwave-complete-in-buffer 'sysvartag 'sysvartag               (idlwave-complete-in-buffer 'sysvartag 'sysvartag
6629                                           tags nil                                           tags nil
6630                                           "Select a system variable tag"                                           "Select a system variable tag"
6631                                           "system variable tag")                                           "system variable tag")
6632               t)) ; return t to skip other completions               t)) ; return t to skip other completions
6633            (t nil))))            (t nil))))
6634    
6635  (defvar name)  ;; Here we fake help using the routine "system variables" with keyword
6636    ;; set to the sysvar.  Name and kwd are global variables here.
6637    (defvar name)
6638  (defvar kwd)  (defvar kwd)
6639  (defun idlwave-complete-sysvar-help (mode word)  (defun idlwave-complete-sysvar-help (mode word)
6640    (cond    (cond
# Line 6051  Gets set in `idlw-rinfo.el'.") Line 6651  Gets set in `idlw-rinfo.el'.")
6651                            (nth 1 idlwave-completion-help-info)                            (nth 1 idlwave-completion-help-info)
6652                          word))))                          word))))
6653     (t (error "This should not happen"))))     (t (error "This should not happen"))))
6654                              
6655    ;; Fake help in the source buffer for class structure tags.
6656    ;; kwd and name are global-variables here.
6657    (defvar idlwave-help-do-class-struct-tag nil)
6658    (defun idlwave-complete-class-structure-tag-help (mode word)
6659      (cond
6660       ((eq mode 'test) ; nothing gets fontified for class tags
6661        nil)
6662       ((eq mode 'set)
6663        (let (class-with)
6664          (when (setq class-with
6665                    (idlwave-class-or-superclass-with-tag
6666                     idlwave-current-tags-class
6667                     word))
6668            (if (assq (idlwave-sintern-class class-with)
6669                      idlwave-system-class-info)
6670                (error "No help available for system class tags."))
6671            (setq name (concat class-with "__define"))))
6672        (setq kwd word
6673              idlwave-help-do-class-struct-tag t))
6674       (t (error "This should not happen"))))
6675    
6676    (defun idlwave-class-or-superclass-with-tag (class tag)
6677      "Find and return the CLASS or one of its superclass with the
6678    associated TAG, if any."
6679      (let ((sclasses (cons class (cdr (assq 'all-inherits
6680                                             (idlwave-class-info class)))))
6681            cl)
6682       (catch 'exit
6683         (while sclasses
6684           (setq cl (pop sclasses))
6685           (let ((tags (idlwave-class-tags cl)))
6686             (while tags
6687               (if (eq t (compare-strings tag 0 nil (car tags) 0 nil t))
6688                 (throw 'exit cl))
6689               (setq tags (cdr tags))))))))
6690    
6691    
6692  (defun idlwave-sysvars-reset ()  (defun idlwave-sysvars-reset ()
6693    (if (and (fboundp 'idlwave-shell-is-running)    (if (and (fboundp 'idlwave-shell-is-running)
# Line 6067  Gets set in `idlw-rinfo.el'.") Line 6703  Gets set in `idlw-rinfo.el'.")
6703    
6704  (defun idlwave-remember-builtin-sysvars ()  (defun idlwave-remember-builtin-sysvars ()
6705    (setq idlwave-builtin-system-variables    (setq idlwave-builtin-system-variables
6706          (mapcar 'downcase          (mapcar 'downcase
6707                  (mapcar 'car idlwave-system-variables-alist))))                  (mapcar 'car idlwave-system-variables-alist))))
6708    
6709  (defun idlwave-sintern-sysvar-alist ()  (defun idlwave-sintern-sysvar-alist ()
6710    (let ((list idlwave-system-variables-alist) entry)    (let ((list idlwave-system-variables-alist) entry)
6711      (while (setq entry (pop list))      (while (setq entry (pop list))
6712        (setcar entry (idlwave-sintern-sysvar (car entry) 'set))        (setcar entry (idlwave-sintern-sysvar (car entry) 'set))
6713        (setcdr entry (mapcar (lambda (x)        (setcdr entry (mapcar (lambda (x)
6714                                (list (idlwave-sintern-sysvartag (car x) 'set)))                                (list (idlwave-sintern-sysvartag (car x) 'set)))
6715                              (cdr entry))))))                              (cdr entry))))))
6716    
# Line 6105  Gets set in `idlw-rinfo.el'.") Line 6741  Gets set in `idlw-rinfo.el'.")
6741        (set-buffer "*Completions*")        (set-buffer "*Completions*")
6742        (save-excursion        (save-excursion
6743          (goto-char (point-min))          (goto-char (point-min))
6744          (while (re-search-forward "\\.*<[^>]+>" nil t)          (let ((buffer-read-only nil))
6745            (put-text-property (match-beginning 0) (match-end 0)            (while (re-search-forward "\\.*<[^>]+>" nil t)
6746                               'face 'font-lock-string-face))))))              (put-text-property (match-beginning 0) (match-end 0)
6747                                   'face 'font-lock-string-face)))))))
6748    
6749  (defun idlwave-uniquify (list)  (defun idlwave-uniquify (list)
6750    (let (nlist)    (let (nlist)
# Line 6138  Restore the pre-completion window config Line 6775  Restore the pre-completion window config
6775        nil)))        nil)))
6776    
6777    ;; Restore the pre-completion window configuration if this is safe.    ;; Restore the pre-completion window configuration if this is safe.
6778      
6779    (if (or (eq verify 'force)                                    ; force    (if (or (eq verify 'force)                                    ; force
6780            (and            (and
6781             (get-buffer-window "*Completions*")                  ; visible             (get-buffer-window "*Completions*")                  ; visible
6782             (idlwave-local-value 'idlwave-completion-p             (idlwave-local-value 'idlwave-completion-p
6783                                  "*Completions*")                ; cib-buffer                                  "*Completions*")                ; cib-buffer
6784             (eq (marker-buffer idlwave-completion-mark)             (eq (marker-buffer idlwave-completion-mark)
6785                 (current-buffer))                                ; buffer OK                 (current-buffer))                                ; buffer OK
# Line 6161  Restore the pre-completion window config Line 6798  Restore the pre-completion window config
6798  (defvar idlwave-last-context-help-pos nil)  (defvar idlwave-last-context-help-pos nil)
6799  (defun idlwave-context-help (&optional arg)  (defun idlwave-context-help (&optional arg)
6800    "Display IDL Online Help on context.    "Display IDL Online Help on context.
6801  If point is on a keyword, help for that keyword will be shown.  If point is on a keyword, help for that keyword will be shown.  If
6802  If point is on a routine name or in the argument list of a routine,  point is on a routine name or in the argument list of a routine, help
6803  help for that routine will be displayed.  for that routine will be displayed.  Works for system routines and
6804  Works for system routines and keywords only."  keywords, it pulls up text help.  For other routies and keywords,
6805    visits the source file, finding help in the header (if
6806    `idlwave-help-source-try-header' is non-nil) or the routine definition
6807    itself."
6808    (interactive "P")    (interactive "P")
6809    (idlwave-require-online-help)    (idlwave-require-online-help)
6810    (idlwave-do-context-help arg))    (idlwave-do-context-help arg))
# Line 6177  Works for system routines and keywords o Line 6817  Works for system routines and keywords o
6817    ;; work.    ;; work.
6818    (setq this-command last-command)    (setq this-command last-command)
6819    (idlwave-do-mouse-completion-help ev))    (idlwave-do-mouse-completion-help ev))
     
6820    
6821  (defvar idlwave-help-is-loaded nil  (defvar idlwave-help-is-loaded nil
6822    "Is online help avaiable?")    "Is online help avaiable?")
# Line 6197  Works for system routines and keywords o Line 6836  Works for system routines and keywords o
6836    (if idlwave-help-is-loaded    (if idlwave-help-is-loaded
6837        t  ;; everything is OK.        t  ;; everything is OK.
6838      (let* ((dir (or (idlwave-help-directory)      (let* ((dir (or (idlwave-help-directory)
6839                      (error "Online Help is not installed (idlwave-help-directory is unknown)")))                      (error "Online Help not installed (help directory unknown) - download at idlwave.org")))
6840             (lfile1 (expand-file-name "idlw-help.elc" dir))             (lfile1 (expand-file-name "idlw-help.elc" dir))
6841             (lfile2 (expand-file-name "idlw-help.el" dir))             (lfile2 (expand-file-name "idlw-help.el" dir))
6842             (hfile (expand-file-name "idlw-help.txt" dir)))             (hfile (expand-file-name "idlw-help.txt" dir)))
6843        (if (or (and (file-regular-p lfile1) (load-file lfile1))        (if (or (and (file-regular-p lfile1) (load-file lfile1))
6844                (and (file-regular-p lfile2) (load-file lfile2)))                (and (file-regular-p lfile2) (load-file lfile2)))
6845            (progn            (progn
6846              (if (and idlwave-help-frame-parameters              (if (and idlwave-help-frame-parameters
6847                       (not (assoc 'width idlwave-help-frame-parameters)))                       (not (assoc 'width idlwave-help-frame-parameters)))
6848                  (push (cons 'width idlwave-help-frame-width)                  (push (cons 'width idlwave-help-frame-width)
6849                        idlwave-help-frame-parameters))                        idlwave-help-frame-parameters))
6850              (or idlwave-help-topics              (or idlwave-help-topics
6851                  (error "File `%s' in help dir `%s' does not define `idlwave-help-topics'"                  (error "File `%s' in help dir `%s' does not define `idlwave-help-topics'"
6852                           "idlw-help.el" dir)))                           "idlw-help.el" dir)))
6853          (error "No such file `%s' in help dir `%s'" "idlw-help.el" dir))          (error "No such file `%s' in help dir `%s'" "idlw-help.el" dir))
6854        (if (file-regular-p hfile)        (if (file-regular-p hfile)
# Line 6279  With ARG, enforce query for the class of Line 6918  With ARG, enforce query for the class of
6918      (if (string-match "\\(pro\\|function\\)[ \t]+\\(\\(.*\\)::\\)?\\(.*\\)"      (if (string-match "\\(pro\\|function\\)[ \t]+\\(\\(.*\\)::\\)?\\(.*\\)"
6919                        resolve)                        resolve)
6920          (setq type (match-string 1 resolve)          (setq type (match-string 1 resolve)
6921                class (if (match-beginning 2)                class (if (match-beginning 2)
6922                          (match-string 3 resolve)                          (match-string 3 resolve)
6923                        nil)                        nil)
6924                name (match-string 4 resolve)))                name (match-string 4 resolve)))
# Line 6288  With ARG, enforce query for the class of Line 6927  With ARG, enforce query for the class of
6927    
6928      (cond      (cond
6929       ((null class)       ((null class)
6930        (idlwave-shell-send-command        (idlwave-shell-send-command
6931         (format "resolve_routine,'%s'%s" (downcase name) kwd)         (format "resolve_routine,'%s'%s" (downcase name) kwd)
6932         'idlwave-update-routine-info         'idlwave-update-routine-info
6933         nil t))         nil t))
6934       (t       (t
6935        (idlwave-shell-send-command        (idlwave-shell-send-command
6936         (format "resolve_routine,'%s__define'%s" (downcase class) kwd)         (format "resolve_routine,'%s__define'%s" (downcase class) kwd)
6937         (list 'idlwave-shell-send-command         (list 'idlwave-shell-send-command
6938               (format "resolve_routine,'%s__%s'%s"               (format "resolve_routine,'%s__%s'%s"
6939                       (downcase class) (downcase name) kwd)                       (downcase class) (downcase name) kwd)
6940               '(idlwave-update-routine-info)               '(idlwave-update-routine-info)
6941               nil t))))))               nil t))))))
# Line 6312  use.  With ARG force class query for obj Line 6951  use.  With ARG force class query for obj
6951           (module (idlwave-fix-module-if-obj_new (idlwave-what-module)))           (module (idlwave-fix-module-if-obj_new (idlwave-what-module)))
6952           (default (concat (idlwave-make-full-name (nth 2 module) (car module))           (default (concat (idlwave-make-full-name (nth 2 module) (car module))
6953                            (if (eq (nth 1 module) 'pro) "<p>" "<f>")))                            (if (eq (nth 1 module) 'pro) "<p>" "<f>")))
6954           (list           (list
6955            (delq nil            (delq nil
6956                  (mapcar (lambda (x)                  (mapcar (lambda (x)
6957                            (if (eq 'system (car-safe (nth 3 x)))                            (if (eq 'system (car-safe (nth 3 x)))
6958                                ;; Take out system routines with no source.                                ;; Take out system routines with no source.
6959                                nil                                nil
# Line 6324  use.  With ARG force class query for obj Line 6963  use.  With ARG force class query for obj
6963                               (cdr x))))                               (cdr x))))
6964                          (idlwave-routines))))                          (idlwave-routines))))
6965           (name (idlwave-completing-read           (name (idlwave-completing-read
6966                  (format "Module (Default %s): "                  (format "Module (Default %s): "
6967                          (if default default "none"))                          (if default default "none"))
6968                  list))                  list))
6969           type class)           type class)
# Line 6354  use.  With ARG force class query for obj Line 6993  use.  With ARG force class query for obj
6993            source (or force-source (nth 3 entry))            source (or force-source (nth 3 entry))
6994            name2 (if (nth 2 entry)            name2 (if (nth 2 entry)
6995                      (idlwave-make-full-name (nth 2 entry) name)                      (idlwave-make-full-name (nth 2 entry) name)
6996                    name1))                                    name1))
6997      (cond      (cond
6998       ((or (null name) (equal name ""))       ((or (null name) (equal name ""))
6999        (error "Abort"))        (error "Abort"))
7000       ((null entry)       ((null entry)
7001        (error "Nothing known about a module %s" name2))        (error "Nothing known about a module %s" name2))
7002       ((eq (car source) 'system)       ((eq (car source) 'system)
7003        (error "Source code for system routine %s is not available"        (error "Source code for system routine %s is not available"
7004               name2))               name2))
7005       ((equal (cdr source) "")       ((equal (cdr source) "")
7006        (error "Source code for routine %s is not available"        (error "Source code for routine %s is not available"
7007               name2))               name2))
7008       ((memq (car source) '(buffer lib compiled))       ((memq (car source) '(buffer lib compiled))
7009        (setq buf1        (setq buf1
7010              (if (eq (car source) 'lib)              (if (eq (car source) 'lib)
7011                  (idlwave-find-file-noselect                  (idlwave-find-file-noselect
7012                   (idlwave-expand-lib-file-name                   (idlwave-expand-lib-file-name
# Line 6382  use.  With ARG force class query for obj Line 7021  use.  With ARG force class query for obj
7021                       (cond ((equal type "f") "function")                       (cond ((equal type "f") "function")
7022                             ((equal type "p") "pro")                             ((equal type "p") "pro")
7023                             (t "\\(pro\\|function\\)"))                             (t "\\(pro\\|function\\)"))
7024                       "\\>[ \t]+"                       "\\>[ \t]+"
7025                       (regexp-quote (downcase name2))                       (regexp-quote (downcase name2))
7026                       "[^a-zA-Z0-9_$]")                       "[^a-zA-Z0-9_$]")
7027               nil t)               nil t)
# Line 6419  Used by `idlwave-routine-info' and `idlw Line 7058  Used by `idlwave-routine-info' and `idlw
7058        (cond        (cond
7059         ((and (eq cw 'procedure)         ((and (eq cw 'procedure)
7060               (not (equal this-word "")))               (not (equal this-word "")))
7061          (setq this-word (idlwave-sintern-routine-or-method          (setq this-word (idlwave-sintern-routine-or-method
7062                           this-word (nth 2 (nth 3 where))))                           this-word (nth 2 (nth 3 where))))
7063          (list this-word 'pro          (list this-word 'pro
7064                (idlwave-determine-class                (idlwave-determine-class
7065                 (cons this-word (cdr (nth 3 where)))                 (cons this-word (cdr (nth 3 where)))
7066                 'pro)))                 'pro)))
7067         ((and (eq cw 'function)         ((and (eq cw 'function)
7068               (not (equal this-word ""))               (not (equal this-word ""))
7069               (or (eq next-char ?\()     ; exclude arrays, vars.               (or (eq next-char ?\()     ; exclude arrays, vars.
7070                   (looking-at "[a-zA-Z0-9_]*[ \t]*(")))                   (looking-at "[a-zA-Z0-9_]*[ \t]*(")))
7071          (setq this-word (idlwave-sintern-routine-or-method          (setq this-word (idlwave-sintern-routine-or-method
7072                           this-word (nth 2 (nth 3 where))))                           this-word (nth 2 (nth 3 where))))
7073          (list this-word 'fun          (list this-word 'fun
7074                (idlwave-determine-class                (idlwave-determine-class
# Line 6489  keyword region, change to the appropriat Line 7128  keyword region, change to the appropriat
7128    
7129  (defun idlwave-fix-keywords (name type class keywords)  (defun idlwave-fix-keywords (name type class keywords)
7130    ;; This fixes the list of keywords.    ;; This fixes the list of keywords.
7131    (let ((case-fold-search t)    (let ((case-fold-search t))
         name1 type1)  
7132    
7133      ;; If this is the OBJ_NEW function, try to figure out the class and use      ;; If this is the OBJ_NEW function, try to figure out the class and use
7134      ;; the keywords from the corresponding INIT method.      ;; the keywords from the corresponding INIT method.
7135      (if (and (equal name "OBJ_NEW")      (if (and (equal (upcase name) "OBJ_NEW")
7136               (or (eq major-mode 'idlwave-mode)               (or (eq major-mode 'idlwave-mode)
7137                   (eq major-mode 'idlwave-shell-mode)))                   (eq major-mode 'idlwave-shell-mode)))
7138          (let* ((bos (save-excursion (idlwave-beginning-of-statement) (point)))          (let* ((bos (save-excursion (idlwave-beginning-of-statement) (point)))
# Line 6505  keyword region, change to the appropriat Line 7143  keyword region, change to the appropriat
7143                               string)                               string)
7144                 (setq class (idlwave-sintern-class (match-string 1 string)))                 (setq class (idlwave-sintern-class (match-string 1 string)))
7145                 (setq idlwave-current-obj_new-class class)                 (setq idlwave-current-obj_new-class class)
7146                 (setq keywords                 (setq keywords
7147                       (append keywords                       (append keywords
7148                               (nth 5 (idlwave-rinfo-assq                               (nth 5 (idlwave-rinfo-assq
7149                                       (idlwave-sintern-method "INIT")                                       (idlwave-sintern-method "INIT")
7150                                       'fun                                       'fun
# Line 6516  keyword region, change to the appropriat Line 7154  keyword region, change to the appropriat
7154      ;; If the class is `t', combine all keywords of all methods NAME      ;; If the class is `t', combine all keywords of all methods NAME
7155      (when (eq class t)      (when (eq class t)
7156        (loop for x in (idlwave-routines) do        (loop for x in (idlwave-routines) do
7157          (and (nth 2 x)                         ; non-nil class              (and (nth 2 x)                ; non-nil class
7158               (or (and (eq (nth 1 x) type)      ; default type                   (eq (nth 1 x) type)      ; correct type
7159                        (eq (car x) name))       ; default name                   (eq (car x) name)        ; correct name
7160                   (and (eq (nth 1 x) type1)     ; backup type                   (mapcar (lambda (k) (add-to-list 'keywords k))
7161                        (eq (car x) name1)))     ; backup name                           (nth 5 x))))
7162               (mapcar (lambda (k) (add-to-list 'keywords k))        (setq keywords (idlwave-uniquify keywords)))
7163                       (nth 5 x))))  
7164        ;; If we have inheritance, add all keywords from superclasses, if
7165        ;; the user indicated that method in
7166        ;; `idlwave-keyword-class-inheritance'
7167        (when (and
7168               idlwave-keyword-class-inheritance
7169               (stringp class)
7170               (or (assq (idlwave-sintern-keyword "_extra") keywords)
7171                   (assq (idlwave-sintern-keyword "_ref_extra") keywords))
7172               (boundp 'super-classes)
7173               ;; Check if one of the keyword-class regexps matches the name
7174               (let ((regexps idlwave-keyword-class-inheritance) re)
7175                 (catch 'exit
7176                   (while (setq re (pop regexps))
7177                     (if (string-match re name) (throw 'exit t))))))
7178          (loop for x in (idlwave-routines) do
7179                (and (nth 2 x)                           ; non-nil class
7180                     (or (eq (nth 2 x) class)            ; the right class
7181                         (memq (nth 2 x) super-classes)) ; an inherited class
7182                     (eq (nth 1 x) type)                 ; correct type
7183                     (eq (car x) name)                   ; correct name
7184                     (mapcar (lambda (k) (add-to-list 'keywords k))
7185                             (nth 5 x))))
7186        (setq keywords (idlwave-uniquify keywords)))        (setq keywords (idlwave-uniquify keywords)))
7187    
     ;; If we have inheritance, add all keywords from superclasses  
     ;; :-(  Taken out because JD says it does not work this way.  
 ;    (when (and (stringp class)  
 ;              (or (assq (idlwave-sintern-keyword "_extra") keywords)  
 ;                  (assq (idlwave-sintern-keyword "_ref_extra") keywords))  
 ;              (boundp 'super-classes))  
 ;      (loop for x in (idlwave-routines) do  
 ;       (and (nth 2 x)                           ; non-nil class  
 ;            (or (eq (nth 2 x) class)            ; the right class  
 ;                (memq (nth 2 x) super-classes)) ; an inherited class  
 ;            (or (and (eq (nth 1 x) type)        ; default type  
 ;                     (eq (car x) name))         ; default name  
 ;                (and (eq (nth 1 x) type1)       ; backup type  
 ;                     (eq (car x) name1)))       ; backup name  
 ;            (mapcar (lambda (k) (add-to-list 'keywords k))  
 ;                    (nth 5 x))))  
 ;      (setq keywords (idlwave-uniquify keywords)))  
       
7188      ;; Return the final list      ;; Return the final list
7189      keywords))      keywords))
7190    
# Line 6567  If we do not know about MODULE, just ret Line 7209  If we do not know about MODULE, just ret
7209                      (assq (idlwave-sintern-keyword "_REF_EXTRA") kwd-alist)))                      (assq (idlwave-sintern-keyword "_REF_EXTRA") kwd-alist)))
7210           (completion-ignore-case t)           (completion-ignore-case t)
7211           candidates)           candidates)
7212      (cond ((assq kwd kwd-alist)      (cond ((assq kwd kwd-alist)
7213             kwd)             kwd)
7214            ((setq candidates (all-completions kwd kwd-alist))            ((setq candidates (all-completions kwd kwd-alist))
7215             (if (= (length candidates) 1)             (if (= (length candidates) 1)
7216                 (car candidates)                 (car candidates)
7217               candidates))               candidates))
7218            ((and entry extra)            ((and entry extra)
7219             ;; Inheritance may cause this keyword to be correct             ;; Inheritance may cause this keyword to be correct
7220             keyword)             keyword)
7221            (entry            (entry
7222             ;; We do know the function, which does not have the keyword.             ;; We do know the function, which does not have the keyword.
# Line 6586  If we do not know about MODULE, just ret Line 7228  If we do not know about MODULE, just ret
7228    
7229  (defvar idlwave-rinfo-mouse-map (make-sparse-keymap))  (defvar idlwave-rinfo-mouse-map (make-sparse-keymap))
7230  (defvar idlwave-rinfo-map (make-sparse-keymap))  (defvar idlwave-rinfo-map (make-sparse-keymap))
7231  (define-key idlwave-rinfo-mouse-map  (define-key idlwave-rinfo-mouse-map
7232    (if (featurep 'xemacs) [button2] [mouse-2])    (if (featurep 'xemacs) [button2] [mouse-2])
7233    'idlwave-mouse-active-rinfo)    'idlwave-mouse-active-rinfo)
7234  (define-key idlwave-rinfo-mouse-map  (define-key idlwave-rinfo-mouse-map
7235    (if (featurep 'xemacs) [(shift button2)] [(shift mouse-2)])    (if (featurep 'xemacs) [(shift button2)] [(shift mouse-2)])
7236    'idlwave-mouse-active-rinfo-shift)    'idlwave-mouse-active-rinfo-shift)
7237  (define-key idlwave-rinfo-mouse-map  (define-key idlwave-rinfo-mouse-map
7238    (if (featurep 'xemacs) [button3] [mouse-3])    (if (featurep 'xemacs) [button3] [mouse-3])
7239    'idlwave-mouse-active-rinfo-right)    'idlwave-mouse-active-rinfo-right)
7240  (define-key idlwave-rinfo-mouse-map " " 'idlwave-active-rinfo-space)  (define-key idlwave-rinfo-mouse-map " " 'idlwave-active-rinfo-space)
# Line 6618  If we do not know about MODULE, just ret Line 7260  If we do not know about MODULE, just ret
7260    (let* ((initial-class (or initial-class class))    (let* ((initial-class (or initial-class class))
7261           (entry (or (idlwave-best-rinfo-assq name type class           (entry (or (idlwave-best-rinfo-assq name type class
7262                                               (idlwave-routines))                                               (idlwave-routines))
7263                      (idlwave-rinfo-assq name type class                      (idlwave-rinfo-assq name type class
7264                                          idlwave-unresolved-routines)))                                          idlwave-unresolved-routines)))
7265           (name (or (car entry) name))           (name (or (car entry) name))
7266           (class (or (nth 2 entry) class))           (class (or (nth 2 entry) class))
# Line 6702  If we do not know about MODULE, just ret Line 7344  If we do not know about MODULE, just ret
7344                    (format calling-seq name))                    (format calling-seq name))
7345                  "\n")                  "\n")
7346          (add-text-properties beg (point) props)          (add-text-properties beg (point) props)
7347            
7348          (insert "Keywords:")          (insert "Keywords:")
7349          (if (null keywords)          (if (null keywords)
7350              (insert " No keywords accepted.")              (insert " No keywords accepted.")
7351            (setq col 9)            (setq col 9)
7352            (mapcar            (mapcar
7353             (lambda (x)             (lambda (x)
7354               (if (>= (+ col 1 (length (car x)))               (if (>= (+ col 1 (length (car x)))
7355                       (window-width))                       (window-width))
7356                   (progn                   (progn
7357                     (insert "\n         ")                     (insert "\n         ")
# Line 6726  If we do not know about MODULE, just ret Line 7368  If we do not know about MODULE, just ret
7368               (add-text-properties beg (point) props)               (add-text-properties beg (point) props)
7369               (setq col (+ col 1 (length (car x)))))               (setq col (+ col 1 (length (car x)))))
7370             keywords))             keywords))
7371            
7372          (setq cnt 1 total (length all))          (setq cnt 1 total (length all))
7373          (while (setq entry (pop all))          (while (setq entry (pop all))
7374            (setq props (list 'mouse-face 'highlight            (setq props (list 'mouse-face 'highlight
# Line 6735  If we do not know about MODULE, just ret Line 7377  If we do not know about MODULE, just ret
7377                              'source (cons (car (nth 2 entry)) (nth 1 entry))                              'source (cons (car (nth 2 entry)) (nth 1 entry))
7378                              'data (cons 'source data)))                              'data (cons 'source data)))
7379            (idlwave-insert-source-location            (idlwave-insert-source-location
7380             (format "\n%-8s  %s"             (format "\n%-8s  %s"
7381                     (if (equal cnt 1)                     (if (equal cnt 1)
7382                         (if (> total 1) "Sources:" "Source:")                         (if (> total 1) "Sources:" "Source:")
7383                       "")                       "")
# Line 6744  If we do not know about MODULE, just ret Line 7386  If we do not know about MODULE, just ret
7386            (incf cnt)            (incf cnt)
7387            (when (and all (> cnt idlwave-rinfo-max-source-lines))            (when (and all (> cnt idlwave-rinfo-max-source-lines))
7388              ;; No more source lines, please              ;; No more source lines, please
7389              (insert (format              (insert (format
7390                       "\n          Source information truncated to %d entries."                       "\n          Source information truncated to %d entries."
7391                       idlwave-rinfo-max-source-lines))                       idlwave-rinfo-max-source-lines))
7392              (setq all nil)))              (setq all nil)))
# Line 6758  If we do not know about MODULE, just ret Line 7400  If we do not know about MODULE, just ret
7400                (unwind-protect                (unwind-protect
7401                    (progn                    (progn
7402                      (select-window win)                      (select-window win)
7403                      (enlarge-window (- (/ (frame-height) 2)                      (enlarge-window (- (/ (frame-height) 2)
7404                                         (window-height)))                                         (window-height)))
7405                      (shrink-window-if-larger-than-buffer))                      (shrink-window-if-larger-than-buffer))
7406                  (select-window ww)))))))))                  (select-window ww)))))))))
# Line 6808  If a file name is inserted, add FILE-PRO Line 7450  If a file name is inserted, add FILE-PRO
7450                 (if shell-flag "S" "-")                 (if shell-flag "S" "-")
7451                 (if buffer-flag "B" "-")                 (if buffer-flag "B" "-")
7452                 "] ")))                 "] ")))
7453      (when (> ndupl 1)      (when (> ndupl 1)
7454        (setq beg (point))        (setq beg (point))
7455        (insert (format "(%dx) " ndupl))        (insert (format "(%dx) " ndupl))
7456        (add-text-properties beg (point) (list 'face 'bold)))        (add-text-properties beg (point) (list 'face 'bold)))
# Line 6832  Return the name of the special lib if th Line 7474  Return the name of the special lib if th
7474                    alist nil)))                    alist nil)))
7475        rtn)        rtn)
7476       (t nil))))       (t nil))))
7477      
7478  (defun idlwave-mouse-active-rinfo-right (ev)  (defun idlwave-mouse-active-rinfo-right (ev)
7479    (interactive "e")    (interactive "e")
7480    (idlwave-mouse-active-rinfo ev 'right))    (idlwave-mouse-active-rinfo ev 'right))
# Line 6863  was pressed." Line 7505  was pressed."
7505            bufwin (get-buffer-window buf t))            bufwin (get-buffer-window buf t))
7506      (cond ((eq id 'class)      (cond ((eq id 'class)
7507             (if (window-live-p bufwin) (select-window bufwin))             (if (window-live-p bufwin) (select-window bufwin))
7508             (idlwave-display-calling-sequence             (idlwave-display-calling-sequence
7509              (idlwave-sintern-method name)              (idlwave-sintern-method name)
7510              type (idlwave-sintern-class word)              type (idlwave-sintern-class word)
7511              initial-class))              initial-class))
7512            ((eq id 'usage)            ((eq id 'usage)
7513             (idlwave-require-online-help)             (idlwave-require-online-help)
# Line 6909  was pressed." Line 7551  was pressed."
7551        (setq bwin (get-buffer-window buffer)))        (setq bwin (get-buffer-window buffer)))
7552      (if (eq (preceding-char) ?/)      (if (eq (preceding-char) ?/)
7553          (insert keyword)          (insert keyword)
7554        (unless (save-excursion        (unless (save-excursion
7555                  (re-search-backward                  (re-search-backward
7556                   "[(,][ \t]*\\(\\$[ \t]*\\(;.*\\)?\n\\)?[ \t]*\\="                   "[(,][ \t]*\\(\\$[ \t]*\\(;.*\\)?\n\\)?[ \t]*\\="
7557                   (min (- (point) 100) (point-min)) t))                   (min (- (point) 100) (point-min)) t))
7558          (insert ", "))          (insert ", "))
7559        (if shift (insert "/"))        (if shift (insert "/"))
# Line 6963  the load path in order to find a definit Line 7605  the load path in order to find a definit
7605  command can be used to detect possible name clashes during this process."  command can be used to detect possible name clashes during this process."
7606    (idlwave-routines)  ; Make sure everything is loaded.    (idlwave-routines)  ; Make sure everything is loaded.
7607    (unless idlwave-library-routines    (unless idlwave-library-routines
7608      (or (y-or-n-p      (or (y-or-n-p
7609           "You don't have a library catalog.  Continue anyway? ")           "You don't have a library catalog.  Continue anyway? ")
7610          (error "Abort")))          (error "Abort")))
7611    (let* ((routines (append idlwave-system-routines    (let* ((routines (append idlwave-system-routines
# Line 6975  command can be used to detect possible n Line 7617  command can be used to detect possible n
7617           (keymap (make-sparse-keymap))           (keymap (make-sparse-keymap))
7618           (props (list 'mouse-face 'highlight           (props (list 'mouse-face 'highlight
7619                        km-prop keymap                        km-prop keymap
7620                        'help-echo "Mouse2: Find source"))                              'help-echo "Mouse2: Find source"))
7621           (nroutines (length (or special-routines routines)))           (nroutines (length (or special-routines routines)))
7622           (step (/ nroutines 99))           (step (/ nroutines 99))
7623           (n 0)           (n 0)
# Line 6999  command can be used to detect possible n Line 7641  command can be used to detect possible n
7641      (message "Sorting routines...done")      (message "Sorting routines...done")
7642    
7643      (define-key keymap (if (featurep 'xemacs) [(button2)] [(mouse-2)])      (define-key keymap (if (featurep 'xemacs) [(button2)] [(mouse-2)])
7644        (lambda (ev)        (lambda (ev)
7645          (interactive "e")          (interactive "e")
7646          (mouse-set-point ev)          (mouse-set-point ev)
7647          (apply 'idlwave-do-find-module          (apply 'idlwave-do-find-module
7648                 (get-text-property (point) 'find-args))))                 (get-text-property (point) 'find-args))))
7649      (define-key keymap [(return)]      (define-key keymap [(return)]
7650        (lambda ()        (lambda ()
7651          (interactive)          (interactive)
7652          (apply 'idlwave-do-find-module          (apply 'idlwave-do-find-module
7653                 (get-text-property (point) 'find-args))))                 (get-text-property (point) 'find-args))))
# Line 7025  command can be used to detect possible n Line 7667  command can be used to detect possible n
7667          (if (memq routine done)          (if (memq routine done)
7668              (setq dtwins nil)              (setq dtwins nil)
7669            (setq dtwins (idlwave-study-twins twins)))            (setq dtwins (idlwave-study-twins twins)))
7670          ;; Mark all twins as delt with          ;; Mark all twins as dealt with
7671          (setq done (append twins done))          (setq done (append twins done))
7672          (when (or (> (length dtwins) 1)          (when (or (> (length dtwins) 1)
7673                    (> (idlwave-count-eq 'lib (nth 2 (car dtwins))) 1)                    (> (idlwave-count-eq 'lib (nth 2 (car dtwins))) 1)
# Line 7036  command can be used to detect possible n Line 7678  command can be used to detect possible n
7678                            (if (eq (nth 1 routine) 'fun) "()" "")))                            (if (eq (nth 1 routine) 'fun) "()" "")))
7679            (while (setq twin (pop dtwins))            (while (setq twin (pop dtwins))
7680              (setq props1 (append (list 'find-args              (setq props1 (append (list 'find-args
7681                                         (list (nth 0 routine)                                         (list (nth 0 routine)
7682                                               (nth 1 routine)                                               (nth 1 routine)
7683                                               (nth 2 routine)                                               (nth 2 routine)
7684                                               (cons 'lib (nth 1 twin))))                                               (cons 'lib (nth 1 twin))))
7685                                   props))                                   props))
# Line 7064  command can be used to detect possible n Line 7706  command can be used to detect possible n
7706               (or (not (stringp sfile))               (or (not (stringp sfile))
7707                   (not (string-match "\\S-" sfile))))                   (not (string-match "\\S-" sfile))))
7708          (setq stype 'unresolved))          (setq stype 'unresolved))
7709      (princ (format "      %-10s %s\n"      (princ (format "      %-10s %s\n"
7710                     stype                     stype
7711                     (if sfile sfile "No source code available")))))                     (if sfile sfile "No source code available")))))
7712    
# Line 7083  ENTRY will also be returned, as the firs Line 7725  ENTRY will also be returned, as the firs
7725                 (eq type (nth 1 candidate))                 (eq type (nth 1 candidate))
7726                 (eq class (nth 2 candidate)))                 (eq class (nth 2 candidate)))
7727            (push candidate twins)))            (push candidate twins)))
7728      (if (setq candidate (idlwave-rinfo-assq name type class      (if (setq candidate (idlwave-rinfo-assq name type class
7729                                              idlwave-unresolved-routines))                                              idlwave-unresolved-routines))
7730          (push candidate twins))          (push candidate twins))
7731      (cons entry (nreverse twins))))      (cons entry (nreverse twins))))
# Line 7093  ENTRY will also be returned, as the firs Line 7735  ENTRY will also be returned, as the firs
7735  Dangerous twins are routines with same name, but in different files  Dangerous twins are routines with same name, but in different files
7736  on the load path.  on the load path.
7737  If a file is in the system library and has an entry in the  If a file is in the system library and has an entry in the
7738  `idlwave-system-routines' list, we omit the latter because many IDL  `idlwave-system-routines' list, we omit the latter because many IDL
7739  routines are implemented as library routines."  routines are implemented as library routines."
7740    (let* ((entry (car entries))    (let* ((entry (car entries))
7741           (name (car entry))      ;           (name (car entry))      ;
7742           (type (nth 1 entry))    ; Must be bound for           (type (nth 1 entry))    ; Must be bound for
7743           (class (nth 2 entry))   ;  idlwave-routine-twin-compare           (class (nth 2 entry))   ;  idlwave-routine-twin-compare
7744           (cnt 0)           (cnt 0)
# Line 7112  routines are implemented as library rout Line 7754  routines are implemented as library rout
7754        (setq key (cond ((eq type 'system) type)        (setq key (cond ((eq type 'system) type)
7755                        (file (file-truename file))                        (file (file-truename file))
7756                        (t 'unresolved)))                        (t 'unresolved)))
7757        (if (and file        (if (and file
7758                 (not syslibp)                 (not syslibp)
7759                 (idlwave-syslib-p file))                 (idlwave-syslib-p file))
7760            ;; We do have an entry in the system library            ;; We do have an entry in the system library
7761            (setq syslibp t))            (setq syslibp t))
7762          
7763        (setq thefile (or thefile file))        (setq thefile (or thefile file))
7764        (if (setq entry (assoc key alist))        (if (setq entry (assoc key alist))
7765            (push type (nth 2 entry))            (push type (nth 2 entry))
7766          (push (list key file (list type)) alist)))          (push (list key file (list type)) alist)))
7767        
7768      (setq alist (nreverse alist))      (setq alist (nreverse alist))
7769        
7770      (when syslibp      (when syslibp
7771        ;; File is system *library* - remove any system entry        ;; File is system *library* - remove any system entry
7772        (setq alist (delq (assoc 'system alist) alist)))        (setq alist (delq (assoc 'system alist) alist)))
7773        
7774      (when (and (idlwave-syslib-scanned-p)      (when (and (idlwave-syslib-scanned-p)
7775                 (setq entry (assoc 'system alist)))                 (setq entry (assoc 'system alist)))
7776        (setcar entry 'builtin))        (setcar entry 'builtin))
# Line 7147  routines are implemented as library rout Line 7789  routines are implemented as library rout
7789  (defun idlwave-routine-entry-compare (a b)  (defun idlwave-routine-entry-compare (a b)
7790    "Compare two routine info entries for sortiung.  This is the general case.    "Compare two routine info entries for sortiung.  This is the general case.
7791  It first compates class, names, and type.  If it turns out that A and B  It first compates class, names, and type.  If it turns out that A and B
7792  are twins (same name, class, and type),  calls another routine which  are twins (same name, class, and type), calls another routine which
7793  compares twins on the basis of their file names and path locations."  compares twins on the basis of their file names and path locations."
7794    (let ((name (car a)) (type (nth 1 a)) (class (nth 2 a)))    (let ((name (car a)) (type (nth 1 a)) (class (nth 2 a)))
7795      (cond      (cond
# Line 7163  compares twins on the basis of their fil Line 7805  compares twins on the basis of their fil
7805       ((not (eq type (nth 1 b)))       ((not (eq type (nth 1 b)))
7806        ;; Type decides        ;; Type decides
7807        (< (if (eq type 'fun) 1 0) (if (eq (nth 1 b) 'fun) 1 0)))        (< (if (eq type 'fun) 1 0) (if (eq (nth 1 b) 'fun) 1 0)))
7808       (t       (t
7809        ;; A and B are twins - so the decision is more complicated.        ;; A and B are twins - so the decision is more complicated.
7810        ;; Call twin-compare with the proper arguments.        ;; Call twin-compare with the proper arguments.
7811        (idlwave-routine-entry-compare-twins a b)))))        (idlwave-routine-entry-compare-twins a b)))))
# Line 7325  Assumes that point is at the beginning o Line 7967  Assumes that point is at the beginning o
7967          (buffer-substring-no-properties begin (point))          (buffer-substring-no-properties begin (point))
7968        (buffer-substring begin (point)))))        (buffer-substring begin (point)))))
7969    
7970  (defun idlwave-function-menu ()  (defalias 'idlwave-function-menu
7971    "Use `imenu' or `function-menu' to jump to a procedure or function."    (condition-case nil
   (interactive)  
   (if (string-match "XEmacs" emacs-version)  
7972        (progn        (progn
7973          (require 'func-menu)          (require 'func-menu)
7974          (function-menu))          'function-menu)
7975      (require 'imenu)      (error (condition-case nil
7976      (imenu (imenu-choose-buffer-index))))                 (progn
7977                     (require 'imenu)
7978                     'imenu)
7979                 (error nil)))))
7980    
7981  ;; Here we kack func-menu.el in order to support this new mode.  ;; Here we kack func-menu.el in order to support this new mode.
7982  ;; The latest versions of func-menu.el already have this stuff in, so  ;; The latest versions of func-menu.el already have this stuff in, so
# Line 7358  Assumes that point is at the beginning o Line 8001  Assumes that point is at the beginning o
8001    (start-process "idldeclient" nil    (start-process "idldeclient" nil
8002                   idlwave-shell-explicit-file-name "-c" "-e"                   idlwave-shell-explicit-file-name "-c" "-e"
8003                   (buffer-file-name) "&"))                   (buffer-file-name) "&"))
8004                    
8005  (defun idlwave-launch-idlhelp ()  (defun idlwave-launch-idlhelp ()
8006    "Start the IDLhelp application."    "Start the IDLhelp application."
8007    (interactive)    (interactive)
8008    (start-process "idlhelp" nil idlwave-help-application))    (start-process "idlhelp" nil idlwave-help-application))
8009    
8010  ;; Menus - using easymenu.el  ;; Menus - using easymenu.el
8011  (defvar idlwave-mode-menu-def  (defvar idlwave-mode-menu-def
8012    `("IDLWAVE"    `("IDLWAVE"
# Line 7426  Assumes that point is at the beginning o Line 8069  Assumes that point is at the beginning o
8069       ["Update Routine Info" idlwave-update-routine-info t]       ["Update Routine Info" idlwave-update-routine-info t]
8070       "--"       "--"
8071       "IDL Library Catalog"       "IDL Library Catalog"
8072       ["Select Catalog Directories" idlwave-create-libinfo-file t]       ["Select Catalog Directories" (idlwave-create-libinfo-file nil) t]
8073       ["Scan Directories" (idlwave-update-routine-info '(16))       ["Scan Directories" (idlwave-update-routine-info '(16))
8074        idlwave-path-alist]        (and idlwave-path-alist (not idlwave-catalog-process))]
8075         ["Scan Directories &" (idlwave-update-routine-info '(64))
8076          (and idlwave-path-alist (not idlwave-catalog-process))]
8077       "--"       "--"
8078       "Routine Shadows"       "Routine Shadows"
8079       ["Check Current Buffer" idlwave-list-buffer-load-path-shadows t]       ["Check Current Buffer" idlwave-list-buffer-load-path-shadows t]
# Line 7448  Assumes that point is at the beginning o Line 8093  Assumes that point is at the beginning o
8093      ("Customize"      ("Customize"
8094       ["Browse IDLWAVE Group" idlwave-customize t]       ["Browse IDLWAVE Group" idlwave-customize t]
8095       "--"       "--"
8096       ["Build Full Customize Menu" idlwave-create-customize-menu       ["Build Full Customize Menu" idlwave-create-customize-menu
8097        (fboundp 'customize-menu-create)])        (fboundp 'customize-menu-create)])
8098      ("Documentation"      ("Documentation"
8099       ["Describe Mode" describe-mode t]       ["Describe Mode" describe-mode t]
# Line 7465  Assumes that point is at the beginning o Line 8110  Assumes that point is at the beginning o
8110    '("Debug"    '("Debug"
8111      ["Start IDL shell" idlwave-shell t]      ["Start IDL shell" idlwave-shell t]
8112      ["Save and .RUN buffer" idlwave-shell-save-and-run      ["Save and .RUN buffer" idlwave-shell-save-and-run
8113       (and (boundp 'idlwave-shell-automatic-start)       (and (boundp 'idlwave-shell-automatic-start)
8114            idlwave-shell-automatic-start)]))            idlwave-shell-automatic-start)]))
8115    
8116  (if (or (featurep 'easymenu) (load "easymenu" t))  (if (or (featurep 'easymenu) (load "easymenu" t))
8117      (progn      (progn
8118        (easy-menu-define idlwave-mode-menu idlwave-mode-map        (easy-menu-define idlwave-mode-menu idlwave-mode-map
8119                          "IDL and WAVE CL editing menu"                          "IDL and WAVE CL editing menu"
8120                          idlwave-mode-menu-def)                          idlwave-mode-menu-def)
8121        (easy-menu-define idlwave-mode-debug-menu idlwave-mode-map        (easy-menu-define idlwave-mode-debug-menu idlwave-mode-map
8122                          "IDL and WAVE CL editing menu"                          "IDL and WAVE CL editing menu"
8123                          idlwave-mode-debug-menu-def)))                          idlwave-mode-debug-menu-def)))
8124    
8125  (defun idlwave-customize ()  (defun idlwave-customize ()
8126    "Call the customize function with idlwave as argument."    "Call the customize function with idlwave as argument."
8127    (interactive)    (interactive)
8128    ;; Try to load the code for the shell, so that we can customize it    ;; Try to load the code for the shell, so that we can customize it
8129    ;; as well.    ;; as well.
8130    (or (featurep 'idlw-shell)    (or (featurep 'idlw-shell)
8131        (load "idlw-shell" t))        (load "idlw-shell" t))
# Line 7491  Assumes that point is at the beginning o Line 8136  Assumes that point is at the beginning o
8136    (interactive)    (interactive)
8137    (if (fboundp 'customize-menu-create)    (if (fboundp 'customize-menu-create)
8138        (progn        (progn
8139          ;; Try to load the code for the shell, so that we can customize it          ;; Try to load the code for the shell, so that we can customize it
8140          ;; as well.          ;; as well.
8141          (or (featurep 'idlw-shell)          (or (featurep 'idlw-shell)
8142              (load "idlw-shell" t))              (load "idlw-shell" t))
8143          (easy-menu-change          (easy-menu-change
8144           '("IDLWAVE") "Customize"           '("IDLWAVE") "Customize"
8145           `(["Browse IDLWAVE group" idlwave-customize t]           `(["Browse IDLWAVE group" idlwave-customize t]
8146             "--"             "--"
# Line 7543  This function was written since `list-ab Line 8188  This function was written since `list-ab
8188    (let ((table (symbol-value 'idlwave-mode-abbrev-table))    (let ((table (symbol-value 'idlwave-mode-abbrev-table))
8189          abbrevs          abbrevs
8190          str rpl func fmt (len-str 0) (len-rpl 0))          str rpl func fmt (len-str 0) (len-rpl 0))
8191      (mapatoms      (mapatoms
8192       (lambda (sym)       (lambda (sym)
8193         (if (symbol-value sym)         (if (symbol-value sym)
8194             (progn             (progn
# Line 7569  This function was written since `list-ab Line 8214  This function was written since `list-ab
8214      (with-output-to-temp-buffer "*Help*"      (with-output-to-temp-buffer "*Help*"
8215        (if arg        (if arg
8216            (progn            (progn
8217              (princ "Abbreviations and Actions in IDLWAVE-Mode\n")              (princ "Abbreviations and Actions in IDLWAVE-Mode\n")
8218              (princ "=========================================\n\n")              (princ "=========================================\n\n")
8219              (princ (format fmt "KEY" "REPLACE" "HOOK"))              (princ (format fmt "KEY" "REPLACE" "HOOK"))
8220              (princ (format fmt "---" "-------" "----")))              (princ (format fmt "---" "-------" "----")))
# Line 7589  This function was written since `list-ab Line 8234  This function was written since `list-ab
8234      (set-buffer "*Help*")      (set-buffer "*Help*")
8235      (setq truncate-lines t)))      (setq truncate-lines t)))
8236    
8237    ;; Add .pro files to speedbar for support, if it's loaded
8238    (eval-after-load "speedbar" '(speedbar-add-supported-extension ".pro"))
8239    
8240  ;; Try to load online help, but catch any errors.  ;; Try to load online help, but catch any errors.
8241  (condition-case nil  (condition-case nil
8242      (idlwave-require-online-help)      (idlwave-require-online-help)
8243    (error nil))    (error nil))
8244    
8245    ;; Set an idle timer to load the routine info.
8246    ;; Will only work on systems which support this.
8247    (or idlwave-routines (idlwave-start-load-rinfo-timer))
8248    
8249  ;; Run the hook  ;; Run the hook
8250  (run-hooks 'idlwave-load-hook)  (run-hooks 'idlwave-load-hook)
8251    

Legend:
Removed from v.3.17  
changed lines
  Added in v.3.17.2.1

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26