]> git.eshelyaron.com Git - emacs.git/commitdiff
Drop IDLWAVE
authorEshel Yaron <me@eshelyaron.com>
Thu, 17 Oct 2024 15:24:04 +0000 (17:24 +0200)
committerEshel Yaron <me@eshelyaron.com>
Thu, 17 Oct 2024 15:26:19 +0000 (17:26 +0200)
14 files changed:
doc/emacs/programs.texi
doc/lispref/loading.texi
doc/misc/Makefile.in
doc/misc/idlwave.texi [deleted file]
etc/TODO
lisp/files.el
lisp/info-look.el
lisp/info.el
lisp/org/ol-info.el
lisp/progmodes/idlw-complete-structtag.el [deleted file]
lisp/progmodes/idlw-help.el [deleted file]
lisp/progmodes/idlw-shell.el [deleted file]
lisp/progmodes/idlw-toolbar.el [deleted file]
lisp/progmodes/idlwave.el [deleted file]

index 2e047857ea0de984964c4041a8baa201883d0814..78b5dfbf5482f6ea230e5b3a49e4e619e0165a6b 100644 (file)
@@ -83,7 +83,6 @@ mode for the C programming language is @code{c-mode}.
 @cindex Javascript mode
 @cindex Awk mode
 @cindex C# mode
-@cindex IDLWAVE mode
 @cindex JSON mode
 @cindex SQL mode
 @cindex TypeScript mode
@@ -93,7 +92,7 @@ mode for the C programming language is @code{c-mode}.
 @cindex TOML mode
   Emacs has programming language modes for Lisp, Scheme, the
 Scheme-based DSSSL expression language, Ada, ASM, AWK, C, C++, C#,
-Elixir, Fortran, Icon, IDL (CORBA), HEEx, IDLWAVE, Java, Javascript,
+Elixir, Fortran, Icon, IDL (CORBA), HEEx, Java, Javascript,
 Lua, M4, Makefiles, Metafont (@TeX{}'s companion for font creation),
 Modula2, Object Pascal, Objective-C, Octave, Pascal, Perl, PHP, Pike,
 PostScript, Prolog, Python, Ruby, Simula, SQL, Tcl, TypeScript,
@@ -142,14 +141,12 @@ For instance, entering C mode runs the hooks @code{prog-mode-hook} and
 @ifnottex
   Separate manuals are available for the modes for Ada (@pxref{Top,,
 Ada Mode, ada-mode, Ada Mode}), C/C++/Objective C/Java/Corba
-IDL/Pike/AWK (@pxref{Top, , CC Mode, ccmode, CC Mode}), Octave, VHDL,
-and IDLWAVE (@pxref{Top,, IDLWAVE, idlwave, IDLWAVE User Manual}).
+IDL/Pike/AWK (@pxref{Top, , CC Mode, ccmode, CC Mode}), Octave, and VHDL.
 @end ifnottex
 @iftex
   The Emacs distribution contains Info manuals for the major modes for
-Ada, C/C++/Objective C/Java/Corba IDL/Pike/AWK, Octave, VHDL, and
-IDLWAVE@.  For Fortran mode, @pxref{Fortran,,, emacs-xtra, Specialized
-Emacs Features}.
+Ada, C/C++/Objective C/Java/Corba IDL/Pike/AWK, Octave, and VHDL.  For
+Fortran mode, @pxref{Fortran,,, emacs-xtra, Specialized Emacs Features}.
 @end iftex
 
 @node Defuns
index 75b9d11028a56b254c3a36b163c0fcc7dae81493..d60a06fb9573ba7776c386f888fdaa14c513cfda 100644 (file)
@@ -887,19 +887,6 @@ already.  If not, it loads the feature from the appropriate file.  This
 file should call @code{provide} at the top level to add the feature to
 @code{features}; if it fails to do so, @code{require} signals an error.
 
-  For example, in @file{idlwave.el}, the definition for
-@code{idlwave-complete-filename} includes the following code:
-
-@example
-(defun idlwave-complete-filename ()
-  "Use the comint stuff to complete a file name."
-   (require 'comint)
-   (let* ((comint-file-name-chars "~/A-Za-z0-9+@@:_.$#%=@{@}\\-")
-          (comint-completion-addsuffix nil)
-          ...)
-       (comint-dynamic-complete-filename)))
-@end example
-
 @noindent
 The expression @code{(require 'comint)} loads the file @file{comint.el}
 if it has not yet been loaded, ensuring that
index 0e10e17f6534c1140db09917f9dee53a42d01bb2..5653d03ea761da663e7b617d2c612c5dfc5dc5a3 100644 (file)
@@ -50,8 +50,6 @@ GZIP_PROG = @GZIP_PROG@
 
 HTML_OPTS = --no-split --html
 
-# Options used only when making info output.
-# (Note that idlwave, info used --nosplit even without the .info extension.)
 INFO_OPTS= --no-split
 
 INSTALL = @INSTALL@
@@ -70,7 +68,7 @@ DOCMISC_W32 = @DOCMISC_W32@
 INFO_COMMON = auth autotype calc ccmode cl dbus dired-x                \
        ediff efaq eglot eieio emacs-gnutls                     \
        emacs-mime epa erc ert eshell eudc eww flymake forms gnus       \
-       htmlfontify idlwave ido info.info mairix-el message     \
+       htmlfontify ido info.info mairix-el message     \
        modus-themes newsticker nxml-mode octave-mode org pcl-cvs pgg   \
        rcirc reftex remember sasl sc ses sieve smtpmail        \
        speedbar todo-mode tramp transient url use-package      \
diff --git a/doc/misc/idlwave.texi b/doc/misc/idlwave.texi
deleted file mode 100644 (file)
index 845c9db..0000000
+++ /dev/null
@@ -1,4255 +0,0 @@
-\input texinfo  @c -*-texinfo-*-
-@c %**start of header
-@setfilename ../../info/idlwave.info
-@settitle IDLWAVE User Manual
-@include docstyle.texi
-@synindex ky cp
-@syncodeindex vr cp
-@syncodeindex fn cp
-@set VERSION 6.1
-@set EDITION 6.1
-@set IDLVERSION 6.3
-@set NSYSROUTINES 4346
-@set DATE April, 2007
-@set AUTHOR J.D. Smith & Carsten Dominik
-@set MAINTAINER J.D. Smith
-@c %**end of header
-@finalout
-
-@copying
-This file documents IDLWAVE, a major mode for editing IDL files with
-Emacs, and interacting with an IDL shell run as a subprocess.
-
-This is edition @value{EDITION} of the IDLWAVE User Manual for IDLWAVE
-@value{VERSION}.
-
-Copyright @copyright{} 1999--2024 Free Software Foundation, Inc.
-
-@quotation
-Permission is granted to copy, distribute and/or modify this document
-under the terms of the GNU Free Documentation License, Version 1.3 or
-any later version published by the Free Software Foundation; with no
-Invariant Sections, with the Front-Cover Texts being ``A GNU Manual'',
-and with the Back-Cover Texts as in (a) below.  A copy of the license
-is included in the section entitled ``GNU Free Documentation License''.
-
-(a) The FSF's Back-Cover Text is: ``You have the freedom to copy and
-modify this GNU manual.''
-@end quotation
-@end copying
-
-@dircategory Emacs editing modes
-@direntry
-* IDLWAVE: (idlwave).           Major mode and shell for IDL files.
-@end direntry
-
-@titlepage
-@title IDLWAVE User Manual
-@subtitle Emacs major mode and shell for IDL
-@subtitle Edition @value{EDITION}, @value{DATE}
-@author by J.D. Smith & Carsten Dominik
-@page
-@vskip 0pt plus 1filll
-@insertcopying
-@end titlepage
-
-@contents
-
-@ifnottex
-@node Top
-@top IDLWAVE
-
-IDLWAVE is a package which supports editing source code written in the
-Interactive Data Language (IDL), and running IDL as an inferior shell.
-
-@insertcopying
-@end ifnottex
-
-@menu
-* Introduction::                What IDLWAVE is, and what it is not
-* IDLWAVE in a Nutshell::       One page quick-start guide
-* Getting Started::             Tutorial
-* The IDLWAVE Major Mode::      The mode for editing IDL programs
-* The IDLWAVE Shell::           The mode for running IDL as an inferior program
-* Acknowledgments::             Who did what
-* Sources of Routine Info::     How does IDLWAVE know about routine XYZ
-* HTML Help Browser Tips::
-* Configuration Examples::      The user is king
-* Windows and macOS::           What still works, and how
-* Troubleshooting::             When good computers turn bad
-* GNU Free Documentation License:: The license for this documentation.
-* Index::                       Fast access
-
-@detailmenu
- --- The Detailed Node Listing ---
-
-Getting Started (Tutorial)
-
-* Lesson I---Development Cycle::
-* Lesson II---Customization::
-* Lesson III---User Catalog::
-
-The IDLWAVE Major Mode
-
-* Code Formatting::             Making code look nice
-* Routine Info::                Calling Sequence and Keyword List
-* Online Help::                 One key press from source to help
-* Completion::                  Completing routine names and Keywords
-* Routine Source::              Finding routines, the easy way
-* Resolving Routines::          Force the Shell to compile a routine
-* Code Templates::              Frequent code constructs
-* Abbreviations::               Abbreviations for common commands
-* Actions::                     Changing case, Padding, End checking
-* Doc Header::                  Inserting a standard header
-* Motion Commands::             Moving through the structure of a program
-* Misc Options::                Things that fit nowhere else
-
-Code Formatting
-
-* Code Indentation::            Reflecting the logical structure
-* Continued Statement Indentation::
-* Comment Indentation::         Special indentation for comment lines
-* Continuation Lines::          Splitting statements over lines
-* Syntax Highlighting::         Font-lock support
-* Octals and Highlighting::     Why "123 causes problems
-
-Online Help
-
-* Help with HTML Documentation::
-* Help with Source::
-
-Completion
-
-* Case of Completed Words::     CaseOFcomPletedWords
-* Object Method Completion and Class Ambiguity::  obj->Method, what?
-* Object Method Completion in the Shell::
-* Class and Keyword Inheritance::  obj->Method, _EXTRA=e
-* Structure Tag Completion::    Completing state.Tag
-
-Actions
-
-* Block Boundary Check::        Is the END statement correct?
-* Padding Operators::           Enforcing space around @samp{=} etc
-* Case Changes::                Enforcing upper case keywords
-
-The IDLWAVE Shell
-
-* Starting the Shell::          How to launch IDL as a subprocess
-* Using the Shell::             Interactively working with the Shell
-* Commands Sent to the Shell::
-* Debugging IDL Programs::
-* Examining Variables::
-* Custom Expression Examination::
-
-Debugging IDL Programs
-
-* A Tale of Two Modes::
-* Debug Key Bindings::
-* Breakpoints and Stepping::
-* Compiling Programs::
-* Walking the Calling Stack::
-* Electric Debug Mode::
-
-Sources of Routine Info
-
-* Routine Definitions::         Where IDL Routines are defined.
-* Routine Information Sources::  So how does IDLWAVE know about...
-* Catalogs::
-* Load-Path Shadows::           Routines defined in several places
-* Documentation Scan::          Scanning the IDL Manuals
-
-Catalogs
-
-* Library Catalogs::
-* User Catalog::
-
-@end detailmenu
-@end menu
-
-@node Introduction
-@chapter Introduction
-@cindex Introduction
-@cindex CORBA (Common Object Request Broker Architecture)
-@cindex Interface Definition Language
-@cindex Interactive Data Language
-@cindex @file{cc-mode.el}
-@cindex @file{idl.el}
-@cindex @file{idl-shell.el}
-@cindex Feature overview
-
-IDLWAVE is a package which supports editing source files written in
-the Interactive Data Language (IDL), and running IDL as an inferior shell@footnote{IDLWAVE can also be used
-for editing source files for the related WAVE/CL language, but with only
-limited support.}.  It is a feature-rich replacement for the IDLDE
-development environment included with IDL, and uses the full power of
-Emacs to make editing and running IDL programs easier, quicker, and more
-structured.
-
-IDLWAVE consists of two main parts: a major mode for editing IDL
-source files (@code{idlwave-mode}) and a mode for running the IDL
-program as an inferior shell (@code{idlwave-shell-mode}).  Although
-one mode can be used without the other, both work together closely to
-form a complete development environment.  Here is a brief summary of
-what IDLWAVE does:
-
-@itemize @bullet
-@item
-Smart code indentation and automatic-formatting.
-@item
-Three level syntax highlighting support.
-@item
-Context-sensitive display of calling sequences and keywords for more
-than 1000 native IDL routines, extensible to any additional number of
-local routines, and already available with many pre-scanned libraries.
-@item
-Fast, context-sensitive online HTML help, or source-header help for
-undocumented routines.
-@item
-Context sensitive completion of routine names, keywords, system
-variables, class names and much more.
-@item
-Easy insertion of code templates and abbreviations of common constructs.
-@item
-Automatic corrections to enforce a variety of customizable coding
-standards.
-@item
-Integrity checks and auto-termination of logical blocks.
-@item
-Routine name space conflict search with likelihood-of-use ranking.
-@item
-Support for @file{imenu}.
-@item
-Documentation support.
-@item
-Running IDL as an inferior Shell with history search, command line
-editing and all the completion and routine info capabilities present in
-IDL source buffers.
-@item
-Full handling of debugging with breakpoints, with interactive setting
-of break conditions, and easy stepping through code.
-@item
-Compilation, execution and interactive single-keystroke debugging of
-programs directly from the source buffer.
-@item
-Quick, source-guided navigation of the calling stack, with variable
-inspection, etc.
-@item
-Examining variables and expressions with a mouse click.
-@item
-And much, much more...
-@end itemize
-
-@c Dead links, 2014/06.
-@ignore
-@ifnottex
-@cindex Screenshots
-Here are a number of screenshots showing IDLWAVE in action:
-
-@itemize @bullet
-@item
-@uref{https://github.com/jdtsmith/idlwave/screenshots/emacs_21_nav.gif,An IDLWAVE buffer}
-@item
-@uref{https://github.com/jdtsmith/idlwave/screenshots/emacs_21_keys.gif,A keyword being completed}
-@item
-@uref{https://github.com/jdtsmith/idlwave/screenshots/emacs_21_help.gif,Online help text.}
-@item
-@uref{https://github.com/jdtsmith/idlwave/screenshots/emacs_21_ri.gif,Routine information displayed}
-@item
-@uref{https://github.com/jdtsmith/idlwave/screenshots/emacs_21_bp.gif,Debugging code
-stopped at a breakpoint}
-@end itemize
-@end ifnottex
-@end ignore
-
-IDLWAVE is the distant successor to the @file{idl.el} and
-@file{idl-shell.el} files written by Chris Chase.  The modes and files
-had to be renamed because of a name space conflict with CORBA's
-@code{idl-mode}, defined in Emacs in the file @file{cc-mode.el}.
-
-In this manual, each section ends with a list of related user options.
-Don't be confused by the sheer number of options available: in most
-cases the default settings are just fine.  The variables are listed here
-to make sure you know where to look if you want to change anything.  For
-a full description of what a particular variable does and how to
-configure it, see the documentation string of that variable (available
-with @kbd{C-h v}).  Some configuration examples are also given in the
-appendix.
-
-@node IDLWAVE in a Nutshell
-@chapter IDLWAVE in a Nutshell
-@cindex Summary of important commands
-@cindex IDLWAVE in a Nutshell
-@cindex Nutshell, IDLWAVE in a
-
-@subheading Editing IDL Programs
-
-@multitable @columnfractions .15 .85
-@item @key{TAB}
-@tab Indent the current line relative to context.
-@item @kbd{C-M-\}
-@tab Re-indent all lines in the current region.
-@item @kbd{C-M-q}
-@tab Re-indent all lines in the current routine.
-@item @kbd{C-u @key{TAB}}
-@tab Re-indent all lines in the current statement.
-@item @kbd{M-@key{RET}}
-@tab Start a continuation line, splitting the current line at point.
-@item @kbd{M-;}
-@tab Start new comment at line beginning or after code, or (un)comment
-highlighted region.
-@item @kbd{M-q}
-@tab Fill the current comment paragraph.
-@item @kbd{C-c ?}
-@tab Display calling sequence and keywords for the procedure or function call
-at point.
-@item @kbd{M-?}
-@tab Load context sensitive online help for nearby routine, keyword, etc.
-@item @kbd{M-@key{TAB}}
-@tab Complete a procedure name, function name or keyword in the buffer.
-@item @kbd{C-c C-i}
-@tab Update IDLWAVE's knowledge about functions and procedures.
-@item @kbd{C-c C-v}
-@tab Visit the source code of a procedure/function.
-@item @kbd{C-u C-c C-v}
-@tab Visit the source code of a procedure/function in this buffer.
-@item @kbd{C-c C-h}
-@tab Insert a standard documentation header.
-@item @kbd{C-c @key{RET}}
-@tab Insert a new timestamp and history item in the documentation header.
-@end multitable
-
-@subheading Running the IDLWAVE Shell, Debugging Programs
-
-@multitable @columnfractions .15 .85
-@item @kbd{C-c C-s}
-@tab Start IDL as a subprocess and/or switch to the shell buffer.
-@item @key{Up}, @kbd{M-p}
-@tab Cycle back through IDL command history.
-@item @key{Down},@kbd{M-n}
-@tab Cycle forward.
-@item @kbd{@key{TAB}}
-@tab Complete a procedure name, function name or keyword in the shell buffer.
-@item @kbd{C-c C-d C-c}
-@tab Save and compile the source file in the current buffer.
-@item @kbd{C-c C-d C-e}
-@tab Compile and run the current region.
-@item @kbd{C-c C-d C-x}
-@tab Go to next syntax error.
-@item @kbd{C-c C-d C-v}
-@tab Switch to electric debug mode.
-@item @kbd{C-c C-d C-b}
-@tab Set a breakpoint at the nearest viable source line.
-@item @kbd{C-c C-d C-d}
-@tab Clear the nearest breakpoint.
-@item @kbd{C-c C-d [}
-@tab Go to the previous breakpoint.
-@item @kbd{C-c C-d ]}
-@tab Go to the next breakpoint.
-@item @kbd{C-c C-d C-p}
-@tab Print the value of the expression near point in IDL.
-@end multitable
-
-@subheading Commonly used Settings in @file{.emacs}
-@lisp
-;; Change the indentation preferences
-;; Start autoloading routine info after 2 idle seconds
-(setq idlwave-init-rinfo-when-idle-after 2)
-;; Pad operators with spaces
-(setq idlwave-do-actions t
-      idlwave-surround-by-blank t)
-;; Syntax Highlighting
-(add-hook 'idlwave-mode-hook 'turn-on-font-lock)
-;; Automatically start the shell when needed
-(setq idlwave-shell-automatic-start t)
-;; Bind debugging commands with CONTROL and SHIFT modifiers
-(setq idlwave-shell-debug-modifiers '(control shift))
-@end lisp
-
-@html
-<A NAME="TUTORIAL"></A>
-@end html
-
-@node Getting Started
-@chapter Getting Started (Tutorial)
-@cindex Quick-Start
-@cindex Tutorial
-@cindex Getting Started
-
-@menu
-* Lesson I---Development Cycle::
-* Lesson II---Customization::
-* Lesson III---User Catalog::
-@end menu
-
-@node  Lesson I---Development Cycle
-@section Lesson I: Development Cycle
-
-The purpose of this tutorial is to guide you through a very basic
-development cycle using IDLWAVE@.  We will paste a simple program into
-a buffer and use the shell to compile, debug and run it.  On the way
-we will use many of the important IDLWAVE commands.  Note, however,
-that IDLWAVE has many more capabilities than covered here, which can
-be discovered by reading the entire manual, or hovering over the
-shoulder of your nearest IDLWAVE guru for a few days.
-
-It is assumed that you have access to Emacs with the full
-IDLWAVE package including online help.  We also assume that you are
-familiar with Emacs and can read the nomenclature of key presses in
-Emacs (in particular, @kbd{C} stands for @key{CONTROL} and @kbd{M} for
-@key{META} (often the @key{ALT} key carries this functionality)).
-
-Open a new source file by typing:
-
-@example
-@kbd{C-x C-f tutorial.pro @key{RET}}
-@end example
-
-A buffer for this file will pop up, and it should be in IDLWAVE mode,
-indicated in the mode line just below the editing window.  Also, the
-menu bar should contain @samp{IDLWAVE}.
-
-Now cut-and-paste the following code, also available as
-@file{tutorial.pro} in the IDLWAVE distribution.
-
-@example
-function daynr,d,m,y
-  ;; compute a sequence number for a date
-  ;; works 1901-2099.
-  if y lt 100 then y = y+1900
-  if m le 2 then delta = 1 else delta = 0
-  m1 = m + delta*12 + 1
-  y1 = y * delta
-  return, d + floor(m1*30.6)+floor(y1*365.25)+5
-end
-
-function weekday,day,month,year
-  ;; compute weekday number for date
-  nr = daynr(day,month,year)
-  return, nr mod 7
-end
-
-pro plot_wday,day,month
-  ;; Plot the weekday of a date in the first 10 years of this century.
-  years = 2000,+indgen(10)
-  wdays = intarr(10)
-  for i=0,n_elements(wdays)-1 do begin
-      wdays[i] =  weekday(day,month,years[i])
-  end
-  plot,years,wdays,YS=2,YT="Wday (0=Sunday)"
-end
-@end example
-
-The indentation probably looks funny, since it's different from the
-settings you use, so use the @key{TAB} key in each line to
-automatically line it up (or, more quickly, @emph{select} the entire
-buffer with @kbd{C-x h}, and indent the whole region with
-@kbd{C-M-\}).  Notice how different syntactical elements are
-highlighted in different colors, if you have set up support for
-font-lock.
-
-Let's check out two particular editing features of IDLWAVE@.  Place the
-cursor after the @code{end} statement of the @code{for} loop and press
-@key{SPC}.  IDLWAVE blinks back to the beginning of the block and
-changes the generic @code{end} to the specific @code{endfor}
-automatically (as long as the variable @code{idlwave-expand-generic-end}
-is turned on; @pxref{Lesson II---Customization}).  Now place the
-cursor in any line you would like to split and press @kbd{M-@key{RET}}.
-The line is split at the cursor position, with the continuation @samp{$}
-and indentation all taken care of.  Use @kbd{C-/} to undo the last
-change.
-
-The procedure @code{plot_wday} is supposed to plot the day of the week
-of a given date for the first 10 years of the 21st century.  As in
-most code, there are a few bugs, which we are going to use IDLWAVE to
-help us fix.
-
-First, let's launch the IDLWAVE shell.  You do this with the command
-@kbd{C-c C-s}.  The Emacs window will split or another window will popup
-to display IDL running in a shell interaction buffer.  Type a few
-commands like @code{print,!PI} to convince yourself that you can work
-there just as well as in a terminal, or the IDLDE@.  Use the arrow keys
-to cycle through your command history.  Are we having fun now?
-
-Now go back to the source window and type @kbd{C-c C-d C-c} to compile
-the program.  If you watch the shell buffer, you see that IDLWAVE types
-@samp{.run "tutorial.pro"} for you.  But the compilation fails because
-there is a comma in the line @samp{years=...}.  The line with the error
-is highlighted and the cursor positioned at the error, so remove the
-comma (you should only need to hit @kbd{Delete}!).  Compile again, using
-the same keystrokes as before.  Notice that the file is automatically
-saved for you.  This time everything should work fine, and you should
-see the three routines compile.
-
-Now we want to use the command to plot the day of the week on January
-1st.  We could type the full command ourselves, but why do that?  Go
-back to the shell window, type @samp{plot_} and hit @key{TAB}.  After
-a bit of a delay (while IDLWAVE initializes its routine info database,
-if necessary), the window will split to show all procedures it knows
-starting with that string, and @w{@code{plot_wday}} should be one of
-them.  Saving the buffer alerted IDLWAVE about this new routine.
-Click with the middle mouse button on @code{plot_wday} and it will be
-copied to the shell buffer, or if you prefer, add @samp{w} to
-@samp{plot_} to make it unambiguous (depending on what other routines
-starting with @samp{plot_} you have installed on your system), hit
-@key{TAB} again, and the full routine name will be completed.  Now
-provide the two arguments:
-
-@example
-plot_wday,1,1
-@end example
-
-@noindent and press @key{RET}.  This fails with an error message telling
-you the @code{YT} keyword to plot is ambiguous.  What are the allowed
-keywords again?  Go back to the source window and put the cursor into
-the ``plot'' line and press @kbd{C-c ?}.  This shows the routine info
-window for the plot routine, which contains a list of keywords, along
-with the argument list.  Oh, we wanted @code{YTITLE}.  Fix that up.
-Recompile with @kbd{C-c C-d C-c}.  Jump back into the shell with
-@kbd{C-c C-s}, press the @key{UP} arrow to recall the previous command
-and execute again.
-
-This time we get a plot, but it is pretty ugly: the points are all
-connected with a line.  Hmm, isn't there a way for @code{plot} to use
-symbols instead?  What was that keyword?  Position the cursor on the
-plot line after a comma (where you'd normally type a keyword), and hit
-@kbd{M-@key{Tab}}.  A long list of plot's keywords appears.  Aha,
-there it is, @code{PSYM}.  Middle click to insert it.  An @samp{=}
-sign is included for you too.  Now what were the values of @code{PSYM}
-supposed to be?  With the cursor on or after the keyword, press
-@kbd{M-?} for online help (alternatively, you could have right clicked
-on the colored keyword itself in the completion list).  A browser will
-pop up showing the HTML documentation for the @code{PYSM} keyword.
-OK, let's use diamonds=4.  Fix this, recompile (you know the command
-by now: @kbd{C-c C-d C-c}), go back to the shell (if it's vanished,
-you know what to do: @kbd{C-c C-s}) and execute again.  Now things
-look pretty good.
-
-Let's try a different day.  How about April fool's day?
-
-@example
-plot_wday,1,4
-@end example
-
-Oops, this looks very wrong.  All April Fool's days cannot be Fridays!
-We've got a bug in the program, perhaps in the @code{daynr} function.
-Let's put a breakpoint on the last line there.  Position the cursor on
-the @samp{return, d+...} line and press @kbd{C-c C-d C-b}.  IDL sets a
-breakpoint (as you see in the shell window), and the break line is
-indicated.  Back to the shell buffer, re-execute the previous command.
-IDL stops at the line with the breakpoint.  Now hold down the SHIFT
-key and click with the middle mouse button on a few variables there:
-@samp{d}, @samp{y}, @samp{m}, @samp{y1}, etc.  Maybe @code{d} isn't
-the correct type.  CONTROL-SHIFT middle-click on it for help.  Well,
-it's an integer, so that's not the problem.  Aha, @samp{y1} is zero,
-but it should be the year, depending on delta.  Shift click
-@samp{delta} to see that it's 0.  Below, we see the offending line:
-@samp{y1=y*delta...} the multiplication should have been a minus sign!
-Hit @kbd{q} to exit the debugging mode, and fix the line to read:
-
-@example
-y1 = y - delta
-@end example
-
-Now remove all breakpoints: @kbd{C-c C-d C-a}.  Recompile and rerun the
-command.  Everything should now work fine.  How about those leap years?
-Change the code to plot 100 years and see that every 28 years, the
-sequence of weekdays repeats.
-
-@node  Lesson II---Customization
-@section Lesson II: Customization
-
-Emacs is probably the most customizable piece of software ever written,
-and it would be a shame if you did not make use of this to adapt IDLWAVE
-to your own preferences.  Customizing Emacs or IDLWAVE is accomplished
-by setting Lisp variables in the @file{.emacs} file in your home
-directory---but do not be dismayed; for the most part, you can just
-copy and work from the examples given here.
-
-Let's first use a boolean variable.  These are variables which you turn
-on or off, much like a checkbox.  A value of @samp{t} means on, a value
-of @samp{nil} means off.  Copy the following line into your
-@file{.emacs} file, exit and restart Emacs.
-
-@lisp
-(setq idlwave-reserved-word-upcase t)
-@end lisp
-
-When this option is turned on, each reserved word you type into an IDL
-source buffer will be converted to upper case when you press @key{SPC}
-or @key{RET} right after the word.  Try it out!  @samp{if} changes to
-@samp{IF}, @samp{begin} to @samp{BEGIN}.  If you don't like this
-behavior, remove the option again from your @file{.emacs} file and
-restart Emacs.
-
-You likely have your own indentation preferences for IDL code.  For
-example, some may prefer to indent the main block of an IDL program
-slightly from the margin and use only 3 spaces as indentation between
-@code{BEGIN} and @code{END}.  Try the following lines in @file{.emacs}:
-
-@lisp
-(setq idlwave-main-block-indent 1)
-(setq idlwave-block-indent 3)
-(setq idlwave-end-offset -3)
-@end lisp
-
-Restart Emacs, and re-indent the program we developed in the first part
-of this tutorial with @kbd{C-c h} and @kbd{C-M-\}.  You may want to keep
-these lines in @file{.emacs}, with values adjusted to your liking.  If
-you want to get more information about any of these variables, type,
-e.g., @kbd{C-h v idlwave-main-block-indent @key{RET}}.  To find which
-variables can be customized, look for items marked @samp{User Option:}
-throughout this manual.
-
-If you cannot seem to master this Lisp customization in @file{.emacs},
-there is another, more user-friendly way to customize all the IDLWAVE
-variables.  You can access it through the IDLWAVE menu in one of the
-@file{.pro} buffers, menu item @code{Customize->Browse IDLWAVE
-Group}.  Here you'll be presented with all the various variables grouped
-into categories.  You can navigate the hierarchy (e.g., @samp{IDLWAVE
-Code Formatting->Idlwave Abbrev And Indent Action->Idlwave Expand
-Generic End} to turn on @code{END} expansion), read about the variables,
-change them, and ``Save for Future Sessions''.  Few of these variables
-need customization, but you can exercise considerable control over
-IDLWAVE's functionality with them.
-
-You may also find the key bindings used for the debugging commands too
-long and complicated.  Often we have heard complaints along the lines
-of, ``Do I really have to go through the finger gymnastics of @kbd{C-c
-C-d C-c} to run a simple command?''  Due to Emacs rules and
-conventions, shorter bindings cannot be set by default, but you can
-easily enable them.  First, there is a way to assign all debugging
-commands in a single sweep to another simpler combination.  The only
-problem is that we have to use something which Emacs does not need for
-other important commands.  One good option is to execute debugging
-commands by holding down @key{CONTROL} and @key{SHIFT} while pressing
-a single character: @kbd{C-S-b} for setting a breakpoint, @kbd{C-S-c}
-for compiling the current source file, @kbd{C-S-a} for deleting all
-breakpoints (try it, it's easier).  You can enable this with:
-
-@lisp
-(setq idlwave-shell-debug-modifiers '(shift control))
-@end lisp
-
-@noindent If you have a special keyboard with, for example, a
-@key{SUPER} key, you could even shorten that:
-
-@lisp
-(setq idlwave-shell-debug-modifiers '(super))
-@end lisp
-
-@noindent to get compilation on @kbd{S-c}.  Often, a modifier key like
-@key{SUPER} or @key{HYPER} is bound or can be bound to an otherwise
-unused key on your keyboard; consult your system documentation.
-
-You can also assign specific commands to keys.  This you must do in the
-@emph{mode-hook}, a special function which is run when a new IDLWAVE
-buffer gets set up.  The possibilities for key customization are
-endless.  Here we set function keys f4-f8 to common debugging commands.
-
-@lisp
-;; First for the source buffer
-(add-hook 'idlwave-mode-hook
-   (lambda ()
-    (local-set-key [f4] 'idlwave-shell-retall)
-    (local-set-key [f5] 'idlwave-shell-break-here)
-    (local-set-key [f6] 'idlwave-shell-clear-current-bp)
-    (local-set-key [f7] 'idlwave-shell-cont)
-    (local-set-key [f8] 'idlwave-shell-clear-all-bp)))
-;; Then for the shell buffer
-(add-hook 'idlwave-shell-mode-hook
-   (lambda ()
-    (local-set-key [f4] 'idlwave-shell-retall)
-    (local-set-key [f5] 'idlwave-shell-break-here)
-    (local-set-key [f6] 'idlwave-shell-clear-current-bp)
-    (local-set-key [f7] 'idlwave-shell-cont)
-    (local-set-key [f8] 'idlwave-shell-clear-all-bp)))
-@end lisp
-
-@node  Lesson III---User Catalog
-@section Lesson III: User and Library Catalogs
-
-We have already used the routine info display in the first part of this
-tutorial.  This was the invoked using @kbd{C-c ?}, and displays
-information about the IDL routine near the cursor position.  Wouldn't it
-be nice to have the same kind of information available for your own
-routines and for the huge amount of code in major libraries like JHUAPL
-or the IDL-Astro library?  In many cases, you may already have this
-information.  Files named @file{.idlwave_catalog} in library directories
-contain scanned information on the routines in that directory; many
-popular libraries ship with these ``library catalogs'' pre-scanned.
-Users can scan their own routines in one of two ways: either using the
-supplied tool to scan directories and build their own
-@file{.idlwave_catalog} files, or using the built-in method to create a
-single ``user catalog'', which we'll show here.  @xref{Catalogs}, for
-more information on choosing which method to use.
-
-To build a user catalog, select @code{Routine Info/Select Catalog
-Directories} from the IDLWAVE entry in the menu bar.  If necessary,
-start the shell first with @kbd{C-c C-s} (@pxref{Starting the Shell}).
-IDLWAVE will find out about the IDL @code{!PATH} variable and offer a
-list of directories on the path.  Simply select them all (or whichever
-you want; directories with existing library catalogs will not be
-selected by default) and click on the @samp{Scan&Save} button.  Then
-go for a cup of coffee while IDLWAVE collects information for each and
-every IDL routine on your search path.  All this information is
-written to the file @file{~/.emacs.d/idlwave/idlusercat.el}
-and will from now on automatically load whenever you use
-IDLWAVE@.  You may find it necessary to rebuild the catalog on occasion
-as your local libraries change, or build a library catalog for those
-directories instead.  Invoke routine info (@kbd{C-c ?}) or completion
-(@kbd{M-@key{TAB}}) on any routine or partial routine name you know to
-be located in the library.  E.g., if you have scanned the IDL-Astro
-library:
-
-@example
-    a=readf@kbd{M-@key{TAB}}
-@end example
-
-expands to ``readfits(''.  Then try
-
-@example
-    a=readfits(@kbd{C-c ?}
-@end example
-
-and you get:
-
-@example
-Usage:    Result = READFITS(filename, header, heap)
-...
-@end example
-
-I hope you made it until here.  Now you are set to work with IDLWAVE@.
-On the way you will want to change other things, and to learn more
-about the possibilities not discussed in this short tutorial.  Read
-the manual, look at the documentation strings of interesting variables
-(with @kbd{C-h v idlwave<-variable-name> @key{RET}}) and ask the
-remaining questions on the newsgroup @code{comp.lang.idl-pvwave}.
-
-@node The IDLWAVE Major Mode
-@chapter The IDLWAVE Major Mode
-@cindex IDLWAVE major mode
-@cindex Major mode, @code{idlwave-mode}
-
-The IDLWAVE major mode supports editing IDL source files.  In this
-chapter we describe the main features of the mode and how to customize
-them.
-
-@menu
-* Code Formatting::             Making code look nice
-* Routine Info::                Calling Sequence and Keyword List
-* Online Help::                 One key press from source to help
-* Completion::                  Completing routine names and Keywords
-* Routine Source::              Finding routines, the easy way
-* Resolving Routines::          Force the Shell to compile a routine
-* Code Templates::              Frequent code constructs
-* Abbreviations::               Abbreviations for common commands
-* Actions::                     Changing case, Padding, End checking
-* Doc Header::                  Inserting a standard header
-* Motion Commands::             Moving through the structure of a program
-* Misc Options::                Things that fit nowhere else
-@end menu
-
-@node Code Formatting
-@section Code Formatting
-@cindex Code formatting
-@cindex Formatting, of code
-
-@menu
-* Code Indentation::            Reflecting the logical structure
-* Continued Statement Indentation::
-* Comment Indentation::         Special indentation for comment lines
-* Continuation Lines::          Splitting statements over lines
-* Syntax Highlighting::         Font-lock support
-* Octals and Highlighting::     Why "123 causes problems
-@end menu
-
-The IDL language, with its early roots in FORTRAN, modern
-implementation in C, and liberal borrowing of features of many vector
-and other languages along its 25+ year history, has inherited an
-unusual mix of syntax elements.  Left to his or her own devices, a
-novice IDL programmer will often conjure code which is very difficult
-to read and impossible to adapt.  Much can be gleaned from studying
-available IDL code libraries for coding style pointers, but, due to
-the variety of IDL syntax elements, replicating this style can be
-challenging at best.  Luckily, IDLWAVE understands the structure of
-IDL code very well, and takes care of almost all formatting issues for
-you.  After configuring it to match your coding standards, you can
-rely on it to help keep your code neat and organized.
-
-
-@node Code Indentation
-@subsection Code Indentation
-@cindex Code indentation
-@cindex Indentation
-
-Like all Emacs programming modes, IDLWAVE performs code indentation.
-The @key{TAB} key indents the current line relative to context.
-@key{LFD} insert a newline and indents the new line.  The indentation is
-governed by a number of variables.  IDLWAVE indents blocks (between
-@code{PRO}/@code{FUNCTION}/@code{BEGIN} and @code{END}), and
-continuation lines.
-
-@cindex Foreign code, adapting
-@cindex Indentation, of foreign code
-@kindex C-M-\
-To re-indent a larger portion of code (e.g., when working with foreign
-code written with different conventions), use @kbd{C-M-\}
-(@code{indent-region}) after marking the relevant code.  Useful marking
-commands are @kbd{C-x h} (the entire file) or @kbd{C-M-h} (the current
-subprogram).  The command @kbd{C-M-q} reindents the entire current
-routine.  @xref{Actions}, for information how to impose additional
-formatting conventions on foreign code.
-
-@defopt idlwave-main-block-indent (@code{2})
-Extra indentation for the main block of code.  That is the block between
-the FUNCTION/PRO statement and the END statement for that program
-unit.
-@end defopt
-
-@defopt idlwave-block-indent (@code{3})
-Extra indentation applied to block lines.  If you change this, you
-probably also want to change @code{idlwave-end-offset}.
-@end defopt
-
-@defopt idlwave-end-offset (@code{-3})
-Extra indentation applied to block END lines.  A value equal to negative
-@code{idlwave-block-indent} will make END lines line up with the block
-BEGIN lines.
-@end defopt
-
-@node Continued Statement Indentation
-@subsection Continued Statement Indentation
-@cindex Indentation, continued statement
-@cindex Continued statement indentation
-Continuation lines (following a line ending with @code{$}) can receive a
-fixed indentation offset from the main level, but in several situations
-IDLWAVE can use a special form of indentation which aligns continued
-statements more naturally.  Special indentation is calculated for
-continued routine definition statements and calls, enclosing parentheses
-(like function calls, structure/class definitions, explicit structures
-or lists, etc.), and continued assignments.  An attempt is made to line
-up with the first non-whitespace character after the relevant opening
-punctuation mark (@code{,},@code{(},@code{@{},@code{[},@code{=}).  For
-lines without any non-comment characters on the line with the opening
-punctuation, the continued line(s) are aligned just past the
-punctuation.  An example:
-
-@example
-function foo, a, b,  $
-              c, d
-  bar =  sin( a + b + $
-              c + d)
-end
-@end example
-@noindent
-
-The only drawback to this special continued statement indentation is
-that it consumes more space, e.g., for long function names or left hand
-sides of an assignment:
-
-@example
-function thisfunctionnameisverylongsoitwillleavelittleroom, a, b, $
-                                                            c, d
-@end example
-
-You can instruct IDLWAVE when to avoid using this special continuation
-indentation by setting the variable
-@code{idlwave-max-extra-continuation-indent}, which specifies the
-maximum additional indentation beyond the basic indent to be
-tolerated, otherwise defaulting to a fixed-offset from the enclosing
-indent (the size of which offset is set in
-@code{idlwave-continuation-indent}).  As a special case, continuations
-of routine calls without any arguments or keywords will @emph{not}
-align the continued line, under the assumption that you continued
-because you needed the space.
-
-Also, since the indentation level can be somewhat dynamic in continued
-statements with special continuation indentation, especially if
-@code{idlwave-max-extra-continuation-indent} is small, the key
-@kbd{C-u @key{TAB}} will re-indent all lines in the current statement.
-Note that @code{idlwave-indent-to-open-paren}, if non-@code{nil},
-overrides the @code{idlwave-max-extra-continuation-indent} limit, for
-parentheses only, forcing them always to line up.
-
-
-@defopt idlwave-continuation-indent (@code{2})
-Extra indentation applied to normal continuation lines.
-@end defopt
-
-@defopt idlwave-max-extra-continuation-indent (@code{20})
-The maximum additional indentation (over the basic continuation-indent)
-that will be permitted for special continues.  To effectively disable
-special continuation indentation, set to @code{0}.  To enable it
-constantly, set to a large number (like @code{100}).  Note that the
-indentation in a long continued statement never decreases from line to
-line, outside of nested parentheses statements.
-@end defopt
-
-@defopt idlwave-indent-to-open-paren (@code{t})
-Non-@code{nil} means indent continuation lines to innermost open
-parenthesis, regardless of whether the
-@code{idlwave-max-extra-continuation-indent} limit is satisfied.
-@end defopt
-
-@node Comment Indentation
-@subsection Comment Indentation
-@cindex Comment indentation
-@cindex Hanging paragraphs
-@cindex Paragraphs, filling
-@cindex Paragraphs, hanging
-
-In IDL, lines starting with a @samp{;} are called @emph{comment lines}.
-Comment lines are indented as follows:
-
-@multitable @columnfractions .1 .90
-@item @code{;;;}
-@tab The indentation of lines starting with three semicolons remains
-unchanged.
-@item @code{;;}
-@tab Lines starting with two semicolons are indented like the surrounding code.
-@item @code{;}
-@tab Lines starting with a single semicolon are indented to a minimum column.
-@end multitable
-
-@noindent
-The indentation of comments starting in column 0 is never changed.
-
-@defopt idlwave-no-change-comment
-The indentation of a comment starting with this regexp will not be
-changed.
-@end defopt
-
-@defopt idlwave-begin-line-comment
-A comment anchored at the beginning of line.
-@end defopt
-
-@defopt idlwave-code-comment
-A comment that starts with this regexp is indented as if it is a part of
-IDL code.
-@end defopt
-
-@node Continuation Lines
-@subsection Continuation Lines and Filling
-@cindex Continuation lines
-@cindex Line splitting
-@cindex String splitting
-@cindex Splitting, of lines
-
-@kindex M-RET
-In IDL, a newline character terminates a statement unless preceded by a
-@samp{$}.  If you would like to start a continuation line, use
-@kbd{M-@key{RET}}, which calls the command @code{idlwave-split-line}.
-It inserts the continuation character @samp{$}, terminates the line and
-indents the new line.  The command @kbd{M-@key{RET}} can also be invoked
-inside a string to split it at that point, in which case the @samp{+}
-concatenation operator is used.
-
-@cindex Filling
-@cindex @code{auto-fill-mode}
-@cindex Hanging paragraphs
-When filling comment paragraphs, IDLWAVE overloads the normal filling
-functions and uses a function which creates the hanging paragraphs
-customary in IDL routine headers.  When @code{auto-fill-mode} is turned
-on (toggle with @kbd{C-c C-a}), comments will be auto-filled.  If the
-first line of a paragraph contains a match for
-@code{idlwave-hang-indent-regexp} (a dash-space by default), subsequent
-lines are positioned to line up after it, as in the following example.
-
-@example
-@group
-;=================================
-; x - an array containing
-;     lots of interesting numbers.
-;
-; y - another variable where
-;     a hanging paragraph is used
-;     to describe it.
-;=================================
-@end group
-@end example
-
-@kindex M-q
-You can also refill a comment at any time paragraph with @kbd{M-q}.
-Comment delimiting lines as in the above example, consisting of one or
-more @samp{;} followed by one or more of the characters @samp{+=-_*},
-are kept in place, as is.
-
-@defopt idlwave-fill-comment-line-only (@code{t})
-Non-@code{nil} means auto fill will only operate on comment lines.
-@end defopt
-
-@defopt idlwave-auto-fill-split-string (@code{t})
-Non-@code{nil} means auto fill will split strings with the IDL @samp{+}
-operator.
-@end defopt
-
-@defopt idlwave-split-line-string (@code{t})
-Non-@code{nil} means @code{idlwave-split-line} will split strings with
-@samp{+}.
-@end defopt
-
-@defopt idlwave-hanging-indent (@code{t})
-Non-@code{nil} means comment paragraphs are indented under the hanging
-indent given by @code{idlwave-hang-indent-regexp} match in the first
-line of the paragraph.
-@end defopt
-
-@defopt idlwave-hang-indent-regexp (@code{"- "})
-Regular expression matching the position of the hanging indent
-in the first line of a comment paragraph.
-@end defopt
-
-@defopt idlwave-use-last-hang-indent (@code{nil})
-Non-@code{nil} means use last match on line for
-@code{idlwave-indent-regexp}.
-@end defopt
-
-@node Syntax Highlighting
-@subsection Syntax Highlighting
-@cindex Syntax highlighting
-@cindex Highlighting of syntax
-@cindex Font lock
-
-Highlighting of keywords, comments, strings etc.@: can be accomplished
-with @code{font-lock}.  If you are using @code{global-font-lock-mode},
-or have @code{font-lock-mode} turned on in any other buffer,
-it should also automatically work in IDLWAVE buffers.  If you'd
-prefer invoking font-lock individually by mode, you can enforce it in
-@code{idlwave-mode} with the following line in your @file{.emacs}:
-
-@lisp
-(add-hook 'idlwave-mode-hook 'turn-on-font-lock)
-@end lisp
-
-@noindent IDLWAVE supports 3 increasing levels of syntax highlighting.
-The variable @code{font-lock-maximum-decoration} determines which level
-is selected.  Individual categories of special tokens can be selected
-for highlighting using the variable
-@code{idlwave-default-font-lock-items}.
-
-@defopt idlwave-default-font-lock-items
-Items which should be fontified on the default fontification level
-2.
-@end defopt
-
-@node Octals and Highlighting
-@subsection Octals and Highlighting
-@cindex Syntax highlighting, Octals
-@cindex Highlighting of syntax, Octals
-
-A rare syntax highlighting problem results from an extremely unfortunate
-notation for octal numbers in IDL: @code{"123}.  This unpaired quotation
-mark is very difficult to parse, given that it can be mixed on a single
-line with any number of strings.  Emacs will incorrectly identify this
-as a string, and the highlighting of following lines of code can be
-distorted, since the string is never terminated.
-
-One solution to this involves terminating the mistakenly identified
-string yourself by providing a closing quotation mark in a comment:
-
-@example
-  string("305B) + $ ;" <--- for font-lock
-   ' is an Angstrom.'
-@end example
-
-@noindent A far better solution is to abandon this notation for octals
-altogether, and use the more sensible alternative IDL provides:
-
-@example
-   string('305'OB) + ' is an Angstrom.'
-@end example
-
-@noindent This simultaneously solves the font-lock problem and is more
-consistent with the notation for hexadecimal numbers, e.g., @code{'C5'XB}.
-
-@node Routine Info
-@section Routine Info
-@cindex Routine info
-@cindex Updating routine info
-@cindex Scanning buffers for routine info
-@cindex Buffers, scanning for routine info
-@cindex Shell, querying for routine info
-
-@kindex C-c C-i
-IDL comes bundled with more than one thousand procedures, functions
-and object methods, and large libraries typically contain hundreds or
-even thousands more (each with a few to tens of keywords and
-arguments).  This large command set can make it difficult to remember
-the calling sequence and keywords for the routines you use, but
-IDLWAVE can help.  It builds up routine information from a wide
-variety of sources; IDLWAVE in fact knows far more about the
-@samp{.pro} routines on your system than IDL itself!  It maintains a
-list of all built-in routines, with calling sequences and
-keywords@footnote{This list is created by scanning the IDL manuals and
-might contain (very few) errors.  Please report any errors to the
-maintainer, so that they can be fixed.}.  It also scans Emacs buffers
-for routine definitions, queries the IDLWAVE-Shell for information
-about routines currently compiled there, and automatically locates
-library and user-created catalogs.  This information is updated
-automatically, and so should usually be current.  To force a global
-update and refresh the routine information, use @kbd{C-c C-i}
-(@code{idlwave-update-routine-info}).
-
-@kindex C-c ?
-To display the information about a routine, press @kbd{C-c ?}, which
-calls the command @code{idlwave-routine-info}.  When the current cursor
-position is on the name or in the argument list of a procedure or
-function, information will be displayed about the routine.  For example,
-consider the indicated cursor positions in the following line:
-
-@example
-plot,x,alog(x+5*sin(x) + 2),
-  |  |   |   |   |  |  |    |
-  1  2   3   4   5  6  7    8
-@end example
-
-@cindex Default routine, for info and help
-On positions 1,2 and 8, information about the @samp{plot} procedure will
-be shown.  On positions 3,4, and 7, the @samp{alog} function will be
-described, while positions 5 and 6 will investigate the @samp{sin}
-function.
-
-When you ask for routine information about an object method, and the
-method exists in several classes, IDLWAVE queries for the class of the
-object, unless the class is already known through a text property on the
-@samp{->} operator (@pxref{Object Method Completion and Class
-Ambiguity}), or by having been explicitly included in the call
-(e.g., @code{a->myclass::Foo}).
-
-@cindex Calling sequences
-@cindex Keywords of a routine
-@cindex Routine source information
-The description displayed contains the calling sequence, the list of
-keywords and the source location of this routine.  It looks like this:
-
-@example
-Usage:    XMANAGER, NAME, ID
-Keywords: BACKGROUND CATCH CLEANUP EVENT_HANDLER GROUP_LEADER
-          JUST_REG MODAL NO_BLOCK
-Source:   SystemLib   [LCSB] /soft1/idl53/lib/xmanager.pro
-@end example
-
-@cindex Categories, of routines
-@cindex Load-path shadows
-@cindex Shadows, load-path
-@cindex IDL variable @code{!PATH}
-@cindex @code{!PATH}, IDL variable
-@cindex IDL variable @code{!DIR}
-@cindex @code{!DIR}, IDL variable
-
-If a definition of this routine exists in several files accessible to
-IDLWAVE, several @samp{Source} lines will point to the different
-files.  This may indicate that your routine is shadowing a system
-library routine, which may or may not be what you want
-(@pxref{Load-Path Shadows}).  The information about the calling
-sequence and keywords is derived from the first source listed.
-Library routines are available only if you have scanned your local IDL
-directories or are using pre-scanned libraries (@pxref{Catalogs}).
-The source entry consists of a @emph{source category}, a set of
-@emph{flags} and the path to the @emph{source file}.  The following
-default categories exist:
-
-@multitable @columnfractions .15 .85
-@item @i{System}
-@tab A system routine of unknown origin.  When the system library has
-been scanned as part of a catalog (@pxref{Catalogs}), this category
-will automatically split into the next two.
-@item @i{Builtin}
-@tab A builtin system routine with no source code available.
-@item @i{SystemLib}
-@tab A library system routine in the official lib directory @file{!DIR/lib}.
-@item @i{Obsolete}
-@tab A library routine in the official lib directory @file{!DIR/lib/obsolete}.
-@item @i{Library}
-@tab A routine in a file on IDL's search path @code{!PATH}.
-@item @i{Other}
-@tab Any other routine with a file not known to be on the search path.
-@item @i{Unresolved}
-@tab An otherwise unknown routine the shell lists as unresolved
-(referenced, but not compiled).
-@end multitable
-
-Any routines discovered in library catalogs (@pxref{Library
-Catalogs}), will display the category assigned during creation,
-e.g., @samp{NasaLib}.  For routines not discovered in this way, you can
-create additional categories based on the routine's filename using the
-variable @code{idlwave-special-lib-alist}.
-
-@cindex Flags, in routine info
-@cindex Duplicate routines
-@cindex Multiply defined routines
-@cindex Routine definitions, multiple
-The flags @code{[LCSB]} indicate the source of the information IDLWAVE
-has regarding the file: from a library catalog (@w{@code{[L---]}}),
-from a user catalog (@w{@code{[-C--]}}, from the IDL Shell
-(@w{@code{[--S-]}}) or from an Emacs buffer (@w{@code{[---B]}}).
-Combinations are possible (a compiled library routine visited in a
-buffer might read @w{@code{[L-SB]}}).  If a file contains multiple
-definitions of the same routine, the file name will be prefixed with
-@samp{(Nx)} where @samp{N} is the number of definitions.
-
-@cindex Online Help from the routine info buffer
-@cindex Active text, in routine info
-@cindex Inserting keywords, from routine info
-@cindex Source file, access from routine info
-Some of the text in the @file{*Help*} routine info buffer will be active
-(it is highlighted when the mouse moves over it).  Typically, clicking
-with the right mouse button invokes online help lookup, and clicking
-with the middle mouse button inserts keywords or visits files:
-
-@multitable @columnfractions 0.15 0.85
-@item @i{Usage}
-@tab If online help is installed, a click with the @emph{right} mouse
-button on the @i{Usage:} line will access the help for the
-routine (@pxref{Online Help}).
-@item @i{Keyword}
-@tab Online help about keywords is also available with the
-@emph{right} mouse button.  Clicking on a keyword with the @emph{middle}
-mouse button will insert this keyword in the buffer from where
-@code{idlwave-routine-info} was called.  Holding down @key{SHIFT} while
-clicking also adds the initial @samp{/}.
-@item @i{Source}
-@tab Clicking with the @emph{middle} mouse button on a @samp{Source} line
-finds the source file of the routine and visits it in another window.
-Another click on the same line switches back to the buffer from which
-@kbd{C-c ?} was called.  If you use the @emph{right} mouse button, the
-source will not be visited by a buffer, but displayed in the online help
-window.
-@item @i{Classes}
-@tab The @i{Classes} line is only included in the routine info window if
-the current class inherits from other classes.  You can click with the
-@emph{middle} mouse button to display routine info about the current
-method in other classes on the inheritance chain, if such a method
-exists there.
-@end multitable
-
-@defopt idlwave-resize-routine-help-window (@code{t})
-Non-@code{nil} means resize the Routine-info @file{*Help*} window to
-fit the content.
-@end defopt
-
-@defopt idlwave-special-lib-alist
-Alist of regular expressions matching special library directories.
-@end defopt
-
-@defopt idlwave-rinfo-max-source-lines (@code{5})
-Maximum number of source files displayed in the Routine Info window.
-@end defopt
-
-
-@html
-<A NAME="ONLINE_HELP"></A>
-@end html
-@node Online Help
-@section Online Help
-
-@cindex Online Help
-@cindex @file{idlw-help.txt}
-@cindex @file{idlw-help.el}
-@cindex Installing online help
-@cindex Online Help, Installation
-@cindex Speed, of online help
-@cindex XML Help Catalog
-
-For IDL system routines, extensive documentation is supplied with IDL@.
-IDLWAVE can access the HTML version of this documentation very quickly
-and accurately, based on the local context.  This can be @emph{much}
-faster than using the IDL online help application, because IDLWAVE
-usually gets you to the right place in the documentation directly---e.g.,
-a specific keyword of a routine---without any additional browsing
-and scrolling.
-
-For this online help to work, an HTML version of the IDL documentation
-is required.  Beginning with IDL 6.2, HTML documentation is distributed
-directly with IDL, along with an XML-based catalog of routine
-information.  By default, IDLWAVE automatically attempts to convert this
-XML catalog into a format Emacs can more easily understand, and caches
-this information in your @code{idlwave_config_directory}
-(@file{~/.emacs.d/idlwave/}, by default).  It also re-scans the XML catalog if
-it is newer than the current cached version.  You can force rescan with
-the menu entry @code{IDLWAVE->Routine Info->Rescan XML Help Catalog}.
-
-Before IDL 6.2, the HTML help was not distributed with IDL, and was not
-part of the standalone IDLWAVE distribution, but had to be downloaded
-separately.  This is no longer necessary: all help and routine
-information is supplied with IDL versions 6.2 and later.
-
-There are a variety of options for displaying the HTML help: see below.
-Help for routines without HTML documentation is also available, by using
-the routine documentation header and/or routine source.
-
-@kindex M-?
-In any IDL program (or, as with most IDLWAVE commands, in the IDL
-Shell), press @kbd{M-?} (@code{idlwave-context-help}), or click with
-@kbd{S-mouse-3} to access context sensitive online help.  The following
-locations are recognized context for help:
-
-@cindex Context, for online help
-@multitable @columnfractions .25 .75
-@item @i{Routine names}
-@tab The name of a routine (function, procedure, method).
-@item @i{Keyword Parameters}
-@tab A keyword parameter of a routine.
-@item @i{System Variables}
-@tab System variables like @code{!DPI}.
-@item @i{System Variable Tags}
-@tab System variables tags like @code{!D.X_SIZE}.
-@item @i{IDL Statements}
-@tab Statements like @code{PRO}, @code{REPEAT}, @code{COMPILE_OPT}, etc.
-@item @i{IDL Controls}
-@tab Control structures like @code{FOR}, @code{SWITCH}, etc.
-@item @i{Class names}
-@tab A class name in an @code{OBJ_NEW} call.
-@item @i{Class Init Keywords}
-@tab Beyond the class name in an @code{OBJ_NEW} call.
-@item @i{Executive Command}
-@tab An executive command like @code{.RUN}.  Mostly useful in the shell.
-@item @i{Structure Tags}
-@tab Structure tags like @code{state.xsize}
-@item @i{Class Tags}
-@tab Class tags like @code{self.value}.
-@item @i{Default}
-@tab The routine that would be selected for routine info display.
-@end multitable
-
-@cindex @code{OBJ_NEW}, special online help
-Note that the @code{OBJ_NEW} function is special in that the help
-displayed depends on the cursor position.  If the cursor is on the
-@samp{OBJ_NEW}, this function is described.  If it is on the class
-name inside the quotes, the documentation for the class is pulled up.
-If the cursor is @emph{after} the class name, anywhere in the argument
-list, the documentation for the corresponding @code{Init} method and
-its keywords is targeted.
-
-Apart from an IDLWAVE buffer or shell, there are two more places from
-which online help can be accessed.
-
-@itemize @bullet
-@item
-Online help for routines and keywords can be accessed through the
-Routine Info display.  Click with @kbd{mouse-3} on an item to see the
-corresponding help (@pxref{Routine Info}).
-@item
-When using completion and Emacs pops up a @file{*Completions*} buffer
-with possible completions, clicking with @kbd{mouse-3} on a completion
-item invokes help on that item (@pxref{Completion}).  Items for which
-help is available in the online system documentation (vs. just the
-program source itself) will be emphasized (e.g., colored blue).
-@end itemize
-@noindent
-In both cases, a blue face indicates that the item is documented in
-the IDL manual, but an attempt will be made to visit non-blue items
-directly in the originating source file.
-
-
-@menu
-* Help with HTML Documentation::
-* Help with Source::
-@end menu
-
-@node Help with HTML Documentation
-@subsection Help with HTML Documentation
-@cindex HTML Help
-@cindex Help using HTML manuals
-@cindex IDL manual, HTML version
-@cindex IDL Assistant
-
-Help using the HTML documentation is invoked with the built-in Emacs
-command @code{browse-url}, which displays the relevant help topic in a
-browser of your choosing.  Beginning with version 6.2, IDL comes with
-the help browser @emph{IDL Assistant}, which it uses by default for
-displaying online help on all supported platforms.  This browser
-offers topical searches, an index, and is also now the default and
-recommended IDLWAVE help browser.  The variable
-@code{idlwave-help-use-assistant} controls whether this browser is
-used.  Note that, due to limitations in the Assistant, invoking help
-within IDLWAVE and @code{? topic} within IDL will result in two
-running copies of Assistant.
-
-Aside from the IDL Assistant, there are many possible browsers to choose
-among, with differing advantages and disadvantages.  The variable
-@code{idlwave-help-browser-function} controls which browser help is sent
-to (as long as @code{idlwave-help-use-assistant} is not set).  This
-function is used to set the variable @code{browse-url-browser-function}
-locally for IDLWAVE help only.  Customize the latter variable to see
-what choices of browsers your system offers.  Certain browsers like EWW
-(@pxref{Top, EWW,, eww, The Emacs Web Wowser Manual}) are run within Emacs,
-and use Emacs buffers to display the HTML help.  This can be convenient,
-especially on small displays, and images can even be displayed in-line
-on newer Emacs versions.  However, better formatting results are often
-achieved with external browsers, like Mozilla.  IDLWAVE assumes any
-browser function containing "w3" is displayed in a local buffer.  If you
-are using another Emacs-local browser for which this is not true, set
-the variable @code{idlwave-help-browser-is-local}.
-
-With IDL 6.2 or later, it is important to ensure that the variable
-@code{idlwave-system-directory} is set (@pxref{Catalogs}).  One easy way
-to ensure this is to run the IDL Shell (@kbd{C-c C-s}).  It will be
-queried for this directory, and the results will be cached to file for
-subsequent use.
-
-@xref{HTML Help Browser Tips}, for more information on selecting and
-configuring a browser for use with IDL's HTML help system.
-
-@defopt idlwave-html-system-help-location @file{help/online_help}
-Relative directory of the system-supplied HTML help directory,
-considered with respect to @code{idlwave-system-directory}.  Relevant
-for IDL 6.2 and greater.  Should not change.
-@end defopt
-
-@defopt idlwave-html-help-location @file{/usr/local/etc/}
-The directory where the @file{idl_html_help} HTML directory live.
-Obsolete and ignored for IDL 6.2 and greater
-(@code{idlwave-html-system-help-location} is used instead).
-@end defopt
-
-@defopt idlwave-help-use-assistant @code{t}
-If set, use the IDL Assistant if possible for online HTML help,
-otherwise use the browser function specified in
-@code{idlwave-help-browser-function}.
-@end defopt
-
-@defopt idlwave-help-browser-function
-The browser function to use to display IDLWAVE HTML help.  Should be
-one of the functions available for setting
-@code{browse-url-browser-function}, which see.
-@end defopt
-
-@defopt idlwave-help-browser-is-local
-Is the browser selected in @code{idlwave-help-browser-function} run in a
-local Emacs buffer or window?  Defaults to @code{t} if the function
-contains "-w3".
-@end defopt
-
-@defopt idlwave-help-link-face
-The face for links to IDLWAVE online help.
-@end defopt
-
-@node Help with Source
-@subsection Help with Source
-@cindex Help using routine source
-
-@cindex Source code, as online help
-@cindex DocLib header, as online help
-For routines which are not documented in an HTML manual (for example
-personal or library routines), the source code itself is used as help
-text.  If the requested information can be found in a (more or less)
-standard DocLib file header, IDLWAVE shows the header (scrolling down to
-a keyword, if appropriate).  Otherwise the routine definition statement
-(@code{pro}/@code{function}) is shown.  The doclib header sections which
-are searched for include @samp{NAME} and @samp{KEYWORDS}.  Localization
-support can be added by customizing the @code{idlwave-help-doclib-name}
-and @code{idlwave-help-doclib-keyword} variables.
-
-@cindex Structure tags, in online help
-@cindex Class tags, in online help
-Help is also available for class structure tags (@code{self.TAG}), and
-generic structure tags, if structure tag completion is enabled
-(@pxref{Structure Tag Completion}).  This is implemented by visiting the
-tag within the class or structure definition source itself.  Help is not
-available on built-in system class tags.
-
-The help window is normally displayed in the same frame, but can be
-popped-up in a separate frame.  The following commands can be used to
-navigate inside the help system for source files:
-
-@multitable  @columnfractions .15 .85
-@item @kbd{@key{SPACE}}
-@tab Scroll forward one page.
-@item @kbd{@key{RET}}
-@tab Scroll forward one line.
-@item @kbd{@key{DEL}}
-@tab Scroll back one page.
-@item @kbd{h}
-@tab Jump to DocLib Header of the routine whose source is displayed
-as help.
-@item @kbd{H}
-@tab Jump to the first DocLib Header in the file.
-@item @kbd{.} @r{(Dot)}
-@tab Jump back and forth between the routine definition (the
-@code{pro}/@code{function} statement) and the description of the help
-item in the DocLib header.
-@item @kbd{F}
-@tab Fontify the buffer like source code.  See the variable @code{idlwave-help-fontify-source-code}.
-@item @kbd{q}
-@tab Kill the help window.
-@end multitable
-
-
-@defopt idlwave-help-use-dedicated-frame (@code{nil})
-Non-@code{nil} means use a separate frame for Online Help if possible.
-@end defopt
-
-@defopt idlwave-help-frame-parameters
-The frame parameters for the special Online Help frame.
-@end defopt
-
-@defopt idlwave-max-popup-menu-items (@code{20})
-Maximum number of items per pane in pop-up menus.
-@end defopt
-
-@defopt idlwave-extra-help-function
-Function to call for help if the normal help fails.
-@end defopt
-
-@defopt idlwave-help-fontify-source-code (@code{nil})
-Non-@code{nil} means fontify source code displayed as help.
-@end defopt
-
-@defopt idlwave-help-source-try-header (@code{t})
-Non-@code{nil} means try to find help in routine header when
-displaying source file.
-@end defopt
-
-@defopt idlwave-help-doclib-name (@code{"name"})
-The case-insensitive heading word in doclib headers to locate the
-@emph{name} section.  Can be a regexp, e.g., @code{"\\(name\\|nom\\)"}.
-@end defopt
-
-@defopt idlwave-help-doclib-keyword (@code{"KEYWORD"})
-The case-insensitive heading word in doclib headers to locate the
-@emph{keywords} section.  Can be a regexp.
-@end defopt
-
-
-@node Completion
-@section Completion
-@cindex Completion
-@cindex Keyword completion
-@cindex Method completion
-@cindex Object method completion
-@cindex Class name completion
-@cindex Function name completion
-@cindex Procedure name completion
-
-@kindex M-TAB
-@kindex C-c C-i
-IDLWAVE offers completion for class names, routine names, keywords,
-system variables, system variable tags, class structure tags, regular
-structure tags and file names.  As in many programming modes, completion
-is bound to @kbd{M-@key{TAB}} (or simply @kbd{@key{TAB}} in the IDLWAVE
-Shell; @pxref{Using the Shell}).  Completion uses exactly the same
-internal information as routine info, so when necessary (rarely) it can
-be updated with @kbd{C-c C-i} (@code{idlwave-update-routine-info}).
-
-The completion function is context sensitive and figures out what to
-complete based on the location of the point.  Here are example lines and
-what @kbd{M-@key{TAB}} would try to complete when the cursor is on the
-position marked with a @samp{_}:
-
-@example
-plo_                    @r{Procedure}
-x = a_                  @r{Function}
-plot,xra_               @r{Keyword of @code{plot} procedure}
-plot,x,y,/x_            @r{Keyword of @code{plot} procedure}
-plot,min(_              @r{Keyword of @code{min} function}
-obj -> a_               @r{Object method (procedure)}
-a[2,3] = obj -> a_      @r{Object method (function)}
-x = obj_new('IDL_       @r{Class name}
-x = obj_new('MyCl',a_   @r{Keyword to @code{Init} method in class @code{MyCl}}
-pro A_                  @r{Class name}
-pro _                   @r{Fill in @code{Class::} of first method in this file}
-!v_                     @r{System variable}
-!version.t_             @r{Structure tag of system variable}
-self.g_                 @r{Class structure tag in methods}
-state.w_                @r{Structure tag, if tag completion enabled}
-name = 'a_              @r{File name (default inside quotes)}
-@end example
-
-@cindex Completion, ambiguity
-@cindex Completion, forcing function name
-The only place where completion is ambiguous is procedure/function
-@emph{keywords} versus @emph{functions}.  After @samp{plot,x,_}, IDLWAVE
-will always assume a keyword to @samp{plot}.  However, a function is
-also a possible completion here.  You can force completion of a function
-name at such a location by using a prefix arg: @kbd{C-u M-@key{TAB}}.
-
-Giving two prefix arguments (@kbd{C-u C-u M-@key{TAB}}) prompts for a
-regular expression to search among the commands to be completed.  As
-an example, completing a blank line in this way will allow you to
-search for a procedure matching a regexp.
-
-@cindex Scrolling the @file{*Completions*} window
-@cindex Completion, scrolling
-@cindex Completion, Online Help
-@cindex Online Help in @file{*Completions*} buffer
-If the list of completions is too long to fit in the
-@file{*Completions*} window, the window can be scrolled by pressing
-@kbd{M-@key{TAB}} repeatedly.  Online help (if installed) for each
-possible completion is available by clicking with @kbd{mouse-3} on the
-item.  Items for which system online help (from the IDL manual) is
-available will be emphasized (e.g., colored blue).  For other items, the
-corresponding source code or DocLib header will be used as the help
-text.
-
-@cindex Completion, canceling
-@cindex Canceling completion
-Completion is not a blocking operation; you are free to continue
-editing, enter commands, or simply ignore the @file{*Completions*}
-buffer during a completion operation.  If, however, the most recent
-command was a completion, @kbd{C-g} will remove the buffer and restore
-the window configuration.  You can also remove the buffer at any time
-with no negative consequences.
-
-@defopt idlwave-keyword-completion-adds-equal (@code{t})
-Non-@code{nil} means completion automatically adds @samp{=} after
-completed keywords.
-@end defopt
-
-@defopt idlwave-function-completion-adds-paren (@code{t})
-Non-@code{nil} means completion automatically adds @samp{(} after
-completed function.  A value of 2 means also add the closing
-parenthesis and position the cursor between the two.
-@end defopt
-
-@defopt idlwave-completion-restore-window-configuration (@code{t})
-Non-@code{nil} means restore window configuration after successful
-completion.
-@end defopt
-
-@defopt idlwave-highlight-help-links-in-completion (@code{t})
-Non-@code{nil} means highlight completions for which system help is
-available.
-@end defopt
-
-@menu
-* Case of Completed Words::     CaseOFcomPletedWords
-* Object Method Completion and Class Ambiguity::  obj->Method, what?
-* Object Method Completion in the Shell::
-* Class and Keyword Inheritance::  obj->Method, _EXTRA=e
-* Structure Tag Completion::    Completing state.Tag
-@end menu
-
-@node  Case of Completed Words
-@subsection Case of Completed Words
-@cindex Case of completed words
-@cindex Mixed case completion
-IDL is a case-insensitive language, so casing is a matter of style
-only.  IDLWAVE helps maintain a consistent casing style for completed
-items.  The case of the completed words is determined by what is
-already in the buffer.  As an exception, when the partial word being
-completed is all lower case, the completion will be lower case as
-well.  If at least one character is upper case, the string will be
-completed in upper case or mixed case, depending on the value of the
-variable @code{idlwave-completion-case}.  The default is to use upper
-case for procedures, functions and keywords, and mixed case for object
-class names and methods, similar to the conventions in the IDL
-manuals.  For instance, to enable mixed-case completion for routines
-in addition to classes and methods, you need an entry such as
-@code{(routine . preserve)} in that variable.  To enable total control
-over the case of completed items, independent of buffer context, set
-@code{idlwave-completion-force-default-case} to non-@code{nil}.
-
-@defopt idlwave-completion-case
-Association list setting the case (UPPER/lower/Capitalized/MixedCase...)
-of completed words.
-@end defopt
-
-@defopt idlwave-completion-force-default-case (@code{nil})
-Non-@code{nil} means completion will always honor the settings in
-@code{idlwave-completion-case}.  When @code{nil} (the default), entirely lower
-case strings will always be completed to lower case, no matter what the
-settings in @code{idlwave-completion-case}.
-@end defopt
-
-@defopt idlwave-complete-empty-string-as-lower-case (@code{nil})
-Non-@code{nil} means the empty string is considered lower case for
-completion.
-@end defopt
-
-@node  Object Method Completion and Class Ambiguity
-@subsection Object Method Completion and Class Ambiguity
-@cindex Object methods
-@cindex Class ambiguity
-@cindex @code{self} object, default class
-An object method is not uniquely determined without the object's class.
-Since the class is almost always omitted in the calling source (as
-required to obtain the true benefits of object-based programming),
-IDLWAVE considers all available methods in all classes as possible
-method name completions.  The combined list of keywords of the current
-method in @emph{all} known classes which contain that method will be
-considered for keyword completion.  In the @file{*Completions*} buffer,
-the matching classes will be shown next to each item (see option
-@code{idlwave-completion-show-classes}).  As a special case, the class
-of an object called @samp{self} is always taken to be the class of the
-current routine, when in an IDLWAVE buffer.  All inherits classes are
-considered as well.
-
-@cindex Forcing class query.
-@cindex Class query, forcing
-You can also call @code{idlwave-complete} with a prefix arg: @kbd{C-u
-M-@key{TAB}}.  IDLWAVE will then prompt you for the class in order to
-narrow down the number of possible completions.  The variable
-@code{idlwave-query-class} can be configured to make such prompting the
-default for all methods (not recommended), or selectively for very
-common methods for which the number of completing keywords would be too
-large (e.g., @code{Init,SetProperty,GetProperty}).
-
-@cindex Saving object class on @code{->}
-@cindex @code{->}
-After you have specified the class for a particular statement (e.g., when
-completing the method), IDLWAVE can remember it for the rest of the
-editing session.  Subsequent completions in the same statement
-(e.g., keywords) can then reuse this class information.  This works by
-placing a text property on the method invocation operator @samp{->},
-after which the operator will be shown in a different face (bold by
-default).  The variable @code{idlwave-store-inquired-class} can be used
-to turn it off or on.
-
-@defopt idlwave-completion-show-classes (@code{1})
-Non-@code{nil} means show up to that many classes in
-@file{*Completions*} buffer when completing object methods and
-keywords.
-@end defopt
-
-@defopt idlwave-completion-fontify-classes (@code{t})
-Non-@code{nil} means fontify the classes in completions buffer.
-@end defopt
-
-@defopt idlwave-query-class (@code{nil})
-Association list governing query for object classes during completion.
-@end defopt
-
-@defopt idlwave-store-inquired-class (@code{t})
-Non-@code{nil} means store class of a method call as text property on
-@samp{->}.
-@end defopt
-
-@defopt idlwave-class-arrow-face
-Face to highlight object operator arrows @samp{->} which carry a saved
-class text property.
-@end defopt
-
-@node Object Method Completion in the Shell
-@subsection Object Method Completion in the Shell
-@cindex Method Completion in Shell
-In the IDLWAVE Shell (@pxref{The IDLWAVE Shell}), objects on which
-methods are being invoked have a special property: they must exist as
-variables, and so their class can be determined (for instance, using the
-@code{obj_class()} function).  In the Shell, when attempting completion,
-routine info, or online help within a method routine, a query is sent to
-determine the class of the object.  If this query is successful, the
-class found will be used to select appropriate completions, routine
-info, or help.  If unsuccessful, information from all known classes will
-be used (as in the buffer).
-
-@node   Class and Keyword Inheritance
-@subsection Class and Keyword Inheritance
-@cindex Inheritance, class
-@cindex Keyword inheritance
-@cindex Inheritance, keyword
-
-Class inheritance affects which methods are called in IDL@.  An object of
-a class which inherits methods from one or more superclasses can
-override that method by defining its own method of the same name, extend
-the method by calling the method(s) of its superclass(es) in its
-version, or inherit the method directly by making no modifications.
-IDLWAVE examines class definitions during completion and routine
-information display, and records all inheritance information it finds.
-This information is displayed if appropriate with the calling sequence
-for methods (@pxref{Routine Info}), as long as variable
-@code{idlwave-support-inheritance} is non-@code{nil}.
-
-In many class methods, @emph{keyword} inheritance (@code{_EXTRA} and
-@code{_REF_EXTRA}) is used hand-in-hand with class inheritance and
-method overriding.  E.g., in a @code{SetProperty} method, this technique
-allows a single call @code{obj->SetProperty} to set properties up the
-entire class inheritance chain.  This is often referred to as
-@emph{chaining}, and is characterized by chained method calls like
-@w{@code{self->MySuperClass::SetProperty,_EXTRA=e}}.
-
-IDLWAVE can accommodate this special synergy between class and keyword
-inheritance: if @code{_EXTRA} or @code{_REF_EXTRA} is detected among a
-method's keyword parameters, all keywords of superclass versions of
-the method being considered can be included in completion.  There is
-of course no guarantee that this type of keyword chaining actually
-occurs, but for some methods it's a very convenient assumption.  The
-variable @code{idlwave-keyword-class-inheritance} can be used to
-configure which methods have keyword inheritance treated in this
-simple, class-driven way.  By default, only @code{Init} and
-@code{(Get|Set)Property} are.  The completion buffer will label
-keywords based on their originating class.
-
-@defopt idlwave-support-inheritance (@code{t})
-Non-@code{nil} means consider inheritance during completion, online help etc.
-@end defopt
-
-@defopt idlwave-keyword-class-inheritance
-A list of regular expressions to match methods for which simple
-class-driven keyword inheritance will be used for Completion.
-@end defopt
-
-@node    Structure Tag Completion
-@subsection Structure Tag Completion
-@cindex Completion, structure tag
-@cindex Structure tag completion
-
-In many programs, especially those involving widgets, large structures
-(e.g., the @samp{state} structure) are used to communicate among
-routines.  It is very convenient to be able to complete structure tags,
-in the same way as for instance variables (tags) of the @samp{self}
-object (@pxref{Object Method Completion and Class Ambiguity}).  Add-in
-code for structure tag completion is available in the form of a loadable
-completion module: @file{idlw-complete-structtag.el}.  Tag completion in
-structures is highly ambiguous (much more so than @samp{self}
-completion), so @code{idlw-complete-structtag} makes an unusual and very
-specific assumption: the exact same variable name is used to refer to
-the structure in all parts of the program.  This is entirely unenforced
-by the IDL language, but is a typical convention.  If you consistently
-refer to the same structure with the same variable name
-(e.g., @samp{state}), structure tags which are read from its definition
-in the same file can be used for completion.
-
-Structure tag completion is not enabled by default.  To enable it,
-simply add the following to your @file{.emacs}:
-
-@lisp
-(with-eval-after-load 'idlwave
-  (require 'idlw-complete-structtag))
-@end lisp
-
-Once enabled, you'll also be able to access online help on the structure
-tags, using the usual methods (@pxref{Online Help}).  In addition,
-structure variables in the shell will be queried for tag names, similar
-to the way object variables in the shell are queried for method names.
-So, e.g.:
-
-@example
-IDL> st.[Tab]
-@end example
-
-@noindent will complete with all structure fields of the structure
-@code{st}.
-
-@node Routine Source
-@section Routine Source
-@cindex Routine source file
-@cindex Module source file
-@cindex Source file, of a routine
-@kindex C-c C-v
-In addition to clicking on a @i{Source:} line in the routine info
-window, there is another way to quickly visit the source file of a
-routine.  The command @kbd{C-c C-v} (@code{idlwave-find-module}) asks
-for a module name, offering the same default as
-@code{idlwave-routine-info} would have used, taken from nearby buffer
-contents.  In the minibuffer, specify a complete routine name (including
-any class part).  IDLWAVE will display the source file in another
-window, positioned at the routine in question.  You can also limit this
-to a routine in the current buffer only, with completion, and a
-context-sensitive default, by using a single prefix (@kbd{C-u C-c C-v})
-or the convenience binding @kbd{C-c C-t}.
-
-@cindex Buffers, killing
-@cindex Killing autoloaded buffers
-Since getting the source of a routine into a buffer is so easy with
-IDLWAVE, too many buffers visiting different IDL source files are
-sometimes created.  The special command @kbd{C-c C-k}
-(@code{idlwave-kill-autoloaded-buffers}) can be used to easily remove
-these buffers.
-
-@node Resolving Routines
-@section Resolving Routines
-@cindex @code{RESOLVE_ROUTINE}
-@cindex Compiling library modules
-@cindex Routines, resolving
-
-The key sequence @kbd{C-c =} calls the command @code{idlwave-resolve}
-and sends the line @samp{RESOLVE_ROUTINE, '@var{routine_name}'} to IDL
-in order to resolve (compile) it.  The default routine to be resolved is
-taken from context, but you get a chance to edit it.  Usually this is
-not necessary, since IDL automatically discovers routines on its path.
-
-@code{idlwave-resolve} is one way to get a library module within reach
-of IDLWAVE's routine info collecting functions.  A better way is to
-keep routine information available in catalogs (@pxref{Catalogs}).
-Routine info on modules will then be available without the need to
-compile the modules first, and even without a running shell.
-
-@xref{Sources of Routine Info}, for more information on the ways IDLWAVE
-collects data about routines, and how to update this information.
-
-@node Code Templates
-@section Code Templates
-@cindex Code templates
-@cindex Templates
-
-IDLWAVE can insert IDL code templates into the buffer.  For a few
-templates, this is done with direct key bindings:
-
-@multitable @columnfractions .15 .85
-@item @kbd{C-c C-c}
-@tab @code{CASE} statement template
-@item @kbd{C-c C-f}
-@tab @code{FOR} loop template
-@item @kbd{C-c C-r}
-@tab @code{REPEAT} loop template
-@item @kbd{C-c C-w}
-@tab @code{WHILE} loop template
-@end multitable
-
-All code templates are also available as abbreviations
-(@pxref{Abbreviations}).
-
-@node Abbreviations
-@section Abbreviations
-@cindex Abbreviations
-
-Special abbreviations exist to enable rapid entry of commonly used
-commands.  Emacs abbreviations are expanded by typing text into the
-buffer and pressing @key{SPC} or @key{RET}.  The special abbreviations
-used to insert code templates all start with a @samp{\} (the backslash),
-or, optionally, any other character set in
-@code{idlwave-abbrev-start-char}.  IDLWAVE ensures that abbreviations are
-only expanded where they should be (i.e., not in a string or comment),
-and permits the point to be moved after an abbreviation expansion:
-very useful for positioning the mark inside of parentheses, etc.
-
-Special abbreviations are pre-defined for code templates and other
-useful items.  To visit the full list of abbreviations, use @kbd{M-x
-idlwave-list-abbrevs}.
-
-Template abbreviations:
-
-@multitable @columnfractions .15 .85
-@item @code{\pr}
-@tab @code{PROCEDURE} template
-@item @code{\fu}
-@tab @code{FUNCTION} template
-@item @code{\c}
-@tab @code{CASE} statement template
-@item @code{\f}
-@tab @code{FOR} loop template
-@item @code{\r}
-@tab @code{REPEAT} loop template
-@item @code{\w}
-@tab @code{WHILE} loop template
-@item @code{\i}
-@tab @code{IF} statement template
-@item @code{\elif}
-@tab @code{IF-ELSE} statement template
-@end multitable
-
-String abbreviations:
-
-@multitable @columnfractions .15 .85
-@item @code{\ap}
-@tab @code{arg_present()}
-@item @code{\b}
-@tab @code{begin}
-@item @code{\cb}
-@tab @code{byte()}
-@item @code{\cc}
-@tab @code{complex()}
-@item @code{\cd}
-@tab @code{double()}
-@item @code{\cf}
-@tab @code{float()}
-@item @code{\cl}
-@tab @code{long()}
-@item @code{\co}
-@tab @code{common}
-@item @code{\cs}
-@tab @code{string()}
-@item @code{\cx}
-@tab @code{fix()}
-@item @code{\e}
-@tab @code{else}
-@item @code{\ec}
-@tab @code{endcase}
-@item @code{\ee}
-@tab @code{endelse}
-@item @code{\ef}
-@tab @code{endfor}
-@item @code{\ei}
-@tab @code{endif else if}
-@item @code{\el}
-@tab @code{endif else}
-@item @code{\en}
-@tab @code{endif}
-@item @code{\er}
-@tab @code{endrep}
-@item @code{\es}
-@tab @code{endswitch}
-@item @code{\ew}
-@tab @code{endwhile}
-@item @code{\g}
-@tab @code{goto,}
-@item @code{\h}
-@tab @code{help,}
-@item @code{\ik}
-@tab @code{if keyword_set() then}
-@item @code{\iap}
-@tab @code{if arg_present() then}
-@item @code{\ine}
-@tab @code{if n_elements() eq 0 then}
-@item @code{\inn}
-@tab @code{if n_elements() ne 0 then}
-@item @code{\k}
-@tab @code{keyword_set()}
-@item @code{\n}
-@tab @code{n_elements()}
-@item @code{\np}
-@tab @code{n_params()}
-@item @code{\oi}
-@tab @code{on_ioerror,}
-@item @code{\or}
-@tab @code{openr,}
-@item @code{\ou}
-@tab @code{openu,}
-@item @code{\ow}
-@tab @code{openw,}
-@item @code{\p}
-@tab @code{print,}
-@item @code{\pt}
-@tab @code{plot,}
-@item @code{\pv}
-@tab @code{ptr_valid()}
-@item @code{\re}
-@tab @code{read,}
-@item @code{\rf}
-@tab @code{readf,}
-@item @code{\rt}
-@tab @code{return}
-@item @code{\ru}
-@tab @code{readu,}
-@item @code{\s}
-@tab @code{size()}
-@item @code{\sc}
-@tab @code{strcompress()}
-@item @code{\sl}
-@tab @code{strlowcase()}
-@item @code{\sm}
-@tab @code{strmid()}
-@item @code{\sn}
-@tab @code{strlen()}
-@item @code{\sp}
-@tab @code{strpos()}
-@item @code{\sr}
-@tab @code{strtrim()}
-@item @code{\st}
-@tab @code{strput()}
-@item @code{\su}
-@tab @code{strupcase()}
-@item @code{\t}
-@tab @code{then}
-@item @code{\u}
-@tab @code{until}
-@item @code{\wc}
-@tab @code{widget_control,}
-@item @code{\wi}
-@tab @code{widget_info()}
-@item @code{\wu}
-@tab @code{writeu,}
-@end multitable
-
-@noindent You can easily add your own abbreviations or override existing
-abbrevs with @code{define-abbrev} in your mode hook, using the
-convenience function @code{idlwave-define-abbrev}:
-
-@lisp
-(add-hook 'idlwave-mode-hook
-          (lambda ()
-            (idlwave-define-abbrev "wb" "widget_base()"
-                     (idlwave-keyword-abbrev 1))
-            (idlwave-define-abbrev "ine" "IF N_Elements() EQ 0 THEN"
-                     (idlwave-keyword-abbrev 11))))
-@end lisp
-
-Notice how the abbreviation (here @emph{wb}) and its expansion
-(@emph{widget_base()}) are given as arguments, and the single argument to
-@code{idlwave-keyword-abbrev} (here @emph{1}) specifies how far back to
-move the point upon expansion (in this example, to put it between the
-parentheses).
-
-The abbreviations are expanded in upper or lower case, depending upon
-the variables @code{idlwave-abbrev-change-case} and, for reserved word
-templates, @code{idlwave-reserved-word-upcase} (@pxref{Case Changes}).
-
-@defopt idlwave-abbrev-start-char (@code{"\"})
-A single character string used to start abbreviations in abbrev mode.
-Beware of common characters which might naturally occur in sequence with
-abbreviation strings.
-@end defopt
-
-@defopt idlwave-abbrev-move (@code{t})
-Non-@code{nil} means the abbrev hook can move point, e.g., to end up
-between the parentheses of a function call.
-@end defopt
-
-@node Actions
-@section Actions
-@cindex Actions
-@cindex Coding standards, enforcing
-
-@emph{Actions} are special formatting commands which are executed
-automatically while you write code in order to check the structure of
-the program or to enforce coding standards.  Most actions which have
-been implemented in IDLWAVE are turned off by default, assuming that the
-average user wants her code the way she writes it.  But if you are a
-lazy typist and want your code to adhere to certain standards, actions
-can be helpful.
-
-Actions can be applied in three ways:
-
-@itemize @bullet
-@item
-Some actions are applied directly while typing.  For example, pressing
-@samp{=} can run a check to make sure that this operator is surrounded
-by spaces and insert these spaces if necessary.  Pressing @key{SPC}
-after a reserved word can call a command to change the word to upper
-case.
-@item
-When a line is re-indented with @key{TAB}, actions can be applied to the
-entire line.  To enable this, the variable @code{idlwave-do-actions}
-must be non-@code{nil}.
-@item
-@cindex Foreign code, adapting
-@cindex Actions, applied to foreign code
-Actions can also be applied to a larger piece of code, e.g., to convert
-foreign code to your own style.  To do this, mark the relevant part of
-the code and execute @kbd{M-x expand-region-abbrevs}.  Useful marking
-commands are @kbd{C-x h} (the entire file) or @kbd{C-M-h} (the current
-subprogram). @xref{Code Indentation}, for information how to adjust the
-indentation of the code.
-@end itemize
-
-@defopt idlwave-do-actions (@code{nil})
-Non-@code{nil} means performs actions when indenting.  Individual action
-settings are described below and set separately.
-@end defopt
-
-@menu
-* Block Boundary Check::        Is the END statement correct?
-* Padding Operators::           Enforcing space around @samp{=} etc
-* Case Changes::                Enforcing upper case keywords
-@end menu
-
-@node Block Boundary Check
-@subsection Block Boundary Check
-@cindex Block boundary check
-@cindex @code{END} type checking
-@cindex @code{END}, automatic insertion
-@cindex @code{END}, expanding
-@cindex Block, closing
-@cindex Closing a block
-
-Whenever you type an @code{END} statement, IDLWAVE finds the
-corresponding start of the block and the cursor blinks back to that
-location for a second.  If you have typed a specific @code{END}, like
-@code{ENDIF} or @code{ENDCASE}, you get a warning if that terminator
-does not match the type of block it terminates.
-
-Set the variable @code{idlwave-expand-generic-end} in order to have all
-generic @code{END} statements automatically expanded to the appropriate
-type.  You can also type @kbd{C-c ]} to close the current block by
-inserting the appropriate @code{END} statement.
-
-@defopt idlwave-show-block (@code{t})
-Non-@code{nil} means point blinks to block beginning for
-@code{idlwave-show-begin}.
-@end defopt
-
-@defopt idlwave-expand-generic-end (@code{t})
-Non-@code{nil} means expand generic END to ENDIF/ENDELSE/ENDWHILE etc.
-@end defopt
-
-@defopt idlwave-reindent-end (@code{t})
-Non-@code{nil} means re-indent line after END was typed.
-@end defopt
-
-@node Padding Operators
-@subsection Padding Operators
-@cindex Padding operators with spaces
-@cindex Operators, padding with spaces
-@cindex Space, around operators
-
-Some operators can be automatically surrounded by spaces.  This can
-happen when the operator is typed, or later when the line is indented.
-IDLWAVE can pad the operators @samp{<}, @samp{>}, @samp{,}, @samp{=},
-and @samp{->}, as well as the modified assignment operators
-(@samp{AND=}, @samp{OR=}, etc.).  This feature is turned off by default.
-If you want to turn it on, customize the variables
-@code{idlwave-surround-by-blank} and @code{idlwave-do-actions} and turn
-both on.  You can also define similar actions for other operators by
-using the function @code{idlwave-action-and-binding} in the mode hook.
-For example, to enforce space padding of the @samp{+} and @samp{*}
-operators (outside of strings and comments, of course), try this in
-@file{.emacs}
-
-@lisp
-(add-hook 'idlwave-mode-hook
-  (lambda ()
-     (setq idlwave-surround-by-blank t)  ; Turn this type of actions on
-     (idlwave-action-and-binding "*" '(idlwave-surround 1 1))
-     (idlwave-action-and-binding "+" '(idlwave-surround 1 1))))
-@end lisp
-
-Note that the modified assignment operators which begin with a word
-(@samp{AND=}, @samp{OR=}, @samp{NOT=}, etc.)@: require a leading space to
-be recognized (e.g., @code{vAND=4} would be interpreted as a variable
-@code{vAND}).  Also note that since, e.g., @code{>} and @code{>=} are
-both valid operators, it is impossible to surround both by blanks while
-they are being typed.  Similarly with @code{&} and @code{&&}.  For
-these, a compromise is made: the padding is placed on the left, and if
-the longer operator is keyed in, on the right as well (otherwise you
-must insert spaces to pad right yourself, or press simply press Tab to
-repad everything if @code{idlwave-do-actions} is on).
-
-@defopt idlwave-surround-by-blank (@code{nil})
-Non-@code{nil} means enable @code{idlwave-surround}.  If non-@code{nil},
-@samp{=}, @samp{<}, @samp{>}, @samp{&}, @samp{,}, @samp{->}, and the
-modified assignment operators (@samp{AND=}, @samp{OR=}, etc.)@: are
-surrounded with spaces by @code{idlwave-surround}.
-@end defopt
-
-@defopt idlwave-pad-keyword (@code{t})
-Non-@code{nil} means space-pad the @samp{=} in keyword assignments.
-@end defopt
-
-@node Case Changes
-@subsection Case Changes
-@cindex Case changes
-@cindex Upcase, enforcing for reserved words
-@cindex Downcase, enforcing for reserved words
-
-Actions can be used to change the case of reserved words or expanded
-abbreviations by customizing the variables
-@code{idlwave-abbrev-change-case} and
-@code{idlwave-reserved-word-upcase}.  If you want to change the case of
-additional words automatically, put something like the following into
-your @file{.emacs} file:
-
-@lisp
-(add-hook 'idlwave-mode-hook
-  (lambda ()
-     ;;  Capitalize system vars
-     (idlwave-action-and-binding idlwave-sysvar '(capitalize-word 1) t)
-     ;;  Capitalize procedure name
-     (idlwave-action-and-binding "\\<\\(pro\\|function\\)\\>[ \t]*\\<"
-                                 '(capitalize-word 1) t)
-     ;;  Capitalize common block name
-     (idlwave-action-and-binding "\\<common\\>[ \t]+\\<"
-                                 '(capitalize-word 1) t)))
-@end lisp
-
-For more information, see the documentation string for the function
-@code{idlwave-action-and-binding}.  For information on controlling the
-case of routines, keywords, classes, and methods as they are completed, see
-@ref{Completion}.
-
-@defopt idlwave-abbrev-change-case (@code{nil})
-Non-@code{nil} means all abbrevs will be forced to either upper or lower
-case.  Valid values are @code{nil}, @code{t}, and @code{down}.
-@end defopt
-
-@defopt idlwave-reserved-word-upcase (@code{nil})
-Non-@code{nil} means reserved words will be made upper case via abbrev
-expansion.
-@end defopt
-
-
-@node Doc Header
-@section Documentation Header
-@cindex Documentation header
-@cindex DocLib header
-@cindex Modification timestamp
-@cindex Header, for file documentation
-@cindex Timestamp, in doc header.
-@cindex Changelog, in doc header.
-
-@kindex C-c C-h
-@kindex C-c C-m
-The command @kbd{C-c C-h} inserts a standard routine header into the
-buffer, with the usual fields for documentation (a different header can
-be specified with @code{idlwave-file-header}).  One of the keywords is
-@samp{MODIFICATION HISTORY} under which the changes to a routine can be
-recorded.  The command @kbd{C-c C-m} jumps to the @samp{MODIFICATION
-HISTORY} of the current routine or file and inserts the user name with a
-timestamp.
-
-@defopt idlwave-file-header
-The doc-header template or a path to a file containing it.
-@end defopt
-
-@defopt idlwave-header-to-beginning-of-file (@code{nil})
-Non-@code{nil} means the documentation header will always be at start
-of file.
-@end defopt
-
-@defopt idlwave-timestamp-hook
-The hook function used to update the timestamp of a function.
-@end defopt
-
-@defopt idlwave-doc-modifications-keyword
-The modifications keyword to use with the log documentation commands.
-@end defopt
-
-@defopt idlwave-doclib-start
-Regexp matching the start of a document library header.
-@end defopt
-
-@defopt idlwave-doclib-end
-Regexp matching the start of a document library header.
-@end defopt
-
-@node Motion Commands
-@section Motion Commands
-@cindex Motion commands
-@cindex Program structure, moving through
-@cindex Code structure, moving through
-@cindex @file{Imenu}
-@cindex Function definitions, jumping to
-@cindex Procedure definitions, jumping to
-
-IDLWAVE supports @file{Imenu}, a package
-which make it easy to jump to the definitions of functions and
-procedures in the current file with a pop-up selection.  To bind
-@file{Imenu} to a mouse-press, use in your @file{.emacs}:
-
-@lisp
-(define-key global-map [S-down-mouse-3] 'imenu)
-@end lisp
-
-@cindex @file{Speedbar}, Emacs package
-
-In addition, @file{Speedbar} support allows convenient navigation of a
-source tree of IDL routine files, quickly stepping to routine
-definitions.  See @code{Tools->Display Speedbar}.
-
-Several commands allow you to move quickly through the structure of an
-IDL program:
-
-@multitable @columnfractions .15 .85
-@item @kbd{C-M-a}
-@tab Beginning of subprogram
-@item @kbd{C-M-e}
-@tab End of subprogram
-@item @kbd{C-c @{}
-@tab Beginning of block (stay inside the block)
-@item @kbd{C-c @}}
-@tab End of block (stay inside the block)
-@item @kbd{C-M-n}
-@tab Forward block (on same level)
-@item @kbd{C-M-p}
-@tab Backward block (on same level)
-@item @kbd{C-M-d}
-@tab Down block (enters a block)
-@item @kbd{C-M-u}
-@tab Backward up block (leaves a block)
-@item @kbd{C-c C-n}
-@tab Next Statement
-@end multitable
-
-
-@node Misc Options
-@section Miscellaneous Options
-@cindex Hooks
-
-@defopt idlwave-help-application
-The external application providing reference help for programming.
-@end defopt
-
-@defopt idlwave-startup-message (@code{t})
-Non-@code{nil} means display a startup message when @code{idlwave-mode}'
-is first called.
-@end defopt
-
-@defopt idlwave-mode-hook
-Normal hook.  Executed when a buffer is put into @code{idlwave-mode}.
-@end defopt
-
-@node The IDLWAVE Shell
-@chapter The IDLWAVE Shell
-@cindex IDLWAVE shell
-@cindex Major mode, @code{idlwave-shell-mode}
-@cindex IDL, as Emacs subprocess
-@cindex Subprocess of Emacs, IDL
-@cindex Comint, Emacs package
-@cindex Windows
-@cindex macOS
-
-The IDLWAVE shell is an Emacs major mode which permits running the IDL
-program as an inferior process of Emacs, and works closely with the
-IDLWAVE major mode in buffers.  It can be used to work with IDL
-interactively, to compile and run IDL programs in Emacs buffers and to
-debug these programs.  The IDLWAVE shell is built on @file{comint}, an
-Emacs packages which handles the communication with the IDL program.
-Unfortunately, IDL for Windows does not have command-prompt versions and
-thus do not allow the interaction with Emacs, so the IDLWAVE shell
-currently works under only Unix and macOS.
-
-@menu
-* Starting the Shell::          How to launch IDL as a subprocess
-* Using the Shell::             Interactively working with the Shell
-* Commands Sent to the Shell::
-* Debugging IDL Programs::
-* Examining Variables::
-* Custom Expression Examination::
-@end menu
-
-@node Starting the Shell
-@section Starting the Shell
-@cindex Starting the shell
-@cindex Shell, starting
-@cindex Dedicated frame, for shell buffer
-@cindex Frame, for shell buffer
-@cindex Subprocess of Emacs, IDL
-
-@kindex C-c C-s
-The IDLWAVE shell can be started with the command @kbd{M-x
-idlwave-shell}.  In @code{idlwave-mode} the function is bound to
-@kbd{C-c C-s}.  It creates a buffer @file{*idl*} which is used to
-interact with the shell.  If the shell is already running, @kbd{C-c
-C-s} will simply switch to the shell buffer.  The command @kbd{C-c
-C-l} (@code{idlwave-shell-recenter-shell-window}) displays the shell
-window without selecting it.  The shell can also be started
-automatically when another command tries to send a command to it.  To
-enable auto start, set the variable
-@code{idlwave-shell-automatic-start} to @code{t}.
-
-In order to create a separate frame for the IDLWAVE shell buffer, call
-@code{idlwave-shell} with a prefix argument: @kbd{C-u C-c C-s} or
-@kbd{C-u C-c C-l}.  If you always want a dedicated frame for the shell
-window, configure the variable
-@code{idlwave-shell-use-dedicated-frame}.
-
-To launch a quick IDLWAVE shell directly from a shell prompt without
-an IDLWAVE buffer (e.g., as a replacement for running inside an
-xterm), define a system alias with the following content:
-
-@example
-emacs -geometry 80x32 -eval "(idlwave-shell 'quick)"
-@end example
-
-Replace the @samp{-geometry 80x32} option with @samp{-nw} if you prefer
-the Emacs process to run directly inside the terminal window.
-
-@cindex ENVI
-@cindex IDL> Prompt
-
-To use IDLWAVE with ENVI or other custom packages which change the
-@samp{IDL> } prompt, you must change the
-@code{idlwave-shell-prompt-pattern}, which defaults to @samp{"^ ?IDL>
-"}.  Normally, you can just replace the @samp{IDL} in this expression
-with the prompt you see.  A suitable pattern which matches the prompt
-for both ENVI and IDL simultaneously is @samp{"^ ?\\(ENVI\\|IDL\\)> "}.
-
-@defopt idlwave-shell-explicit-file-name (@file{idl})
-This is the command to run IDL.
-@end defopt
-
-@defopt idlwave-shell-command-line-options
-A list of command line options for calling the IDL program.
-@end defopt
-
-@defopt idlwave-shell-prompt-pattern
-Regexp to match IDL prompt at beginning of a line.
-@end defopt
-
-@defopt idlwave-shell-process-name
-Name to be associated with the IDL process.
-@end defopt
-
-@defopt idlwave-shell-automatic-start  (@code{nil})
-Non-@code{nil} means attempt to invoke idlwave-shell if not already
-running.
-@end defopt
-
-@defopt idlwave-shell-initial-commands
-Initial commands, separated by newlines, to send to IDL.
-@end defopt
-
-@defopt idlwave-shell-save-command-history (@code{t})
-Non-@code{nil} means preserve command history between sessions.
-@end defopt
-
-@defopt idlwave-shell-command-history-file (@file{~/.emacs.d/idlwave/.idlwhist})
-The file in which the command history of the idlwave shell is saved.
-Unless it's an absolute path, it goes in
-@code{idlwave-config-directory}.
-@end defopt
-
-@defopt idlwave-shell-use-dedicated-frame (@code{nil})
-Non-@code{nil} means IDLWAVE should use a special frame to display the
-shell buffer.
-@end defopt
-
-@defopt idlwave-shell-use-dedicated-window (@code{nil})
-Non-@code{nil} means use a dedicated window for the shell, taking care
-not it replace it with other buffers.
-@end defopt
-
-@defopt idlwave-shell-frame-parameters
-The frame parameters for a dedicated idlwave-shell frame.
-@end defopt
-
-@defopt idlwave-shell-raise-frame (@code{t})
-Non-@code{nil} means @code{idlwave-shell} raises the frame showing the shell
-window.
-@end defopt
-
-@defopt idlwave-shell-temp-pro-prefix
-The prefix for temporary IDL files used when compiling regions.
-@end defopt
-
-@cindex Hooks
-@defopt idlwave-shell-mode-hook
-Hook for customizing @code{idlwave-shell-mode}.
-@end defopt
-
-@node Using the Shell
-@section Using the Shell
-@cindex Comint
-@cindex Shell, basic commands
-
-The IDLWAVE shell works in the same fashion as other shell modes in
-Emacs.  It provides command history, command line editing and job
-control.  The @key{UP} and @key{DOWN} arrows cycle through the input
-history just like in an X terminal@footnote{This is different from
-normal Emacs/Comint behavior, but more like an xterm.  If you prefer the
-default comint functionality, check the variable
-@code{idlwave-shell-arrows-do-history}.}.  The history is preserved
-between emacs and IDL sessions.  Here is a list of commonly used
-commands:
-
-@multitable @columnfractions .12 .88
-@item @key{UP}, @kbd{M-p}
-@tab Cycle backwards in input history
-@item @key{DOWN}, @kbd{M-n}
-@tab Cycle forwards in input history
-@item @kbd{M-r}
-@tab Previous input matching a regexp
-@item @kbd{M-s}
-@tab Next input matching a regexp
-@item @kbd{return}
-@tab Send input or copy line to current prompt
-@item @kbd{C-c C-a}
-@tab Beginning of line; skip prompt
-@item @kbd{C-c C-u}
-@tab Kill input to beginning of line
-@item @kbd{C-c C-w}
-@tab Kill word before cursor
-@item @kbd{C-c C-c}
-@tab Send ^C
-@item @kbd{C-c C-z}
-@tab Send ^Z
-@item @kbd{C-c C-\}
-@tab Send ^\
-@item @kbd{C-c C-o}
-@tab Delete last batch of process output
-@item @kbd{C-c C-r}
-@tab Show last batch of process output
-@item @kbd{C-c C-l}
-@tab List input history
-@end multitable
-
-In addition to these standard @file{comint} commands,
-@code{idlwave-shell-mode} provides many of the same commands which
-simplify writing IDL code available in IDLWAVE buffers.  This includes
-abbreviations, online help, and completion.  See @ref{Routine Info} and
-@ref{Online Help} and @ref{Completion} for more information on these
-commands.
-
-@cindex Completion, in the shell
-@cindex Routine info, in the shell
-@cindex Online Help, in the shell
-@multitable @columnfractions .12 .88
-@item @kbd{@key{TAB}}
-@tab  Completion of file names (between quotes and after executive
-commands @samp{.run} and @samp{.compile}), routine names, class names,
-keywords, system variables, system variable tags etc.
-(@code{idlwave-shell-complete}).
-@item @kbd{M-@key{TAB}}
-@tab Same as @key{TAB}
-@item @kbd{C-c ?}
-@tab Routine Info display (@code{idlwave-routine-info})
-@item @kbd{M-?}
-@tab IDL online help on routine (@code{idlwave-routine-info-from-idlhelp})
-@item @kbd{C-c C-i}
-@tab Update routine info from buffers and shell
-(@code{idlwave-update-routine-info})
-@item @kbd{C-c C-v}
-@tab Find the source file of a routine (@code{idlwave-find-module})
-@item @kbd{C-c C-t}
-@tab Find the source file of a routine in the currently visited file
-(@code{idlwave-find-module-this-file}).
-@item @kbd{C-c =}
-@tab Compile a library routine (@code{idlwave-resolve})
-@end multitable
-
-@defopt idlwave-shell-arrows-do-history (@code{t})
-Non-@code{nil} means @key{UP} and @key{DOWN} arrows move through command
-history like xterm.
-@end defopt
-
-@defopt idlwave-shell-comint-settings
-Alist of special settings for the comint variables in the IDLWAVE Shell.
-@end defopt
-
-@defopt idlwave-shell-file-name-chars
-The characters allowed in file names, as a string.  Used for file name
-completion.
-@end defopt
-
-@defopt idlwave-shell-graphics-window-size
-Size of IDL graphics windows popped up by special IDLWAVE command.
-@end defopt
-
-@cindex Input mode
-@cindex Character input mode (Shell)
-@cindex Line input mode (Shell)
-@cindex Magic spells, for input mode
-@cindex Spells, magic
-IDLWAVE works in line input mode: You compose a full command line, using
-all the power Emacs gives you to do this.  When you press @key{RET}, the
-whole line is sent to IDL@.  Sometimes it is necessary to send single
-characters (without a newline), for example when an IDL program is
-waiting for single character input with the @code{GET_KBRD} function.
-You can send a single character to IDL with the command @kbd{C-c C-x}
-(@code{idlwave-shell-send-char}).  When you press @kbd{C-c C-y}
-(@code{idlwave-shell-char-mode-loop}), IDLWAVE runs a blocking loop
-which accepts characters and immediately sends them to IDL@.  The loop
-can be exited with @kbd{C-g}.  It terminates also automatically when the
-current IDL command is finished.  Check the documentation of the two
-variables described below for a way to make IDL programs trigger
-automatic switches of the input mode.
-
-@defopt idlwave-shell-use-input-mode-magic (@code{nil})
-Non-@code{nil} means IDLWAVE should check for input mode spells in
-output.
-@end defopt
-
-@defopt idlwave-shell-input-mode-spells
-The three regular expressions which match the magic spells for input
-modes.
-@end defopt
-
-@node Commands Sent to the Shell
-@section Commands Sent to the Shell
-@cindex Commands in shell, showing
-@cindex Showing commands in shell
-
-The IDLWAVE buffers and shell interact very closely.  In addition to the
-normal commands you enter at the @code{IDL>} prompt, many other special
-commands are sent to the shell, sometimes as a direct result of invoking
-a key command, menu item, or toolbar button, but also automatically, as
-part of the normal flow of information updates between the buffer and
-shell.
-
-The commands sent include @code{breakpoint}, @code{.step} and other
-debug commands (@pxref{Debugging IDL Programs}), @code{.run} and other
-compilation statements (@pxref{Compiling Programs}), examination
-commands like @code{print} and @code{help} (@pxref{Examining
-Variables}), and other special purpose commands designed to keep
-information on the running shell current.
-
-By default, much of this background shell input and output is hidden
-from the user, but this is configurable.  The custom variable
-@code{idlwave-abbrev-show-commands} allows you to configure which
-commands sent to the shell are shown there.  For a related customization
-for separating the output of @emph{examine} commands, see @ref{Examining
-Variables}.
-
-@defopt idlwave-shell-show-commands (@code{'(run misc breakpoint)})
-A list of command types to echo in the shell when sent.  Possible values
-are @code{run} for @code{.run}, @code{.compile} and other run commands,
-@code{misc} for lesser used commands like @code{window},
-@code{retall},@code{close}, etc., @code{breakpoint} for breakpoint
-setting and clearing commands, and @code{debug} for other debug,
-stepping, and continue commands.  In addition, if the variable is set to
-the single symbol @code{'everything}, all the copious shell input is
-displayed (which is probably only useful for debugging purposes).
-N.B.  For hidden commands which produce output by side-effect, that
-output remains hidden (e.g., stepping through a @code{print} command).
-As a special case, any error message in the output will be displayed
-(e.g., stepping to an error).
-@end defopt
-
-@node Debugging IDL Programs
-@section Debugging IDL Programs
-@cindex Debugging
-@cindex Key bindings for debugging
-@cindex Toolbar
-
-Programs can be compiled, run, and debugged directly from the source
-buffer in Emacs, walking through arbitrarily deeply nested code,
-printing expressions and skipping up and down the calling stack along
-the way.  IDLWAVE makes compiling and debugging IDL programs far less
-cumbersome by providing a full-featured, key/menu/toolbar-driven
-interface to commands like @code{breakpoint}, @code{.step},
-@code{.run}, etc.  It can even perform complex debug operations not
-natively supported by IDL (like continuing to the line at the cursor).
-
-The IDLWAVE shell installs key bindings both in the shell buffer and
-in all IDL code buffers of the current Emacs session, so debug
-commands work in both places (in the shell, commands operate on the
-last file compiled).  On Emacs versions which support it, a debugging
-toolbar is also installed.  The toolbar display can be toggled with
-@kbd{C-c C-d C-t} (@code{idlwave-shell-toggle-toolbar}).
-
-
-@defopt idlwave-shell-use-toolbar (@code{t})
-Non-@code{nil} means use the debugging toolbar in all IDL related
-buffers.
-@end defopt
-
-@menu
-* A Tale of Two Modes::
-* Debug Key Bindings::
-* Breakpoints and Stepping::
-* Compiling Programs::
-* Walking the Calling Stack::
-* Electric Debug Mode::
-@end menu
-
-
-@node A Tale of Two Modes
-@subsection A Tale of Two Modes
-@cindex Electric Debug Mode
-@cindex Debugging Interface
-
-The many debugging, compiling, and examination commands provided in
-IDLWAVE are available simultaneously through two different interfaces:
-the original, multi-key command interface, and the new Electric Debug
-Mode.  The functionality they offer is similar, but the way you interact
-with them is quite different.  The main difference is that, in Electric
-Debug Mode, the source buffers are made read-only, and single
-key-strokes are used to step through, examine expressions, set and
-remove breakpoints, etc.  The same variables, prefix arguments, and
-settings apply to both versions, and both can be used interchangeably.
-By default, when breakpoints are hit, Electric Debug Mode is enabled.
-The traditional interface is described first.  @xref{Electric Debug
-Mode}, for more on that mode.  Note that electric debug mode can be
-prevented from activating automatically by customizing the variable
-@code{idlwave-shell-automatic-electric-debug}.
-
-@node Debug Key Bindings
-@subsection Debug Key Bindings
-@kindex C-c C-d
-@cindex Key bindings
-
-The standard debugging key bindings are always available by default on
-the prefix key @kbd{C-c C-d}, so, for example, setting a breakpoint is
-done with @kbd{C-c C-d C-b}, and compiling a source file with @kbd{C-c
-C-d C-c}.  You can also easily configure IDLWAVE to use one or more
-modifier keys not in use by other commands, in lieu of the prefix
-@kbd{C-c C-d} (though these bindings will typically also be available;
-see @code{idlwave-shell-activate-prefix-keybindings}).  For
-example, if you include in @file{.emacs}:
-
-@lisp
-(setq idlwave-shell-debug-modifiers '(control shift))
-@end lisp
-
-@noindent a breakpoint can then be set by pressing @kbd{b} while holding down
-@kbd{shift} and @kbd{control} keys, i.e., @kbd{C-S-b}.  Compiling a
-source file will be on @kbd{C-S-c}, deleting a breakpoint @kbd{C-S-d},
-etc.  In the remainder of this chapter we will assume that the
-@kbd{C-c C-d} bindings are active, but each of these bindings will
-have an equivalent shortcut if modifiers are given in the
-@code{idlwave-shell-debug-modifiers} variable (@pxref{Lesson
-II---Customization}).  A much simpler and faster form of debugging for
-running code is also available by default; see @ref{Electric Debug
-Mode}.
-
-@defopt idlwave-shell-prefix-key (@kbd{C-c C-d})
-The prefix key for the debugging map
-@code{idlwave-shell-mode-prefix-map}.
-@end defopt
-
-@defopt idlwave-shell-activate-prefix-keybindings (@code{t})
-Non-@code{nil} means debug commands will be bound to the prefix
-key, like @kbd{C-c C-d C-b}.
-@end defopt
-
-@defopt idlwave-shell-debug-modifiers (@code{nil})
-List of modifier keys to use for additional, alternative binding of
-debugging commands in the shell and source buffers.  Can be one or
-more of @code{control}, @code{meta}, @code{super}, @code{hyper},
-@code{alt}, and @code{shift}.
-@end defopt
-
-@node Breakpoints and Stepping
-@subsection Breakpoints and Stepping
-@cindex Breakpoints
-@cindex Stepping
-@cindex Execution, controlled
-
-@kindex C-c C-d C-b
-@kindex C-c C-d C-b
-IDLWAVE helps you set breakpoints and step through code.  Setting a
-breakpoint in the current line of the source buffer is accomplished
-with @kbd{C-c C-d C-b} (@code{idlwave-shell-break-here}).  With a
-prefix arg of 1 (i.e., @kbd{C-1 C-c C-d C-b}), the breakpoint gets a
-@code{/ONCE} keyword, meaning that it will be deleted after first use.
-With a numeric prefix greater than one (e.g., @kbd{C-4 C-c C-d C-b}),
-the breakpoint will only be active the @code{nth} time it is hit.
-With a single non-numeric prefix (i.e., @kbd{C-u C-c C-d C-b}), prompt
-for a condition: an IDL expression to be evaluated and trigger the
-breakpoint only if true.  To clear the breakpoint in the current line,
-use @kbd{C-c C-d C-d} (@code{idlwave-clear-current-bp}).  When
-executed from the shell window, the breakpoint where IDL is currently
-stopped will be deleted.  To clear all breakpoints, use @kbd{C-c C-d
-C-a} (@code{idlwave-clear-all-bp}).  Breakpoints can also be disabled
-and re-enabled: @kbd{C-c C-d C-\}
-(@code{idlwave-shell-toggle-enable-current-bp}).
-
-Breakpoint lines are highlighted or indicated with an icon in the source
-code (different icons for conditional, after, and other break types).
-Disabled breakpoints are @emph{grayed out} by default.  Note that IDL
-places breakpoints as close as possible on or after the line you
-specify.  IDLWAVE queries the shell for the actual breakpoint location
-which was set, so the exact line you specify may not be marked.  You can
-re-sync the breakpoint list and update the display at any time (e.g., if
-you add or remove some on the command line) using @kbd{C-c C-d C-l}.
-
-In recent IDLWAVE versions, the breakpoint line is highlighted when the
-mouse is moved over it, and a tooltip pops up describing the break
-details.  @kbd{mouse-3} on the breakpoint line pops up a menu of
-breakpoint actions, including clearing, disabling, and adding or
-changing break conditions or ``after'' break count.
-
-Once the program has stopped somewhere, you can step through it.  The
-most important stepping commands are @kbd{C-c C-d C-s} to execute one
-line of IDL code ("step into"); @kbd{C-c C-d C-n} to step a single line,
-treating procedure and function calls as a single step ("step over");
-@kbd{C-c C-d C-h} to continue execution to the line at the cursor and
-@kbd{C-c C-d C-r} to continue execution.  @xref{Commands Sent to the
-Shell}, for information on displaying or hiding the breakpoint and
-stepping commands the shell receives.  Here is a summary of the
-breakpoint and stepping commands:
-
-@multitable @columnfractions .23 .77
-@item @kbd{C-c C-d C-b}
-@tab Set breakpoint (@code{idlwave-shell-break-here})
-@item @kbd{C-c C-d C-i}
-@tab Set breakpoint in module named here (@code{idlwave-shell-break-in})
-@item @kbd{C-c C-d C-d}
-@tab Clear current breakpoint (@code{idlwave-shell-clear-current-bp})
-@item @kbd{C-c C-d C-a}
-@tab Clear all breakpoints (@code{idlwave-shell-clear-all-bp})
-@item @kbd{C-c C-d [}
-@tab Go to the previous breakpoint (@code{idlwave-shell-goto-previous-bp})
-@item @kbd{C-c C-d ]}
-@tab Go to the next breakpoint (@code{idlwave-shell-goto-next-bp})
-@item @kbd{C-c C-d C-\}
-@tab Disable/Enable current breakpoint (@code{idlwave-shell-toggle-enable-current-bp})
-@item @kbd{C-c C-d C-j}
-@tab Set a breakpoint at the beginning of the enclosing routine.
-@item @kbd{C-c C-d C-s}
-@tab Step, into function calls (@code{idlwave-shell-step})
-@item @kbd{C-c C-d C-n}
-@tab Step, over function calls (@code{idlwave-shell-stepover})
-@item @kbd{C-c C-d C-k}
-@tab Skip one statement (@code{idlwave-shell-skip})
-@item @kbd{C-c C-d C-u}
-@tab Continue to end of block (@code{idlwave-shell-up})
-@item @kbd{C-c C-d C-m}
-@tab Continue to end of function (@code{idlwave-shell-return})
-@item @kbd{C-c C-d C-o}
-@tab Continue past end of function (@code{idlwave-shell-out})
-@item @kbd{C-c C-d C-h}
-@tab Continue to line at cursor position (@code{idlwave-shell-to-here})
-@item @kbd{C-c C-d C-r}
-@tab Continue execution to next breakpoint, if any (@code{idlwave-shell-cont})
-@item @kbd{C-c C-d C-up}
-@tab Show higher level in calling stack (@code{idlwave-shell-stack-up})
-@item @kbd{C-c C-d C-down}
-@tab Show lower level in calling stack (@code{idlwave-shell-stack-down})
-@end multitable
-
-All of these commands have equivalents in Electric Debug Mode, which
-provides faster single-key access (@pxref{Electric Debug Mode}).
-
-The line where IDL is currently stopped, at breakpoints, halts, and
-errors, etc., is marked with a color overlay or arrow, depending on the
-setting in @code{idlwave-shell-mark-stop-line}.  If an overlay face is
-used to mark the stop line (as it is by default), when stepping through
-code, the face color is temporarily changed to gray, until IDL completes
-the next command and moves to the new line.
-
-@defopt idlwave-shell-mark-breakpoints (@code{t})
-Non-@code{nil} means mark breakpoints in the source file buffers.  The
-value indicates the preferred method.  Valid values are @code{nil},
-@code{t}, @code{face}, and @code{glyph}.
-@end defopt
-
-@defopt idlwave-shell-breakpoint-face
-The face for breakpoint lines in the source code if
-@code{idlwave-shell-mark-breakpoints} has the value @code{face}.
-@end defopt
-
-@defopt idlwave-shell-breakpoint-popup-menu (@code{t})
-Whether to pop-up a menu and present a tooltip description on
-breakpoint lines.
-@end defopt
-
-@defopt idlwave-shell-mark-stop-line (@code{t})
-Non-@code{nil} means mark the source code line where IDL is currently
-stopped.  The value specifies the preferred method.  Valid values are
-@code{nil}, @code{t}, @code{arrow}, and @code{face}.
-@end defopt
-
-@defopt idlwave-shell-overlay-arrow (@code{">"})
-The overlay arrow to display at source lines where execution halts, if
-configured in @code{idlwave-shell-mark-stop-line}.
-@end defopt
-
-@defopt idlwave-shell-stop-line-face
-The face which highlights the source line where IDL is stopped, if
-configured in @code{idlwave-shell-mark-stop-line}.
-@end defopt
-
-
-@node Compiling Programs
-@subsection Compiling Programs
-@cindex Compiling programs
-@cindex Programs, compiling
-@cindex Default command line, executing
-@cindex Executing a default command line
-
-@kindex C-c C-d C-c
-In order to compile the current buffer under the IDLWAVE shell, press
-@kbd{C-c C-d C-c} (@code{idlwave-save-and-run}).  This first saves the
-current buffer and then sends the command @samp{.run path/to/file} to the
-shell.  You can also execute @kbd{C-c C-d C-c} from the shell buffer, in
-which case the most recently compiled buffer will be saved and
-re-compiled.
-
-When developing or debugging a program, it is often necessary to execute
-the same command line many times.  A convenient way to do this is
-@kbd{C-c C-d C-y} (@code{idlwave-shell-execute-default-command-line}).
-This command first resets IDL from a state of interrupted execution by
-closing all files and returning to the main interpreter level.  Then a
-default command line is send to the shell.  To edit the default command
-line, call @code{idlwave-shell-execute-default-command-line} with a
-prefix argument: @kbd{C-u C-c C-d C-y}.  If no default command line has
-been set (or you give two prefix arguments), the last command on the
-@code{comint} input history is sent.
-
-@kindex C-c C-d C-e
-@cindex Compiling regions
-For quickly compiling and running the currently marked region as a main
-level program @kbd{C-c C-d C-e} (@code{idlwave-shell-run-region}) is
-very useful.  A temporary file is created holding the contents of the
-current region (with @code{END} appended), and run from the shell.
-
-@node Walking the Calling Stack
-@subsection Walking the Calling Stack
-@cindex Calling stack, walking
-
-While debugging a program, it can be very useful to check the context in
-which the current routine was called, for instance to help understand
-the value of the arguments passed.  To do so conveniently you need to
-examine the calling stack.  If execution is stopped somewhere deep in a
-program, you can use the commands @kbd{C-c C-d C-@key{UP}}
-(@code{idlwave-shell-stack-up}) and @kbd{C-c C-d C-@key{DOWN}}
-(@code{idlwave-shell-stack-down}), or the corresponding toolbar buttons,
-to move up or down through the calling stack.  The mode line of the
-shell window will indicate the position within the stack with a label
-like @samp{[-3:MYPRO]}.  The line of IDL code at that stack position
-will be highlighted.  If you continue execution, IDLWAVE will
-automatically return to the current level. @xref{Examining Variables},
-for information how to examine the value of variables and expressions on
-higher calling stack levels.
-
-@html
-<A NAME="EDEBUG"></A>
-@end html
-@node Electric Debug Mode
-@subsection Electric Debug Mode
-@cindex Electric Debug Mode
-@cindex @samp{*Debugging*}
-
-Even with a convenient debug key prefix enabled, repetitive stepping,
-variable examination (@pxref{Examining Variables}), and other debugging
-activities can be awkward and slow using commands which require multiple
-keystrokes.  Luckily, there's a better way, inspired by the lisp e-debug
-mode, and available through the @emph{Electric Debug Mode}.  By default,
-as soon as a breakpoint is hit, this minor mode is enabled.  The buffer
-showing the line where execution has halted is switched to Electric
-Debug Mode.  This mode is visible as @samp{*Debugging*} in the mode
-line, and a different face (violet by default, if color is available)
-for the line stopped at point.  The buffer is made read-only and
-single-character bindings for the most commonly used debugging commands
-are enabled.  These character commands (a list of which is available
-with @kbd{C-?}) are:
-
-@multitable @columnfractions .2 .8
-@item @kbd{a}
-@tab Clear all breakpoints (@code{idlwave-shell-clear-all-bp})
-@item @kbd{b}
-@tab Set breakpoint, @kbd{C-u b} for a conditional break, @kbd{C-n b} for nth hit (@code{idlwave-shell-break-here})
-@item @kbd{d}
-@tab Clear current breakpoint (@code{idlwave-shell-clear-current-bp})
-@item @kbd{e}
-@tab Prompt for expression to print (@code{idlwave-shell-clear-current-bp}).
-@item @kbd{h}
-@tab Continue to the line at cursor position (@code{idlwave-shell-to-here})
-@item @kbd{i}
-@tab Set breakpoint in module named here (@code{idlwave-shell-break-in})
-@item @kbd{[}
-@tab Go to the previous breakpoint in the file (@code{idlwave-shell-goto-previous-bp})
-@item @kbd{]}
-@tab Go to the next breakpoint in the file
-(@code{idlwave-shell-goto-next-bp})
-@item @kbd{\}
-@tab Disable/Enable current breakpoint (@code{idlwave-shell-toggle-enable-current-bp})
-@item @kbd{j}
-@tab Set breakpoint at beginning of enclosing routine (@code{idlwave-shell-break-this-module})
-@item @kbd{k}
-@tab Skip one statement (@code{idlwave-shell-skip})
-@item @kbd{m}
-@tab Continue to end of function (@code{idlwave-shell-return})
-@item @kbd{n}
-@tab Step, over function calls (@code{idlwave-shell-stepover})
-@item @kbd{o}
-@tab Continue past end of function (@code{idlwave-shell-out})
-@item @kbd{p}
-@tab Print expression near point or in region with @kbd{C-u p} (@code{idlwave-shell-print})
-@item @kbd{q}
-@tab End the debugging session and return to the Shell's main level
-(@code{idlwave-shell-retall})
-@item @kbd{r}
-@tab Continue execution to next breakpoint, if any (@code{idlwave-shell-cont})
-@item @kbd{s} or @kbd{@key{SPACE}}
-@tab Step, into function calls (@code{idlwave-shell-step})
-@item @kbd{t}
-@tab Print a calling-level traceback in the shell
-@item @kbd{u}
-@tab Continue to end of block (@code{idlwave-shell-up})
-@item @kbd{v}
-@tab Turn Electric Debug Mode off
-(@code{idlwave-shell-electric-debug-mode})
-@item @kbd{x}
-@tab Examine expression near point (or in region with @kbd{C-u x})
-with shortcut of examine type.
-@item @kbd{z}
-@tab Reset IDL (@code{idlwave-shell-reset})
-@item @kbd{+} or @kbd{=}
-@tab Show higher level in calling stack (@code{idlwave-shell-stack-up})
-@item @kbd{-} or @kbd{_}
-@tab Show lower level in calling stack (@code{idlwave-shell-stack-down})
-@item @kbd{?}
-@tab Help on expression near point or in region with @kbd{C-u ?}
-(@code{idlwave-shell-help-expression})
-@item @kbd{C-?}
-@tab Show help on the commands available.
-@end multitable
-
-Most single-character electric debug bindings use the final keystroke
-of the equivalent multiple key commands (which are of course also
-still available), but some differ (e.g., @kbd{e},@kbd{t},@kbd{q},@kbd{x}).
-Some have additional convenience bindings (like @kbd{@key{SPACE}} for
-stepping).  All prefix and other argument options described in this
-section for the commands invoked by electric debug bindings are still
-valid.  For example, @kbd{C-u b} sets a conditional breakpoint, just
-as it did with @kbd{C-u C-c C-d C-b}.
-
-You can toggle the electric debug mode at any time in a buffer using
-@kbd{C-c C-d C-v} (@kbd{v} to turn it off while in the mode), or from
-the Debug menu.  Normally the mode will be enabled and disabled at the
-appropriate times, but occasionally you might want to edit a file
-while still debugging it, or switch to the mode for conveniently
-setting lots of breakpoints.
-
-To quickly abandon a debugging session and return to normal editing at
-the Shell's main level, use @kbd{q} (@code{idlwave-shell-retall}).
-This disables electric debug mode in all IDLWAVE buffers@footnote{Note
-that this binding is not symmetric: @kbd{C-c C-d C-q} is bound to
-@code{idlwave-shell-quit}, which quits your IDL session.}.  Help is
-available for the command shortcuts with @kbd{C-?}.  If you find this
-mode gets in your way, you can keep it from automatically activating
-by setting the variable @code{idlwave-shell-automatic-electric-debug}
-to @code{nil}, or @code{'breakpoint}.  If you'd like the convenient
-electric debug shortcuts available also when run-time errors are
-encountered, set to @code{t}.
-
-@defopt idlwave-shell-automatic-electric-debug (@code{'breakpoint})
-Whether to enter electric debug mode automatically when a breakpoint
-or run-time error is encountered, and then disable it in all buffers
-when the $MAIN$ level is reached (either through normal program
-execution, or retall).  In addition to @code{nil} for never, and
-@code{t} for both breakpoints and errors, this can be
-@code{'breakpoint} (the default) to enable it only at breakpoint
-halts.
-@end defopt
-
-@defopt idlwave-shell-electric-stop-color (Violet)
-Default color of the stopped line overlay when in electric debug mode.
-@end defopt
-
-@defopt idlwave-shell-electric-stop-line-face
-The face to use for the stopped line.  Defaults to a face similar to the
-modeline, with color @code{idlwave-shell-electric-stop-color}.
-@end defopt
-
-@defopt idlwave-shell-electric-zap-to-file (@code{t})
-If set, when entering electric debug mode, select the window displaying
-the file where point is stopped.  This takes point away from the shell
-window, but is useful for immediate stepping, etc.
-@end defopt
-
-@html
-<A NAME="EXAMINE"></A>
-@end html
-@node Examining Variables
-@section Examining Variables
-@cindex @code{PRINT} expressions
-@cindex @code{HELP}, on expressions
-@cindex Expressions, printing & help
-@cindex Examining expressions
-@cindex Printing expressions
-@cindex Mouse binding to print expressions
-
-@kindex C-c C-d C-p
-Do you find yourself repeatedly typing, e.g., @code{print,n_elements(x)},
-and similar statements to remind yourself of the
-type/size/structure/value/etc.@: of variables and expressions in your code
-or at the command line?  IDLWAVE has a suite of special commands to
-automate these types of variable or expression examinations.  They work
-by sending statements to the shell formatted to include the indicated
-expression, and can be accessed in several ways.
-
-These @emph{examine} commands can be used in the shell or buffer at any
-time (as long as the shell is running), and are very useful when
-execution is stopped in a buffer due to a triggered breakpoint or error,
-or while composing a long command in the IDLWAVE shell.  In the latter
-case, the command is sent to the shell and its output is visible, but
-point remains unmoved in the command being composed: you can inspect
-the constituents of a command you're building without interrupting the
-process of building it!  You can even print arbitrary expressions from
-older input or output further up in the shell window; any expression,
-variable, number, or function you see can be examined.
-
-If the variable @code{idlwave-shell-separate-examine-output} is
-non-@code{nil} (the default), all examine output will be sent to a
-special @file{*Examine*} buffer, rather than the shell.  The output of
-prior examine commands is saved in this buffer.  In this buffer @kbd{c}
-clears the contents, and @kbd{q} hides the buffer.
-
-The two most basic examine commands are bound to @kbd{C-c C-d C-p}, to
-print the expression at point, and @kbd{C-c C-d ?}, to invoke help on
-this expression@footnote{Available as @kbd{p} and @kbd{?} in Electric
-Debug Mode (@pxref{Electric Debug Mode})}.  The expression at point is
-either an array expression or a function call, or the contents of a pair
-of parentheses.  The chosen expression is highlighted, and
-simultaneously the resulting output is highlighted in the shell or
-separate output buffer.  Calling the above commands with a prefix
-argument will use the current region as expression instead of using the
-one at point. which can be useful for examining complicated, multi-line
-expressions.  Two prefix arguments (@kbd{C-u C-u C-c C-d C-p}) will
-prompt for an expression to print directly.  By default, when invoking
-print, only an initial portion of long arrays will be printed, up to
-@code{idlwave-shell-max-print-length}.
-
-For added speed and convenience, there are mouse bindings which allow
-you to click on expressions and examine their values.  Use
-@kbd{S-mouse-2} to print an expression and @kbd{C-M-mouse-2} to invoke
-help (i.e., you need to hold down @key{META} and @key{CONTROL} while
-clicking with the middle mouse button).  If you simply click, the
-nearest expression will be selected in the same manner as described
-above.  You can also @emph{drag} the mouse in order to highlight
-exactly the specific expression or sub-expression you want to examine.
-For custom expression examination, and the powerful customizable
-pop-up examine selection, @xref{Custom Expression Examination}.
-
-@cindex Printing expressions, on calling stack
-@cindex Restrictions for expression printing
-The same variable inspection commands work both in the IDL Shell and
-IDLWAVE buffers, and even for variables at higher levels of the calling
-stack.  For instance, if you're stopped at a breakpoint in a routine,
-you can examine the values of variables and expressions inside its
-calling routine, and so on, all the way up through the calling stack.
-Simply step up the stack, and print variables as you see them
-(@pxref{Walking the Calling Stack}, for information on stepping back
-through the calling stack).  The following restrictions apply for all
-levels except the current:
-
-@itemize @bullet
-@item
-Array expressions must use the @samp{[ ]} index delimiters.  Identifiers
-with a @samp{( )} will be interpreted as function calls.
-@item
-@cindex ROUTINE_NAMES, IDL procedure
-N.B.: printing values of expressions on higher levels of the calling
-stack uses the @emph{unsupported} IDL routine @code{ROUTINE_NAMES},
-which may or may not be available in future versions of IDL@.  Caveat
-Examinor.
-@end itemize
-
-@defopt idlwave-shell-expression-face
-The face for @code{idlwave-shell-expression-overlay}.
-Allows you to choose the font, color and other properties for
-the expression printed by IDL.
-@end defopt
-
-@defopt idlwave-shell-output-face
-The face for @code{idlwave-shell-output-overlay}.
-Allows you to choose the font, color and other properties for the most
-recent output of IDL when examining an expression."
-@end defopt
-
-@defopt idlwave-shell-separate-examine-output (@code{t})
-If non-@code{nil}, re-direct the output of examine commands to a special
-@file{*Examine*} buffer, instead of in the shell itself.
-@end defopt
-
-@defopt idlwave-shell-max-print-length (200)
-The maximum number of leading array entries to print, when examining
-array expressions.
-@end defopt
-
-@node Custom Expression Examination
-@section Custom Expression Examination
-@cindex Expressions, custom examination
-@cindex Custom expression examination
-
-The variety of possible variable and expression examination commands is
-endless (just look, for instance, at the keyword list to
-@code{widget_info()}).  Rather than attempt to include them all, IDLWAVE
-provides two easy methods to customize your own commands, with a special
-mouse examine command, and two macros for generating your own examine
-key and mouse bindings.
-
-The most powerful and flexible mouse examine command of all is
-available on @kbd{C-S-mouse-2}.  Just as for all the other mouse
-examine commands, it permits click or drag expression selection, but
-instead of sending hard-coded commands to the shell, it pops-up a
-customizable selection list of examine functions to choose among,
-configured with the @code{idlwave-shell-examine-alist}
-variable@footnote{In Electric Debug Mode (@pxref{Electric Debug
-Mode}), the key @kbd{x} provides a single-character shortcut interface
-to the same examine functions for the expression at point or marked by
-the region.}.  This variable is a list of key-value pairs (an
-@emph{alist} in Emacs parlance), where the key gives a name to be
-shown for the examine command, and the value is the command strings
-itself, in which the text @code{___} (three underscores) will be
-replaced by the selected expression before being sent to the shell.
-An example might be key @code{Structure Help} with value
-@code{help,___,/STRUCTURE}.  In that case, you'd be prompted with
-@emph{Structure Help}, which might send something like
-@code{help,var,/STRUCTURE} to the shell for output.
-@code{idlwave-shell-examine-alist} comes configured by default with a
-large list of examine commands, but you can easily customize it to add
-your own.
-
-In addition to configuring the functions available to the pop-up mouse
-command, you can easily create your own customized bindings to inspect
-expressions using the two convenience macros
-@code{idlwave-shell-examine} and @code{idlwave-shell-mouse-examine}.
-These create keyboard or mouse-based custom inspections of variables,
-sharing all the same properties of the built-in examine commands.
-Both functions take a single string argument sharing the syntax of the
-@code{idlwave-shell-examine-alist} values, e.g.:
-
-@lisp
-(add-hook 'idlwave-shell-mode-hook
-          (lambda ()
-            (idlwave-shell-define-key-both [s-down-mouse-2]
-                                 (idlwave-shell-mouse-examine
-                                  "print, size(___,/DIMENSIONS)"))
-            (idlwave-shell-define-key-both [f9] (idlwave-shell-examine
-                                       "print, size(___,/DIMENSIONS)"))
-            (idlwave-shell-define-key-both [f10] (idlwave-shell-examine
-                                        "print,size(___,/TNAME)"))
-            (idlwave-shell-define-key-both [f11] (idlwave-shell-examine
-                                        "help,___,/STRUCTURE"))))
-@end lisp
-
-@noindent Now pressing @key{f9}, or middle-mouse dragging with the
-@key{SUPER} key depressed, will print the dimensions of the nearby or
-highlighted expression.  Pressing @key{f10} will give the type string,
-and @key{f11} will show the contents of a nearby structure.  As you can
-see, the possibilities are only marginally finite.
-
-@defopt idlwave-shell-examine-alist
-An alist of examine commands in which the keys name the command and
-are displayed in the selection pop-up, and the values are custom IDL
-examine command strings to send, after all instances of @code{___}
-(three underscores) are replaced by the indicated expression.
-@end defopt
-
-@node Acknowledgments
-@chapter Acknowledgments
-@cindex Acknowledgments
-@cindex Maintainer, of IDLWAVE
-@cindex Authors, of IDLWAVE
-@cindex Contributors, to IDLWAVE
-@cindex Email address, of Maintainer
-@cindex Thanks
-
-@noindent
-The main contributors to the IDLWAVE package have been:
-
-@itemize @minus
-@item
-@uref{mailto:chase@@att.com, @b{Chris Chase}}, the original author.
-Chris wrote @file{idl.el} and @file{idl-shell.el} and maintained them
-for several years.
-
-@item
-@uref{mailto:dominik@@astro.uva.nl, @b{Carsten Dominik}} was in charge
-of the package from version 3.0, during which time he overhauled almost
-everything, modernized IDLWAVE with many new features, and developed the
-manual.
-
-@item
-@uref{mailto:jdsmith@@as.arizona.edu, @b{J.D. Smith}}, the current
-maintainer, as of version 4.10, helped shape object method completion
-and most new features introduced in versions 4.x, and introduced many
-new features for IDLWAVE versions 5.x and 6.x.
-@end itemize
-
-@noindent
-The following people have also contributed to the development of IDLWAVE
-with patches, ideas, bug reports and suggestions.
-
-@itemize @minus
-@item
-Ulrik Dickow <dickow__at__nbi.dk>
-@item
-Eric E. Dors <edors__at__lanl.gov>
-@item
-Stein Vidar H. Haugan <s.v.h.haugan__at__astro.uio.no>
-@item
-David Huenemoerder <dph__at__space.mit.edu>
-@item
-Kevin Ivory <Kevin.Ivory__at__linmpi.mpg.de>
-@item
-Dick Jackson <dick__at__d-jackson.com>
-@item
-Xuyong Liu <liu__at__stsci.edu>
-@item
-Simon Marshall <Simon.Marshall__at__esrin.esa.it>
-@item
-Craig Markwardt <craigm__at__cow.physics.wisc.edu>
-@item
-Laurent Mugnier <mugnier__at__onera.fr>
-@item
-Lubos Pochman <lubos__at__rsinc.com>
-@item
-Bob Portmann <portmann__at__al.noaa.gov>
-@item
-Patrick M. Ryan <pat__at__jaameri.gsfc.nasa.gov>
-@item
-Marty Ryba <ryba__at__ll.mit.edu>
-@item
-Phil Williams <williams__at__irc.chmcc.org>
-@item
-Phil Sterne <sterne__at__dublin.llnl.gov>
-@item
-Paul Sorenson <aardvark62__at__msn.com>
-@end itemize
-
-Doug Dirks was instrumental in providing the crucial IDL XML catalog to
-support HTML help with IDL v6.2 and later, and Ali Bahrami provided
-scripts and documentation to interface with the IDL Assistant.
-
-@noindent
-Thanks to everyone!
-
-@node Sources of Routine Info
-@appendix Sources of Routine Info
-
-@cindex Sources of routine information
-In @ref{Routine Info} and @ref{Completion} we showed how IDLWAVE
-displays the calling sequence and keywords of routines, and completes
-routine names and keywords.  For these features to work, IDLWAVE must
-know about the accessible routines.
-
-@menu
-* Routine Definitions::         Where IDL Routines are defined.
-* Routine Information Sources::  So how does IDLWAVE know about...
-* Catalogs::
-* Load-Path Shadows::           Routines defined in several places
-* Documentation Scan::          Scanning the IDL Manuals
-@end menu
-
-@node Routine Definitions
-@appendixsec Routine Definitions
-@cindex Routine definitions
-@cindex IDL variable @code{!PATH}
-@cindex @code{!PATH}, IDL variable
-@cindex @code{CALL_EXTERNAL}, IDL routine
-@cindex @code{LINKIMAGE}, IDL routine
-@cindex External routines
-
-@noindent Routines which can be used in an IDL program can be defined in
-several places:
-
-@enumerate
-@item
-@emph{Builtin routines} are defined inside IDL itself.  The source code
-of such routines is not available, but instead are learned about through
-the IDL documentation.
-@item
-Routines which are @emph{part of the current program}, are defined in a
-file explicitly compiled by the user.  This file may or may not be
-located on the IDL search path.
-@item
-@emph{Library routines} are defined in files located on IDL's search
-path.  When a library routine is called for the first time, IDL will
-find the source file and compile it dynamically.  A special sub-category
-of library routines are the @emph{system routines} distributed with IDL,
-and usually available in the @file{lib} subdirectory of the IDL
-distribution.
-@item
-External routines written in other languages (like Fortran or C) can be
-called with @code{CALL_EXTERNAL}, linked into IDL via @code{LINKIMAGE},
-or included as dynamically loaded modules (DLMs).  Currently IDLWAVE
-cannot provide routine info and completion for such external routines,
-except by querying the Shell for calling information (DLMs only).
-@end enumerate
-
-@node Routine Information Sources
-@appendixsec Routine Information Sources
-@cindex Routine info sources
-@cindex Builtin list of routines
-@cindex Updating routine info
-@cindex Scanning buffers for routine info
-@cindex Buffers, scanning for routine info
-@cindex Shell, querying for routine info
-
-@noindent To maintain the most comprehensive information about all IDL
-routines on a system, IDLWAVE collects data from many sources:
-
-@enumerate
-
-@item
-It has a @emph{builtin list} with information about the routines IDL
-ships with.  IDLWAVE @value{VERSION} is distributed with a list of
-@value{NSYSROUTINES} routines and object methods, reflecting IDL version
-@value{IDLVERSION}.  As of IDL v6.2, the routine info is distributed
-directly with IDL in the form of an XML catalog which IDLWAVE scans.
-Formerly, this list was created by scanning the IDL manuals to produce
-the file @file{idlw-rinfo.el}.
-
-@item
-IDLWAVE @emph{scans} all its @emph{buffers} in the current Emacs session
-for routine definitions.  This is done automatically when routine
-information or completion is first requested by the user.  Each new
-buffer and each buffer saved after making changes is also scanned.  The
-command @kbd{C-c C-i} (@code{idlwave-update-routine-info}) can be used
-at any time to rescan all buffers.
-
-@item
-If you have an IDLWAVE-Shell running in the Emacs session, IDLWAVE will
-@emph{query the shell} for compiled routines and their arguments.  This
-happens automatically when routine information or completion is first
-requested by the user.  Each time an Emacs buffer is compiled with
-@kbd{C-c C-d C-c}, the routine info for that file is queried.  Though
-rarely necessary, the command @kbd{C-c C-i}
-(@code{idlwave-update-routine-info}) can be used to explicitly update
-the shell routine data.
-
-@item
-Many popular libraries are distributed with routine information already
-scanned into @emph{library catalogs} (@pxref{Library Catalogs}).  These
-per-directory catalog files can also be built by the user with the
-supplied @file{idlwave_catalog} tool.  They are automatically discovered
-by IDLWAVE.
-
-@item
-IDLWAVE can scan selected directories of source files and store the
-result in a single @emph{user catalog} file which will be
-automatically loaded just like @file{idlw-rinfo.el}. @xref{User
-Catalog}, for information on how to scan files in this way.
-@end enumerate
-
-Loading all the routine and catalog information can be a time consuming
-process, especially over slow networks.  Depending on the system and
-network configuration it could take up to 30 seconds (though locally on
-fast systems is usually only a few seconds).  In order to minimize the
-wait time upon your first completion or routine info command in a
-session, IDLWAVE uses Emacs idle time to do the initialization in six
-steps, yielding to user input in between.  If this gets into your way,
-set the variable @code{idlwave-init-rinfo-when-idle-after} to 0 (zero).
-The more routines documented in library and user catalogs, the slower
-the loading will be, so reducing this number can help alleviate any long
-load times.
-
-@defopt idlwave-init-rinfo-when-idle-after (@code{10})
-Seconds of idle time before routine info is automatically initialized.
-@end defopt
-
-@defopt idlwave-scan-all-buffers-for-routine-info (@code{t})
-Non-@code{nil} means scan all buffers for IDL programs when updating
-info.
-@end defopt
-
-@defopt idlwave-query-shell-for-routine-info (@code{t})
-Non-@code{nil} means query the shell for info about compiled routines.
-@end defopt
-
-@defopt idlwave-auto-routine-info-updates
-Controls under what circumstances routine info is updated automatically.
-@end defopt
-
-@html
-<A NAME="CATALOGS"></A>
-@end html
-@node Catalogs
-@appendixsec Catalogs
-@cindex Catalogs
-
-@emph{Catalogs} are files containing scanned information on individual
-routines, including arguments and keywords, calling sequence, file path,
-class and procedure vs. function type, etc.  They represent a way of
-extending the internal built-in information available for IDL system
-routines (@pxref{Routine Info}) to other source collections.
-
-Starting with version 5.0, there are two types of catalogs available
-with IDLWAVE@.  The traditional @emph{user catalog} and the newer
-@emph{library catalogs}.  Although they can be used interchangeably, the
-library catalogs are more flexible, and preferred.  There are few
-occasions when a user catalog might be preferred---read below.  Both
-types of catalogs can coexist without causing problems.
-
-To facilitate the catalog systems, IDLWAVE stores information it gathers
-from the shell about the IDL search paths, and can write this
-information out automatically, or on-demand (menu @code{Debug->Save Path
-Info}).  On systems with no shell from which to discover the path
-information (e.g., Windows), a library path must be specified in
-@code{idlwave-library-path} to allow library catalogs to be located, and
-to setup directories for user catalog scan (@pxref{User Catalog} for
-more on this variable).  Note that, before the shell is running, IDLWAVE
-can only know about the IDL search path by consulting the file pointed
-to by @code{idlwave-path-file} (@file{~/.emacs.d/idlwave/idlpath.el}, by
-default).  If @code{idlwave-auto-write-path} is enabled (which is the
-default), the paths are written out whenever the IDLWAVE shell is
-started.
-
-@defopt idlwave-auto-write-path  (@code{t})
-Write out information on the !PATH and !DIR paths from IDL automatically
-when they change and when the Shell is closed.  These paths are needed
-to locate library catalogs.
-@end defopt
-
-@defopt idlwave-library-path
-IDL library path for Windows and macOS@.  Under Unix/macOS, will be
-obtained from the Shell when run.
-@end defopt
-
-@defopt idlwave-system-directory
-The IDL system directory for Windows and macOS@.  Also needed for
-locating HTML help and the IDL Assistant for IDL v6.2 and later.  Under
-Unix/macOS, will be obtained from the Shell and recorded, if run.
-@end defopt
-
-@defopt idlwave-config-directory (@file{~/.emacs.d/idlwave})
-Default path where IDLWAVE saves configuration information, a user
-catalog (if any), and a cached scan of the XML catalog (IDL v6.2 and
-later).
-@end defopt
-
-@menu
-* Library Catalogs::
-* User Catalog::
-@end menu
-
-@html
-<A NAME="LIBRARY_CATALOGS"></A>
-@end html
-@node Library Catalogs
-@appendixsubsec Library Catalogs
-@cindex @file{.idlwave_catalog}
-@cindex Library catalogs
-@cindex @code{idlwave_catalog}
-
-Library catalogs consist of files named @file{.idlwave_catalog} stored
-in directories containing @code{.pro} routine files.  They are
-discovered on the IDL search path and loaded automatically when routine
-information is read.  Each catalog file documents the routines found in
-that directory---one catalog per directory.  Every catalog has a
-library name associated with it (e.g., @emph{AstroLib}).  This name will
-be shown briefly when the catalog is found, and in the routine info of
-routines it documents.
-
-Many popular libraries of routines are shipped with IDLWAVE catalog
-files by default, and so will be automatically discovered.  Library
-catalogs are scanned externally to Emacs using a tool provided with
-IDLWAVE@.  Each catalog can be re-scanned independently of any other.
-Catalogs can easily be made available system-wide with a common source
-repository, providing uniform routine information, and lifting the
-burden of scanning from the user (who may not even know they're using a
-scanned catalog).  Since all catalogs are independent, they can be
-re-scanned automatically to gather updates, e.g., in a @file{cron} job.
-Scanning is much faster than with the built-in user catalog method.  One
-minor disadvantage: the entire IDL search path is scanned for catalog
-files every time IDLWAVE starts up, which might be slow if accessing IDL
-routines over a slow network.
-
-A Perl tool to create library catalogs is distributed with IDLWAVE:
-@code{idlwave_catalog}.  It can be called quite simply:
-@example
-idlwave_catalog MyLib
-@end example
-
-@noindent This will scan all directories recursively beneath the current and
-populate them with @file{.idlwave_catalog} files, tagging the routines
-found there with the name library ``MyLib''.  The full usage
-information:
-
-@example
-Usage: idlwave_catalog  [-l] [-v] [-d] [-s] [-f] [-h] libname
-       libname - Unique name of the catalog (4 or more alphanumeric
-                 characters).
-            -l - Scan local directory only, otherwise recursively
-                 catalog all directories at or beneath this one.
-            -v - Print verbose information.
-            -d - Instead of scanning, delete all .idlwave_catalog files
-                 here or below.
-            -s - Be silent.
-            -f - Force overwriting any catalogs found with a different
-                 library name.
-            -h - Print this usage.
-@end example
-
-To re-load the library catalogs on the IDL path, force a system routine
-info update using a single prefix to @code{idlwave-update-routine-info}:
-@kbd{C-u C-c C-i}.
-
-@defopt idlwave-use-library-catalogs  (@code{t})
-Whether to search for and load library catalogs.  Disable if load
-performance is a problem and/or the catalogs are not needed.
-@end defopt
-
-@node User Catalog
-@appendixsubsec User Catalog
-@cindex User catalog
-@cindex IDL library routine info
-@cindex Windows
-@cindex macOS
-@cindex IDL variable @code{!DIR}
-@cindex @code{!DIR}, IDL variable
-
-The user catalog is the old routine catalog system.  It is produced
-within Emacs, and stored in a single file in the user's home directory
-(@file{.emacs.d/idlwave/idlusercat.el} by default).  Although library catalogs
-are more flexible, there may be reasons to prefer a user catalog
-instead, including:
-
-@itemize @bullet
-@item The scan is internal to Emacs, so you don't need a working Perl
-installation, as you do for library catalogs.
-@item Can be used to scan directories for which the user has no write
-privileges.
-@item Easy widget-based path selection.
-@end itemize
-
-However, no routine info is available in the user catalog by default;
-the user must actively complete a scan.  In addition, this type of
-catalog is all or nothing: if a single routine changes, the entire
-catalog must be rescanned to update it.  Creating the user catalog is
-also much slower than scanning library catalogs.
-
-You can scan any of the directories on the currently known path.  Under
-Windows, you need to specify the IDL search path in
-the variable @code{idlwave-library-path}, and the location of the IDL
-directory (the value of the @code{!DIR} system variable) in the variable
-@code{idlwave-system-directory}, like this@footnote{The initial @samp{+}
-leads to recursive expansion of the path, just like in IDL}:
-
-@lisp
-(setq idlwave-library-path
-        '("+c:/RSI/IDL56/lib/" "+c:/user/me/idllibs"))
-(setq idlwave-system-directory "c:/RSI/IDL56/")
-@end lisp
-
-@noindent Under GNU/Linux and UNIX, these values will be automatically
-gathered from the IDLWAVE shell, if run.
-
-The command @kbd{M-x idlwave-create-user-catalog-file} (or the menu item
-@samp{IDLWAVE->Routine Info->Select Catalog Directories}) can then be
-used to create a user catalog.  It brings up a widget in which you can
-select some or all directories on the search path.  Directories which
-already contain a library catalog are marked with @samp{[LIB]}, and need
-not be scanned (although there is no harm if you do so, other than the
-additional memory used for the duplication).
-
-After selecting directories, click on the @w{@samp{[Scan & Save]}}
-button in the widget to scan all files in the selected directories and
-write out the resulting routine information.  In order to update the
-library information using the directory selection, call the command
-@code{idlwave-update-routine-info} with a double prefix argument:
-@w{@kbd{C-u C-u C-c C-i}}.  This will rescan files in the previously
-selected directories, write an updated version of the user catalog file
-and rebuild IDLWAVE's internal lists.  If you give three prefix
-arguments @w{@kbd{C-u C-u C-u C-c C-i}}, updating will be done with a
-background job@footnote{Unix systems only, I think.}.  You can continue
-to work, and the library catalog will be re-read when it is ready.  If
-you find you need to update the user catalog often, you should consider
-building a library catalog for your routines instead (@pxref{Library
-Catalogs}).
-
-@defopt idlwave-special-lib-alist
-Alist of regular expressions matching special library directories for
-labeling in routine-info display.
-@end defopt
-
-@node Load-Path Shadows
-@appendixsec Load-Path Shadows
-@cindex Load-path shadows
-@cindex Shadows, load-path
-@cindex Duplicate routines
-@cindex Multiply defined routines
-@cindex Routine definitions, multiple
-@cindex Application, testing for shadowing
-@cindex Buffer, testing for shadowing
-
-IDLWAVE can compile a list of routines which are (re-)defined in more
-than one file.  Since one definition will hide (shadow) the others
-depending on which file is compiled first, such multiple definitions are
-called "load-path shadows".  IDLWAVE has several routines to scan for
-load path shadows.  The output is placed into the special buffer
-@file{*Shadows*}.  The format of the output is identical to the source
-section of the routine info buffer (@pxref{Routine Info}).  The
-different definitions of a routine are ordered by @emph{likelihood of
-use}.  So the first entry will be most likely the one you'll get if an
-unsuspecting command uses that routine.  Before listing shadows, you
-should make sure that routine info is up-to-date by pressing @kbd{C-c
-C-i}.  Here are the different routines (also available in the Menu
-@samp{IDLWAVE->Routine Info}):
-
-@table @asis
-@item @kbd{M-x idlwave-list-buffer-load-path-shadows}
-This command checks the names of all routines defined in the current
-buffer for shadowing conflicts with other routines accessible to
-IDLWAVE@.  The command also has a key binding: @kbd{C-c C-b}
-@item @kbd{M-x idlwave-list-shell-load-path-shadows}.
-Checks all routines compiled under the shell for shadowing.  This is
-very useful when you have written a complete application.  Just compile
-the application, use @code{RESOLVE_ALL} to compile any routines used by
-your code, update the routine info inside IDLWAVE with @kbd{C-c C-i} and
-then check for shadowing.
-@item @kbd{M-x idlwave-list-all-load-path-shadows}
-This command checks all routines accessible to IDLWAVE for conflicts.
-@end table
-
-For these commands to work fully you need to scan the entire load path
-in either a user or library catalog.  Also, IDLWAVE should be able to
-distinguish between the system library files (normally installed in
-@file{/usr/local/rsi/idl/lib}) and any site specific or user specific
-files.  Therefore, such local files should not be installed inside the
-@file{lib} directory of the IDL directory.  This is also advisable for
-many other reasons.
-
-@cindex Windows
-@cindex IDL variable @code{!DIR}
-@cindex @code{!DIR}, IDL variable
-Users of Windows also must set the variable
-@code{idlwave-system-directory} to the value of the @code{!DIR} system
-variable in IDL@.  IDLWAVE appends @file{lib} to the value of this
-variable and assumes that all files found on that path are system
-routines.
-
-Another way to find out if a specific routine has multiple definitions
-on the load path is routine info display (@pxref{Routine Info}).
-
-@node Documentation Scan
-@appendixsec Documentation Scan
-@cindex @file{get_html_rinfo}
-@cindex @file{idlw-rinfo.el}
-@cindex Scanning the documentation
-@cindex Perl program, to create @file{idlw-rinfo.el}
-
-@strong{Starting with version 6.2, IDL is distributed directly with HTML
-online help, and an XML-based catalog of routine information}.  This
-makes scanning the manuals with the tool @file{get_html_rinfo}, and the
-@file{idlw-rinfo.el} file it produced, as described here, entirely
-unnecessary.  The information is left here for users wishing to produce
-a catalog of older IDL versions' help.
-
-
-IDLWAVE derives its knowledge about system routines from the IDL
-manuals.  The file @file{idlw-rinfo.el} contains the routine information
-for the IDL system routines, and links to relevant sections of the HTML
-documentation.  The Online Help feature of IDLWAVE requires HTML
-versions of the IDL manuals to be available; the HTML documentation is
-not distributed with IDLWAVE by default, but must be downloaded
-separately.
-
-The HTML files and related images can be produced from the
-@file{idl.chm} HTMLHelp file distributed with IDL using the free
-Microsoft HTML Help Workshop.  If you are lucky, the maintainer of
-IDLWAVE will always have access to the newest version of IDL and provide
-updates.  The IDLWAVE distribution also contains the Perl program
-@file{get_html_rinfo} which constructs the @file{idlw-rinfo.el} file by
-scanning the HTML documents produced from the IDL documentation.
-Instructions on how to use @file{get_html_rinfo} are in the program
-itself.
-
-@node HTML Help Browser Tips
-@appendix HTML Help Browser Tips
-@cindex Browser Tips
-
-There are a wide variety of possible browsers to use for displaying
-the online HTML help available with IDLWAVE (starting with version
-5.0).  Since IDL v6.2, a single cross-platform HTML help browser, the
-@emph{IDL Assistant} is distributed with IDL@.  If this help browser is
-available, it is the preferred choice, and the default.  The variable
-@code{idlwave-help-use-assistant}, enabled by default, controls
-whether this help browser is used.  If you use the IDL Assistant, the
-tips here are not relevant.
-
-Since IDLWAVE runs on many different system types, a single browser
-configuration is not possible, but choices abound.  The default
-@code{idlwave-help-browser-function} inherits the browser configured
-in @code{browse-url-browser-function}.
-
-Note that the HTML files recompiled from the help sources contain
-specific references to the @samp{Symbol} font, which by default is not
-permitted in normal encodings (it's invalid, technically).  Though it
-only impacts a few symbols, you can trick Mozilla-based browsers into
-recognizing @samp{Symbol} by following the directions
-@c This page is 11 years old.  Is it still relevant?
-@uref{http://hutchinson.belmont.ma.us/tth/Xfonts.html, here}.  With
-this fix in place, HTML help pages look almost identical to their PDF
-equivalents (yet can be bookmarked, browsed as history, searched,
-etc.).
-
-@c Not updated in over a decade.
-@c Maybe you want to recommend eww these days.
-@ignore
-@noindent Individual platform recommendations:
-
-@itemize @bullet
-@item Unix/macOS: The @uref{http://www.w3m.org,@code{w3m}} browser
-and its associated
-@uref{http://emacs-w3m.namazu.org/,@code{emacs-w3m}} emacs mode
-provide in-buffer browsing with image display, and excellent speed and
-formatting.  Both the Emacs mode and the browser itself must be
-downloaded separately.  To use this browser, include
-
-@lisp
-(setq idlwave-help-browser-function 'w3m-browse-url)
-@end lisp
-
-in your @file{.emacs}.  Setting a few other nice @code{w3m} options
-cuts down on screen clutter:
-
-@lisp
-(setq w3m-use-tab nil
-      w3m-use-header-line nil
-      w3m-use-toolbar nil)
-@end lisp
-
-If you use a dedicated frame for help, you might want to add the
-following, to get consistent behavior with the @kbd{q} key:
-
-@lisp
-;; Close my help window when w3m closes.
-(defadvice w3m-close-window (after idlwave-close activate)
-  (if (boundp 'idlwave-help-frame)
-      (idlwave-help-quit)))
-@end lisp
-
-Note that you can open the file in an external browser from within
-@code{w3m} using @kbd{M}.
-@end itemize
-@end ignore
-
-@node Configuration Examples
-@appendix Configuration Examples
-@cindex Configuration examples
-@cindex Example configuration
-@cindex @file{.emacs}
-@cindex Default settings, of options
-@cindex Interview, with the maintainer
-
-@noindent
-@b{Question:} You have all these complicated configuration options in
-your package, but which ones do @emph{you} as the maintainer actually
-set in your own configuration?
-
-@noindent
-@b{Answer:} Not many, beyond custom key bindings.  I set most defaults
-the way that seems best.  However, the default settings do not turn on
-features which:
-
-@itemize @minus
-@item
-are not self-evident (i.e., too magic) when used by an unsuspecting user.
-@item
-are too intrusive.
-@item
-will not work properly on all Emacs installations.
-@item
-break with widely used standards.
-@item
-use function or other non-standard keys.
-@item
-are purely personal customizations, like additional key bindings, and
-library names.
-@end itemize
-
-@noindent To see what I mean, here is the @emph{entire} configuration
-the old maintainer had in his @file{.emacs}:
-
-@lisp
-(setq idlwave-shell-debug-modifiers '(control shift)
-      idlwave-store-inquired-class t
-      idlwave-shell-automatic-start t
-      idlwave-main-block-indent 2
-      idlwave-init-rinfo-when-idle-after 2
-      idlwave-help-dir "~/lib/emacs/idlwave"
-      idlwave-special-lib-alist '(("/idl-astro/" . "AstroLib")
-                                  ("/jhuapl/" . "JHUAPL-Lib")
-                                  ("/dominik/lib/idl/" . "MyLib")))
-@end lisp
-
-However, if you are an Emacs power-user and want IDLWAVE to work
-completely differently, you can change almost every aspect of it.  Here
-is an example of a much more extensive configuration of IDLWAVE@.  The
-user is King!
-
-@example
-;;; Settings for IDLWAVE mode
-
-(setq idlwave-block-indent 3)           ; Indentation settings
-(setq idlwave-main-block-indent 3)
-(setq idlwave-end-offset -3)
-(setq idlwave-continuation-indent 1)
-(setq idlwave-begin-line-comment "^;[^;]")  ; Leave ";" but not ";;"
-                                            ; anchored at start of line.
-(setq idlwave-surround-by-blank t)      ; Turn on padding ops =,<,>
-(setq idlwave-pad-keyword nil)          ; Remove spaces for keyword '='
-(setq idlwave-expand-generic-end t)     ; convert END to ENDIF etc...
-(setq idlwave-reserved-word-upcase t)   ; Make reserved words upper case
-                                        ; (with abbrevs only)
-(setq idlwave-abbrev-change-case nil)   ; Don't force case of expansions
-(setq idlwave-hang-indent-regexp ": ")  ; Change from "- " for auto-fill
-(setq idlwave-show-block nil)           ; Turn off blinking to begin
-(setq idlwave-abbrev-move t)            ; Allow abbrevs to move point
-(setq idlwave-query-class '((method-default . nil) ; No query for method
-                            (keyword-default . nil); or keyword completion
-                            ("INIT" . t)           ; except for these
-                            ("CLEANUP" . t)
-                            ("SETPROPERTY" .t)
-                            ("GETPROPERTY" .t)))
-
-;; Using w3m for help (must install w3m and emacs-w3m)
-(autoload 'w3m-browse-url "w3m" "Interface for w3m on Emacs." t)
-(setq idlwave-help-browser-function 'w3m-browse-url
-      w3m-use-tab nil ; no tabs, location line, or toolbar
-      w3m-use-header-line nil
-      w3m-use-toolbar nil)
-
-;; Close my help window or frame when w3m closes with 'q'.
-(defadvice w3m-close-window (after idlwave-close activate)
-  (if (boundp 'idlwave-help-frame)
-      (idlwave-help-quit)))
-
-;; Some setting can only be done from a mode hook.  Here is an example:
-(add-hook 'idlwave-mode-hook
-  (lambda ()
-    (setq case-fold-search nil)          ; Make searches case sensitive
-    ;; Run other functions here
-    (font-lock-mode 1)                   ; Turn on font-lock mode
-    (idlwave-auto-fill-mode 0)           ; Turn off auto filling
-    (setq idlwave-help-browser-function 'browse-url-w3)
-
-    ;; Pad with 1 space (if -n is used then make the
-    ;; padding a minimum of n spaces.)  The defaults use -1
-    ;; instead of 1.
-    (idlwave-action-and-binding "=" '(idlwave-expand-equal 1 1))
-    (idlwave-action-and-binding "<" '(idlwave-surround 1 1))
-    (idlwave-action-and-binding ">" '(idlwave-surround 1 1 '(?-)))
-    (idlwave-action-and-binding "&" '(idlwave-surround 1 1))
-
-    ;; Only pad after comma and with exactly 1 space
-    (idlwave-action-and-binding "," '(idlwave-surround nil 1))
-    (idlwave-action-and-binding "&" '(idlwave-surround 1 1))
-
-    ;; Pad only after '->', remove any space before the arrow
-    (idlwave-action-and-binding "->"  '(idlwave-surround 0 -1 nil 2))
-
-    ;; Set some personal bindings
-    ;; (In this case, makes ',' have the normal self-insert behavior.)
-    (local-set-key "," 'self-insert-command)
-    (local-set-key [f5] 'idlwave-shell-break-here)
-    (local-set-key [f6] 'idlwave-shell-clear-current-bp)
-
-    ;; Create a newline, indenting the original and new line.
-    ;; A similar function that does _not_ reindent the original
-    ;; line is on "\C-j" (The default for emacs programming modes).
-    (local-set-key "\n" 'idlwave-newline)
-    ;; (local-set-key "\C-j" 'idlwave-newline) ; My preference.
-
-    ;; Some personal abbreviations
-    (define-abbrev idlwave-mode-abbrev-table
-      (concat idlwave-abbrev-start-char "wb") "widget_base()"
-      (idlwave-keyword-abbrev 1))
-    (define-abbrev idlwave-mode-abbrev-table
-      (concat idlwave-abbrev-start-char "on") "obj_new()"
-      (idlwave-keyword-abbrev 1))
-    ))
-
-;;; Settings for IDLWAVE SHELL mode
-
-(setq idlwave-shell-overlay-arrow "=>")        ; default is ">"
-(setq idlwave-shell-use-dedicated-frame t)     ; Make a dedicated frame
-(setq idlwave-shell-prompt-pattern "^WAVE> ")  ; default is "^IDL> "
-(setq idlwave-shell-explicit-file-name "wave")
-(setq idlwave-shell-process-name "wave")
-(setq idlwave-shell-use-toolbar nil)           ; No toolbar
-
-;; Most shell interaction settings can be done from the shell-mode-hook.
-(add-hook 'idlwave-shell-mode-hook
-          (lambda ()
-            ;; Set up some custom key and mouse examine commands
-            (idlwave-shell-define-key-both [s-down-mouse-2]
-                                 (idlwave-shell-mouse-examine
-                                  "print, size(___,/DIMENSIONS)"))
-            (idlwave-shell-define-key-both [f9] (idlwave-shell-examine
-                                       "print, size(___,/DIMENSIONS)"))
-            (idlwave-shell-define-key-both [f10] (idlwave-shell-examine
-                                        "print,size(___,/TNAME)"))
-            (idlwave-shell-define-key-both [f11] (idlwave-shell-examine
-                                        "help,___,/STRUCTURE"))))
-@end example
-
-@html
-<A NAME="WINDOWS_MAC"></A>
-@end html
-@node Windows and macOS
-@appendix Windows and macOS
-@cindex Windows
-@cindex macOS
-
-IDLWAVE was developed on a UNIX system.  However, thanks to the
-portability of Emacs, much of IDLWAVE does also work under different
-operating systems like Windows (with NTEmacs).
-
-The only real problem is that there is no command-line version of IDL
-for Windows with which IDLWAVE can interact.  As a
-result, the IDLWAVE Shell does not work and you have to rely on IDLDE
-to run and debug your programs.  However, editing IDL source files
-with Emacs/IDLWAVE works with all bells and whistles, including
-routine info, completion and fast online help.  Only a small amount of
-additional information must be specified in your @file{.emacs} file:
-the path names which, on a UNIX system, are automatically gathered by
-talking to the IDL program.
-
-Here is an example of the additional configuration needed for a Windows
-system.  I am assuming that IDLWAVE has been installed in
-@w{@samp{C:\Program Files\IDLWAVE}} and that IDL is installed in
-@w{@samp{C:\RSI\IDL63}}.
-
-@lisp
-;; location of the lisp files (only needed if IDLWAVE is not part of
-;; your default X/Emacs installation)
-(setq load-path (cons "c:/program files/IDLWAVE" load-path))
-
-;; The location of the IDL library directories, both standard,  and your own.
-;; note that the initial "+" expands the path recursively
-(setq idlwave-library-path
-        '("+c:/RSI/IDL63/lib/" "+c:/path/to/my/idllibs" ))
-
-;; location of the IDL system directory (try "print,!DIR")
-(setq idlwave-system-directory "c:/RSI/IDL63/")
-
-@end lisp
-
-@noindent Furthermore, Windows sometimes tries to outsmart you; make
-sure you check the following things:
-
-@itemize @bullet
-@item When you download the IDLWAVE distribution, make sure you save the
-file under the names @file{idlwave.tar.gz}.
-@item M-@key{TAB} switches among running programs---use @key{ESC}-@key{TAB}
-instead.
-@item Other issues as yet unnamed...
-@end itemize
-
-Windows users who'd like to make use of IDLWAVE's context-aware HTML
-help can skip the browser and use the HTMLHelp functionality directly.
-@xref{Help with HTML Documentation}.
-
-@html
-<A NAME="TROUBLE"></A>
-@end html
-@node Troubleshooting
-@appendix Troubleshooting
-@cindex Troubleshooting
-
-Although IDLWAVE usually installs and works without difficulty, a few
-common problems and their solutions are documented below.
-
-@enumerate
-
-@item @strong{Whenever an IDL error occurs or a breakpoint is hit, I get
-errors or strange behavior when I try to type anything into some of my
-IDLWAVE buffers.}
-
-This is a @emph{feature}, not an error.  You're in @emph{Electric
-Debug Mode} (@pxref{Electric Debug Mode}).  You should see
-@code{*Debugging*} in the mode-line.  The buffer is read-only and all
-debugging and examination commands are available as single keystrokes;
-@kbd{C-?} lists these shortcuts.  Use @kbd{q} to quit the mode, and
-customize the variable @code{idlwave-shell-automatic-electric-debug}
-if you prefer not to enter electric debug on breakpoints@dots{} but
-you really should try it before you disable it!  You can also
-customize this variable to enter debug mode when errors are
-encountered.
-
-@item @strong{I get errors like @samp{Searching for program: no such
-file or directory, idl} when attempting to start the IDL shell.}
-
-IDLWAVE needs to know where IDL is in order to run it as a process.
-By default, it attempts to invoke it simply as @samp{idl}, which
-presumes such an executable is on your search path.  You need to
-ensure @samp{idl} is on your @samp{$PATH}, or specify the full
-pathname to the idl program with the variable
-@code{idlwave-shell-explicit-file-name}.  Note that you may need to
-set your shell search path in two places when running Emacs as an Aqua
-application with macOS; see the next topic.
-
-@item @strong{IDLWAVE is disregarding my @samp{IDL_PATH} which I set
-under macOS}
-
-If you run Emacs directly as an Aqua application, rather than from the
-console shell, the environment is set not from your usual shell
-configuration files (e.g., @file{.cshrc}), but from the file
-@file{~/.MacOSX/environment.plist}.  Either include your path settings
-there, or start Emacs and IDLWAVE from the shell.
-
-@item @strong{@kbd{M-@key{TAB}} doesn't complete words, it switches
-windows on my desktop.}
-
-Your system is trapping @kbd{M-@key{TAB}} and using it for its own
-nefarious purposes: Emacs never sees the keystrokes.  On many Unix
-systems, you can reconfigure your window manager to use another key
-sequence for switching among windows.  Another option is to use the
-equivalent sequence @kbd{@key{ESC}-@key{TAB}}.
-
-@item @strong{When stopping at breakpoints or errors, IDLWAVE does not
-seem to highlight the relevant line in the source.}
-
-IDLWAVE scans for error and halt messages and highlights the stop
-location in the correct file.  However, if you've changed the system
-variable @samp{!ERROR_STATE.MSG_PREFIX}, it is unable to parse these
-message correctly.  Don't do that.
-
-@item @strong{IDLWAVE doesn't work correctly when using ENVI.}
-
-Though IDLWAVE was not written with ENVI in mind, it works just fine
-with it, as long as you update the prompt it's looking for (@samp{IDL>
-} by default).  You can do this with the variable
-@code{idlwave-shell-prompt-pattern} (@pxref{Starting the Shell}), e.g.,
-in your @file{.emacs}:
-
-@lisp
-(setq idlwave-shell-prompt-pattern "^\r? ?\\(ENVI\\|IDL\\)> ")
-@end lisp
-
-@item @strong{Attempts to set breakpoints fail: no breakpoint is
-indicated in the IDLWAVE buffer.}
-
-IDL changed its breakpoint reporting format starting with IDLv5.5.  The
-first version of IDLWAVE to support the new format is IDLWAVE v4.10.  If
-you have an older version and are using IDL >v5.5, you need to upgrade,
-and/or make sure your recent version of IDLWAVE is being found on the
-Emacs load-path (see the next entry).  You can list the version being
-used with @kbd{C-h v idlwave-mode-version @key{RET}}.
-
-@item @strong{I installed a new version of IDLWAVE, but the old
-version is still being used} or @strong{IDLWAVE works, but when I
-tried to install the optional modules @file{idlw-roprompt.el} or
-@file{idlw-complete-structtag}, I get errors like @samp{Cannot open
-load file}}.
-
-The problem is that your Emacs is not finding the version of IDLWAVE you
-installed.  Emacs might come with an older bundled copy of IDLWAVE
-which is likely what's being used instead.
-You need to make sure your Emacs @emph{load-path} contains the directory
-where IDLWAVE is installed (@file{/usr/local/share/emacs/site-lisp}, by
-default), @emph{before} Emacs's default search directories.  You can
-accomplish this by putting the following in your @file{.emacs}:
-
-@lisp
-(setq load-path (cons "/usr/local/share/emacs/site-lisp" load-path))
-@end lisp
-
-@noindent You can check on your load-path value using @kbd{C-h v
-load-path @key{RET}}, and @kbd{C-h m} in an IDLWAVE buffer should show
-you the version Emacs is using.
-
-@item @strong{IDLWAVE is screwing up the formatting of my @file{.idl} files.}
-
-Actually, this isn't IDLWAVE at all, but @samp{idl-mode}, an unrelated
-programming mode for CORBA's Interface Definition Language (you should
-see @samp{(IDL)}, not @samp{(IDLWAVE)} in the mode-line).  One
-solution: don't name your file @file{.idl}, but rather @file{.pro}.
-Another solution: make sure @file{.idl} files load IDLWAVE instead of
-@samp{idl-mode} by adding the following to your @file{.emacs}:
-
-@lisp
-(setcdr (rassoc 'idl-mode auto-mode-alist) 'idlwave-mode)
-@end lisp
-
-@item @strong{The routine info for my local routines is out of date!}
-
-IDLWAVE collects routine info from various locations (@pxref{Routine
-Information Sources}).  Routines in files visited in a buffer or
-compiled in the shell should be up to date.  For other routines, the
-information is only as current as the most recent scan.  If you have a
-rapidly changing set of routines, and you'd like the latest routine
-information to be available for it, one powerful technique is to make
-use of the library catalog tool, @samp{idlwave_catalog}.  Simply add a
-line to your @samp{cron} file (@samp{crontab -e} will let you edit this
-on some systems), like this
-
-@example
-45 3 * * 1-5 (cd /path/to/myidllib; /path/to/idlwave_catalog MyLib)
-@end example
-
-@noindent where @samp{MyLib} is the name of your library.  This will
-rescan all @file{.pro} files at or below @file{/path/to/myidllib} every
-week night at 3:45am.  You can even scan site-wide libraries with this
-method, and the most recent information will be available to all users.
-Since the scanning is very fast, there is very little impact.
-
-@item @strong{All the Greek-font characters in the HTML help are
-displayed as Latin characters!}
-
-Unfortunately, the HTMLHelp files RSI provides attempt to switch to
-@samp{Symbol} font to display Greek characters, which is not really an
-permitted method for doing this in HTML@.  There is a "workaround" for
-some browsers: @xref{HTML Help Browser Tips}.
-
-@item @strong{In the shell, my long commands are truncated at 256 characters!}
-
-This actually happens when running IDL in an XTerm as well.  There are
-a couple of workarounds: @code{define_key,/control,'^d'} (e.g., in
-your @file{$IDL_STARTUP} file) will disable the @samp{EOF} character
-and give you a 512 character limit.  You won't be able to use
-@kbd{C-d} to quit the shell, however.  Another possibility is
-@code{!EDIT_INPUT=0}, which gives you an @emph{infinite} limit (OK, a
-memory-bounded limit), but disables the processing of background
-widget events (those with @code{/NO_BLOCK} passed to @code{XManager}).
-
-@item @strong{When I invoke IDL HTML help on a routine, the page which
-is loaded is one page off, e.g., for @code{CONVERT_COORD}, I get
-@code{CONTOUR}.}
-
-You have a mismatch between your help index and the HTML help package
-you downloaded.  You need to ensure you download a ``downgrade kit'' if
-you are using anything older than the latest HTML help package.  A new
-help package appears with each IDL release (assuming the documentation
-is updated).
-Starting with IDL 6.2, the HTML help and its catalog are
-distributed with IDL, and so should never be inconsistent.
-
-@end enumerate
-
-@node GNU Free Documentation License
-@appendix GNU Free Documentation License
-@include doclicense.texi
-
-@node Index
-@unnumbered Index
-@printindex cp
-
-@bye
index f9918fede38bf585b3ad98e4c43bdd1089a2695a..88287931cf7a6f257a1eb9a75d7bfb8b4eba16cb 100644 (file)
--- a/etc/TODO
+++ b/etc/TODO
@@ -39,11 +39,6 @@ is not always true.
 We need to figure out how to best include GNU ELPA packages in the
 Emacs tarball before doing any of the items below.
 
-*** Move idlwave to elpa.gnu.org
-Need to sync up the Emacs and external versions.
-See <https://lists.gnu.org/r/emacs-devel/2014-07/msg00008.html>
-<https://debbugs.gnu.org/39992>
-
 *** Move Org mode to elpa.gnu.org
 See <https://lists.gnu.org/r/emacs-devel/2014-08/msg00300.html>
 <https://lists.gnu.org/r/emacs-devel/2014-11/msg00257.html>
index 730026e925fac1b57b46dbe819f015a4455b0ffe..10c8999b3ef95274c9c36e9d10e377f4d78953b7 100644 (file)
@@ -3088,8 +3088,6 @@ since only a single case-insensitive search through the alist is made."
      ;; Anyway, the following extensions are supported by gfortran.
      ("\\.f9[05]\\'" . f90-mode)
      ("\\.f0[38]\\'" . f90-mode)
-     ("\\.indent\\.pro\\'" . fundamental-mode) ; to avoid idlwave-mode
-     ("\\.\\(pro\\|PRO\\)\\'" . idlwave-mode)
      ("\\.prolog\\'" . prolog-mode)
      ("\\.tar\\'" . tar-mode)
      ;; The list of archive file extensions should be in sync with
index 6926d524b82da09ce120bc7131570f842b307ca3..392d9da71e69706f4f834848c2d2c8b6d4ba3175 100644 (file)
@@ -1063,7 +1063,6 @@ Return nil if there is nothing appropriate in the buffer near point."
    ("forms" "Index")
    ("gnus" "Index")
    ("htmlfontify" "Functions" "Variables & Customization")
-   ("idlwave" "Index")
    ("ido" "Variable Index" "Function Index")
    ("info" "Index")
    ("mairix" "(mairix-el)Variable Index" "(mairix-el)Function Index")
index 858a9cd173857020640f7aa4eadedb9d2ce887a5..d199918bc1733ffcb65dd4c2456302cf99b17b4e 100644 (file)
@@ -218,7 +218,7 @@ These directories are searched after those in `Info-directory-list'."
       "ede" "ediff" "edt" "efaq" "efaq-w32" "eglot" "eieio"
       "eintr" "elisp" "emacs" "emacs-gnutls" "emacs-mime" "epa" "erc"
       "ert" "eshell" "eudc" "eww" "flymake" "forms" "gnus"
-      "htmlfontify" "idlwave" "ido" "info" "mairix-el" "message"
+      "htmlfontify" "ido" "info" "mairix-el" "message"
       "mh-e" "modus-themes" "newsticker" "nxml-mode" "octave-mode"
       "org" "pcl-cvs" "pgg" "rcirc" "reftex" "remember" "sasl" "sc"
       "semantic" "ses" "sieve" "smtpmail" "speedbar" "srecode"
@@ -4728,7 +4728,7 @@ Advanced commands:
 \f
 (defvar Info-file-list-for-emacs
   '("ediff" "eudc" "forms" "gnus" "info" ("Info" . "info")
-    "sc" "message" ("dired" . "dired-x") "viper" "idlwave"
+    "sc" "message" ("dired" . "dired-x") "viper"
     ("c" . "ccmode") ("c++" . "ccmode") ("objc" . "ccmode")
     ("java" . "ccmode") ("idl" . "ccmode") ("pike" . "ccmode")
     ("skeleton" . "autotype") ("auto-insert" . "autotype")
index ff9156c5296c22c88d6a28dfeb70a72e6267ebfb..282d528473db22d05f1b0bf6ce18502fa5c6350b 100644 (file)
@@ -131,7 +131,7 @@ If LINK is not an info link then DESC is returned."
   '("ada-mode" "auth" "autotype" "bovine" "calc" "ccmode" "cl" "dbus" "dired-x"
     "ede" "ediff" "efaq-w32" "efaq" "eglot" "eieio" "eintr"
     "elisp" "emacs-gnutls" "emacs-mime" "emacs" "epa" "erc" "ert" "eshell"
-    "eudc" "eww" "flymake" "forms" "gnus" "htmlfontify" "idlwave" "ido" "info"
+    "eudc" "eww" "flymake" "forms" "gnus" "htmlfontify" "ido" "info"
     "mairix-el" "message" "modus-themes" "newsticker" "nxml-mode" "octave-mode"
     "org" "pcl-cvs" "pgg" "rcirc" "reftex" "remember" "sasl" "sc" "semantic"
     "ses" "sieve" "smtpmail" "speedbar" "srecode" "todo-mode" "tramp" "transient"
diff --git a/lisp/progmodes/idlw-complete-structtag.el b/lisp/progmodes/idlw-complete-structtag.el
deleted file mode 100644 (file)
index bcc2ee2..0000000
+++ /dev/null
@@ -1,243 +0,0 @@
-;;; idlw-complete-structtag.el --- Completion of structure tags.  -*- lexical-binding: t; -*-
-
-;; Copyright (C) 2001-2024 Free Software Foundation, Inc.
-
-;; Author: Carsten Dominik <dominik@astro.uva.nl>
-;; Maintainer: emacs-devel@gnu.org
-;; Old-Version: 1.2
-;; Keywords: languages
-;; Package: idlwave
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software: you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, either version 3 of the License, or
-;; (at your option) any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; Completion of structure tags can be done automatically in the
-;; shell, since the list of tags can be determined dynamically through
-;; interaction with IDL.
-
-;; Completion of structure tags in a source buffer is highly ambiguous
-;; since you never know what kind of structure a variable will hold at
-;; runtime.  To make this feature useful in source buffers, we need a
-;; special assumption/convention.  We will assume that the structure is
-;; defined in the same buffer and directly assigned to the correct
-;; variable.  This is mainly useful for applications in which there is one
-;; main structure which contains a large amount of information (and many
-;; tags).  For example, many widget applications define a "state" structure
-;; that contains all important data about the application.  The different
-;; routines called by the event handler then use this structure.  If you
-;; use the same variable name for this structure throughout your
-;; application (a good idea for many reasons), IDLWAVE can support
-;; completion for its tags.
-;;
-;; This file is a completion plugin which implements this kind of
-;; completion.  It is also an example which shows how completion plugins
-;; should be programmed.
-;;
-;; New versions of IDLWAVE, documentation, and more information available
-;; from:
-;;                 https://github.com/jdtsmith/idlwave
-;;
-;; INSTALLATION
-;; ============
-;; Load it with the following line in your init file:
-;;
-;;   (with-eval-after-load 'idlwave
-;;     (require 'idlw-complete-structtag))
-;;
-;; DESCRIPTION
-;; ===========
-;; Suppose your IDL program contains something like
-;;
-;;     myvar = state.a*
-;;
-;; where the star marks the cursor position.  If you now press the
-;; completion key M-TAB, IDLWAVE searches the current file for a
-;; structure definition
-;;
-;;   state = {tag1:val1, tag2:val2, ...}
-;;
-;; and offers the tags for completion.
-;;
-;; In the idlwave shell, idlwave sends a "print,tag_names()" for the
-;; variable to idl and determines the current tag list dynamically.
-;;
-;; Notes
-;; -----
-;;  - The structure definition assignment "state = {...}" must use the
-;;    same variable name as the completion location "state.*".
-;;  - The structure definition must be in the same file.
-;;  - The structure definition is searched backwards and then forward
-;;    from the current position, until a definition with tags is found.
-;;  - The file is parsed again for each new completion variable and location.
-;;  - You can force an update of the tag list with the usual command
-;;    to update routine info in IDLWAVE: C-c C-i
-
-;;; Code:
-
-(require 'idlwave)
-
-(declare-function idlwave-shell-buffer "idlw-shell")
-
-;; Some variables to identify the previously used structure
-(defvar idlwave-current-tags-var nil)
-(defvar idlwave-current-tags-buffer nil)
-(defvar idlwave-current-tags-completion-pos nil)
-
-;; The tag list used for completion will be stored in the following vars
-(defvar idlwave-current-struct-tags nil)
-(defvar idlwave-sint-structtags nil)
-
-;; Create the sintern type for structure talks
-(idlwave-new-sintern-type structtag)
-
-;; Hook the plugin into idlwave
-(add-hook 'idlwave-complete-functions #'idlwave-complete-structure-tag)
-(add-hook 'idlwave-update-rinfo-hook #'idlwave-structtag-reset)
-
-;;; The main code follows below
-(defvar idlwave-completion-help-info)
-(defun idlwave-complete-structure-tag ()
-  "Complete a structure tag.
-This works by looking in the current file for a structure assignment to a
-variable with the same name and takes the tags from there.  Quite useful
-for big structures like the state variables of a widget application.
-
-In the idlwave shell, the current content of the variable is used to get
-an up-to-date completion list."
-  (interactive)
-  (let ((pos (point))
-        start
-       (case-fold-search t))
-    (if (save-excursion
-         ;; Check if the context is right.
-          ;; In the shell, this could be extended to expressions like
-          ;; x[i+4].name.g*.  But it is complicated because we would have
-          ;; to really parse this expression.  For now, we allow only
-          ;; substructures, like "aaa.bbb.ccc.ddd"
-         (skip-chars-backward "a-zA-Z0-9._$")
-          (setq start (point)) ;; remember the start of the completion pos.
-         (and (< (point) pos)
-              (not (equal (char-before) ?!)) ; no sysvars
-              (looking-at "\\([a-zA-Z][.a-zA-Z0-9_]*\\)\\.")
-              (>= pos (match-end 0))
-              (not (string= (downcase (match-string 1)) "self"))))
-       (let* ((var (downcase (match-string 1))))
-         ;; Check if we need to update the "current" structure.  Basically we
-          ;; do it always, except for subsequent completions at the same
-          ;; spot, to save a bit of time.  Implementation:  We require
-          ;; an update if
-          ;; - the variable is different or
-          ;; - the buffer is different or
-          ;; - we are completing at a different position
-         (if (or (not (string= var (or idlwave-current-tags-var "@")))
-                 (not (eq (current-buffer) idlwave-current-tags-buffer))
-                  (not (equal start idlwave-current-tags-completion-pos)))
-             (idlwave-prepare-structure-tag-completion var))
-          (setq idlwave-current-tags-completion-pos start)
-         (setq idlwave-completion-help-info
-               (list 'idlwave-complete-structure-tag-help))
-         (idlwave-complete-in-buffer 'structtag 'structtag
-                                     idlwave-current-struct-tags nil
-                                     "Select a structure tag" "structure tag")
-         t) ; we did the completion: return t to skip other completions
-      nil))) ; return nil to allow looking for other ways to complete
-
-(defun idlwave-structtag-reset ()
-  "Force an update of the current structure tag list upon next use."
-  (setq idlwave-current-tags-buffer nil))
-
-(defvar idlwave-structtag-struct-location nil
-  "The location of the structure definition, for help display.")
-
-(defun idlwave-prepare-structure-tag-completion (var)
-  "Find and parse the tag list for structure tag completion."
-  ;; This works differently in source buffers and in the shell
-  (if (derived-mode-p 'idlwave-shell-mode)
-      ;; OK, we are in the shell, do it dynamically
-      (progn
-        (message "preparing shell tags")
-        ;; The following call puts the tags into `idlwave-current-struct-tags'
-        (idlwave-complete-structure-tag-query-shell var)
-        ;; initialize
-        (setq idlwave-sint-structtags nil
-              idlwave-current-tags-buffer (current-buffer)
-              idlwave-current-tags-var var
-              idlwave-structtag-struct-location (point)
-              idlwave-current-struct-tags
-              (mapcar (lambda (x)
-                        (list (idlwave-sintern-structtag x 'set)))
-                      idlwave-current-struct-tags))
-        (if (not idlwave-current-struct-tags)
-            (error "Cannot complete structure tags of variable %s" var)))
-    ;; Not the shell, so probably a source buffer.
-    (unless
-        (catch 'exit
-          (save-excursion
-            (goto-char (point-max))
-            ;; Find possible definitions of the structure.
-            (while (idlwave-find-structure-definition var nil 'all)
-              (let ((tags (idlwave-struct-tags)))
-                (when tags
-                  ;; initialize
-                  (setq idlwave-sint-structtags nil
-                        idlwave-current-tags-buffer (current-buffer)
-                        idlwave-current-tags-var var
-                        idlwave-structtag-struct-location (point)
-                        idlwave-current-struct-tags
-                        (mapcar (lambda (x)
-                                  (list (idlwave-sintern-structtag x 'set)))
-                                tags))
-                  (throw 'exit t))))))
-      (error "Cannot complete structure tags of variable %s" var))))
-
-(defun idlwave-complete-structure-tag-query-shell (var)
-  "Ask the shell for the tags of the structure in variable or expression VAR."
-  (idlwave-shell-send-command
-   (format "if size(%s,/TYPE) eq 8 then print,tag_names(%s)" var var)
-   'idlwave-complete-structure-tag-get-tags-from-help
-   'hide 'wait))
-
-(defvar idlwave-shell-prompt-pattern)
-(defvar idlwave-shell-command-output)
-(defun idlwave-complete-structure-tag-get-tags-from-help ()
-  "Filter structure tag name output, result to `idlwave-current-struct-tags'."
-    (setq idlwave-current-struct-tags
-         (if (string-match (concat "tag_names(.*) *\n"
-                                   "\\(\\(.*[\r\n]?\\)*\\)"
-                                   "\\(" idlwave-shell-prompt-pattern "\\)")
-                           idlwave-shell-command-output)
-             (split-string (match-string 1 idlwave-shell-command-output)))))
-
-
-;; Fake help in the source buffer for structure tags.
-;; idlw-help-kwd is a global-variable (from idlwave-do-mouse-completion-help).
-(defvar idlw-help-kwd)
-(defvar idlwave-help-do-struct-tag)
-(defun idlwave-complete-structure-tag-help (mode word)
-  (cond
-   ((eq mode 'test)
-    ;; fontify only in source buffers, not in the shell.
-    (not (equal idlwave-current-tags-buffer
-                (get-buffer (idlwave-shell-buffer)))))
-   ((eq mode 'set)
-    (setq idlw-help-kwd word
-         idlwave-help-do-struct-tag idlwave-structtag-struct-location))
-   (t (error "This should not happen"))))
-
-(provide 'idlw-complete-structtag)
-
-;;; idlw-complete-structtag.el ends here
diff --git a/lisp/progmodes/idlw-help.el b/lisp/progmodes/idlw-help.el
deleted file mode 100644 (file)
index c311e1c..0000000
+++ /dev/null
@@ -1,1357 +0,0 @@
-;;; idlw-help.el --- HTML Help code for IDLWAVE  -*- lexical-binding: t; -*-
-
-;; Copyright (C) 2000-2024 Free Software Foundation, Inc.
-;;
-;; Authors: JD Smith <jd.smith@utoledo.edu>
-;;          Carsten Dominik <dominik@science.uva.nl>
-;; Maintainer: emacs-devel@gnu.org
-;; Package: idlwave
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software: you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, either version 3 of the License, or
-;; (at your option) any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; The help link information for IDLWAVE's online help feature for
-;; system routines is extracted automatically from the IDL
-;; documentation, and is available, along with general routine
-;; information, in the file idlw-rinfo.el.  The HTML help file
-;; themselves are not distributable with Emacs, but are available,
-;; along with new versions of IDLWAVE, documentation, and more
-;; information, at:
-;;
-;;           https://github.com/jdtsmith/idlwave
-;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-\f
-
-;;; Code:
-
-(require 'browse-url)
-
-(defgroup idlwave-online-help nil
-  "Online Help options for IDLWAVE mode."
-  :group 'idlwave)
-
-(defcustom idlwave-html-help-pre-v6 nil
-  "Whether pre or post-v6.0 IDL help documents are being used."
-  :type 'boolean)
-
-(defvar idlwave-html-link-sep
-  (if idlwave-html-help-pre-v6 "#" "#wp"))
-
-(defcustom idlwave-html-system-help-location   "help/online_help/"
-  "The directory, relative to `idlwave-system-directory', where the IDL
-HTML help files live, for IDL 6.2 and later.  This location, if found,
-is used in preference to the old `idlwave-html-help-location'."
-  :type 'directory)
-
-(defcustom idlwave-html-help-location
-   (if (memq system-type '(ms-dos windows-nt))
-      nil
-    "/usr/local/etc/")
-  "The directory where the idl_html_help/ dir lives.
-Obsolete for IDL 6.2 or later (see `idlwave-html-system-help-location')."
-  :type 'directory)
-
-(defcustom idlwave-help-use-assistant t
-  "Whether to use the IDL Assistant as the help browser."
-  :type 'boolean)
-
-(defcustom idlwave-help-browser-function browse-url-browser-function
-  "Function to use to display HTML help.
-Defaults to `browse-url-browser-function', which see."
-  :type 'function)
-
-(defcustom idlwave-help-browser-generic-program browse-url-generic-program
-  "Program to run if using `browse-url-generic-program'."
-  :type '(choice (const nil) string))
-
-;; AFAICS, never used since it was introduced in 2004.
-(defcustom idlwave-help-browser-generic-args
-  (if (boundp 'browse-url-generic-args)
-      browse-url-generic-args "")
-  "Program args to use if using `browse-url-generic-program'."
-  :type '(repeat string))
-
-(defcustom idlwave-help-browser-is-local nil
-  "Whether the browser will display locally in an Emacs window.
-Several browsers run and/or display inside Emacs windows, but most are
-external programs.  If the browser name contains \"-w3\", it is
-assumed to be local to Emacs.  For other local browsers, this variable
-must be explicitly set non-nil in order for the variable
-`idlwave-help-use-dedicated-frame' to function."
-  :type 'boolean)
-
-(defcustom idlwave-help-use-dedicated-frame t
-  "Non-nil means, use a separate frame for Online Help if possible."
-  :type 'boolean)
-
-(defcustom idlwave-help-frame-parameters
-  '((height . 32) (unsplittable . t))
-  "The frame parameters for the special Online Help frame.
-See also `idlwave-help-use-dedicated-frame'.
-If you do not set the frame width here, the value specified in
-`idlw-help.el' will be used."
-  :type '(repeat
-         (cons symbol sexp)))
-
-(defcustom idlwave-max-popup-menu-items 20
-  "Maximum number of items per pane in popup menus.
-Currently only used for class selection during completion help."
-  :type 'integer)
-
-(defcustom idlwave-extra-help-function 'idlwave-help-with-source
-  "The function to call for online help if the normal help fails.
-Online help works only for system routines which are described in the
-IDL manuals.  A function may be specified to access help from other sources.
-
-The function must accept four arguments: NAME, TYPE, CLASS, KEYWORD.
-The Help buffer is current when this function is called, and the help
-text should be loaded into this buffer.  If help is found, the
-function should return the buffer position which should be used as
-`window-start' in the help window.  Also, the variable
-`idlwave-help-mode-line-indicator' should be set to a useful string,
-which will be displayed in the mode line of the help window.  If
-should also set the variable `idlwave-help-min-frame-width' to a
-positive integer.  IDLWAVE will ensure that the help frame is at least
-that many columns wide.  Failure to find help should be indicated by
-throwing an error.
-
-When this variable is non-nil, IDLWAVE will allow the mouse-3 help click
-for every routine and keyword, even though the item may not be highlighted
-in blue (indicating the availability of system documentation).
-
-The default value for this function is `idlwave-help-with-source' which
-loads the routine source file into the help buffer.  If you try to write
-a different function which accesses a special help file or so, it is
-probably a good idea to still call this function as a fallback."
-  :type 'symbol)
-
-(defcustom idlwave-help-fontify-source-code nil
-  "Non-nil means, fontify source code displayed as help like normal code."
-  :type 'boolean)
-
-(defcustom idlwave-help-source-try-header t
-  "Non-nil means, try to find help in routine header when displaying source.
-Routines which are not documented in the system manual use their source as
-help text.  When this variable is non-nil, we try to find a description of
-the help item in the first routine doclib header above the routine definition.
-If the variable is nil, or if we cannot find/parse the header, the routine
-definition is displayed instead."
-  :type 'boolean)
-
-
-(defcustom idlwave-help-doclib-name "name"
-  "A regexp for the heading word to search for in doclib headers
-which specifies the `name' section.  Can be used for localization
-support."
-  :type 'regexp)
-
-(defcustom idlwave-help-doclib-keyword "KEYWORD"
-  "A regexp for the heading word to search for in doclib headers
-which specifies the `keywords' section.  Can be used for localization
-support."
-  :type 'regexp)
-
-(defface idlwave-help-link
-  '((t :inherit link))
-  "Face for highlighting links into IDLWAVE online help.")
-
-(defvar idlwave-help-activate-links-aggressively nil
-  "Obsolete variable.")
-
-(defvar idlwave-completion-help-info)
-
-(defvar idlwave-help-frame nil
-  "The frame for display of IDL online help.")
-(defvar idlwave-help-frame-width 102
-  "The default width of the help frame.")
-
-(defvar idlwave-html-help-is-available nil
-  "Is the system online help text available?")
-
-(defvar idlwave-help-mode-line-indicator ""
-  "Used for the special mode line in the `idlwave-help-mode'.")
-
-(defvar idlwave-help-window-configuration nil)
-(defvar idlwave-help-special-topic-words nil) ; defined by get_rinfo
-
-;; Define the key bindings for the Help application
-
-(defvar idlwave-help-mode-map
-  (let ((map (make-sparse-keymap)))
-    (define-key map "q" #'idlwave-help-quit)
-    (define-key map "w" #'widen)
-    (define-key map "\C-m" (lambda (arg)
-                             (interactive "p")
-                             (scroll-up arg)))
-    (define-key map " " #'scroll-up-command)
-    (define-key map [?\S-\ ] #'scroll-down-command)
-    (define-key map [delete] #'scroll-down-command)
-    (define-key map "h" #'idlwave-help-find-header)
-    (define-key map "H" #'idlwave-help-find-first-header)
-    (define-key map "." #'idlwave-help-toggle-header-match-and-def)
-    (define-key map "F" #'idlwave-help-fontify)
-    (define-key map "\M-?" #'idlwave-help-return-to-calling-frame)
-    (define-key map "x" #'idlwave-help-return-to-calling-frame)
-    map)
-  "The keymap used in `idlwave-help-mode'.")
-
-;; Define the menu for the Help application
-
-(easy-menu-define idlwave-help-menu idlwave-help-mode-map
-  "Menu for Help IDLWAVE system."
-  '("IDLHelp"
-    ["Definition <-> Help Text" idlwave-help-toggle-header-match-and-def t]
-    ["Find DocLib Header" idlwave-help-find-header t]
-    ["Find First DocLib Header" idlwave-help-find-first-header t]
-    ["Fontify help buffer" idlwave-help-fontify t]
-    "--"
-    ["Quit" idlwave-help-quit t]))
-
-(defvar idlwave-help-def-pos)
-(defvar idlwave-help-args)
-(defvar idlwave-help-in-header)
-(declare-function idlwave-prepare-structure-tag-completion "idlw-complete-structtag")
-(declare-function idlwave-all-method-classes "idlwave")
-(declare-function idlwave-all-method-keyword-classes "idlwave")
-(declare-function idlwave-beginning-of-statement "idlwave")
-(declare-function idlwave-best-rinfo-assoc "idlwave")
-(declare-function idlwave-class-found-in "idlwave")
-(declare-function idlwave-class-or-superclass-with-tag "idlwave")
-(declare-function idlwave-completing-read "idlwave")
-(declare-function idlwave-current-routine "idlwave")
-(declare-function idlwave-downcase-safe "idlwave")
-(declare-function idlwave-entry-find-keyword "idlwave")
-(declare-function idlwave-expand-keyword "idlwave")
-(declare-function idlwave-find-class-definition "idlwave")
-(declare-function idlwave-find-inherited-class "idlwave")
-(declare-function idlwave-find-struct-tag "idlwave")
-(declare-function idlwave-in-quote "idlwave")
-(declare-function idlwave-make-full-name "idlwave")
-(declare-function idlwave-members-only "idlwave")
-(declare-function idlwave-popup-select "idlwave")
-(declare-function idlwave-routine-source-file "idlwave")
-(declare-function idlwave-routines "idlwave")
-(declare-function idlwave-sintern-class "idlwave")
-(declare-function idlwave-sintern-keyword "idlwave")
-(declare-function idlwave-sintern-method "idlwave")
-(declare-function idlwave-sintern-routine-or-method "idlwave")
-(declare-function idlwave-sintern-sysvar "idlwave" t t);idlwave-new-sintern-type
-(declare-function idlwave-sintern-sysvartag "idlwave" t t)
-(declare-function idlwave-substitute-link-target "idlwave")
-(declare-function idlwave-sys-dir "idlwave")
-(declare-function idlwave-this-word "idlwave")
-(declare-function idlwave-what-module-find-class "idlwave")
-(declare-function idlwave-where "idlwave")
-
-(define-derived-mode idlwave-help-mode special-mode "IDLWAVE Help"
-  "Major mode for displaying IDL Help.
-
-This is a VIEW mode for the ASCII version of IDL Help files,
-with some extras.  Its main purpose is speed - so don't
-expect a fully hyper-linked help.
-
-Scrolling:          SPC  DEL  RET
-Text Searches:      Inside Topic: Use Emacs search functions
-Exit:               [q]uit or mouse button 3 will kill the frame
-
-When the help text is a source file, the following commands are available
-
-Fontification:      [F]ontify the buffer like source code
-Jump:               [h] to function doclib header
-                    [H] to file doclib header
-                    [.] back and forth between header and definition
-
-Here are all keybindings.
-\\{idlwave-help-mode-map}"
-  (buffer-disable-undo)
-  (setq truncate-lines t)
-  (setq case-fold-search t)
-  (setq mode-line-format
-       (list ""
-             'mode-line-modified
-             'mode-line-buffer-identification
-             ":  " 'idlwave-help-mode-line-indicator
-             " -%-"))
-  (setq buffer-read-only t)
-  (set (make-local-variable 'idlwave-help-def-pos) nil)
-  (set (make-local-variable 'idlwave-help-args) nil)
-  (set (make-local-variable 'idlwave-help-in-header) nil))
-
-(defun idlwave-html-help-location ()
-  "Return the help directory where HTML files are, or nil if that is unknown."
-  (let ((syshelp-dir (expand-file-name
-                     idlwave-html-system-help-location (idlwave-sys-dir)))
-       (help-dir (or (and (stringp idlwave-html-help-location)
-                          (> (length idlwave-html-help-location) 0)
-                          idlwave-html-help-location)
-                     (getenv "IDLWAVE_HELP_LOCATION"))))
-    (if (and syshelp-dir (file-directory-p syshelp-dir))
-       syshelp-dir
-      (if help-dir
-         (progn
-           (setq help-dir (expand-file-name "idl_html_help" help-dir))
-           (if (file-directory-p help-dir) help-dir))))))
-
-(defvar idlwave-help-assistant-available nil)
-
-(defun idlwave-help-check-locations ()
-  ;; Check help locations and assistant.
-  (let ((sys-dir (idlwave-sys-dir))
-       (help-loc (idlwave-html-help-location)))
-    (if (or (not (file-directory-p sys-dir))
-           (not help-loc)
-           (not (file-directory-p help-loc)))
-       (message
-        "HTML help location not found: try setting `idlwave-system-directory' and/or `idlwave-html-help-location'."))
-    ;; see if we have the assistant
-    (when (and idlwave-help-use-assistant
-              (not (eq (idlwave-help-assistant-available) t)))
-      (message "Cannot locate IDL Assistant, enabling default browser.")
-      (setq idlwave-help-use-assistant nil))))
-
-
-(defvar idlwave-current-obj_new-class)
-(defvar idlwave-help-diagnostics)
-(defvar idlwave-experimental)
-(defvar idlwave-last-context-help-pos)
-(defun idlwave-do-context-help (&optional arg)
-  "Wrapper around the call to `idlwave-do-context-help1'.
-It collects and prints the diagnostics messages."
-  (let ((marker (list (current-buffer) (point)))
-       (idlwave-help-diagnostics nil))
-    ;; Check for frame switching.  When the command is invoked twice
-    ;; at the same position, we try to switch to the help frame
-    ;; FIXME:  Frame switching works only on XEmacs
-    (if (and idlwave-experimental
-            (equal last-command this-command)
-            (equal idlwave-last-context-help-pos marker))
-       (idlwave-help-select-help-frame)
-      ;; Do the real thing.
-      (setq idlwave-last-context-help-pos marker)
-      (idlwave-do-context-help1 arg)
-      (if idlwave-help-diagnostics
-         (message "%s" (mapconcat #'identity
-                                  (nreverse idlwave-help-diagnostics)
-                                  "; "))))))
-
-(defvar idlwave-help-do-class-struct-tag nil)
-(defvar idlwave-structtag-struct-location)
-(defvar idlwave-help-do-struct-tag nil)
-(defvar idlwave-system-variables-alist)
-(defvar idlwave-executive-commands-alist)
-(defvar idlwave-system-class-info)
-(defvar idlwave-query-class)
-(defvar idlwave-force-class-query)
-(defvar idlw-help-name)
-(defvar idlw-help-kwd)
-(defvar idlw-help-link)
-
-(defun idlwave-do-context-help1 (&optional arg)
-  "The work-horse version of `idlwave-context-help', which see."
-  (save-excursion
-    (if (equal (char-after) ?/)
-       (forward-char 1)
-      (if (equal (char-before) ?=)
-         (backward-char 1)))
-    (let* ((idlwave-query-class nil)
-          (idlwave-force-class-query (equal arg '(4)))
-          (chars "a-zA-Z0-9_$.!")
-          (beg (save-excursion (skip-chars-backward chars) (point)))
-          (end (save-excursion (skip-chars-forward chars) (point)))
-          (this-word (buffer-substring-no-properties beg end))
-          (st-ass (assoc-string this-word
-                                idlwave-help-special-topic-words t))
-          (classtag (and (string-match "self\\." this-word)
-                         (< beg (- end 4))))
-          (structtag (and (fboundp 'idlwave-complete-structure-tag)
-                          (string-match "\\`\\([^.]+\\)\\." this-word)
-                          (< beg (- end 4))))
-          module keyword cw mod1 mod2 mod3)
-      (if (or arg
-             (and (not classtag)
-                  (not structtag)
-                  (not (member (string-to-char this-word) '(?! ?.)))))
-         ;; Need the module information
-         (progn
-           ;; MODULE is (name type class), for this or any inheriting class
-           (setq module (idlwave-what-module-find-class)
-                 cw (nth 2 (idlwave-where))) ;what would we complete here?
-           ;; Correct for OBJ_NEW, we may need an INIT method instead.
-           (if (equal (idlwave-downcase-safe (car module)) "obj_new")
-               (let* ((bos (save-excursion (idlwave-beginning-of-statement)
-                                           (point)))
-                      (str (buffer-substring bos (point))))
-                 (if (string-match "OBJ_NEW([ \t]*['\"]\\([a-zA-Z][a-zA-Z0-9$_]+\\)['\"]" str)
-                     (setq module (list "init" 'fun (match-string 1 str))
-                           idlwave-current-obj_new-class (match-string 1 str))
-                   )))))
-      (cond
-       (arg (setq mod1 module))
-
-       ;; A special topic -- only system help
-       ((and st-ass (not (memq cw '(function-keyword procedure-keyword))))
-       (setq mod1 (list (cdr st-ass))))
-
-       ;; A system variable -- only system help
-       ((string-match
-        "\\`!\\([a-zA-Z0-9_]+\\)\\(\\.\\([A-Za-z0-9_]+\\)\\)?"
-        this-word)
-       (let* ((word  (match-string-no-properties 1 this-word))
-              (entry (assq (idlwave-sintern-sysvar word)
-                           idlwave-system-variables-alist))
-              (tag (match-string-no-properties 3 this-word))
-              (tag-target (if tag
-                              (cdr
-                               (assq (idlwave-sintern-sysvartag tag)
-                                     (cdr (assq 'tags entry))))))
-              (link (nth 1 (assq 'link entry))))
-         (if tag-target
-             (setq link (idlwave-substitute-link-target link
-                                                        tag-target)))
-         (setq mod1 (list link))))
-
-       ;; An executive command -- only system help
-       ((string-match "^\\.\\([A-Z_]+\\)" this-word)
-       (let* ((word  (match-string 1 this-word))
-              (link  (cdr (assoc-string
-                           word
-                           idlwave-executive-commands-alist t))))
-         (setq mod1 (list link))))
-
-       ;; A class -- system OR in-text help (via class__define).
-       ((and (eq cw 'class)
-            (or (idlwave-in-quote)  ; e.g. obj_new
-                (re-search-backward "\\<inherits[ \t]+[A-Za-z0-9_]*\\="
-                                    (max (point-min) (- (point) 40)) t)))
-       ;; Class completion inside string delimiters must be
-       ;; the class inside OBJ_NEW.
-       (let* ((entry  (assq
-                       (idlwave-sintern-class this-word)
-                       idlwave-system-class-info))
-              (name   (concat (downcase this-word) "__define"))
-              (link   (nth 1 (assq 'link entry))))
-         (setq mod1 (list link name 'pro))))
-
-       ;; A class structure tag (self.BLAH) -- only in-text help available
-       (classtag
-       (let ((tag (substring this-word (match-end 0)))
-             class-with found-in)
-         (when (setq class-with
-                     (idlwave-class-or-superclass-with-tag
-                      (nth 2 (idlwave-current-routine))
-                      tag))
-           (setq found-in (idlwave-class-found-in class-with))
-           (if (assq (idlwave-sintern-class class-with)
-                     idlwave-system-class-info)
-               (error "No help available for system class tags"))
-           (setq idlwave-help-do-class-struct-tag t)
-           (setq mod1 (list nil
-                            (if found-in
-                                (cons (concat found-in "__define") class-with)
-                              (concat class-with "__define"))
-                            'pro
-                            nil ; no class.... it's a procedure!
-                            tag)))))
-
-       ;; A regular structure tag -- only in text, and if
-       ;; optional `complete-structtag' loaded.
-       (structtag
-       (let ((var (match-string 1 this-word))
-             (tag (substring this-word (match-end 0))))
-         ;; Check if we need to update the "current" structure
-         (idlwave-prepare-structure-tag-completion var)
-         (setq idlwave-help-do-struct-tag
-               idlwave-structtag-struct-location
-               mod1 (list nil nil nil nil tag))))
-
-       ;; A routine keyword -- in text or system help
-       ((and (memq cw '(function-keyword procedure-keyword))
-            (stringp this-word)
-            (string-match "\\S-" this-word)
-            (not (string-search "!" this-word)))
-       (cond ((or (= (char-before beg) ?/)
-                  (save-excursion (goto-char end)
-                                  (looking-at "[ \t]*=")))
-              ;; Certainly a keyword. Check for abbreviation etc.
-              (setq keyword (idlwave-expand-keyword this-word module))
-              (cond
-               ((null keyword)
-                (idlwave-help-diagnostics
-                 (format "%s does not accept `%s' kwd"
-                         (idlwave-make-full-name (nth 2 module)
-                                                 (car module))
-                         (upcase this-word))
-                 'ding))
-               ((consp keyword)
-                (idlwave-help-diagnostics
-                 (format "%d matches for kwd abbrev `%s'"
-                         (length keyword) this-word)
-                 'ding)
-                ;; We continue anyway with the first match...
-                (setq keyword (car keyword))))
-              ;; Keyword, or just module
-              (setq mod1 (append (list t) module (list keyword)))
-              (setq mod2 (append (list t) module)))
-             ((equal (char-after end) ?\()
-              ;; A function - what-module will have caught this
-              (setq mod1 (append (list t) module)))
-             (t
-              ;; undecided - try function, keyword, then enclosing mod.
-              ;; Check for keyword abbreviations, but do not report
-              ;; errors, because it might be something else.
-              ;; FIXME: is this a good way to handle this?
-              (setq keyword (idlwave-expand-keyword this-word module))
-              (if (consp keyword) (setq keyword (car keyword)))
-              (setq mod1 (append (list t) module (list keyword))
-                    mod2 (list t this-word 'fun nil)
-                    mod3 (append (list t) module)))))
-
-       ;; Everything else
-       (t
-       (setq mod1 (append (list t) module))))
-      (if mod3
-         (condition-case nil
-             (apply #'idlwave-online-help mod1)
-           (error (condition-case nil
-                      (apply #'idlwave-online-help mod2)
-                    (error (apply #'idlwave-online-help mod3)))))
-       (if mod2
-           (condition-case nil
-               (apply #'idlwave-online-help mod1)
-             (error (apply #'idlwave-online-help mod2)))
-         (if mod1
-             (apply #'idlwave-online-help mod1)
-           (error "Don't know which item to show help for")))))))
-
-(defun idlwave-do-mouse-completion-help (ev)
-  "Display online help on an item in the *Completions* buffer.
-Needs additional info stored in global `idlwave-completion-help-info'."
-  (let* ((cw (selected-window))
-        (info idlwave-completion-help-info) ; global passed in
-        (what (nth 0 info))
-        (idlw-help-name (nth 1 info))
-        (type (nth 2 info))
-        (class (nth 3 info))
-        (need-class class)
-        (idlw-help-kwd (nth 4 info))
-        (sclasses (nth 5 info))
-        word idlw-help-link)
-    (mouse-set-point ev)
-
-
-    ;; See if we can also find help somewhere, e.g. for multiple classes
-    (setq word (idlwave-this-word))
-    (if (string= word "")
-       (error "No help item selected"))
-    (setq idlw-help-link (get-text-property 0 'link word))
-    (select-window cw)
-    (cond
-     ;; Routine name
-     ((memq what '(procedure function routine))
-      (setq idlw-help-name word)
-      (if (or (eq class t)
-             (and (stringp class) sclasses))
-         (let* ((classes (idlwave-all-method-classes
-                          (idlwave-sintern-method idlw-help-name)
-                          type)))
-           (setq idlw-help-link t)             ; No specific link valid yet
-           (if sclasses
-               (setq classes (idlwave-members-only
-                              classes (cons class sclasses))))
-           (setq class (idlwave-popup-select ev classes
-                                             "Select Class" 'sort))))
-
-      ;; XXX is this necessary, given all-method-classes?
-      (if (stringp class)
-         (setq class (idlwave-find-inherited-class
-                      (idlwave-sintern-routine-or-method idlw-help-name class)
-                      type (idlwave-sintern-class class)))))
-
-     ;; Keyword
-     ((eq what 'keyword)
-      (setq idlw-help-kwd word)
-      (if (or (eq class t)
-             (and (stringp class) sclasses))
-         (let ((classes  (idlwave-all-method-keyword-classes
-                          (idlwave-sintern-method idlw-help-name)
-                          (idlwave-sintern-keyword idlw-help-kwd)
-                          type)))
-           (setq idlw-help-link t) ; Link can't be correct yet
-           (if sclasses
-               (setq classes (idlwave-members-only
-                              classes (cons class sclasses))))
-           (setq class (idlwave-popup-select ev classes
-                                             "Select Class" 'sort))
-           ;; XXX is this necessary, given all-method-keyword-classes?
-           (if (stringp class)
-               (setq class (idlwave-find-inherited-class
-                            (idlwave-sintern-routine-or-method
-                             idlw-help-name class)
-                            type (idlwave-sintern-class class)))))
-       (if (string= (downcase idlw-help-name) "obj_new")
-           (setq class idlwave-current-obj_new-class
-                 idlw-help-name "Init"))))
-
-     ;; Class name
-     ((eq what 'class)
-      (setq class word
-           word nil))
-
-     ;; A special named function to call which sets some of our variables
-     ((and (symbolp what)
-          (fboundp what))
-      (funcall what 'set word))
-
-     (t (error "Cannot help with this item")))
-    (if (and need-class (not class)
-            (not (and idlw-help-link (not (eq idlw-help-link t)))))
-       (error "Cannot help with this item"))
-    (idlwave-online-help idlw-help-link (or idlw-help-name word)
-                        type class idlw-help-kwd)))
-
-(defvar idlwave-highlight-help-links-in-completion)
-(defvar idlwave-completion-help-links)
-(defun idlwave-highlight-linked-completions ()
-  "Highlight all completions for which help is available and attach link.
-Those words in `idlwave-completion-help-links' have links.  The
-`idlwave-help-link' face is used for this."
-  (if idlwave-highlight-help-links-in-completion
-      (with-current-buffer "*Completions*"
-       (save-excursion
-         (let* ((case-fold-search t)
-                (props (list 'face 'idlwave-help-link))
-                (info idlwave-completion-help-info) ; global passed in
-                (what (nth 0 info))  ; what was completed, or a func
-                ;; (class (nth 3 info)) ; any class
-                word beg end doit)
-           (goto-char (point-min))
-           (re-search-forward "possible completions are:" nil t)
-           (while (re-search-forward "\\s-\\([A-Za-z0-9_.]+\\)\\(\\s-\\|\\'\\)"
-                                     nil t)
-             (setq beg (match-beginning 1) end (match-end 1)
-                   word (match-string 1) doit nil)
-             ;; Call special completion function test
-             (if (and (symbolp what)
-                      (fboundp what))
-                 (setq doit (funcall what 'test word))
-               ;; Look for special link property passed in help-links
-               (if idlwave-completion-help-links
-                   (setq doit (assoc-string
-                               word idlwave-completion-help-links t))))
-             (when doit
-               (if (consp doit)
-                   (setq props (append props `(link ,(cdr doit)))))
-               (let ((buffer-read-only nil))
-                 (add-text-properties beg end props)))
-             (goto-char end)))))))
-
-;; Arrange for this function to be called after completion
-(add-hook 'idlwave-completion-setup-hook
-         #'idlwave-highlight-linked-completions)
-
-(defvar idlwave-help-return-frame nil
-  "The frame to return to from the help frame.")
-
-(defun idlwave-help-quit ()
-  "Exit IDLWAVE Help buffer.  Kill the dedicated frame if any."
-  (interactive)
-  (cond ((and idlwave-help-use-dedicated-frame
-             (eq (selected-frame) idlwave-help-frame))
-        (if (and idlwave-experimental
-                 (frame-live-p idlwave-help-return-frame))
-            ;; Try to select the return frame.
-            ;; This can crash on slow network connections, obviously when
-            ;; we kill the help frame before the return-frame is selected.
-            ;; To protect the workings, we wait for up to one second
-            ;; and check if the return-frame *is* now selected.
-            ;; This is marked "experimental" since we are not sure when
-            ;; it's OK.
-            (let ((maxtime 1.0) (time 0.) (step 0.1))
-              (select-frame idlwave-help-return-frame)
-              (while (and (sit-for step)
-                          (not (eq (selected-frame)
-                                   idlwave-help-return-frame))
-                          (< (setq time (+ time step)) maxtime)))))
-        (delete-frame idlwave-help-frame))
-       ((window-configuration-p idlwave-help-window-configuration)
-        (set-window-configuration idlwave-help-window-configuration)
-        (select-window (previous-window)))
-       (t (kill-buffer (idlwave-help-get-help-buffer)))))
-
-
-(defvar default-toolbar-visible-p)
-
-(defun idlwave-help-display-help-window (&optional pos-or-func)
-  "Display the help window.
-Move window start to POS-OR-FUNC, if passed as a position, or call it
-if passed as a function.  See `idlwave-help-use-dedicated-frame'."
-  (let ((cw (selected-window))
-       (buf (idlwave-help-get-help-buffer)))
-    (if (and window-system idlwave-help-use-dedicated-frame)
-       (progn
-         (idlwave-help-show-help-frame)
-         (switch-to-buffer buf))
-      ;; Do it in this frame and save the window configuration
-      (if (not (get-buffer-window buf nil))
-         (setq idlwave-help-window-configuration
-               (current-window-configuration)))
-      (display-buffer buf nil (selected-frame))
-      (select-window (get-buffer-window buf)))
-    (raise-frame)
-    (if pos-or-func
-       (if (functionp pos-or-func)
-           (funcall pos-or-func)
-         (goto-char pos-or-func)
-         (recenter 0)))
-    (select-window cw)))
-
-(defun idlwave-help-select-help-frame ()
-  "Select the help frame."
-  (if (and (frame-live-p idlwave-help-frame)
-          (not (eq (selected-frame) idlwave-help-frame)))
-      (progn
-       (setq idlwave-help-return-frame (selected-frame))
-       (select-frame idlwave-help-frame))))
-
-(defun idlwave-help-return-to-calling-frame ()
-  "Select the frame from which the help frame was selected."
-  (interactive)
-  (if (and (frame-live-p idlwave-help-return-frame)
-          (not (eq (selected-frame) idlwave-help-return-frame)))
-      (select-frame idlwave-help-return-frame)))
-
-(defun idlwave-online-help (link &optional name type class keyword)
-  "Display HTML or other special help on a certain topic.
-Either loads an HTML link, if LINK is non-nil, or gets special-help on
-the optional arguments, if any special help is defined.  If LINK is
-t, first look up the optional arguments in the routine info list to
-see if a link is set for it.  Try extra help functions if necessary."
-  ;; Lookup link
-  (if (eq link t)
-      (let ((entry (idlwave-best-rinfo-assoc name type class
-                                            (idlwave-routines) nil t)))
-       (if entry
-           (cond
-            ;; Try keyword link
-            ((and keyword
-                  (setq link (cdr
-                              (idlwave-entry-find-keyword entry keyword)))))
-            ;; Default, regular entry link
-            (t (setq link (idlwave-entry-has-help entry))))
-         (if (and
-              class
-              ;; Check for system class help
-              (setq entry (assq (idlwave-sintern-class class)
-                                idlwave-system-class-info)
-                    link (nth 1 (assq 'link entry))))
-             (message
-              (concat "No routine info for %s"
-                      ", falling back on class help.")
-              (idlwave-make-full-name class name))))))
-
-  (cond
-   ;; An explicit link
-   ((stringp link)
-    (idlwave-help-html-link link))
-
-   ;; Any extra help
-   (idlwave-extra-help-function
-    (idlwave-help-get-special-help name type class keyword))
-
-   ;; Nothing worked
-   (t (idlwave-help-error name type class keyword))))
-
-
-(defun idlwave-help-get-special-help (name type class keyword)
-  "Call the function given by `idlwave-extra-help-function'."
-  (let* ((cw (selected-window))
-        (help-pos (with-current-buffer (idlwave-help-get-help-buffer)
-                    (let ((buffer-read-only nil))
-                      (funcall idlwave-extra-help-function
-                               name type class keyword)))))
-    (if help-pos
-       (idlwave-help-display-help-window help-pos)
-      (idlwave-help-error name type class keyword))
-    (select-window cw)))
-
-(defun idlwave-help-html-link (link)
-  "Get HTML help on a given LINK."
-  (let ((browse-url-browser-function idlwave-help-browser-function)
-       (help-loc (idlwave-html-help-location))
-       (browse-url-generic-program idlwave-help-browser-generic-program)
-       ;(browse-url-generic-args idlwave-help-browser-generic-args)
-       full-link)
-
-    ;; Just a regular file name (+ anchor name)
-    (unless (and (stringp help-loc)
-                (file-directory-p help-loc))
-      (error "Invalid help location"))
-    (setq full-link (browse-url-file-url (expand-file-name link help-loc)))
-
-    ;; Select the browser
-    (cond
-     (idlwave-help-use-assistant
-      (idlwave-help-assistant-open-link link))
-
-     ((or idlwave-help-browser-is-local
-         (string-match "w3" (symbol-name idlwave-help-browser-function)))
-      (idlwave-help-display-help-window (lambda () (browse-url full-link))))
-
-     (t (browse-url full-link)))))
-
-;; A special help routine for source-level syntax help in files.
-(defvar idlwave-help-fontify-source-code)
-(defvar idlwave-help-source-try-header)
-(defvar idlwave-current-tags-buffer)
-(defvar idlwave-current-tags-class)
-(defun idlwave-help-with-source (name type class keyword)
-  "Provide help for routines not documented in the IDL manuals.
-Works by loading the routine source file into the help buffer.
-Depending on the value of `idlwave-help-source-try-header', it
-attempts to show the routine definition or the header description.
-If `idlwave-help-do-class-struct-tag' is non-nil, keyword is a tag
-to show help on from the class definition structure.
-If `idlwave-help-do-struct-tag' is non-nil, show help from the
-matching structure tag definition.
-
-This function can be used as `idlwave-extra-help-function'."
-  (let* ((class-struct-tag idlwave-help-do-class-struct-tag)
-        (struct-tag idlwave-help-do-struct-tag)
-        (case-fold-search t)
-        (real-class (if (consp name) (cdr name)))
-        (name (if (consp name) (car name) name))
-        (class-only (and (stringp class) (not (stringp name))))
-        file header-pos def-pos in-buf)
-    (if class-only   ;Help with class?  Using "Init" as source.
-       (setq name "Init"
-             type 'fun))
-    (if (not struct-tag)
-       (setq file
-             (idlwave-routine-source-file
-              (nth 3 (idlwave-best-rinfo-assoc
-                      name (or type t) class (idlwave-routines))))))
-    (setq idlwave-help-def-pos nil
-         idlwave-help-args (list name type class keyword)
-         idlwave-help-in-header nil
-         idlwave-help-do-struct-tag nil
-         idlwave-help-do-class-struct-tag nil)
-    (if (or struct-tag (stringp file))
-       (progn
-         (setq in-buf ; structure-tag completion is always in current buffer
-               (if struct-tag
-                   idlwave-current-tags-buffer
-                  (find-buffer-visiting file)))
-         ;; see if file is in a visited buffer, insert those contents
-         (if in-buf
-             (progn
-               (setq file (buffer-file-name in-buf))
-               (erase-buffer)
-               (insert-buffer-substring in-buf))
-           (if (file-exists-p file) ;; otherwise just load the file
-               (progn
-                 (erase-buffer)
-                 (insert-file-contents file nil nil nil 'replace))
-             (idlwave-help-error name type class keyword)))
-         (goto-char (point-min))
-         (if (and idlwave-help-fontify-source-code (not in-buf))
-             (idlwave-help-fontify)))
-      (idlwave-help-error name type class keyword))
-    (setq idlwave-help-mode-line-indicator file)
-
-    ;; Try to find a good place to display
-    (setq def-pos
-         ;; Find the class structure tag if that's what we're after
-         (cond
-          ;; Class structure tags: find the class or named structure
-          ;; definition
-          (class-struct-tag
-           (save-excursion
-             (setq class
-                   (if (string-match "[a-zA-Z0-9]\\(__\\)" name)
-                       (substring name 0 (match-beginning 1))
-                     idlwave-current-tags-class))
-             (and
-              (idlwave-find-class-definition class nil real-class)
-              (idlwave-find-struct-tag keyword))))
-
-          ;; Generic structure tags: the structure definition
-          ;; location within the file has been recorded in
-          ;; `struct-tag'
-          (struct-tag
-           (save-excursion
-             (and
-              (integerp struct-tag)
-              (goto-char struct-tag)
-              (idlwave-find-struct-tag keyword))))
-
-          ;; Just find the routine definition
-          (t
-           (if class-only (point-min)
-             (idlwave-help-find-routine-definition name type class keyword))))
-         idlwave-help-def-pos def-pos)
-
-    (if (and idlwave-help-source-try-header
-            (not (or struct-tag class-struct-tag)))
-       ;; Check if we can find the header
-       (save-excursion
-         (goto-char (or def-pos (point-max)))
-         (setq header-pos (idlwave-help-find-in-doc-header
-                           name type class keyword 'exact)
-               idlwave-help-in-header header-pos)))
-
-    (if (or header-pos def-pos)
-       (progn
-         (if (boundp 'idlwave-help-min-frame-width)
-             (setq idlwave-help-min-frame-width 80))
-         (goto-char (or header-pos def-pos)))
-      (idlwave-help-error name type class keyword))
-
-    (point)))
-
-
-(defun idlwave-help-find-routine-definition (name type class _keyword)
-  "Find the definition of routine CLASS::NAME in current buffer.
-Returns the point of match if successful, nil otherwise.
-KEYWORD is ignored."
-  (save-excursion
-    (goto-char (point-max))
-    (if (re-search-backward
-        (concat "^[ \t]*"
-                (if (eq type 'pro) "pro"
-                  (if (eq type 'fun) "function"
-                    "\\(pro\\|function\\)"))
-                "[ \t]+"
-                (regexp-quote (downcase (idlwave-make-full-name class name)))
-                "[, \t\r\n]")
-        nil t)
-       (match-beginning 0)
-      nil)))
-
-(defvar idlwave-doclib-start)
-(defvar idlwave-doclib-end)
-(defun idlwave-help-find-in-doc-header (name _type class keyword
-                                            &optional exact)
-  "Find the requested help in the doc-header above point.
-
-First checks if there is a doc-lib header which describes the correct
-routine.  Then tries to find the KEYWORDS section and the KEYWORD, if
-given.  Returns the point which should be window start of the help
-window.  If EXACT is non-nil, the full help position must be found -
-down to the keyword requested.  This setting is for context help, if
-the exact spot is needed.
-
-If EXACT is nil, the position of the header is returned if it
-describes the correct routine - even if the keyword description cannot
-be found.  TYPE is ignored.
-
-This function expects a more or less standard routine header.  In
-particular it looks for the `NAME:' tag, either with a colon, or alone
-on a line.  Then `NAME:' must be followed by the routine name on the
-same or the next line.  When KEYWORD is non-nil, looks first for a
-`KEYWORDS' section.  It is amazing how inconsistent this is through
-some IDL libraries I have seen.  We settle for a line containing an
-upper case \"KEYWORD\" string.  If this line is not found we search
-for the keyword anyway to increase the hit-rate
-
-When one of these sections exists we check for a line starting with any of
-
-  /KEYWORD  KEYWORD-  KEYWORD=  KEYWORD
-
-with spaces allowed between the keyword and the following dash or equal sign.
-If there is a match, we assume it is the keyword description."
-  (let* ((case-fold-search t)
-        (rname (if (stringp class)
-                   (concat
-                    "\\("
-                    ;; Traditional name or class::name
-                    "\\("
-                    "\\(" (regexp-quote (downcase class)) "::\\)?"
-                    (regexp-quote (downcase name))
-                    "\\>\\)"
-                    (concat
-                     "\\|"
-                     ;; class__define or just class
-                     (regexp-quote (downcase class)) "\\(__define\\)?")
-                    "\\)")
-                 (regexp-quote (downcase name))))
-
-        ;; NAME tag plus the routine name.  The new version is from JD.
-        (name-re (concat
-                  "\\(^;+\\*?[ \t]*"
-                  idlwave-help-doclib-name
-                  "\\([ \t]*:\\|[ \t]*$\\)[ \t]*\\(\n;+[ \t]*\\)*"
-                  rname
-                  "\\|"
-                  "^;+[ \t]*"
-                  rname
-                  ":[ \t]*$\\)"))
-
-        ;; Header start plus name
-        ;; (header-re (concat "\\(" idlwave-doclib-start "\\).*\n"
-        ;;                 "\\(^;+.*\n\\)*"
-        ;;                 "\\(" name-re "\\)"))
-        ;; A keywords section
-        (kwds-re (concat                                   ; forgiving
-                  "^;+\\*?[ \t]*"
-                  "\\([-A-Z_ ]*"
-                  idlwave-help-doclib-keyword
-                  "[-A-Z_ ]*\\)"
-                  "\\(:\\|[ \t]*\n\\)"))
-
-        ;; The individual keyword description line.
-        (kwd-re (if keyword                                ; hard (well...)
-                    (concat
-                     "^;+[ \t]+"
-                     "\\(/" (regexp-quote (upcase keyword))
-                     "\\|"  (regexp-quote (upcase keyword)) "[ \t]*[-=:\n]"
-                     "\\)")))
-        (kwd-re2 (if keyword                               ; forgiving
-                     (concat
-                      "^;+[ \t]+"
-                      (regexp-quote (upcase keyword))
-                     "\\>")))
-        dstart dend name-pos kwds-pos kwd-pos)
-    (catch 'exit
-      (save-excursion
-       (goto-char (point-min))
-       (while (and (setq dstart (re-search-forward idlwave-doclib-start nil t))
-                   (setq dend (re-search-forward idlwave-doclib-end nil t)))
-         ;; found a routine header
-         (goto-char dstart)
-         (if (setq name-pos (re-search-forward name-re dend t))
-             (progn
-               (if keyword
-                   ;; We do need a keyword
-                   (progn
-                     ;; Try to find a keyword section, but don't force it.
-                     (goto-char name-pos)
-                     (if (let ((case-fold-search nil))
-                           (re-search-forward kwds-re dend t))
-                         (setq kwds-pos (match-beginning 0)))
-                     ;; Find the keyword description
-                     (if (or (let ((case-fold-search nil))
-                               (re-search-forward kwd-re dend t))
-                             (re-search-forward kwd-re dend t)
-                             (let ((case-fold-search nil))
-                               (re-search-forward kwd-re2 dend t))
-                             (re-search-forward kwd-re2 dend t))
-                         (setq kwd-pos (match-beginning 0))
-                       (if exact
-                           (progn
-                             (idlwave-help-diagnostics
-                              (format "Could not find description of kwd %s"
-                                      (upcase keyword)))
-                             (throw 'exit nil))))))
-               ;; Return the best position we got
-               (throw 'exit (or kwd-pos kwds-pos name-pos dstart)))
-           (goto-char dend))))
-      (idlwave-help-diagnostics "Could not find doclib header")
-      (throw 'exit nil))))
-
-(defun idlwave-help-diagnostics (string &optional ding)
-  "Add a diagnostics string to the list.
-When DING is non-nil, ring the bell as well."
-  (if (boundp 'idlwave-help-diagnostics)
-      (progn
-       (setq idlwave-help-diagnostics
-             (cons string idlwave-help-diagnostics))
-       (if ding (ding)))))
-
-(defun idlwave-help-toggle-header-top-and-def (&optional _arg)
-  (interactive)
-  (let (pos)
-    (if idlwave-help-in-header
-       ;; Header was the last thing displayed
-       (progn
-         (setq idlwave-help-in-header nil)
-         (setq pos idlwave-help-def-pos))
-      ;; Try to display header
-      (setq pos (idlwave-help-find-in-doc-header
-                (nth 0 idlwave-help-args)
-                (nth 1 idlwave-help-args)
-                (nth 2 idlwave-help-args)
-                nil))
-      (if pos
-         (setq idlwave-help-in-header t)
-       (error "Cannot find doclib header for routine %s"
-              (idlwave-make-full-name (nth 2 idlwave-help-args)
-                                      (nth 0 idlwave-help-args)))))
-    (if pos
-       (progn
-         (goto-char pos)
-         (recenter 0)))))
-
-(defun idlwave-help-find-first-header (&optional _arg)
-  (interactive)
-  (let (pos)
-    (save-excursion
-      (goto-char (point-min))
-      (if (re-search-forward idlwave-doclib-start nil t)
-         (setq pos (match-beginning 0))))
-    (if pos
-       (progn
-         (goto-char pos)
-         (recenter 0))
-      (error "No DocLib Header in current file"))))
-
-(defun idlwave-help-find-header (arg)
-  "Jump to the DocLib Header."
-  (interactive "P")
-  (if arg
-      (idlwave-help-find-first-header nil)
-    (setq idlwave-help-in-header nil)
-    (idlwave-help-toggle-header-match-and-def arg 'top)))
-
-(defun idlwave-help-toggle-header-match-and-def (&optional _arg top)
-  (interactive)
-  (let ((args idlwave-help-args)
-       pos)
-    (if idlwave-help-in-header
-       ;; Header was the last thing displayed
-       (progn
-         (setq idlwave-help-in-header nil)
-         (setq pos idlwave-help-def-pos))
-      ;; Try to display header
-      (setq pos (apply #'idlwave-help-find-in-doc-header
-                      (if top
-                          (list (car args) (nth 1 args) (nth 2 args) nil)
-                        args)))
-      (if pos
-         (setq idlwave-help-in-header t)
-       (error "Cannot find doclib header for routine %s"
-              (idlwave-make-full-name (nth 2 idlwave-help-args)
-                                      (nth 0 idlwave-help-args)))))
-    (if pos
-       (progn
-         (goto-char pos)
-         (recenter 0)))))
-
-(defvar idlwave-mode-syntax-table)
-(defvar idlwave-font-lock-defaults)
-(defun idlwave-help-fontify ()
-  "Fontify the Help buffer as source code.
-Useful when source code is displayed as help.  See the option
-`idlwave-help-fontify-source-code'."
-  (interactive)
-  (let ((major-mode 'idlwave-mode)
-        (font-lock-verbose
-         (if (called-interactively-p 'interactive) font-lock-verbose nil)))
-    (with-syntax-table idlwave-mode-syntax-table
-      (set (make-local-variable 'font-lock-defaults)
-           idlwave-font-lock-defaults)
-      (if (fboundp 'font-lock-ensure) ; Emacs >= 25.1
-          (font-lock-ensure)
-        ;; Silence "interactive use only" warning on Emacs >= 25.1.
-        (with-no-warnings (font-lock-fontify-buffer))))))
-
-
-(defun idlwave-help-error (name _type class keyword)
-  (error "Can't find help on %s%s %s"
-        (or (and (or class name) (idlwave-make-full-name class name))
-            "<unknown>")
-        (if keyword (format ", keyword %s" (upcase keyword)) "")
-        (if idlwave-html-help-location
-            ""
-          "(help location unknown)")))
-
-(defun idlwave-help-show-help-frame ()
-  "Show the help frame, creating it if necessary."
-  ;; Use a special frame for this
-  (unless (frame-live-p idlwave-help-frame)
-    (setq idlwave-help-frame
-         (make-frame idlwave-help-frame-parameters))
-    ;; Strip menubar (?) and toolbar from the Help frame.
-    (modify-frame-parameters idlwave-help-frame
-                             '(;;(menu-bar-lines . 0)
-                               (tool-bar-lines . 0))))
-  (select-frame idlwave-help-frame))
-
-(defun idlwave-help-get-help-buffer ()
-  "Return the IDLWAVE Help buffer.  Make it first if necessary."
-  (let ((buf (get-buffer "*IDLWAVE Help*")))
-    (if buf
-       nil
-      (setq buf (get-buffer-create "*IDLWAVE Help*"))
-      (with-current-buffer buf
-       (idlwave-help-mode)))
-    buf))
-
-(defun idlwave-grep (regexp list)
-  (let (rtn)
-    (while list
-      (if (string-match regexp (car list))
-         (setq rtn (cons (car list) rtn)))
-      (setq list (cdr list)))
-    (nreverse rtn)))
-
-(defun idlwave-entry-has-help (entry)
-  (and entry (car (nth 5 entry))))
-
-(defun idlwave-has-help (name type class)
-  "Does this have help associated with it?"
-  (let ((entry (idlwave-best-rinfo-assoc name type class (idlwave-routines))))
-    (idlwave-entry-has-help entry)))
-
-;;----- Control the IDL Assistant, which shipped with IDL v6.2
-(defvar idlwave-help-assistant-process nil)
-(defvar idlwave-help-assistant-socket nil)
-
-;; The Windows version does not have a !DIR/bin/* set of front-end
-;; scripts, but instead only links directly to bin.x86.  As a result,
-;; we must pass the -profile argument as well.
-(defvar idlwave-help-assistant-command
-  (if (memq system-type '(ms-dos windows-nt))
-      "bin/bin.x86/idl_assistant.exe"
-    "bin/idl_assistant")
-  "The command, rooted at `idlwave-system-directory', which invokes the
-IDL assistant.")
-
-(defun idlwave-help-assistant-available ()
-  (if idlwave-help-assistant-available
-      (eq idlwave-help-assistant-available t)
-    (setq idlwave-help-assistant-available
-         (if (file-executable-p (idlwave-help-assistant-command))
-             t
-           'not-available))))
-
-(defun idlwave-help-assistant-command ()
-  (expand-file-name idlwave-help-assistant-command (idlwave-sys-dir)))
-
-(defun idlwave-help-assistant-start (&optional full-link)
-  "Start the IDL Assistant, loading link FULL-LINK, if passed."
-  (when (or (not idlwave-help-assistant-socket)
-           (not (eq (process-status idlwave-help-assistant-socket) 'open)))
-    (let* ((help-loc (idlwave-html-help-location))
-          (command (idlwave-help-assistant-command))
-          (extra-args
-           (nconc
-            (if (memq system-type '(ms-dos windows-nt))
-                `("-profile" ,(expand-file-name "idl.adp" help-loc)))
-            (if full-link `("-file" ,full-link))))
-          port)
-      (if idlwave-help-assistant-socket
-         (delete-process idlwave-help-assistant-socket))
-
-      (setq idlwave-help-assistant-process
-           (apply #'start-process
-                  "IDL_ASSISTANT_PROC" nil command "-server" extra-args))
-
-      (set-process-filter idlwave-help-assistant-process
-                         (lambda (_proc string)
-                           (setq port (string-to-number string))))
-      (unless (accept-process-output idlwave-help-assistant-process 15)
-       (error "Failed binding IDL_ASSISTANT socket"))
-      (if (not port)
-         (error "Unable to open IDL_ASSISTANT")
-       (set-process-filter idlwave-help-assistant-process nil)
-       (setq idlwave-help-assistant-socket
-             (open-network-stream "IDL_ASSISTANT_SOCK"
-                                  nil "localhost" port))
-       (if (eq (process-status idlwave-help-assistant-socket) 'open)
-           (progn
-             (process-send-string  idlwave-help-assistant-socket
-                                   (concat "setHelpPath " help-loc "\n"))
-             t)
-         (idlwave-help-assistant-close)
-         (error "Cannot communicate with IDL_ASSISTANT"))))))
-
-(defun idlwave-help-assistant-raise ()
-  (idlwave-help-assistant-start)
-  (process-send-string idlwave-help-assistant-socket "raise\n"))
-
-(defun idlwave-help-assistant-open-link (&optional link)
-  ;; Open a link (file name with anchor, no leading path) in the assistant.
-  (let ((help-loc (idlwave-html-help-location))
-       topic anchor file just-started exists full-link)
-
-    (if (string-match "\\.html" link)
-       (setq topic (substring link 0 (match-beginning 0))
-             anchor (substring link (match-end 0)))
-      (error "Malformed help link"))
-
-    (setq file (expand-file-name (concat topic ".html") help-loc))
-    (if (file-exists-p file)
-       (setq exists t)
-      (setq file (expand-file-name
-                 (concat (upcase topic) ".html") help-loc))
-      (setq exists (file-exists-p file)))
-
-    (setq full-link    (concat file anchor)
-         just-started (idlwave-help-assistant-start (if exists full-link)))
-    (if exists
-       (progn
-         (if (not just-started)
-             (process-send-string idlwave-help-assistant-socket
-                                  (concat "openLink " full-link "\n")))
-         (process-send-string idlwave-help-assistant-socket
-                              (concat "searchIndexNoOpen " topic "\n")))
-      (process-send-string idlwave-help-assistant-socket
-                          (concat "searchIndexAndOpen " topic "\n"))))
-  (idlwave-help-assistant-raise))
-
-(defvar idlwave-help-assistant-help-with-topic-history nil
-  "The history of help topics selected with the minibuffer.")
-
-(defvar idlwave-system-routines)
-
-(defun idlwave-help-assistant-help-with-topic (&optional topic)
-  "Prompt for and provide help with TOPIC."
-  (interactive)
-  (let (list)
-    (unless topic
-      (idlwave-routines)
-      (setq list (append (mapcar (lambda (x)
-                                  (concat (nth 2 x) (car x)))
-                                idlwave-system-routines)
-                        (mapcar (lambda (x)
-                                  (concat "." (car x)))
-                                idlwave-executive-commands-alist)
-                        idlwave-system-class-info))
-      (setq topic
-           (idlwave-completing-read
-            "Help Topic: " list
-            nil nil nil
-            'idlwave-help-assistant-help-with-topic-history)))
-    (if (and topic (not (string= topic "")))
-       (idlwave-help-assistant-open-link (concat topic ".html")))))
-
-(defun idlwave-help-assistant-close ()
-  (when (and idlwave-help-assistant-process
-            (eq (process-status idlwave-help-assistant-process) 'run))
-    (when idlwave-help-assistant-socket
-      (process-send-string idlwave-help-assistant-socket "quit\n")
-      (delete-process idlwave-help-assistant-socket))
-    (stop-process idlwave-help-assistant-process)
-    (delete-process idlwave-help-assistant-process)
-    (setq idlwave-help-assistant-socket nil
-         idlwave-help-assistant-process nil)))
-
-;;; Obsolete
-
-(defvar idlwave-help-browse-url-available t)
-(make-obsolete-variable 'idlwave-help-browse-url-available nil "28.1")
-(defvar idlwave-help-use-hh nil "Obsolete variable.")
-(make-obsolete-variable 'idlwave-help-use-hh nil "28.1")
-(defvar idlwave-help-directory ""
-  "Obsolete variable.  See `idlwave-html-help-location'.")
-(make-obsolete-variable 'idlwave-help-directory nil "28.1")
-
-(provide 'idlw-help)
-(provide 'idlwave-help)
-
-;;; idlw-help.el ends here
diff --git a/lisp/progmodes/idlw-shell.el b/lisp/progmodes/idlw-shell.el
deleted file mode 100644 (file)
index b5d91f4..0000000
+++ /dev/null
@@ -1,4490 +0,0 @@
-;;; idlw-shell.el --- run IDL as an inferior process of Emacs.  -*- lexical-binding:t -*-
-
-;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
-
-;; Authors: JD Smith <jd.smith@utoledo.edu>
-;;          Carsten Dominik <dominik@astro.uva.nl>
-;;          Chris Chase <chase@att.com>
-;; Maintainer: emacs-devel@gnu.org
-;; Keywords: processes
-;; Package: idlwave
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software: you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, either version 3 of the License, or
-;; (at your option) any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-;;
-;; This mode is for IDL version 5 or later.
-;;
-;; Runs IDL as an inferior process of Emacs, much like the Emacs
-;; `shell' or `telnet' commands.  Provides command history and
-;; searching.  Provides debugging commands available in buffers
-;; visiting IDL procedure files, e.g., breakpoint setting, stepping,
-;; execution until a certain line, printing expressions under point,
-;; visual line pointer for current execution line, etc.
-;;
-;; Documentation should be available online with `M-x idlwave-info'.
-;;
-;; New versions of IDLWAVE, documentation, and more information
-;; available from:
-;;                 https://github.com/jdtsmith/idlwave
-;;
-;; INSTALLATION:
-;; =============
-;;
-;; Follow the instructions in the INSTALL file of the distribution.
-;; In short, put this file on your load path and add the following
-;; lines to your init file:
-;;
-;; (autoload 'idlwave-shell "idlw-shell" "IDLWAVE Shell" t)
-;;
-;;
-;; SOURCE
-;; ======
-;;
-;;   The newest version of this file can be found on the maintainers
-;;   web site.
-;;
-;;     https://github.com/jdtsmith/idlwave
-;;
-;; DOCUMENTATION
-;; =============
-;;
-;; IDLWAVE is documented online in info format.
-;; A printable version of the documentation is available from the
-;; maintainers webpage (see under SOURCE)
-;;
-;;
-;; CUSTOMIZATION VARIABLES
-;; =======================
-;;
-;; IDLWAVE has customize support - so if you want to learn about
-;; the variables which control the behavior of the mode, use
-;; `M-x idlwave-customize'.
-;;
-;;--------------------------------------------------------------------------
-;;
-\f
-;;; Code:
-
-(require 'comint)
-(require 'idlwave)
-
-(eval-when-compile (require 'cl-lib))
-
-(defvar idlwave-shell-have-new-custom nil)
-
-;;; Customizations: idlwave-shell group
-
-;; General/Misc. customizations
-(defgroup idlwave-shell-general-setup nil
-  "General setup of the Shell interaction for IDLWAVE/Shell."
-  :prefix "idlwave-shell"
-  :group 'idlwave)
-
-(defcustom idlwave-shell-prompt-pattern "^\r? ?IDL> "
-  "Regexp to match IDL prompt at beginning of a line.
-For example, \"^\\r?IDL> \" or \"^\\r?WAVE> \".
-The \"^\\r?\" is needed, to indicate the beginning of the line, with
-optional return character (which IDL seems to output randomly).
-This variable is used to initialize `comint-prompt-regexp' in the
-process buffer."
-  :group 'idlwave-shell-general-setup
-  :type 'regexp)
-
-(defcustom idlwave-shell-process-name "idl"
-  "Name to be associated with the IDL process.
-The buffer for the process output is made by surrounding this
-name with `*'s."
-  :group 'idlwave-shell-general-setup
-  :type 'string)
-
-;; (defcustom idlwave-shell-automatic-start...)  See idlwave.el
-
-(defcustom idlwave-shell-use-dedicated-window nil
-  "Non-nil means, never replace the shell frame with another buffer."
-  :group 'idlwave-shell-general-setup
-  :type 'boolean)
-
-(defcustom idlwave-shell-use-dedicated-frame nil
-  "Non-nil means, IDLWAVE should use a special frame to display shell buffer."
-  :group 'idlwave-shell-general-setup
-  :type 'boolean)
-
-(defcustom idlwave-shell-frame-parameters
-  '((height . 30) (unsplittable . nil))
-  "The frame parameters for a dedicated `idlwave-shell' frame.
-See also `idlwave-shell-use-dedicated-frame'.
-The default makes the frame splittable, so that completion works correctly."
-  :group 'idlwave-shell-general-setup
-  :type '(repeat
-         (cons symbol sexp)))
-
-(defcustom idlwave-shell-raise-frame t
-  "Non-nil means, `idlwave-shell' raises the frame showing the shell window."
-  :group 'idlwave-shell-general-setup
-  :type 'boolean)
-
-(defcustom idlwave-shell-arrows-do-history t
-  "Non-nil means UP and DOWN arrows move through command history.
-This variable can have 3 values:
-nil        Arrows just move the cursor
-t          Arrows force the cursor back to the current command line and
-           walk the history
-`cmdline'  When the cursor is in the current command line, arrows walk the
-           history.  Everywhere else in the buffer, arrows move the cursor."
-  :group 'idlwave-shell-general-setup
-  :type '(choice
-         (const :tag "never" nil)
-         (const :tag "everywhere" t)
-         (const :tag "in command line only" cmdline)))
-
-;; FIXME: add comint-input-ring-size?
-
-(defcustom idlwave-shell-use-toolbar t
-  "Non-nil means, use the debugging toolbar in all IDL related buffers.
-Starting the shell will then add the toolbar to all `idlwave-mode' buffers.
-Exiting the shell will removed everywhere.
-At any time you can toggle the display of the toolbar with
-\\[idlwave-shell-toggle-toolbar]."
-  :group 'idlwave-shell-general-setup
-  :type 'boolean)
-
-(defcustom idlwave-shell-temp-pro-prefix "/tmp/idltemp"
-  "The prefix for temporary IDL files used when compiling regions.
-It should be an absolute pathname.
-The full temporary file name is obtained by using `make-temp-file'
-so that the name will be unique among multiple Emacs processes."
-  :group 'idlwave-shell-general-setup
-  :type 'string)
-
-(defcustom idlwave-shell-prefix-key "\C-c\C-d"
-  "The prefix key for the debugging map `idlwave-shell-mode-prefix-map'.
-This variable must already be set when idlwave-shell.el is loaded.
-Setting it in the mode-hook is too late."
-  :group 'idlwave-shell-general-setup
-  :type 'string)
-
-(defcustom idlwave-shell-activate-prefix-keybindings t
-  "Non-nil means, the debug commands will be bound to the prefix key.
-The prefix key itself is given in the option `idlwave-shell-prefix-key'.
-So by default setting a breakpoint will be on C-c C-d C-b."
-  :group 'idlwave-shell-general-setup
-  :type 'boolean)
-
-(defcustom idlwave-shell-automatic-electric-debug 'breakpoint
-  "Enter the electric-debug minor mode automatically.
-This occurs at a breakpoint or any other halt.  The mode is exited
-upon return to the main level.  Can be set to `breakpoint' to enter
-electric debug mode only when breakpoints are tripped."
-  :group 'idlwave-shell-general-setup
-  :type '(choice
-         (const :tag "never" nil)
-         (const :tag "always" t)
-         (const :tag "for breakpoints only" breakpoint)))
-
-(defcustom idlwave-shell-electric-zap-to-file t
-  "When entering electric debug mode, select the window displaying the
-file at which point is stopped.  This takes point away from the shell
-window, but is useful for stepping, etc."
-  :group 'idlwave-shell-general-setup
-  :type 'boolean)
-
-;; (defcustom idlwave-shell-debug-modifiers... See idlwave.el
-
-(defcustom idlwave-shell-use-truename nil
-  "Non-nil means, use `file-truename' when looking for buffers.
-If this variable is non-nil, Emacs will use the function `file-truename' to
-resolve symbolic links in the file paths printed by e.g., STOP commands.
-This means, unvisited files will be loaded under their truename.
-However, when a file is already visited under a different name, IDLWAVE will
-reuse that buffer.
-This option was once introduced in order to avoid multiple buffers visiting
-the same file.  However, IDLWAVE no longer makes this mistake, so it is safe
-to set this option to nil."
-  :group 'idlwave-shell-general-setup
-  :type 'boolean)
-
-(defcustom idlwave-shell-file-name-chars "~/A-Za-z0-9+:_.$#%={}\\- "
-  "The characters allowed in file names, as a string.
-Used for file name completion.  Must not contain `\\='', `,' and `\"'
-because these are used as separators by IDL."
-  :group 'idlwave-shell-general-setup
-  :type 'string)
-
-(defcustom idlwave-shell-mode-hook '()
-  "Hook for customizing `idlwave-shell-mode'."
-  :group 'idlwave-shell-general-setup
-  :type 'hook)
-
-(defcustom idlwave-shell-graphics-window-size '(500 400)
-  "Size of IDL graphics windows popped up by special IDLWAVE command.
-The command is \\`C-c C-d C-f' and accepts as a prefix the window nr.
-A command like `WINDOW,N,xsize=XX,ysize=YY' is sent to IDL."
-  :group 'idlwave-shell-general-setup
-  :type '(list
-         (integer :tag "x size")
-         (integer :tag "y size")))
-
-
-;; Commands Sent to Shell... etc.
-(defgroup idlwave-shell-command-setup nil
-  "Setup for command parameters of the Shell interaction for IDLWAVE."
-  :prefix "idlwave-shell"
-  :group 'idlwave)
-
-(defcustom idlwave-shell-initial-commands "!more=0 & defsysv,'!ERROR_STATE',EXISTS=__e & if __e then begin & !ERROR_STATE.MSG_PREFIX=\"% \" & delvar,__e & endif"
-  "Initial commands, separated by newlines, to send to IDL.
-This string is sent to the IDL process by `idlwave-shell-mode' which is
-invoked by `idlwave-shell'."
-  :group 'idlwave-shell-command-setup
-  :type 'string)
-
-(defcustom idlwave-shell-save-command-history t
-  "Non-nil means preserve command history between sessions.
-The file `idlwave-shell-command-history-file' is used to save and restore
-the history."
-  :group 'idlwave-shell-command-setup
-  :type 'boolean)
-
-(defcustom idlwave-shell-command-history-file "idlwhist"
-  "The file in which the command history of the idlwave shell is saved.
-In order to change the size of the history, see the variable
-`comint-input-ring-size'.
-The history is only saved if the variable `idlwave-shell-save-command-history'
-is non-nil."
-  :group 'idlwave-shell-command-setup
-  :type 'file)
-
-(defcustom idlwave-shell-show-commands
-  '(run misc breakpoint)
-  "A list of command types to show output from in the shell.
-Possibilities are `run', `debug', `breakpoint', and `misc'.  Unselected
-types are not displayed in the shell.  The type `everything' causes all
-the copious shell traffic to be displayed."
-  :group 'idlwave-shell-command-setup
-  :type '(choice
-         (const everything)
-         (set :tag "Checklist" :greedy t
-              (const :tag "All .run and .compile commands"        run)
-              (const :tag "All breakpoint commands"               breakpoint)
-              (const :tag "All debug and stepping commands"       debug)
-              (const :tag "Close, window, retall, etc. commands"  misc))))
-
-(defcustom idlwave-shell-max-print-length 200
-  "Maximum number of array elements to print when examining."
-  :group 'idlwave-shell-command-setup
-  :type 'integer)
-
-(defcustom idlwave-shell-examine-alist
-  `(("Print"           . ,(concat "idlwave_print_safe,___,"
-                                  (number-to-string
-                                   idlwave-shell-max-print-length)))
-    ("Help"            . "help,___")
-    ("Structure Help"          . "help,___,/STRUCTURE")
-    ("Dimensions"      . "print,size(___,/DIMENSIONS)")
-    ("Type"            . "print,size(___,/TNAME)")
-    ("N_Elements"      . "print,n_elements(___)")
-    ("All Size Info"   . "help,(__IWsz__=size(___,/STRUCTURE)),/STRUCTURE & print,__IWsz__.DIMENSIONS")
-    ("Ptr Valid"       . "print,ptr_valid(___)")
-    ("Arg Present"      . "print,arg_present(___)")
-    ("Widget Valid"     . "print,widget_info(___,/VALID)")
-    ("Widget Geometry"  . "help,widget_info(___,/GEOMETRY)"))
-  "Alist of special examine commands for popup selection.
-The keys are used in the selection popup created by
-`idlwave-shell-examine-select', and the corresponding value is sent as
-a command to the shell, with special sequence `___' replaced by the
-expression being examined."
-  :group 'idlwave-shell-command-setup
-  :type '(repeat
-         (cons
-          (string :tag "Label  ")
-          (string :tag "Command"))))
-
-(defcustom idlwave-shell-separate-examine-output t
-  "Non-nil means, put output of examine commands in their own buffer."
-  :group 'idlwave-shell-command-setup
-  :type 'boolean)
-
-(defcustom idlwave-shell-comint-settings
-  '((comint-scroll-to-bottom-on-input . t)
-    (comint-scroll-to-bottom-on-output . t)
-    (comint-scroll-show-maximum-output . nil)
-    (comint-prompt-read-only . t))
-
-  "Alist of special settings for the comint variables in the IDLWAVE Shell.
-Each entry is a cons cell with the name of a variable and a value.
-The function `idlwave-shell-mode' will make local variables out of each entry.
-Changes to this variable will only be active when the shell buffer is
-newly created."
-  :group 'idlwave-shell-command-setup
-  :type '(repeat
-         (cons variable sexp)))
-
-(defcustom idlwave-shell-query-for-class t
-  "Non-nil means query the shell for object class on object completions."
-  :group 'idlwave-shell-command-setup
-  :type 'boolean)
-
-(defcustom idlwave-shell-use-input-mode-magic nil
-  "Non-nil means, IDLWAVE should check for input mode spells in output.
-The spells are strings printed by your IDL program and matched
-by the regular expressions in `idlwave-shell-input-mode-spells'.
-When these expressions match, IDLWAVE switches to character input mode and
-back, respectively.  See `idlwave-shell-input-mode-spells' for details."
-  :group 'idlwave-shell-command-setup
-  :type 'boolean)
-
-(defcustom idlwave-shell-input-mode-spells
-  '("^<onechar>$" "^<chars>$" "^</chars>$")
-  "The three regular expressions which match the magic spells for input modes.
-
-When the first regexp matches in the output stream of IDL, IDLWAVE
-prompts for a single character and sends it immediately to IDL, similar
-to the command \\[idlwave-shell-send-char].
-
-When the second regexp matches, IDLWAVE switches to a blocking
-single-character input mode.  This is the same mode which can be entered
-manually with \\[idlwave-shell-char-mode-loop].
-This input mode exits when the third regexp matches in the output,
-or when the IDL prompt is encountered.
-
-The variable `idlwave-shell-use-input-mode-magic' must be non-nil to enable
-scanning for these expressions.  If the IDL program produces lots of
-output, shell operation may be slowed down.
-
-This mechanism is useful for correct interaction with the IDL function
-GET_KBRD, because in normal operation IDLWAVE only sends \\n terminated
-strings.  Here is some example code which makes use of the default spells.
-
-  print,\\='<chars>\\='               ; Make IDLWAVE switch to character mode
-  REPEAT BEGIN
-      A = GET_KBRD(1)
-      PRINT, BYTE(A)
-  ENDREP UNTIL A EQ \\='q\\='
-  print,\\='</chars>\\='              ; Make IDLWAVE switch back to line mode
-
-  print,\\='Quit the program, y or n?\\='
-  print,\\='<onechar>\\='             ; Ask IDLWAVE to send one character
-  answer = GET_KBRD(1)
-
-Since the IDLWAVE shell defines the system variable `!IDLWAVE_VERSION',
-you could actually check if you are running under Emacs before printing
-the magic strings.  Here is a procedure which uses this.
-
-Usage:
-======
-idlwave_char_input               ; Make IDLWAVE send one character
-idlwave_char_input,/on           ; Start the loop to send characters
-idlwave_char_input,/off          ; End the loop to send characters
-
-
-pro idlwave_char_input,on=on,off=off
-  ;; Test if we are running under Emacs
-  defsysv,\\='!idlwave_version\\=',exists=running_emacs
-  if running_emacs then begin
-      if keyword_set(on) then         print,\\='<chars>\\=' $
-        else if keyword_set(off) then print,\\='</chars>\\=' $
-        else                          print,\\='<onechar>\\='
-  endif
-end"
-  :group 'idlwave-shell-command-setup
-  :type '(list
-         (regexp :tag "One-char  regexp")
-         (regexp :tag "Char-mode regexp")
-         (regexp :tag "Line-mode regexp")))
-
-(defcustom idlwave-shell-breakpoint-popup-menu t
-  "If non-nil, provide a menu on mouse-3 on breakpoint lines, and
-popup help text on the line."
-  :group 'idlwave-shell-command-setup
-  :type 'boolean)
-
-(defcustom idlwave-shell-reset-no-prompt nil
-  "If non-nil, skip the yes/no prompt when resetting the IDL session."
-  :group 'idlwave-shell-command-setup
-  :type 'boolean)
-
-;; Breakpoint Overlays etc
-(defgroup idlwave-shell-highlighting-and-faces nil
-  "Highlighting and faces used by the IDLWAVE Shell mode."
-  :prefix "idlwave-shell"
-  :group 'idlwave)
-
-(defcustom idlwave-shell-mark-stop-line t
-  "Non-nil means, mark the source code line where IDL is currently stopped.
-Value decides about the method which is used to mark the line.  Valid values
-are:
-
-nil       Do not mark the line
-`arrow'   Use the overlay arrow
-`face'    Use `idlwave-shell-stop-line-face' to highlight the line.
-t         Use what IDLWAVE thinks is best.  Will be a face where possible,
-          otherwise the overlay arrow.
-The overlay-arrow has the disadvantage to hide the first chars of a line.
-Since many people do not have the main block of IDL programs indented,
-a face highlighting may be better."
-  :group 'idlwave-shell-highlighting-and-faces
-  :type '(choice
-         (const :tag "No marking" nil)
-         (const :tag "Use overlay arrow" arrow)
-         (const :tag "Highlight with face" face)
-         (const :tag "Face or arrow." t)))
-
-(defcustom idlwave-shell-overlay-arrow ">"
-  "The overlay arrow to display at source lines where execution halts.
-We use a single character by default, since the main block of IDL procedures
-often has no indentation.  Where possible, IDLWAVE will use overlays to
-display the stop-lines.  The arrow is only used on character-based terminals.
-See also `idlwave-shell-mark-stop-line'."
-  :group 'idlwave-shell-highlighting-and-faces
-  :type 'string)
-
-(defcustom idlwave-shell-stop-line-face 'highlight
-  "The face for `idlwave-shell-stop-line-overlay'.
-Allows you to choose the font, color and other properties for
-line where IDL is stopped.  See also `idlwave-shell-mark-stop-line'."
-  :group 'idlwave-shell-highlighting-and-faces
-  :type 'symbol)
-
-(defcustom idlwave-shell-electric-stop-color "Violet"
-  "The color for the default face or overlay arrow when stopped."
-  :group 'idlwave-shell-highlighting-and-faces
-  :type 'string)
-
-(defcustom idlwave-shell-electric-stop-line-face
-  (prog1
-      (copy-face 'mode-line 'idlwave-shell-electric-stop-line)
-    (set-face-background 'idlwave-shell-electric-stop-line
-                        idlwave-shell-electric-stop-color)
-    (condition-case nil
-       (set-face-foreground 'idlwave-shell-electric-stop-line nil)
-      (error nil)))
-  "The face for `idlwave-shell-stop-line-overlay' when in electric debug mode.
-Allows you to choose the font, color and other properties for the line
-where IDL is stopped, when in Electric Debug Mode."
-  :group 'idlwave-shell-highlighting-and-faces
-  :type 'symbol)
-
-(defcustom idlwave-shell-mark-breakpoints t
-  "Non-nil means, mark breakpoints in the source files.
-Valid values are:
-nil        Do not mark breakpoints.
-`face'     Highlight line with `idlwave-shell-breakpoint-face'.
-`glyph'    Red dot at the beginning of line.  If the display does not
-           support glyphs, will use `face' instead.
-t          Glyph when possible, otherwise face (same effect as `glyph')."
-  :group 'idlwave-shell-highlighting-and-faces
-  :type '(choice
-         (const :tag "No marking" nil)
-         (const :tag "Highlight with face" face)
-         (const :tag "Display glyph (red dot)" glyph)
-         (const :tag "Glyph or face." t)))
-
-(defcustom idlwave-shell-breakpoint-face 'idlwave-shell-bp
-  "The face for breakpoint lines in the source code.
-Allows you to choose the font, color and other properties for
-lines which have a breakpoint.  See also `idlwave-shell-mark-breakpoints'."
-  :group 'idlwave-shell-highlighting-and-faces
-  :type 'symbol)
-
-(if (not idlwave-shell-have-new-custom)
-    ;; Just copy the underline face to be on the safe side.
-    (copy-face 'underline 'idlwave-shell-bp)
-  ;; We have the new customize - use it to define a customizable face
-  (defface idlwave-shell-bp
-    '((((class color)) (:foreground "Black" :background "Pink"))
-      (t (:underline t)))
-    "Face for highlighting lines with breakpoints."
-    :group 'idlwave-shell-highlighting-and-faces))
-
-(defcustom idlwave-shell-disabled-breakpoint-face
-  'idlwave-shell-disabled-bp
-  "The face for disabled breakpoint lines in the source code.
-Allows you to choose the font, color and other properties for
-lines which have a breakpoint.  See also `idlwave-shell-mark-breakpoints'."
-  :group 'idlwave-shell-highlighting-and-faces
-  :type 'symbol)
-
-(if (not idlwave-shell-have-new-custom)
-    ;; Just copy the underline face to be on the safe side.
-    (copy-face 'underline 'idlwave-shell-disabled-bp)
-  ;; We have the new customize - use it to define a customizable face
-  (defface idlwave-shell-disabled-bp
-    '((((class color)) (:foreground "Black" :background "gray"))
-      (t (:underline t)))
-    "Face for highlighting lines with breakpoints."
-    :group 'idlwave-shell-highlighting-and-faces))
-
-
-(defcustom idlwave-shell-expression-face 'secondary-selection
-  "The face for `idlwave-shell-expression-overlay'.
-Allows you to choose the font, color and other properties for
-the expression printed by IDL."
-  :group 'idlwave-shell-highlighting-and-faces
-  :type 'symbol)
-
-(defcustom idlwave-shell-output-face 'secondary-selection
-  "The face for `idlwave-shell-output-overlay'.
-Allows you to choose the font, color and other properties for
-the expression output by IDL."
-  :group 'idlwave-shell-highlighting-and-faces
-  :type 'symbol)
-
-;;; End user customization variables
-
-;;; External variables
-(defvar comint-last-input-start)
-(defvar comint-last-input-end)
-
-;; Other variables
-(defvar idlwave-shell-temp-pro-file nil
-  "Absolute pathname for temporary IDL file for compiling regions.")
-
-(defvar idlwave-shell-temp-rinfo-save-file nil
-  "Absolute pathname for temporary IDL file save file for routine_info.
-This is used to speed up the reloading of the routine info procedure
-before use by the shell.")
-
-(defun idlwave-shell-temp-file (type)
-  "Return a temp file, creating it if necessary.
-
-TYPE is either `pro' or `rinfo', and `idlwave-shell-temp-pro-file' or
-`idlwave-shell-temp-rinfo-save-file' is set (respectively)."
-  (cond
-   ((eq type 'rinfo)
-    (or idlwave-shell-temp-rinfo-save-file
-       (setq idlwave-shell-temp-rinfo-save-file
-             (make-temp-file idlwave-shell-temp-pro-prefix))))
-   ((eq type 'pro)
-    (or idlwave-shell-temp-pro-file
-       (setq idlwave-shell-temp-pro-file
-             (make-temp-file idlwave-shell-temp-pro-prefix))))
-   (t (error "Wrong argument (idlwave-shell-temp-file): %s"
-            (symbol-name type)))))
-
-
-(define-obsolete-function-alias 'idlwave-shell-make-temp-file
-  #'make-temp-file "27.1")
-
-(defvar idlwave-shell-dirstack-query "cd,current=___cur & print,___cur"
-  "Command used by `idlwave-shell-resync-dirs' to query IDL for
-the directory stack.")
-
-(defvar idlwave-shell-path-query "print,'PATH:<'+transpose(expand_path(!PATH,/ARRAY))+'>' & print,'SYSDIR:<'+!dir+'>'"
-
-  "The command which gets !PATH and !DIR info from the shell.")
-
-(defvar idlwave-shell-mode-line-info nil
-  "Additional info displayed in the mode line.")
-
-(defvar idlwave-shell-default-directory nil
-  "The default directory in the `idlwave-shell' buffer, of outside use.")
-
-(defvar idlwave-shell-last-save-and-action-file nil
-  "The last file which was compiled with `idlwave-shell-save-and-...'.")
-
-(defvar idlwave-shell-stop-line-overlay nil
-  "The overlay for where IDL is currently stopped.")
-(defvar idlwave-shell-is-stopped nil)
-(defvar idlwave-shell-expression-overlay nil
-  "The overlay for the examined expression.")
-(defvar idlwave-shell-output-overlay nil
-  "The overlay for the last IDL output.")
-
-;; If these were already overlays, delete them.  This probably means that we
-;; are reloading this file.
-(if (overlayp idlwave-shell-stop-line-overlay)
-    (delete-overlay idlwave-shell-stop-line-overlay))
-(if (overlayp idlwave-shell-expression-overlay)
-    (delete-overlay idlwave-shell-expression-overlay))
-(if (overlayp idlwave-shell-output-overlay)
-    (delete-overlay idlwave-shell-output-overlay))
-
-;; Set to nil initially
-(setq idlwave-shell-stop-line-overlay nil
-      idlwave-shell-expression-overlay nil
-      idlwave-shell-output-overlay nil)
-
-;; Define the shell stop overlay.  When left nil, the arrow will be used.
-(cond
- ((or (null idlwave-shell-mark-stop-line)
-      (eq idlwave-shell-mark-stop-line 'arrow))
-  ;; Leave the overlay nil
-  nil)
-
- ((eq idlwave-shell-mark-stop-line 'face)
-  ;; Try to use a face.  If not possible, arrow will be used anyway
-  ;; So who can display faces?
-  (when window-system
-    (progn
-      (setq idlwave-shell-stop-line-overlay (make-overlay 1 1))
-      (overlay-put idlwave-shell-stop-line-overlay
-                  'face idlwave-shell-stop-line-face))))
-
- (t
-  ;; IDLWAVE may decide.  Will use a face on window systems, arrow elsewhere
-  (if window-system
-      (progn
-       (setq idlwave-shell-stop-line-overlay (make-overlay 1 1))
-       (overlay-put idlwave-shell-stop-line-overlay
-                    'face idlwave-shell-stop-line-face)))))
-
-;; Now the expression and output overlays
-(setq idlwave-shell-expression-overlay (make-overlay 1 1))
-(overlay-put idlwave-shell-expression-overlay
-            'face idlwave-shell-expression-face)
-(overlay-put idlwave-shell-expression-overlay
-            'priority 1)
-(setq idlwave-shell-output-overlay (make-overlay 1 1))
-(overlay-put idlwave-shell-output-overlay
-            'face idlwave-shell-output-face)
-
-(copy-face idlwave-shell-stop-line-face
-          'idlwave-shell-pending-stop)
-(copy-face idlwave-shell-electric-stop-line-face
-          'idlwave-shell-pending-electric-stop)
-(set-face-background 'idlwave-shell-pending-stop "gray70")
-(set-face-background 'idlwave-shell-pending-electric-stop "gray70")
-
-
-
-(defvar idlwave-shell-bp-query "help,/breakpoints"
-  "Command to obtain list of breakpoints.")
-
-(defvar idlwave-shell-command-output nil
-  "String for accumulating current command output.")
-
-(defvar idlwave-shell-post-command-hook nil
-  "Lisp list expression or function to run when an IDL command is finished.
-The current command is finished when the IDL prompt is displayed.
-This is evaluated if it is a list or called with funcall.")
-
-(defvar idlwave-shell-sentinel-hook nil
-  "Hook run when the IDL process exits.")
-
-(defvar idlwave-shell-hide-output nil
-  "If non-nil the process output is not inserted into the output buffer.")
-
-(defvar idlwave-shell-show-if-error nil
-  "If non-nil the process output is inserted into the output buffer if
-it contains an error message, even if hide-output is non-nil.")
-
-(defvar idlwave-shell-accumulation nil
-  "Accumulate last line of output.")
-
-(defvar idlwave-shell-command-line-to-execute nil)
-(defvar idlwave-shell-cleanup-hook nil
-  "List of functions to do cleanup when the shell exits.")
-
-(defvar idlwave-shell-pending-commands nil
-  "List of commands to be sent to IDL.
-Each element of the list is list of \(CMD PCMD HIDE), where CMD is a
-string to be sent to IDL and PCMD is a post-command to be placed on
-`idlwave-shell-post-command-hook'.  If HIDE is non-nil, hide the output
-from command CMD.  PCMD and HIDE are optional.")
-
-(defun idlwave-shell-buffer ()
-  "Name of buffer associated with IDL process.
-The name of the buffer is made by surrounding `idlwave-shell-process-name'
-with `*'s."
-  (concat "*" idlwave-shell-process-name "*"))
-
-(defvar idlwave-shell-ready nil
-  "If non-nil can send next command to IDL process.")
-
-;;; The following are the types of messages we attempt to catch to
-;;; resync our idea of where IDL execution currently is.
-;;;
-
-(defvar idlwave-shell-halt-frame nil
-  "The frame associated with halt/breakpoint messages.")
-
-(defvar idlwave-shell-step-frame nil
-  "The frame associated with step messages.")
-
-(defvar idlwave-shell-trace-frame nil
-  "The frame associated with trace messages.")
-
-(defconst idlwave-shell-halt-messages
-  '("^% Interrupted at:"
-    "^% Stepped to:"
-    "^% Skipped to:"
-    "^% Stop encountered:"
-    )
-  "A list of regular expressions matching IDL messages.
-These are the messages containing file and line information where
-IDL is currently stopped.")
-
-
-(defconst idlwave-shell-halt-messages-re
-  (mapconcat #'identity idlwave-shell-halt-messages "\\|")
-  "The regular expression computed from `idlwave-shell-halt-messages'.")
-
-(defconst idlwave-shell-trace-message-re
-  "^% At "    ;; First line of a trace message
-  "A regular expression matching IDL trace messages.
-These are the messages containing file and line information of a
-current traceback.")
-
-(defconst idlwave-shell-step-messages
-  '("^% Stepped to:"
-    )
-  "A list of regular expressions matching stepped execution messages.
-These are IDL messages containing file and line information where
-IDL has currently stepped.")
-
-(defvar idlwave-shell-break-message "^% Breakpoint at:"
-  "Regular expression matching an IDL breakpoint message line.")
-
-(defconst idlwave-shell-electric-debug-help
-  "   ==> IDLWAVE Electric Debug Mode Help <==
-
- Break Point Setting and Clearing:
-  b         Set breakpoint ([C-u b] for conditional, [C-n b] nth hit, etc.).
-  d         Clear nearby breakpoint.
-  a          Clear all breakpoints.
-  i         Set breakpoint in routine named here.
-  j          Set breakpoint at beginning of containing routine.
-  \\          Toggle breakpoint disable
-  ]          Go to next breakpoint in file.
-  [          Go to previous breakpoint in file.
-
- Stepping, Continuing, and the Stack:
-  s or SPACE Step, into function calls.
-  n         Step, over function calls.
-  k         Skip one statement.
-  m         Continue to end of function.
-  o         Continue past end of function.
-  u         Continue to end of block.
-  h         Continue to line at cursor position.
-  r         Continue execution to next breakpoint, if any.
-  + or =     Show higher level in calling stack.
-  - or _     Show lower level in calling stack.
-
- Examining Expressions (with prefix for examining the region):
-  p         Print expression near point or in region ([C-u p]).
-  ?          Help on expression near point or in region ([C-u ?]).
-  x          Examine expression near point or in region ([C-u x]) with
-             letter completion of the examine type.
-  e          Prompt for an expression to print.
-
- Miscellaneous:
-  q         Quit - end debugging session and return to the Shell's main level.
-  v         Turn Electric Debugging Mode off (C-c C-d C-v to return).
-  t         Print a calling-level traceback in the shell.
-  z         Reset IDL.
-  C-?        Show this help menu.")
-
-(defvar idlwave-shell-bp-alist)
-;(defvar idlwave-shell-post-command-output)
-(defvar idlwave-shell-sources-alist)
-(defvar idlwave-shell-menu-def)
-(defvar idlwave-shell-mode-menu)
-(defvar idlwave-shell-initial-commands)
-(defvar idlwave-shell-syntax-error)
-(defvar idlwave-shell-other-error)
-(defvar idlwave-shell-error-buffer)
-(defvar idlwave-shell-error-last)
-(defvar idlwave-shell-bp-buffer)
-(defvar idlwave-shell-sources-query)
-(defvar idlwave-shell-mode-map)
-(defvar idlwave-shell-calling-stack-index)
-(defvar idlwave-shell-only-prompt-pattern nil)
-(defvar tool-bar-map)
-
-(define-derived-mode idlwave-shell-mode comint-mode "IDL-Shell"
-  "Major mode for interacting with an inferior IDL process.
-
-1. Shell Interaction
-   -----------------
-   RET after the end of the process' output sends the text from the
-   end of process to the end of the current line.  RET before end of
-   process output copies the current line (except for the prompt) to
-   the end of the buffer.
-
-   Command history, searching of previous commands, command line
-   editing are available via the comint-mode key bindings, by default
-   mostly on the key \\`C-c'.  Command history is also available with
-   the arrow keys UP and DOWN.
-
-2. Completion
-   ----------
-   TAB and M-TAB do completion of IDL routines, classes and keywords -
-   similar to M-TAB in `idlwave-mode'.  In executive commands and
-   strings, it completes file names.  Abbreviations are also expanded
-   like in `idlwave-mode'.
-
-3. Routine Info
-   ------------
-   \\[idlwave-routine-info] displays information about an IDL routine near point,
-   just like in `idlwave-mode'.  The module used is the one at point or
-   the one whose argument list is being edited.
-   To update IDLWAVE's knowledge about compiled or edited modules, use
-   \\[idlwave-update-routine-info].
-   \\[idlwave-find-module] find the source of a module.
-   \\[idlwave-resolve] tells IDL to compile an unresolved module.
-   \\[idlwave-context-help] shows the online help on the item at
-   point, if online help has been installed.
-
-
-4. Debugging
-   ---------
-   A complete set of commands for compiling and debugging IDL programs
-   is available from the menu.  Also keybindings starting with a
-   \\`C-c C-d' prefix are available for most commands in the *idl* buffer
-   and also in source buffers.  The best place to learn about the
-   keybindings is again the menu.
-
-   On Emacs versions where this is possible, a debugging toolbar is
-   installed.
-
-   When IDL is halted in the middle of a procedure, the corresponding
-   line of that procedure file is displayed with an overlay in another
-   window.  Breakpoints are also highlighted in the source.
-
-   \\[idlwave-shell-resync-dirs] queries IDL in order to change Emacs current directory
-   to correspond to the IDL process current directory.
-
-5. Expression Examination
-   ----------------------
-
-   Expressions near point can be examined with print,
-   \\[idlwave-shell-print] or \\[idlwave-shell-mouse-print] with the
-   mouse, help, \\[idlwave-shell-help-expression] or
-   \\[idlwave-shell-mouse-help] with the mouse, or with a
-   configurable set of custom examine commands using
-   \\[idlwave-shell-examine-select].  The mouse examine commands can
-   also work by click and drag, to select an expression for
-   examination.
-
-6. Hooks
-   -----
-   Turning on `idlwave-shell-mode' runs `comint-mode-hook' and
-   `idlwave-shell-mode-hook' (in that order).
-
-7. Documentation and Customization
-   -------------------------------
-   Info documentation for this package is available.  Use \\[idlwave-info]
-   to display (complain to your sysadmin if that does not work).
-   For PostScript and HTML versions of the documentation, see IDLWAVE's
-   website at URL `https://github.com/jdtsmith/idlwave'.
-   IDLWAVE has customize support - see the group `idlwave'.
-
-8. Keybindings
-   -----------
-\\{idlwave-shell-mode-map}"
-  :abbrev-table idlwave-mode-abbrev-table
-  (idlwave-setup) ; Make sure config files and paths, etc. are available.
-  (unless (file-name-absolute-p idlwave-shell-command-history-file)
-    (setq idlwave-shell-command-history-file
-         (expand-file-name idlwave-shell-command-history-file
-                           idlwave-config-directory)))
-
-  (setq comint-prompt-regexp idlwave-shell-prompt-pattern)
-  (setq comint-process-echoes t)
-
-  ;; Can not use history expansion because "!" is used for system variables.
-  (setq comint-input-autoexpand nil)
-  ;; (setq comint-input-ring-size 64)
-
-  (set (make-local-variable 'completion-ignore-case) t)
-  (set (make-local-variable 'comint-completion-addsuffix) '("/" . ""))
-  (setq comint-input-ignoredups t)
-  (setq idlwave-shell-mode-line-info nil)
-  (setq mode-line-format
-       '(""
-         mode-line-modified
-         mode-line-buffer-identification
-         "   "
-         global-mode-string
-         "   %[("
-         mode-name
-         mode-line-process
-         minor-mode-alist
-         "%n"
-         ")%]-"
-         idlwave-shell-mode-line-info
-         "---"
-         (line-number-mode "L%l--")
-         (column-number-mode "C%c--")
-         (-3 . "%p")
-         "-%-"))
-  ;; (make-local-variable 'idlwave-shell-bp-alist)
-  (setq idlwave-shell-halt-frame nil
-        idlwave-shell-trace-frame nil
-        idlwave-shell-command-output nil
-        idlwave-shell-step-frame nil)
-  (idlwave-shell-display-line nil)
-  (setq idlwave-shell-calling-stack-index 0)
-  (setq idlwave-shell-only-prompt-pattern
-       (concat "\\`[ \t\n]*"
-               (substring idlwave-shell-prompt-pattern 1)
-               "[ \t\n]*\\'"))
-
-  (when idlwave-shell-query-for-class
-      (add-hook 'idlwave-determine-class-functions
-               #'idlwave-shell-get-object-class nil t)
-      (setq idlwave-store-inquired-class t))
-
-  ;; Make sure comint-last-input-end does not go to beginning of
-  ;; buffer (in case there were other processes already in this buffer).
-  (set-marker comint-last-input-end (point))
-  (setq idlwave-idlwave_routine_info-compiled nil)
-  (setq idlwave-shell-ready nil)
-  (setq idlwave-shell-bp-alist nil)
-  (idlwave-shell-update-bp-overlays) ; Throw away old overlays
-  (setq idlwave-shell-post-command-hook nil ;clean up any old stuff
-       idlwave-shell-sources-alist nil)
-  (setq idlwave-shell-default-directory default-directory)
-  (setq idlwave-shell-hide-output nil)
-
-  (add-hook 'kill-buffer-hook #'idlwave-shell-kill-shell-buffer-confirm
-           nil 'local)
-  (add-hook 'kill-buffer-hook #'idlwave-shell-delete-temp-files nil 'local)
-  (add-hook 'kill-emacs-hook #'idlwave-shell-delete-temp-files)
-
-  ;; Set the optional comint variables
-  (when idlwave-shell-comint-settings
-    (let ((list idlwave-shell-comint-settings) entry)
-      (while (setq entry (pop list))
-       (set (make-local-variable (car entry)) (cdr entry)))))
-
-
-  (unless (memq #'comint-carriage-motion
-               (default-value 'comint-output-filter-functions))
-    ;; Strip those pesky ctrl-m's.
-    (add-hook 'comint-output-filter-functions
-             (lambda (string)
-               (when (string-search "\r" string)
-                 (let ((pmark (process-mark (get-buffer-process
-                                             (current-buffer)))))
-                   (save-excursion
-                     ;; bare CR -> delete preceding line
-                     (goto-char comint-last-output-start)
-                     (while (search-forward "\r" pmark t)
-                       (delete-region (point) (line-beginning-position)))))))
-               'append 'local)
-    (add-hook 'comint-output-filter-functions #'comint-strip-ctrl-m nil 'local))
-
-  ;; Python-mode, bundled with many Emacs installs, quite cavalierly
-  ;; adds this function to the global default hook.  It interferes
-  ;; with overlay-arrows.
-  ;; FIXME: We should fix this interference rather than globally turn it off.
-  (when (fboundp 'py-pdbtrack-track-stack-file)
-    (remove-hook 'comint-output-filter-functions
-                 #'py-pdbtrack-track-stack-file))
-
-  ;; IDLWAVE syntax, and turn on abbreviations
-  (set (make-local-variable 'comment-start) ";")
-  (setq abbrev-mode t)
-
-  (add-hook 'post-command-hook #'idlwave-command-hook nil t)
-
-  ;; Read the command history?
-  (when (and idlwave-shell-save-command-history
-            (stringp idlwave-shell-command-history-file))
-    (set (make-local-variable 'comint-input-ring-file-name)
-        idlwave-shell-command-history-file)
-    (if (file-regular-p idlwave-shell-command-history-file)
-       (comint-read-input-ring)))
-
-  ;; Turn off the non-debug toolbar buttons (open,save,etc.)
-  (set (make-local-variable 'tool-bar-map) nil)
-
-  (idlwave-shell-send-command idlwave-shell-initial-commands nil 'hide)
-  ;; Turn off IDL's ^d interpreting, and define a system
-  ;; variable which knows the version of IDLWAVE
-  (idlwave-shell-send-command
-   (format "defsysv,'!idlwave_version','%s',1" idlwave-mode-version)
-   nil 'hide)
-  ;; Read the paths, and save if they changed
-  (idlwave-shell-send-command idlwave-shell-path-query
-                             'idlwave-shell-get-path-info
-                             'hide))
-
-(defvar idlwave-system-directory)
-(defun idlwave-shell-get-path-info (&optional no-write)
-  "Get the path lists, writing to file unless NO-WRITE is set."
-  (let* ((rpl (idlwave-shell-path-filter))
-        (sysdir (car rpl))
-        (dirs (cdr rpl))
-        (old-path-alist idlwave-path-alist)
-        (old-sys-dir idlwave-system-directory)
-        path-changed sysdir-changed)
-    (when sysdir
-      (setq idlwave-system-directory sysdir)
-      (if (setq sysdir-changed
-               (not (string= idlwave-system-directory old-sys-dir)))
-         (put 'idlwave-system-directory 'from-shell t)))
-    ;; Preserve any existing flags
-    (setq idlwave-path-alist
-         (mapcar (lambda (x)
-                   (let ((old-entry (assoc x old-path-alist)))
-                     (if old-entry
-                         (cons x (cdr old-entry))
-                       (list x))))
-                 dirs))
-    (if (setq path-changed (not (equal idlwave-path-alist old-path-alist)))
-       (put 'idlwave-path-alist 'from-shell t))
-    (if idlwave-path-alist
-       (if (and (not no-write)
-                idlwave-auto-write-paths
-                (or sysdir-changed path-changed)
-                (not idlwave-library-path))
-           (idlwave-write-paths))
-      ;; Fall back
-      (setq idlwave-path-alist old-path-alist))))
-
-(if (not (fboundp 'idl-shell))
-    (defalias 'idl-shell #'idlwave-shell))
-
-(defvar idlwave-shell-idl-wframe nil
-  "Frame for displaying the IDL shell window.")
-(defvar idlwave-shell-display-wframe nil
-  "Frame for displaying the IDL source files.")
-
-(defvar idlwave-shell-calling-stack-index 0)
-(defvar idlwave-shell-calling-stack-routine nil)
-
-(defun idlwave-shell-source-frame ()
-  "Return the frame to be used for source display."
-  (if idlwave-shell-use-dedicated-frame
-      ;; We want separate frames for source and shell
-      (if (frame-live-p idlwave-shell-display-wframe)
-         ;; The frame exists, so we use it.
-         idlwave-shell-display-wframe
-       ;; The frame does not exist.  We use the current frame.
-       ;; However, if the current is the shell frame, we make a new frame,
-       ;; or recycle the first existing visible frame
-       (setq idlwave-shell-display-wframe
-             (if (eq (selected-frame) idlwave-shell-idl-wframe)
-                 (or
-                  (let ((flist (visible-frame-list)))
-                    (catch 'exit
-                      (while flist
-                        (if (not (eq (car flist)
-                                     idlwave-shell-idl-wframe))
-                            (throw 'exit (car flist))
-                          (setq flist (cdr flist))))))
-                  (make-frame))
-               (selected-frame))))))
-
-(defun idlwave-shell-shell-frame ()
-  "Return the frame to be used for the shell buffer."
-  (if idlwave-shell-use-dedicated-frame
-      ;; We want a dedicated frame
-      (if (frame-live-p idlwave-shell-idl-wframe)
-         ;; It does exist, so we use it.
-         idlwave-shell-idl-wframe
-       ;; It does not exist.  Check if we have a source frame.
-       (if (not (frame-live-p idlwave-shell-display-wframe))
-           ;; We do not have a source frame, so we use this one.
-           (setq idlwave-shell-display-wframe (selected-frame)))
-       ;; Return a new frame
-       (setq idlwave-shell-idl-wframe
-             (make-frame idlwave-shell-frame-parameters)))))
-
-;;;###autoload
-(defun idlwave-shell (&optional arg)
-  "Run an inferior IDL, with I/O through buffer `(idlwave-shell-buffer)'.
-If buffer exists but shell process is not running, start new IDL.
-If buffer exists and shell process is running, just switch to the buffer.
-
-When called with a prefix ARG, or when `idlwave-shell-use-dedicated-frame'
-is non-nil, the shell buffer and the source buffers will be in
-separate frames.
-
-The command to run comes from variable `idlwave-shell-explicit-file-name',
-with options taken from `idlwave-shell-command-line-options'.
-
-The buffer is put in `idlwave-shell-mode', providing commands for sending
-input and controlling the IDL job.  See help on `idlwave-shell-mode'.
-See also the variable `idlwave-shell-prompt-pattern'.
-
-\(Type \\[describe-mode] in the shell buffer for a list of commands.)"
-  (interactive "P")
-  (if (eq arg 'quick)
-      (progn
-       (let ((idlwave-shell-use-dedicated-frame nil))
-         (idlwave-shell nil)
-         (delete-other-windows))
-       (and idlwave-shell-use-dedicated-frame
-            (setq idlwave-shell-idl-wframe (selected-frame)))
-       (add-hook 'idlwave-shell-sentinel-hook
-                 #'save-buffers-kill-emacs t))
-
-    ;; A non-nil arg means, we want a dedicated frame.  This will last
-    ;; for the current editing session.
-    (if arg (setq idlwave-shell-use-dedicated-frame t))
-    (if (equal arg '(16)) (setq idlwave-shell-use-dedicated-frame nil))
-
-    ;; Check if the process still exists.  If not, create it.
-    (unless (comint-check-proc (idlwave-shell-buffer))
-      (let* ((prg (or idlwave-shell-explicit-file-name "idl"))
-            (buf (apply #'make-comint
-                        idlwave-shell-process-name prg nil
-                        (if (stringp idlwave-shell-command-line-options)
-                            (idlwave-split-string
-                             idlwave-shell-command-line-options)
-                          idlwave-shell-command-line-options)))
-            (process (get-buffer-process buf)))
-       (setq idlwave-idlwave_routine_info-compiled nil)
-       (set-process-filter process #'idlwave-shell-filter)
-       (set-process-sentinel process #'idlwave-shell-sentinel)
-       (set-buffer buf)
-       (idlwave-shell-mode)))
-    (let ((window (idlwave-display-buffer (idlwave-shell-buffer) nil
-                                         (idlwave-shell-shell-frame)))
-         (current-window (selected-window)))
-      (select-window window)
-      (goto-char (point-max))
-      (if idlwave-shell-use-dedicated-window
-         (set-window-dedicated-p window t))
-      (select-window current-window)
-      (if idlwave-shell-ready
-         (raise-frame (window-frame window)))
-      (if (eq (selected-frame) (window-frame window))
-         (select-window window))))
-  ;; Save the paths at the end, if they are from the Shell and new.
-  (add-hook 'idlwave-shell-sentinel-hook
-           (lambda ()
-             (if (and
-                  idlwave-auto-write-paths
-                  idlwave-path-alist
-                  (not idlwave-library-path)
-                  (get 'idlwave-path-alist 'from-shell))
-                 (idlwave-write-paths)))))
-
-(defun idlwave-shell-recenter-shell-window (&optional arg)
-  "Run `idlwave-shell', but make sure the current window stays selected."
-  (interactive "P")
-  (let ((window (selected-window)))
-    (idlwave-shell arg)
-    (select-window window)))
-
-(defun idlwave-shell-hide-p (type &optional list)
-  "Whether to hide this type of command.
-Return either nil or `hide'."
-  (let ((list (or list idlwave-shell-show-commands)))
-    (if (listp list)
-      (if (not (memq type list)) 'hide))))
-
-(defun idlwave-shell-add-or-remove-show (type)
-  "Add or remove a show command from the list."
-  (if (listp idlwave-shell-show-commands)
-      (setq idlwave-shell-show-commands
-           (if (memq type idlwave-shell-show-commands)
-               (delq type idlwave-shell-show-commands)
-             (add-to-list'idlwave-shell-show-commands type)))
-    (setq idlwave-shell-show-commands (list type))))
-
-
-(defun idlwave-shell-send-command (&optional cmd pcmd hide preempt
-                                            show-if-error)
-  "Send a command to IDL process.
-
-\(CMD PCMD HIDE) are placed at the end of `idlwave-shell-pending-commands'.
-If IDL is ready the first command in `idlwave-shell-pending-commands',
-CMD, is sent to the IDL process.
-
-If optional second argument PCMD is non-nil it will be placed on
-`idlwave-shell-post-command-hook' when CMD is executed.
-
-If the optional third argument HIDE is non-nil, then hide output from
-CMD, unless it is the symbol `mostly', in which case only output
-beginning with \"%\" is hidden, and all other output (i.e., the
-results of a PRINT command), is shown.  This helps with, e.g.,
-stepping through code with output.
-
-If optional fourth argument PREEMPT is non-nil CMD is put at front of
-`idlwave-shell-pending-commands'.  If PREEMPT is `wait', wait for all
-output to complete and the next prompt to arrive before returning
-\(useful if you need an answer now).  IDL is considered ready if the
-prompt is present and if `idlwave-shell-ready' is non-nil.
-
-If SHOW-IF-ERROR is non-nil, show the output if it contains an error
-message, independent of what HIDE is set to."
-
-;  (setq hide nil)  ;  FIXME: turn this on for debugging only
-;  (if (null cmd)
-;      (progn
-;      (message "SENDING Pending commands: %s"
-;               (prin1-to-string idlwave-shell-pending-commands)))
-;  (message "SENDING %s|||%s" cmd pcmd))
-  (if (and (symbolp idlwave-shell-show-commands)
-          (eq idlwave-shell-show-commands 'everything))
-      (setq hide nil))
-  (let ((save-buffer (current-buffer))
-       buf proc)
-    ;; Get or make the buffer and its process
-    (if (or (not (setq buf (get-buffer (idlwave-shell-buffer))))
-           (not (setq proc (get-buffer-process buf))))
-       (if (not idlwave-shell-automatic-start)
-           (error "%s"
-            (substitute-command-keys
-             "You need to first start an IDL shell with \\[idlwave-shell]"))
-         (idlwave-shell-recenter-shell-window)
-         (setq buf (get-buffer (idlwave-shell-buffer)))
-         (if (or (not (setq buf (get-buffer (idlwave-shell-buffer))))
-                 (not (setq proc (get-buffer-process buf))))
-             ;; Still nothing
-             (error "Problem with autostarting IDL shell"))))
-    (when (or cmd idlwave-shell-pending-commands)
-      (set-buffer buf)
-      ;; To make this easy, always push CMD onto pending commands
-      (if cmd
-         (setq idlwave-shell-pending-commands
-               (if preempt
-                   ;; Put at front.
-                   (append (list (list cmd pcmd hide show-if-error))
-                           idlwave-shell-pending-commands)
-                 ;; Put at end.
-                 (append idlwave-shell-pending-commands
-                         (list (list cmd pcmd hide show-if-error))))))
-      ;; Check if IDL ready
-      (let ((save-point (point-marker)))
-       (goto-char (process-mark proc))
-       (if (and idlwave-shell-ready
-                ;; Check for IDL prompt
-                (prog2
-                  (forward-line 0)
-                  ;; (beginning-of-line) ; Changed for Emacs 21
-                  (looking-at idlwave-shell-prompt-pattern)
-                  (goto-char (process-mark proc))))
-           ;; IDL ready for command, execute it
-           (let* ((lcmd (car idlwave-shell-pending-commands))
-                  (cmd (car lcmd))
-                  (pcmd (nth 1 lcmd))
-                  (hide (nth 2 lcmd))
-                  (show-if-error (nth 3 lcmd)))
-             ;; If this is an executive command, reset the stack pointer
-             (if (eq (string-to-char cmd) ?.)
-                 (setq idlwave-shell-calling-stack-index 0))
-             ;; Set post-command
-             (setq idlwave-shell-post-command-hook pcmd)
-             ;; Output hiding
-             (setq idlwave-shell-hide-output hide)
-             ;;Showing errors
-             (setq idlwave-shell-show-if-error show-if-error)
-             ;; Pop command
-             (setq idlwave-shell-pending-commands
-                   (cdr idlwave-shell-pending-commands))
-             ;; Send command for execution
-             (set-marker comint-last-input-start (point))
-             (set-marker comint-last-input-end (point))
-             (comint-simple-send proc cmd)
-             (setq idlwave-shell-ready nil)
-             (if (equal preempt 'wait) ; Get all the output at once
-               (while (not idlwave-shell-ready)
-                 (when (not (accept-process-output proc 6)) ; long wait
-                   (setq idlwave-shell-pending-commands nil)
-                   (error "Process timed out"))))))
-       (goto-char save-point))
-      (set-buffer save-buffer))))
-
-(defun idlwave-shell-send-char (c &optional error)
-  "Send one character to the shell, without a newline."
-  (interactive "cChar to send to IDL: \np")
-  (let ((errf (if error 'error 'message))
-       buf proc)
-    (if (or (not (setq buf (get-buffer (idlwave-shell-buffer))))
-           (not (setq proc (get-buffer-process buf))))
-       (funcall errf "Shell is not running"))
-    (if (equal c ?\C-g)
-       (funcall errf "Abort")
-      (comint-send-string proc (char-to-string c)))))
-
-(defvar idlwave-shell-char-mode-active)
-(defun idlwave-shell-input-mode-magic (string)
-  "Check STRING for magic words and toggle character input mode.
-See also the variable `idlwave-shell-input-mode-spells'."
-  (cond
-   ((string-match (car idlwave-shell-input-mode-spells) string)
-    (call-interactively 'idlwave-shell-send-char))
-   ((and (boundp 'idlwave-shell-char-mode-active)
-        (string-match (nth 2 idlwave-shell-input-mode-spells) string))
-    (setq idlwave-shell-char-mode-active 'exit))
-   ((string-match (nth 1 idlwave-shell-input-mode-spells) string)
-    ;; Set a timer which will soon start the character loop
-    (run-at-time 0.5 nil #'idlwave-shell-char-mode-loop 'no-error))))
-
-(defvar keyboard-quit)
-(defun idlwave-shell-char-mode-loop (&optional no-error)
-  "Enter a loop which accepts single characters and sends them to IDL.
-Characters are sent one by one, without newlines.  The loop is blocking
-and intercepts all input events to Emacs.  You can use this command
-to interact with the IDL command GET_KBRD.
-The loop can be aborted by typing \\[keyboard-quit].  The loop also exits automatically
-when the IDL prompt gets displayed again after the current IDL command."
-  (interactive)
-
-  ;; First check if there is a shell waiting for input
-  (let ((idlwave-shell-char-mode-active t)
-       (errf (if no-error 'message 'error))
-       buf proc c)
-    (if (or (not (setq buf (get-buffer (idlwave-shell-buffer))))
-           (not (setq proc (get-buffer-process buf))))
-       (funcall errf "Shell is not running"))
-    (if idlwave-shell-ready
-       (funcall errf "No IDL program seems to be waiting for input"))
-
-    ;; OK, start the loop
-    (message (substitute-command-keys
-              "Character mode on:  Sending single chars (\\[keyboard-quit] to exit)"))
-    (message
-     (catch 'exit
-       (while t
-        ;; Wait for input
-        ;; FIXME: Is it too dangerous to inhibit quit here?
-        (let ((inhibit-quit t))
-          ;; We wait and check frequently if we should abort
-          (while (sit-for 0.3)
-            (and idlwave-shell-ready
-                 (throw 'exit "Character mode off (prompt displayed)"))
-            (and (eq idlwave-shell-char-mode-active 'exit)
-                 (throw 'exit "Character mode off (closing spell incantation)")))
-          ;; Interpret input as a character - ignore non-char input
-          (condition-case nil
-              (setq c (read-char))
-            (error (ding) (throw 'exit "Character mode off")))
-          (cond
-           ((null c)               ; Non-char event: ignore
-            (ding))
-           ((equal c ?\C-g)        ; Abort the loop
-            (setq keyboard-quit nil)
-            (ding)
-            (throw 'exit "Character mode off (keyboard quit)"))
-           (t                     ; Send the character and continue the loop
-            (comint-send-string proc (char-to-string c))))
-          (and (eq idlwave-shell-char-mode-active 'exit)
-               (throw 'exit "Single char loop exited"))))))))
-
-(defun idlwave-shell-move-or-history (up &optional arg)
-  "When in last line of process buffer, do `comint-previous-input'.
-Otherwise just move the line.  Move down unless UP is non-nil."
-  (let* ((proc-pos (marker-position
-                   (process-mark (get-buffer-process (current-buffer)))))
-        (arg (or arg 1))
-        (arg (if up arg (- arg))))
-    (if (eq t idlwave-shell-arrows-do-history) (goto-char proc-pos))
-    (if (and idlwave-shell-arrows-do-history
-             (>= (1+ (line-end-position)) proc-pos))
-       (comint-previous-input arg)
-      (forward-line (- arg)))))
-
-(defun idlwave-shell-up-or-history (&optional arg)
-  "When in last line of process buffer, move to previous input.
-Otherwise just go up one line."
-  (interactive "p")
-  (idlwave-shell-move-or-history t arg))
-
-(defun idlwave-shell-down-or-history (&optional arg)
-  "When in last line of process buffer, move to next input.
-Otherwise just go down one line."
-  (interactive "p")
-  (idlwave-shell-move-or-history nil arg))
-
-(define-obsolete-function-alias 'idlwave-shell-comint-filter
-  #'comint-output-filter "25.1")
-
-(defun idlwave-shell-is-running ()
-  "Return t if the shell process is running."
-  (eq (process-status idlwave-shell-process-name) 'run))
-
-(defun idlwave-shell-filter-hidden-output (output)
-  "Filter hidden output, leaving the good stuff.
-
-Remove everything to the first newline, and all lines with % in front
-of them, with optional follow-on lines starting with two spaces.  This
-works well enough, since any print output typically arrives before
-error messages, etc."
-  (setq output (substring output (string-search "\n" output)))
-  (while (string-match "\\(\n\\|\\`\\)%.*\\(\n  .*\\)*" output)
-    (setq output (replace-match "" nil t output)))
-  (unless
-      (string-match idlwave-shell-only-prompt-pattern output)
-    output))
-
-(defvar idlwave-shell-hidden-output-buffer " *idlwave-shell-hidden-output*"
-  "Buffer containing hidden output from IDL commands.")
-(defvar idlwave-shell-current-state nil)
-
-(defun idlwave-shell-filter (proc string)
-  "Watch for IDL prompt and filter incoming text.
-When the IDL prompt is received executes `idlwave-shell-post-command-hook'
-and then calls `idlwave-shell-send-command' for any pending commands."
-  ;; We no longer do the cleanup here - this is done by the process sentinel
-  (if (eq (process-status idlwave-shell-process-name) 'run)
-      ;; OK, process is still running, so we can use it.
-      (let ((data (match-data)) p full-output)
-       (unwind-protect
-           (progn
-             ;; Ring the bell if necessary
-             (while (setq p (string-search "\C-G" string))
-               (ding)
-               (aset string p ?\C-j ))
-             (if idlwave-shell-hide-output
-                 (save-excursion
-                   (while (setq p (string-search "\C-M" string))
-                     (aset string p ?\  ))
-                   (set-buffer
-                    (get-buffer-create idlwave-shell-hidden-output-buffer))
-                   (goto-char (point-max))
-                   (insert string))
-               (comint-output-filter proc string))
-             ;; Watch for magic - need to accumulate the current line
-             ;; since it may not be sent all at once.
-             (if (string-search "\n" string)
-                 (progn
-                   (if idlwave-shell-use-input-mode-magic
-                       (idlwave-shell-input-mode-magic
-                        (concat idlwave-shell-accumulation string)))
-                   (setq idlwave-shell-accumulation
-                         (substring string
-                                    (string-match "[^\n\r]*\\'" string))))
-               (setq idlwave-shell-accumulation
-                     (concat idlwave-shell-accumulation string)))
-
-
-              ;; ;; Test/Debug code
-             ;;(with-current-buffer
-             ;;    (get-buffer-create "*idlwave-shell-output*")
-             ;;  (goto-char (point-max))
-             ;;  (insert "\nReceived STRING\n===>\n" string "\n<====\n"))
-
-             ;; Check for prompt in current accumulating output
-             (when (setq idlwave-shell-ready
-                         (string-match idlwave-shell-prompt-pattern
-                                       idlwave-shell-accumulation))
-               ;; Gather the command output
-               (if idlwave-shell-hide-output
-                   (with-current-buffer idlwave-shell-hidden-output-buffer
-                     (setq full-output (buffer-string))
-                     (goto-char (point-max))
-                     (re-search-backward idlwave-shell-prompt-pattern nil t)
-                     (goto-char (match-end 0))
-                     (setq idlwave-shell-command-output
-                           (buffer-substring-no-properties
-                            (point-min) (point)))
-                     (delete-region (point-min) (point)))
-                 (setq idlwave-shell-command-output
-                       (with-current-buffer (process-buffer proc)
-                       (buffer-substring-no-properties
-                        (save-excursion
-                          (goto-char (process-mark proc))
-                          (forward-line 0) ; Emacs 21 (beginning-of-line nil)
-                          (point))
-                        comint-last-input-end))))
-
-               ;; Scan for state and do post commands - bracket
-               ;; them with idlwave-shell-ready=nil since they may
-               ;; call idlwave-shell-send-command themselves.
-               (let ((idlwave-shell-ready nil))
-                 (idlwave-shell-scan-for-state)
-                 ;; Show the output in the shell if it contains an error
-                 (if idlwave-shell-hide-output
-                     (if (and idlwave-shell-show-if-error
-                              (eq idlwave-shell-current-state 'error))
-                         (comint-output-filter proc full-output)
-                       ;; If it's only *mostly* hidden, filter % lines,
-                       ;; and show anything that remains
-                       (if (eq idlwave-shell-hide-output 'mostly)
-                           (let ((filtered
-                                  (idlwave-shell-filter-hidden-output
-                                   full-output)))
-                             (if filtered
-                                 (comint-output-filter
-                                  proc filtered))))))
-
-                 ;; Call the post-command hook
-                 (if (functionp idlwave-shell-post-command-hook)
-                     ;;(message "Calling command function")
-                     (funcall idlwave-shell-post-command-hook)
-                   ;;(message "Calling list")
-                   ;;(prin1 idlwave-shell-post-command-hook)
-                   (eval idlwave-shell-post-command-hook t))
-
-                 ;; Reset to default state for next command.
-                 ;; Also we do not want to find this prompt again.
-                 (setq idlwave-shell-accumulation nil
-                       idlwave-shell-command-output nil
-                       idlwave-shell-post-command-hook nil
-                       idlwave-shell-hide-output nil
-                       idlwave-shell-show-if-error nil))
-               ;; Done with post command.  Do pending command if
-               ;; any.
-               (idlwave-shell-send-command)))
-         (store-match-data data)))))
-
-(defun idlwave-shell-sentinel (process event)
-  "The sentinel function for the IDLWAVE shell process."
-  (let* ((buf (idlwave-shell-buffer))
-        (win (get-buffer-window buf)))
-    (when (get-buffer buf)
-      (with-current-buffer (idlwave-shell-buffer)
-       (goto-char (point-max))
-       (insert (format "\n\n  Process %s %s" process event))
-       (if (and idlwave-shell-save-command-history
-                (stringp idlwave-shell-command-history-file))
-           (condition-case nil
-               (comint-write-input-ring)
-             (error nil)))))
-
-    (when (and (> (length (frame-list)) 1)
-              (frame-live-p idlwave-shell-idl-wframe))
-      (delete-frame idlwave-shell-idl-wframe)
-      (setq idlwave-shell-idl-wframe nil
-           idlwave-shell-display-wframe nil))
-    (when (and (window-live-p win)
-              (not (one-window-p 'nomini)))
-      (delete-window win))
-    (idlwave-shell-cleanup)
-    ;; Run the hook, if possible in the shell buffer.
-    (if (get-buffer buf)
-       (with-current-buffer buf
-         (run-hooks 'idlwave-shell-sentinel-hook))
-      (run-hooks 'idlwave-shell-sentinel-hook))))
-
-(defvar idlwave-shell-error-buffer " *idlwave-shell-errors*"
-  "Buffer containing syntax errors from IDL compilations.")
-
-;; FIXME: the following two variables do not currently allow line breaks
-;; in module and file names.  I am not sure if it will be necessary to
-;; change this.  Currently it seems to work the way it is.
-(defvar idlwave-shell-syntax-error
-  "^% Syntax error.\\s-*\n\\s-*At:\\s-*\\(.*\\),\\s-*Line\\s-*\\(.*\\)"
-  "A regular expression to match an IDL syntax error.
-The first pair matches the file name, the second pair matches the line
-number.")
-
-(defvar idlwave-shell-other-error
-  "^% .*\n\\s-*At:\\s-*\\(.*\\),\\s-*Line\\s-*\\(.*\\)"
-  "A regular expression to match any IDL error.")
-
-(defvar idlwave-shell-halting-error
-  "^% .*\n\\([^%].*\n\\)*% Execution halted at:\\(\\s-*\\S-+\\s-*[0-9]+.*\\)\n"
-  "A regular expression to match errors which halt execution.")
-
-(defvar idlwave-shell-cant-continue-error
-  "^% Can't continue from this point.\n"
-  "A regular expression to match errors stepping errors.")
-
-(defvar idlwave-shell-file-line-message
-  (concat
-   "\\("                                 ; program name group (1)
-   "\\$MAIN\\$\\|"                      ; main level routine
-   "\\<[a-zA-Z][a-zA-Z0-9_$:]*"          ; start with a letter followed by [..]
-   "\\([ \t]*\n[ \t]*[a-zA-Z0-9_$:]+\\)*"; continuation lines program name (2)
-   "\\)"                                 ; end program name group (1)
-   "[ \t\n]+"                            ; white space
-   "\\("                                 ; line number group (3)
-   "[0-9]+"                              ; the line number (the fix point)
-   "\\([ \t]*\n[ \t]*[0-9]+\\)*"         ; continuation lines number (4)
-   "\\)"                                 ; end line number group (3)
-   "[ \t\n]+"                            ; white space
-   "\\("                                 ; file name group (5)
-   "[^ \t\n]+"                           ; file names can contain any non-white
-   "\\([ \t]*\n[ \t]*[^ \t\n]+\\)*"      ; continuation lines file name (6)
-   "\\)"                                 ; end line number group (5)
-   )
-  "A regular expression to parse out the file name and line number.
-The 1st group should match the subroutine name.
-The 3rd group is the line number.
-The 5th group is the file name.
-All parts may contain linebreaks surrounded by spaces.  This is important
-in IDL5 which inserts random linebreaks in long module and file names.")
-
-(defvar idlwave-shell-electric-debug-mode) ; defined by easy-mmode
-
-(defun idlwave-shell-scan-for-state ()
-  "Scan for state info.
-Looks for messages in output from last IDL command indicating where
-IDL has stopped.  The types of messages we are interested in are
-execution halted, stepped, breakpoint, interrupted at and trace
-messages.  For breakpoint messages process any attached count or
-command parameters.  Update the stop line if a message is found.
-The variable `idlwave-shell-current-state' is set to `error', `halt',
-or `breakpoint', which describes the status, or nil for none of
-the above."
-  (let (trace)
-    (cond
-     ;; Make sure we have output
-     ((not idlwave-shell-command-output))
-
-     ;; First Priority: Syntax and other errors
-     ((or
-       (string-match idlwave-shell-syntax-error
-                    idlwave-shell-command-output)
-       (string-match idlwave-shell-other-error
-                    idlwave-shell-command-output))
-      (with-current-buffer
-         (get-buffer-create idlwave-shell-error-buffer)
-       (erase-buffer)
-       (insert idlwave-shell-command-output)
-       (goto-char (point-min))
-       (setq idlwave-shell-error-last (point)))
-      (setq idlwave-shell-current-state 'error)
-      (idlwave-shell-goto-next-error))
-
-     ;; Second Priority: Halting errors
-     ((string-match idlwave-shell-halting-error
-                   idlwave-shell-command-output)
-      ;; Grab the file and line state info.
-      (setq idlwave-shell-calling-stack-index 0)
-      (setq idlwave-shell-halt-frame
-           (idlwave-shell-parse-line
-            (substring idlwave-shell-command-output
-                       (match-beginning 2)))
-           idlwave-shell-current-state 'error)
-      (idlwave-shell-display-line (idlwave-shell-pc-frame)))
-
-     ;; Third Priority: Various types of innocuous HALT and
-     ;; TRACEBACK messages.
-     ((or (setq trace (string-match idlwave-shell-trace-message-re
-                                   idlwave-shell-command-output))
-         (string-match idlwave-shell-halt-messages-re
-                       idlwave-shell-command-output))
-      ;; Grab the file and line state info.
-      (setq idlwave-shell-calling-stack-index 0)
-      (setq idlwave-shell-halt-frame
-           (idlwave-shell-parse-line
-            (substring idlwave-shell-command-output (match-end 0))))
-      (setq idlwave-shell-current-state 'halt)
-      ;; Don't debug trace messages
-      (idlwave-shell-display-line
-       (idlwave-shell-pc-frame) nil
-       (if trace 'disable
-        (if idlwave-shell-electric-debug-mode 'force))))
-
-     ;; Fourth Priority: Breakpoints
-     ((string-match idlwave-shell-break-message
-                   idlwave-shell-command-output)
-      (setq idlwave-shell-calling-stack-index 0)
-      (setq idlwave-shell-halt-frame
-           (idlwave-shell-parse-line
-            (substring idlwave-shell-command-output (match-end 0))))
-      ;; We used to count hits on breakpoints
-      ;; this is no longer supported since IDL breakpoints
-      ;; have learned counting.
-      ;; Do breakpoint command processing
-      (let ((bp (assoc
-                (list
-                 (nth 0 idlwave-shell-halt-frame)
-                 (nth 1 idlwave-shell-halt-frame))
-                idlwave-shell-bp-alist)))
-       ;(message "Scanning with %s" bp)
-       (if bp
-           (let ((cmd (idlwave-shell-bp-get bp 'cmd)))
-             (if cmd ;; Execute any breakpoint command
-                 (if (functionp cmd) (funcall cmd) (eval cmd t))))
-         ;; A breakpoint that we did not know about - perhaps it was
-         ;; set by the user...  Let's update our list.
-         (idlwave-shell-bp-query)))
-      (setq idlwave-shell-current-state 'breakpoint)
-      (idlwave-shell-display-line (idlwave-shell-pc-frame)))
-
-     ;; Last Priority: Can't Step errors
-     ((string-match idlwave-shell-cant-continue-error
-                   idlwave-shell-command-output)
-      (setq idlwave-shell-current-state 'breakpoint))
-
-     ;; Otherwise, no particular state
-     (t (setq idlwave-shell-current-state nil)))))
-
-
-(defun idlwave-shell-parse-line (string &optional skip-main)
-  "Parse IDL message for the subroutine, file name and line number."
-;We need to work hard here to remove the stupid line breaks inserted by
-;IDL5.  These line breaks can be right in the middle of procedure
-;or file names.
-;It is very difficult to come up with a robust solution.  This one seems
-;to be pretty good though.
-;
-;Here is in what ways it improves over the previous solution:
-;
-;1. The procedure name can be split and will be restored.
-;2. The number can be split.  I have never seen this, but who knows.
-;3. We do not require the `.pro' extension for files.
-;
-;This function can still break when the file name ends on an end line
-;and the message line contains an additional line with garbage.  Then
-;the first part of that garbage will be added to the file name.
-;However, the function checks the existence of the files with and
-;without this last part - thus the function only breaks if file name
-;plus garbage match an existing regular file.  This is hopefully very
-;unlikely.
-;
-;If optional arg SKIP-MAIN is non-nil, don't parse $MAIN$ routine stop
-;statements.
-
-  (let (number procedure file)
-    (when (and (not (if skip-main (string-match ":\\s-*\\$MAIN" string)))
-              (string-match idlwave-shell-file-line-message string))
-      (setq procedure (match-string 1 string)
-           number (match-string 3 string)
-           file (match-string 5 string))
-
-      ;; Repair the strings
-      (setq procedure (idlwave-shell-repair-string procedure))
-      (setq number (idlwave-shell-repair-string number))
-      (setq file (idlwave-shell-repair-file-name file))
-
-      ;; If we have a file, return the frame list
-      (if file
-         (list (idlwave-shell-file-name file)
-               (string-to-number number)
-               procedure)
-       ;; No success finding a file
-       nil))))
-
-(defun idlwave-shell-repair-string (string)
-  "Repair a string by taking out all linebreaks.  This is destructive!"
-  (while (string-match "[ \t]*\n[ \t]*" string)
-    (setq string (replace-match "" t t string)))
-  string)
-
-(defun idlwave-shell-repair-file-name (file)
-  "Repair a file name string by taking out all linebreaks.
-The last line of STRING may be garbage - we check which one makes a valid
-file name."
-  (let ((file1 "") (file2 "") (start 0))
-    ;; We scan no further than to the next "^%" line
-    (if (string-match "^%" file)
-       (setq file (substring file 0 (match-beginning 0))))
-    ;; Take out the line breaks
-    (while (string-match "[ \t]*\n[ \t]*" file start)
-      (setq file1 (concat file1 (substring file start (match-beginning 0)))
-           start (match-end 0)))
-    (setq file2 (concat file1 (substring file start)))
-    (cond
-     ((file-regular-p file2) file2)
-     ((file-regular-p file1) file1)
-     ;; If we cannot verify the existence of the file, we return the shorter
-     ;; name.  The idea behind this is that this may be a relative file name
-     ;; and our idea about the current working directory may be wrong.
-     ;; If it is a relative file name, it hopefully is short.
-     ((not (string= "" file1)) file1)
-     ((not (string= "" file2)) file2)
-     (t nil))))
-
-(defun idlwave-shell-cleanup ()
-  "Do necessary cleanup for a terminated IDL process."
-  (setq idlwave-shell-step-frame nil
-        idlwave-shell-halt-frame nil
-        idlwave-shell-pending-commands nil
-       idlwave-shell-command-line-to-execute nil
-       idlwave-shell-bp-alist nil
-       idlwave-shell-calling-stack-index 0
-       idlwave-idlwave_routine_info-compiled nil)
-  (idlwave-shell-delete-temp-files)
-  (idlwave-shell-display-line nil)
-  (idlwave-shell-update-bp-overlays) ; kill old overlays
-  (idlwave-shell-kill-buffer idlwave-shell-hidden-output-buffer)
-  (idlwave-shell-kill-buffer idlwave-shell-bp-buffer)
-  (idlwave-shell-kill-buffer idlwave-shell-error-buffer)
-  ;; (idlwave-shell-kill-buffer (idlwave-shell-buffer))
-  (and (get-buffer (idlwave-shell-buffer))
-       (bury-buffer (get-buffer (idlwave-shell-buffer))))
-  (run-hooks 'idlwave-shell-cleanup-hook))
-
-(defun idlwave-shell-kill-buffer (buf)
-  "Kill buffer BUF if it exists."
-  (if (setq buf (get-buffer buf))
-      (kill-buffer buf)))
-
-(defun idlwave-shell-kill-shell-buffer-confirm ()
-  (when (idlwave-shell-is-running)
-    (ding)
-    (unless (y-or-n-p "IDL shell is running.  Are you sure you want to kill the buffer? ")
-      (error "Abort"))
-    (message "Killing buffer *idl* and the associated process")))
-
-(defun idlwave-shell-window (n)
-  "Issue a `window,N' command to IDL, with special window size.
-The size is given by `idlwave-shell-graphics-window-size'."
-  (interactive "P")
-  (let ((n (if n (prefix-numeric-value n) 0)))
-    (idlwave-shell-send-command
-     (apply #'format "window,%d,xs=%d,ys=%d"
-           n idlwave-shell-graphics-window-size)
-     nil (idlwave-shell-hide-p 'misc) nil t)))
-
-(defun idlwave-shell-resync-dirs ()
-  "Resync the buffer's idea of the current directory.
-This command queries IDL with the command bound to
-`idlwave-shell-dirstack-query', reads the output for the new
-directory."
-  (interactive)
-  (idlwave-shell-send-command idlwave-shell-dirstack-query
-                             'idlwave-shell-filter-directory
-                             'hide 'wait))
-
-(defun idlwave-shell-retall ()
-  "Return from the entire calling stack.
-Also get rid of widget events in the queue."
-  (interactive)
-  (save-selected-window
-    ;;if (widget_info(/MANAGED))[0] gt 0 then for i=0,n_elements(widget_info(/MANAGED))-1 do widget_control,(widget_info(/MANAGED))[i],/clear_events &
-    (idlwave-shell-send-command "retall" nil
-                               (if (idlwave-shell-hide-p 'misc) 'mostly)
-                               nil t)
-    (idlwave-shell-display-line nil)))
-
-(defun idlwave-shell-closeall ()
-  "Close all open files."
-  (interactive)
-  (idlwave-shell-send-command "close,/all" nil
-                             (idlwave-shell-hide-p 'misc) nil t))
-
-(defun idlwave-shell-quit (&optional arg)
-  "Exit the IDL process after confirmation.
-With prefix ARG, exit without confirmation."
-  (interactive "P")
-  (if (not (idlwave-shell-is-running))
-      (error "Shell is not running")
-    (if (or arg (y-or-n-p "Exit the IDLWAVE Shell? "))
-       (condition-case nil
-           (idlwave-shell-send-command "exit")
-         (error nil)))))
-
-(defun idlwave-shell-reset (&optional hidden)
-  "Reset IDL.  Return to main level and destroy the leftover variables.
-This issues the following commands:
-RETALL
-WIDGET_CONTROL,/RESET
-CLOSE, /ALL
-HEAP_GC, /VERBOSE"
-  ;; OBJ_DESTROY, OBJ_VALID()  FIXME: should this be added?
-  (interactive "P")
-  (when (or idlwave-shell-reset-no-prompt
-           (yes-or-no-p "Really Reset IDL and discard current session? "))
-    (message "Resetting IDL")
-    (setq idlwave-shell-calling-stack-index 0)
-    ;; Give widget exit handlers a chance
-    (idlwave-shell-send-command "retall" nil hidden)
-    (idlwave-shell-send-command "widget_control,/reset" nil hidden)
-    (idlwave-shell-send-command "close,/all" nil hidden)
-    ;; (idlwave-shell-send-command "obj_destroy, obj_valid()" nil hidden)
-    (idlwave-shell-send-command "heap_gc,/verbose" nil hidden)
-    (idlwave-shell-display-line nil)))
-
-(defun idlwave-shell-path-filter ()
-  ;; Convert the output of the path query into a list of directories
-  (let ((path-string idlwave-shell-command-output)
-       (case-fold-search t)
-       (start 0)
-       dirs sysdir)
-    (while (string-match "^PATH:[ \t]*<\\(.*\\)>[ \t]*\n" path-string start)
-      (push (match-string 1 path-string) dirs)
-      (setq start (match-end 0)))
-    (setq dirs (mapcar #'file-name-as-directory dirs))
-    (if (string-match "^SYSDIR:[ \t]*<\\(.*\\)>[ \t]*\n" path-string)
-       (setq sysdir (file-name-as-directory
-                     (match-string 1 path-string))))
-    (cons sysdir (nreverse dirs))))
-
-(defun idlwave-shell-routine-info-filter ()
-  "Parse the special output from idlwave_routine_info.pro."
-  (let ((text idlwave-shell-command-output)
-       (start 0)
-       sep sep-re file type spec specs name cs key keys class entry)
-    ;;    (message "GOT: %s" text) ;??????????????????????
-    ;; Initialize variables
-    (setq idlwave-compiled-routines nil
-         idlwave-unresolved-routines nil)
-    ;; Cut out the correct part of the output.
-    (if (string-match
-        "^>>>BEGIN OF IDLWAVE ROUTINE INFO (\"\\(.+\\)\" IS THE SEPARATOR.*"
-        text)
-       (setq sep (match-string 1 text)
-             sep-re (concat (regexp-quote sep) " *")
-             text (substring text (match-end 0)))
-      ;; Set dummy values and kill the text
-      (setq sep "@" sep-re "@ *" text "")
-      (if idlwave-idlwave_routine_info-compiled
-         (message
-          "Routine Info warning: No match for BEGIN line in \n>>>\n%s\n<<<\n"
-          idlwave-shell-command-output)))
-    (if (string-match "^>>>END OF IDLWAVE ROUTINE INFO.*" text)
-       (setq text (substring text 0 (match-beginning 0)))
-      (if idlwave-idlwave_routine_info-compiled
-         (message
-          "Routine Info warning: No match for END line in \n>>>\n%s\n<<<\n"
-          idlwave-shell-command-output)))
-    ;; Match the output lines
-    (while (string-match "^IDLWAVE-\\(PRO\\|FUN\\): \\(.*\\)" text start)
-      (setq start (match-end 0))
-      (setq type (match-string 1 text)
-           spec (match-string 2 text)
-           specs (idlwave-split-string spec sep-re)
-           name (nth 0 specs)
-           class (if (equal (nth 1 specs) "") nil (nth 1 specs))
-           file (nth 2 specs)
-           cs (nth 3 specs)
-           key (nth 4 specs)
-           keys (if (and (stringp key)
-                         (not (string-match "\\` *\\'" key)))
-                    (mapcar #'list
-                            (delete "" (idlwave-split-string key " +")))))
-      (setq name (idlwave-sintern-routine-or-method name class t)
-           class (idlwave-sintern-class class t)
-           file (if (equal file "") nil file)
-           keys (mapcar (lambda (x)
-                          (list (idlwave-sintern-keyword (car x) t)))
-                        keys))
-
-      ;; In the following ignore routines already defined in buffers,
-      ;; assuming that if the buffer stuff differs, it is a "new"
-      ;; version, not yet compiled, and should take precedence.
-      ;; We could do the same for the library to avoid duplicates -
-      ;; but I think frequently a user might have several versions of
-      ;; the same function in different programs, and in this case the
-      ;; compiled one will be the best guess of all versions.
-      ;; Therefore, we leave duplicates of library routines in.
-      (cond ((string= name "$MAIN$"))    ; ignore this one
-           ((and (string= type "PRO")
-                 ;; FIXME: is it OK to make the buffer routines dominate?
-                 (or t (null file)
-                     (not (idlwave-rinfo-assq name 'pro class
-                                              idlwave-buffer-routines)))
-                 ;; FIXME: is it OK to make the library routines dominate?
-                 ;;(not (idlwave-rinfo-assq name 'pro class
-                 ;;                       idlwave-library-routines))
-                 )
-            (setq entry (list name 'pro class
-                              (cons 'compiled
-                                    (if file
-                                        (list
-                                         (file-name-nondirectory file)
-                                         (idlwave-sintern-dir
-                                          (file-name-directory file)))))
-                              cs (cons nil keys)))
-            (if file
-                (push entry idlwave-compiled-routines)
-              (push entry idlwave-unresolved-routines)))
-
-           ((and (string= type "FUN")
-                 ;; FIXME: is it OK to make the buffer routines dominate?
-                 (or t (not file)
-                     (not (idlwave-rinfo-assq name 'fun class
-                                              idlwave-buffer-routines)))
-                 ;; FIXME: is it OK to make the library routines dominate?
-                 ;; (not (idlwave-rinfo-assq name 'fun class
-                 ;;                       idlwave-library-routines))
-                 )
-            (setq entry (list name 'fun class
-                              (cons 'compiled
-                                    (if file
-                                        (list
-                                         (file-name-nondirectory file)
-                                         (idlwave-sintern-dir
-                                          (file-name-directory file)))))
-                              cs (cons nil keys)))
-            (if file
-                (push entry idlwave-compiled-routines)
-              (push entry idlwave-unresolved-routines))))))
-  ;; Reverse the definitions so that they are alphabetically sorted.
-  (setq idlwave-compiled-routines (nreverse idlwave-compiled-routines)
-       idlwave-unresolved-routines (nreverse idlwave-unresolved-routines)))
-
-(defun idlwave-shell-filter-directory ()
-  "Get the current directory from `idlwave-shell-command-output'.
-Change the default directory for the process buffer to concur."
-  (with-current-buffer (idlwave-shell-buffer)
-    (if (string-match ",___cur[\n\r ]+\\([^\n\r]+\\)[\n\r]"
-                     idlwave-shell-command-output)
-       (let ((dir (substring idlwave-shell-command-output
-                             (match-beginning 1) (match-end 1))))
-          ;; (message "Setting Emacs working dir to %s" dir)
-         (setq idlwave-shell-default-directory dir)
-         (setq default-directory (file-name-as-directory dir))))))
-
-(defvar idlwave-shell-get-object-class nil)
-(defun idlwave-shell-get-object-class (apos)
-  "Query the shell for the class of the object before point."
-  (let ((bos (save-excursion (idlwave-start-of-substatement 'pre) (point)))
-       (bol (save-excursion (forward-line 0) (point)))
-       expression)
-    (save-excursion
-      (goto-char apos)
-      (setq expression (buffer-substring
-                       (catch 'exit
-                         (while t
-                           (if (not (re-search-backward
-                                     "[^][.A-Za-z0-9_() ]" bos t))
-                               (throw 'exit bos)) ;ran into bos
-                           (if (not (idlwave-is-pointer-dereference bol))
-                               (throw 'exit (1+ (point))))))
-                       apos)))
-    (when (not (string= expression ""))
-      (setq idlwave-shell-get-object-class nil)
-      (idlwave-shell-send-command
-       (concat "if obj_valid(" expression ") then print,obj_class("
-              expression ")")
-       'idlwave-shell-parse-object-class
-       'hide 'wait)
-      ;; If we don't know anything about the class, update shell routines
-      (if (and idlwave-shell-get-object-class
-              (not (assoc-string idlwave-shell-get-object-class
-                                 (idlwave-class-alist) t)))
-         (idlwave-shell-maybe-update-routine-info))
-      idlwave-shell-get-object-class)))
-
-(defun idlwave-shell-parse-object-class ()
-  "Parse the output of the obj_class command."
-  (let ((match "obj_class([^\n\r]+[\n\r ]"))
-    (if (string-match (concat match "\\([A-Za-z_0-9]+\\) *[\n\r]\\("
-                             idlwave-shell-prompt-pattern "\\)")
-                     idlwave-shell-command-output)
-       (setq idlwave-shell-get-object-class
-             (match-string 1 idlwave-shell-command-output)))))
-
-(defvar idlwave-sint-sysvars nil)
-(idlwave-new-sintern-type execcomm)
-
-(defun idlwave-shell-complete (&optional arg)
-  "Do completion in the `idlwave-shell' buffer.
-Calls `idlwave-shell-complete-filename' after some executive commands or
-in strings.  Otherwise, calls `idlwave-complete' to complete modules and
-keywords."
-  (interactive "P")
-  (let (exec-cmd)
-    (cond
-     ((and
-       (setq exec-cmd (idlwave-shell-executive-command))
-       (cdr exec-cmd)
-       (member (upcase (cdr exec-cmd))
-              '(".R" ".RU" ".RUN" ".RN" ".RNE" ".RNEW"
-                ".COM" ".COMP" ".COMPI" ".COMPIL" ".COMPILE")))
-      ;; We are in a command line with an executive command
-      (idlwave-shell-complete-filename))
-
-     ((car-safe exec-cmd)
-      (setq idlwave-completion-help-info
-           '(idlwave-shell-complete-execcomm-help))
-      (idlwave-complete-in-buffer 'execcomm 'execcomm
-                                 idlwave-executive-commands-alist nil
-                                 "Select an executive command"
-                                 "system variable"))
-
-     ((idlwave-shell-batch-command)
-      (idlwave-shell-complete-filename))
-
-     ((idlwave-shell-shell-command)
-      (idlwave-shell-complete-filename))
-
-     ((and (idlwave-shell-filename-string)
-          (save-excursion
-            (beginning-of-line)
-            (let ((case-fold-search t))
-              (not (looking-at ".*obj_new")))))
-      (idlwave-shell-complete-filename))
-
-     (t
-      ;; Default completion of modules and keywords
-      (idlwave-complete arg)))))
-
-;; Get rid of opaque dynamic variable passing of idlw-help-link?
-(defvar idlw-help-link) ; dynamic variable from idlwave-do-mouse-completion-help
-(defun idlwave-shell-complete-execcomm-help (mode word)
-  (let ((word (or (nth 1 idlwave-completion-help-info) word))
-       (entry (assoc-string word idlwave-executive-commands-alist t)))
-    (cond
-     ((eq mode 'test)
-      (and (stringp word) entry (cdr entry)))
-     ((eq mode 'set)
-      (if entry (setq idlw-help-link (cdr entry)))) ; setting dynamic variable!
-     (t (error "This should not happen")))))
-
-(defun idlwave-shell-complete-filename ()
-  "Complete a file name at point if after a file name.
-We assume that we are after a file name when completing one of the
-args of an executive .run, .rnew or .compile."
-  ;; CWD might have changed, resync, to set default directory
-  (idlwave-shell-resync-dirs)
-  (let ((comint-file-name-chars idlwave-shell-file-name-chars))
-    (comint-dynamic-complete-filename)))
-
-(defun idlwave-shell-executive-command ()
-  "Return the name of the current executive command, if any."
-  (save-excursion
-    (idlwave-beginning-of-statement)
-    (cons (looking-at "[ \t]*\\.")
-         (if (looking-at "[ \t]*[.]\\([^ \t\n\r]+\\)[ \t]")
-             (match-string 1)))))
-
-(defun idlwave-shell-filename-string ()
-  "Return t if in a string and after what could be a file name."
-  (let ((limit (line-beginning-position)))
-    (save-excursion
-      ;; Skip backwards over file name chars
-      (skip-chars-backward idlwave-shell-file-name-chars limit)
-      ;; Check of the next char is a string delimiter
-      (and (memq (preceding-char) '(?\' ?\")) t))))
-
-(defun idlwave-shell-batch-command ()
-  "Return t if we're in a batch command statement like \"@foo\"."
-  (let ((limit (line-beginning-position)))
-    (save-excursion
-      ;; Skip backwards over filename
-      (skip-chars-backward idlwave-shell-file-name-chars limit)
-      (skip-chars-backward " \t" limit)
-      (and (eq (preceding-char) ?@) (not (idlwave-in-quote))))))
-
-(defun idlwave-shell-shell-command ()
-  "Return t if we're in a shell command statement like \"$ls\"."
-  (save-excursion
-    (idlwave-beginning-of-statement)
-    (looking-at "\\$")))
-
-;; Debugging Commands ------------------------------------------------------
-
-(defun idlwave-shell-redisplay (&optional hide)
-  "Try to resync the display with where execution has stopped.
-Issues a \"help,/trace\" command followed by a call to
-`idlwave-shell-display-line'.  Also updates the breakpoint
-overlays."
-  (interactive)
-  (setq idlwave-shell-calling-stack-index 0)
-  (idlwave-shell-send-command
-   "help,/trace"
-   '(idlwave-shell-display-line
-     (idlwave-shell-pc-frame))
-   hide)
-  (idlwave-shell-bp-query))
-
-(defun idlwave-shell-display-level-in-calling-stack (&optional hide)
-  (idlwave-shell-send-command
-   "help,/trace"
-   `(progn
-      ;; scanning for the state will reset the stack level - restore it
-      (setq idlwave-shell-calling-stack-index
-           ,idlwave-shell-calling-stack-index)
-      ;; parse the stack and visit the selected frame
-      (idlwave-shell-parse-stack-and-display))
-   hide))
-
-(defun idlwave-shell-parse-stack-and-display ()
-  (let* ((lines (delete "" (idlwave-split-string
-                           idlwave-shell-command-output "^%")))
-        (stack (delq nil (mapcar #'idlwave-shell-parse-line lines)))
-        (nmax (1- (length stack)))
-        (nmin 0) message)
-    (cond
-     ((< nmax nmin)
-      (setq idlwave-shell-calling-stack-index 0)
-      (ding)
-      (message "Problem with calling stack"))
-     ((> idlwave-shell-calling-stack-index nmax)
-      (ding)
-      (setq idlwave-shell-calling-stack-index nmax
-           message (format "%d is the highest calling stack level - can't go further up"
-                           (- nmax))))
-     ((< idlwave-shell-calling-stack-index nmin)
-      (ding)
-      (setq idlwave-shell-calling-stack-index nmin
-           message (format "%d is the current calling stack level - can't go further down"
-                           (- nmin)))))
-    (setq idlwave-shell-calling-stack-routine
-         (nth 2 (nth idlwave-shell-calling-stack-index stack)))
-
-    ;; force edebug for this frame if we're in that mode already
-    (idlwave-shell-display-line
-     (nth idlwave-shell-calling-stack-index stack) nil
-     (if idlwave-shell-electric-debug-mode 'force))
-    (message "%s" (or message
-                     (format "In routine %s (stack level %d)"
-                             idlwave-shell-calling-stack-routine
-                             (- idlwave-shell-calling-stack-index))))))
-
-(defun idlwave-shell-stack-up ()
-  "Display the source code one step up the calling stack."
-  (interactive)
-  (cl-incf idlwave-shell-calling-stack-index)
-  (idlwave-shell-display-level-in-calling-stack 'hide))
-(defun idlwave-shell-stack-down ()
-  "Display the source code one step down the calling stack."
-  (interactive)
-  (cl-decf idlwave-shell-calling-stack-index)
-  (idlwave-shell-display-level-in-calling-stack 'hide))
-
-(defun idlwave-shell-goto-frame (&optional frame)
-  "Set buffer to FRAME with point at the frame line.
-If the optional argument FRAME is nil then `idlwave-shell-pc-frame'
-is used.  Does nothing if the resulting frame is nil."
-  (if frame ()
-    (setq frame (idlwave-shell-pc-frame)))
-  (cond
-   (frame
-    (set-buffer (idlwave-find-file-noselect (car frame) 'shell))
-    (widen)
-    (goto-char (point-min))
-    (forward-line (1- (nth 1 frame))))))
-
-(defun idlwave-shell-pc-frame ()
-  "Return the frame for IDL execution."
-  (and idlwave-shell-halt-frame
-       (list (nth 0 idlwave-shell-halt-frame)
-            (nth 1 idlwave-shell-halt-frame)
-            (nth 2 idlwave-shell-halt-frame))))
-
-(defun idlwave-shell-valid-frame (frame)
-  "Check that frame is for an existing file."
-  (file-readable-p (car frame)))
-
-(defun idlwave-shell-stop-line-pending ()
-  ;; Temporarily change the color of the stop line overlay
-  (if idlwave-shell-stop-line-overlay
-      (overlay-put idlwave-shell-stop-line-overlay 'face
-                  (if idlwave-shell-electric-debug-mode
-                      'idlwave-shell-pending-electric-stop
-                    'idlwave-shell-pending-stop))))
-
-(defvar idlwave-shell-suppress-electric-debug nil)
-(defun idlwave-shell-display-line (frame &optional col debug)
-  "Display frame file in other window with overlay arrow.
-
-FRAME is a list of file name, line number, and subroutine name.  If
-FRAME is nil then remove overlay.  If COL is set, move point to that
-column in the line.  If DEBUG is non-nil, enable the electric debug
-mode.  If it is `disable', do not enable no matter what the setting of
-`idlwave-shell-automatic-electric-debug'.  If it is `force', enable no
-matter what the settings of that variable."
-  (if (not frame)
-      ;; remove stop-line overlay from old position
-      (progn
-        (setq overlay-arrow-string nil)
-       (setq idlwave-shell-mode-line-info nil)
-       (setq idlwave-shell-is-stopped nil)
-        (if idlwave-shell-stop-line-overlay
-            (delete-overlay idlwave-shell-stop-line-overlay))
-       ;; turn off electric debug everywhere, if it's on
-       (idlwave-shell-electric-debug-all-off))
-    (if (not (idlwave-shell-valid-frame frame))
-       ;; fixme: errors are dangerous in shell filters.  but i think i
-       ;; have never encountered this one.
-        (error "Invalid frame - unable to access file: %s" (car frame))
-      ;;
-      ;; buffer : the buffer to display a line in.
-      ;; select-shell: current buffer is the shell.
-      ;;
-      (setq idlwave-shell-mode-line-info
-           (if (nth 2 frame)
-               (format "[%d:%s]"
-                       (- idlwave-shell-calling-stack-index)
-                       (nth 2 frame))))
-      (let* ((buffer (idlwave-find-file-noselect (car frame) 'shell))
-             (select-shell (equal (buffer-name) (idlwave-shell-buffer)))
-             window pos electric)
-
-       ;; first make sure the shell window is visible
-       (idlwave-display-buffer (idlwave-shell-buffer)
-                               nil (idlwave-shell-shell-frame))
-
-       ;; now display the buffer and remember which window it is.
-       (setq window (idlwave-display-buffer buffer
-                                            nil (idlwave-shell-source-frame)))
-
-       ;; enter the buffer and mark the line
-        (with-current-buffer buffer
-          (save-restriction
-            (widen)
-            (goto-char (point-min))
-            (forward-line (1- (nth 1 frame)))
-            (setq pos (point))
-           (setq idlwave-shell-is-stopped t)
-
-            (if idlwave-shell-stop-line-overlay
-                (progn
-                 ;; restore face and move overlay
-                 (overlay-put idlwave-shell-stop-line-overlay 'face
-                              (if idlwave-shell-electric-debug-mode
-                                   idlwave-shell-electric-stop-line-face
-                                 idlwave-shell-stop-line-face))
-                 (move-overlay idlwave-shell-stop-line-overlay
-                                (point) (line-end-position)
-                               (current-buffer)))
-             ;; use the arrow instead, but only if marking is wanted.
-             (if idlwave-shell-mark-stop-line
-                 (setq overlay-arrow-string idlwave-shell-overlay-arrow))
-              (or overlay-arrow-position  ; create the marker if necessary
-                  (setq overlay-arrow-position (make-marker)))
-             (set-marker overlay-arrow-position (point) buffer)))
-
-         ;; if the point is outside the restriction, widen the buffer.
-          (if (or (< pos (point-min)) (> pos (point-max)))
-             (progn
-               (widen)
-               (goto-char pos)))
-
-         ;; if we have the column of the error, move the cursor there.
-          (if col (move-to-column col))
-          (setq pos (point))
-
-         ;; enter electric debug mode, if not prohibited and not in
-         ;; it already
-         (when  (and (not idlwave-shell-electric-debug-mode)
-                     (or (eq debug 'force)
-                         (and
-                          (not (eq debug 'disable)) ;; explicitly disabled
-                          (or
-                           (eq idlwave-shell-automatic-electric-debug t)
-                           (and
-                            (eq idlwave-shell-automatic-electric-debug
-                                'breakpoint)
-                            (not (eq idlwave-shell-current-state 'error))))
-                          (not idlwave-shell-suppress-electric-debug))))
-           (idlwave-shell-electric-debug-mode t))
-         (setq electric idlwave-shell-electric-debug-mode))
-
-       ;; Make sure pos is really displayed in the window.
-       (set-window-point window pos)
-
-       ;; If we came from the shell, go back there.  Otherwise select
-       ;; the window where the error/halt is displayed.
-        (if (or (and idlwave-shell-electric-zap-to-file electric)
-               (and (equal (buffer-name) (idlwave-shell-buffer))
-                    (not select-shell)))
-            (select-window window))))))
-
-
-(defun idlwave-shell-step (arg)
-  "Step one source line.
-If given prefix argument ARG, step ARG source lines."
-  (interactive "p")
-  (or (not arg) (< arg 1)
-      (setq arg 1))
-  (idlwave-shell-stop-line-pending)
-  (idlwave-shell-send-command
-   (concat ".s " (if (integerp arg) (int-to-string arg) arg))
-   nil (if (idlwave-shell-hide-p 'debug) 'mostly) nil t))
-
-(defun idlwave-shell-stepover (arg)
-  "Stepover one source line.
-If given prefix argument ARG, step ARG source lines.
-Uses IDL's stepover executive command which does not enter called functions."
-  (interactive "p")
-  (or (not arg) (< arg 1)
-      (setq arg 1))
-  (idlwave-shell-stop-line-pending)
-  (idlwave-shell-send-command
-   (concat ".so " (if (integerp arg) (int-to-string arg) arg))
-   nil (if (idlwave-shell-hide-p 'debug) 'mostly) nil t))
-
-(defun idlwave-shell-break-here (&optional count cmd condition disabled
-                                          no-show)
-  "Set breakpoint at current line.
-
-If COUNT is nil then an ordinary breakpoint is set.  We treat a COUNT
-of 1 as a temporary breakpoint using the ONCE keyword.  Counts greater
-than 1 use the IDL AFTER=count keyword to break only after reaching
-the statement COUNT times.
-
-Optional argument CMD is a list or function to evaluate upon reaching
-the breakpoint.  CONDITION is a break condition, and DISABLED, if
-non-nil disables the breakpoint."
-  (interactive "P")
-  (when (listp count)
-    (if (equal (car count) 4)
-       (setq condition (read-string "Break Condition: ")))
-    (setq count nil))
-  (idlwave-shell-set-bp
-   ;; Create breakpoint
-   (idlwave-shell-bp (idlwave-shell-current-frame)
-                    (list count cmd condition disabled)
-                    (idlwave-shell-current-module))
-   no-show))
-
-(defun idlwave-shell-set-bp-check (bp)
-  "Check for failure to set breakpoint.
-This is run on `idlwave-shell-post-command-hook'.
-Offers to recompile the procedure if we failed.  This usually fixes
-the problem with not being able to set the breakpoint."
-  ;; Scan for message
-  (if idlwave-shell-command-output
-      (cond
-       ((string-match "% BREAKPOINT: *Unable to find code"
-                     idlwave-shell-command-output)
-       ;; Offer to recompile
-        (if (progn
-              (beep)
-              (y-or-n-p
-               (concat "Okay to recompile file "
-                       (idlwave-shell-bp-get bp 'file) "?")))
-            ;; Recompile
-            (progn
-              ;; Clean up before retrying
-              (idlwave-shell-command-failure)
-              (idlwave-shell-send-command
-               (concat ".run \"" (idlwave-shell-bp-get bp 'file) "\"") nil
-              (if (idlwave-shell-hide-p 'run) 'mostly) nil t)
-              ;; Try setting breakpoint again
-              (idlwave-shell-set-bp bp))
-          (beep)
-          (message "Unable to set breakpoint.")
-          (idlwave-shell-command-failure))
-       nil)
-
-       ((string-match "% Syntax error" idlwave-shell-command-output)
-       (message "Syntax error in condition.")
-       (idlwave-shell-command-failure)
-       nil)
-
-       (t 'okay))))
-
-(defun idlwave-shell-command-failure ()
-  "Do any necessary clean up when an IDL command fails.
-Call this from a function attached to `idlwave-shell-post-command-hook'
-that detects the failure of a command.
-For example, this is called from `idlwave-shell-set-bp-check' when a
-breakpoint can not be set."
-  ;; Clear pending commands
-  (setq idlwave-shell-pending-commands nil))
-
-(defun idlwave-shell-cont (&optional no-show)
-  "Continue executing."
-  (interactive)
-  (idlwave-shell-stop-line-pending)
-  (idlwave-shell-send-command ".c" (unless no-show
-                                    '(idlwave-shell-redisplay 'hide))
-                             (if (idlwave-shell-hide-p 'debug) 'mostly)
-                             nil t))
-
-(defun idlwave-shell-go ()
-  "Run .GO.  This starts the main program of the last compiled file."
-  (interactive)
-  (idlwave-shell-stop-line-pending)
-  (idlwave-shell-send-command ".go" '(idlwave-shell-redisplay 'hide)
-                             (if (idlwave-shell-hide-p 'debug) 'mostly)
-                             nil t))
-
-(defun idlwave-shell-return ()
-  "Run .RETURN (continue to next return, but stay in subprogram)."
-  (interactive)
-  (idlwave-shell-stop-line-pending)
-  (idlwave-shell-send-command ".return" '(idlwave-shell-redisplay 'hide)
-                             (if (idlwave-shell-hide-p 'debug) 'mostly)
-                             nil t))
-
-(defun idlwave-shell-skip ()
-  "Run .SKIP (skip one line, then step)."
-  (interactive)
-  (idlwave-shell-stop-line-pending)
-  (idlwave-shell-send-command ".skip" '(idlwave-shell-redisplay 'hide)
-                             (if (idlwave-shell-hide-p 'debug) 'mostly)
-                             nil t))
-
-(defun idlwave-shell-clear-bp (bp &optional no-query)
-  "Clear breakpoint BP.
-Clears in IDL and in `idlwave-shell-bp-alist'."
-  (let ((index (idlwave-shell-bp-get bp)))
-    (if index
-        (progn
-          (idlwave-shell-send-command
-           (concat "breakpoint,/clear," (int-to-string index))
-          nil (idlwave-shell-hide-p 'breakpoint) nil t)
-         (unless no-query (idlwave-shell-bp-query))))))
-
-(defun idlwave-shell-current-frame ()
-  "Return a list containing the current file name and line point is in.
-If in the IDL shell buffer, returns `idlwave-shell-pc-frame'."
-  (if (eq (current-buffer) (get-buffer (idlwave-shell-buffer)))
-      ;; In IDL shell
-      (idlwave-shell-pc-frame)
-    ;; In source
-    (list (idlwave-shell-file-name (buffer-file-name))
-          (save-restriction
-            (widen)
-            (1+ (count-lines 1 (line-beginning-position)))))))
-
-(defun idlwave-shell-current-module ()
-  "Return the name of the module for the current file.
-Returns nil if unable to obtain a module name."
-  (if (eq (current-buffer) (get-buffer (idlwave-shell-buffer)))
-      ;; In IDL shell
-      (nth 2 idlwave-shell-halt-frame)
-    ;; In pro file
-    (save-restriction
-      (widen)
-      (save-excursion
-        (if (idlwave-prev-index-position)
-           (let* ((module (idlwave-what-module))
-                  (name (idlwave-make-full-name (nth 2 module) (car module)))
-                  (type (nth 1 module)))
-             (list (upcase name) type)))))))
-
-(defun idlwave-shell-clear-current-bp ()
-  "Remove breakpoint at current line.
-This command can be called from the shell buffer if IDL is currently
-stopped at a breakpoint."
-  (interactive)
-  (let ((bp (idlwave-shell-find-current-bp)))
-    (if bp (idlwave-shell-clear-bp bp))))
-
-
-(defun idlwave-shell-toggle-enable-current-bp (&optional bp force
-                                                        no-update)
-  "Disable or enable current breakpoint or a breakpoint passed in BP.
-If FORCE is `disable' or `enable', for that condition instead of
-toggling.  If NO-UPDATE is non-nil, don't update the breakpoint
-list after toggling."
-  (interactive)
-  (let* ((bp (or bp (idlwave-shell-find-current-bp)))
-        (disabled (idlwave-shell-bp-get bp 'disabled)))
-    (cond ((eq force 'disable) (setq disabled nil))
-         ((eq force 'enable) (setq disabled t)))
-    (when bp
-      (setf (nth 3 (cdr (cdr bp))) (not disabled))
-      (idlwave-shell-send-command
-       (concat "breakpoint,"
-              (if disabled "/enable," "/disable,")
-              (int-to-string (idlwave-shell-bp-get bp)))
-       nil (idlwave-shell-hide-p 'breakpoint) nil t)
-      (unless no-update (idlwave-shell-bp-query)))))
-
-(defun idlwave-shell-enable-all-bp (&optional enable no-update bpl)
-  "Disable all breakpoints we know about which need disabling.
-If ENABLE is non-nil, enable them instead."
-  (let  ((bpl (or bpl idlwave-shell-bp-alist)) disabled modified)
-    (while bpl
-      (setq disabled (idlwave-shell-bp-get (car bpl) 'disabled))
-      (when (xor (not disabled) (eq enable 'enable))
-       (idlwave-shell-toggle-enable-current-bp
-        (car bpl) (if (eq enable 'enable) 'enable 'disable) no-update)
-       (push (car bpl) modified))
-      (setq bpl (cdr bpl)))
-    (unless no-update (idlwave-shell-bp-query))
-    modified))
-
-(defun idlwave-shell-to-here ()
-  "Set a breakpoint with count 1 then continue."
-  (interactive)
-  ;; temporarily disable all other breakpoints
-  (let ((disabled (idlwave-shell-enable-all-bp 'disable 'no-update)))
-    (idlwave-shell-break-here 1 nil nil nil 'no-show)
-    (idlwave-shell-cont 'no-show)
-    (idlwave-shell-enable-all-bp 'enable 'no-update disabled))
-  (idlwave-shell-redisplay)) ; sync up everything at the end
-
-(defun idlwave-shell-break-this-module (&optional arg)
-  (interactive "P")
-  (save-excursion
-    (idlwave-beginning-of-subprogram)
-    (idlwave-shell-break-here arg)))
-
-(defun idlwave-shell-break-in ()
-  "Look for a module name near point and set a break point for it.
-The command looks for an identifier near point and sets a breakpoint
-for the first line of the corresponding module.  If MODULE is t, set
-in the current routine."
-  (interactive)
-  (let* ((module (idlwave-fix-module-if-obj_new (idlwave-what-module)))
-        (type (nth 1 module))
-        (name (car module))
-        (class (nth 2 module)))
-    (if module
-       (progn
-         (setq module (idlwave-make-full-name class name))
-         (idlwave-shell-module-source-query module type)
-         (idlwave-shell-set-bp-in-module name type class))
-      (error "No identifier at point"))))
-
-
-(defun idlwave-shell-set-bp-in-module (name type class)
-  "Set breakpoint in module.
-Assumes that `idlwave-shell-sources-alist' contains an entry for that module."
-  (let* ((module (idlwave-make-full-name class name))
-        (source-file
-         (car-safe (cdr-safe
-                    (or
-                     (assoc (upcase module)
-                            idlwave-shell-sources-alist)
-                     (nth 3 (idlwave-best-rinfo-assoc name type class
-                                                      (idlwave-routines)))))))
-        buf)
-    (if (or (not source-file)
-           (not (file-regular-p source-file))
-           (not (setq buf
-                       (or (find-buffer-visiting source-file)
-                          (find-file-noselect source-file)))))
-       (progn
-         (message "The source file for module %s is probably not compiled"
-                  module)
-         (beep))
-      (with-current-buffer buf
-       (save-excursion
-         (goto-char (point-min))
-         (let ((case-fold-search t))
-           (if (re-search-forward
-                (concat "^[ \t]*\\(pro\\|function\\)[ \t]+"
-                        (downcase module)
-                        "[ \t\n,]") nil t)
-               (progn
-                 (goto-char (match-beginning 1))
-                 (message "Setting breakpoint for module %s" module)
-                 (idlwave-shell-break-here))
-             (message "Cannot find module %s in file %s" module source-file)
-             (beep))))))))
-
-(defun idlwave-shell-up ()
-  "Run to end of current block.
-Sets a breakpoint with count 1 at end of block, then continues."
-  (interactive)
-  (if (idlwave-shell-pc-frame)
-      (save-excursion
-        (idlwave-shell-goto-frame)
-        ;; find end of subprogram
-        (let ((eos (save-excursion
-                     (idlwave-beginning-of-subprogram)
-                     (idlwave-forward-block)
-                     (point))))
-          (idlwave-backward-up-block -1)
-          ;; move beyond end block line - IDL will not break there.
-          ;; That is, you can put a breakpoint there but when IDL does
-          ;; break it will report that it is at the next line.
-          (idlwave-next-statement)
-          (idlwave-end-of-statement)
-          ;; Make sure we are not beyond subprogram
-          (if (< (point) eos)
-              ;; okay
-              ()
-            ;; Move back inside subprogram
-            (goto-char eos)
-            (idlwave-previous-statement))
-          (idlwave-shell-to-here)))))
-
-(defun idlwave-shell-out ()
-  "Attempt to run until this procedure exits.
-Runs to the last statement and then steps 1 statement.  Use the .out command."
-  (interactive)
-  (idlwave-shell-send-command ".o" nil
-                             (if (idlwave-shell-hide-p 'debug) 'mostly)
-                             nil t))
-
-(defun idlwave-shell-goto-previous-bp ()
-  "Move to the previous breakpoint in the buffer."
-  (interactive)
-  (idlwave-shell-move-to-bp -1))
-(defun idlwave-shell-goto-next-bp ()
-  "Move to the next breakpoint in the buffer."
-  (interactive)
-  (idlwave-shell-move-to-bp 1))
-
-(defun idlwave-shell-move-to-bp (dir)
-  "Move to the next or previous breakpoint, depending on direction DIR."
-  (let* ((frame (idlwave-shell-current-frame))
-        (file (car frame))
-        (orig-bp-line (nth 1 frame))
-        (bp-alist idlwave-shell-bp-alist)
-        (orig-func (if (> dir 0) '> '<))
-        (closer-func (if (> dir 0) '< '>))
-        bp bp-line cur-line)
-    (while (setq bp (pop bp-alist))
-      (when (string= file (car (car bp)))
-       (setq cur-line (nth 1 (car bp)))
-       (if (and
-            (funcall orig-func cur-line orig-bp-line)
-            (or (not bp-line) (funcall closer-func cur-line bp-line)))
-           (setq bp-line cur-line))))
-    (unless bp-line (error "No further breakpoints"))
-    (goto-char (point-min))
-    (forward-line (1- bp-line))))
-
-;; Examine Commands ------------------------------------------------------
-
-(defun idlwave-shell-help-expression (arg)
-  "Print help on current expression.  See `idlwave-shell-print'."
-  (interactive "P")
-  (idlwave-shell-print arg 'help))
-
-(defun idlwave-shell--mouse-examine (event help &optional ev)
-  "Expansion function for expression examination."
-  (let* ((transient-mark-mode t))
-    (mouse-drag-track event)
-    (idlwave-shell-print (if (region-active-p) '(4) nil)
-                        help ev)))
-
-(define-obsolete-function-alias
-  'idlwave-default-mouse-track-event-is-with-button #'always "28.1")
-
-(define-obsolete-function-alias 'idlwave-xemacs-hack-mouse-track
-  #'ignore "27.1")
-;;; End terrible hack section
-
-(defun idlwave-shell-mouse-print (event)
-  "Print value of variable at the mouse position, with `print'."
-  (interactive "e")
-  (idlwave-shell--mouse-examine event nil))
-
-(defun idlwave-shell-mouse-help (event)
-  "Print value of variable at the mouse position, with `help'."
-  (interactive "e")
-  (idlwave-shell--mouse-examine event 'help))
-
-(defun idlwave-shell-examine-select (event)
-  "Pop-up a list to select from for examining the expression."
-  (interactive "e")
-  (idlwave-shell--mouse-examine event nil event))
-
-(defmacro idlwave-shell-examine (help)
-  "Create a function for key-driven expression examination."
-  `(lambda ()
-     (interactive)
-     (idlwave-shell-print nil ,help)))
-
-(defvar idlwave-shell-examine-label nil
-  "Label to include with examine text if in a separate buffer.")
-(defvar idlwave-shell-examine-completion-list nil)
-
-(defun idlwave-shell-print (arg &optional help ev complete-help-type)
-  "Print current expression.
-
-With HELP non-nil, show help on expression.  If HELP is a string,
-the expression will be put in place of ___, e.g.:
-
-   print,size(___,/DIMENSIONS)
-
-HELP can also be a cons cell ( NAME . STRING ) in which case NAME will
-be used to label the help print-out.
-
-Otherwise, print is called on the expression.
-
-An expression is an identifier plus 1 pair of matched parentheses
-directly following the identifier - an array or function call.
-Alternatively, an expression is the contents of any matched
-parentheses when the open parenthesis is not directly preceded by an
-identifier.  If point is at the beginning or within an expression
-return the inner-most containing expression, otherwise, return the
-preceding expression.
-
-With prefix arg, or if transient mode set and the region is defined,
-use the current region as the expression.
-
-With double prefix arg ARG prompt for an expression.
-
-If EV is a valid event passed, pop-up a list from
-`idlwave-shell-examine-alist' from which to select the help
-command text.  If instead COMPLETE-HELP-TYPE is non-nil, choose
-from `idlwave-shell-examine-alist' via mini-buffer shortcut key."
-  (interactive "P")
-
-  ;; For speed: assume the helper routine hasn't been lost, e.g. with
-  ;; .FULL_RESET_SESSION.  We'll recover if necessary
-  (unless idlwave-idlwave_routine_info-compiled
-    (idlwave-shell-compile-helper-routines))
-  (save-excursion
-    (let* ((process (get-buffer-process (current-buffer)))
-          (process-mark (if process (process-mark process)))
-          (stack-label
-           (if (and (integerp idlwave-shell-calling-stack-index)
-                    (> idlwave-shell-calling-stack-index 0))
-               (format "  [-%d:%s]"
-                       idlwave-shell-calling-stack-index
-                       idlwave-shell-calling-stack-routine)))
-          expr beg end cmd)
-      (cond
-       ((equal arg '(16))
-       (setq expr (read-string "Expression: ")))
-       ((and (or arg (region-active-p))
-            (< (- (region-end) (region-beginning)) 2000))
-       (setq beg (region-beginning)
-             end (region-end)))
-       (t
-       (with-syntax-table idlwave-find-symbol-syntax-table
-        ;; Move to beginning of current or previous expression
-        (if (looking-at "\\<\\|(")
-            ;; At beginning of expression, don't move backwards unless
-            ;; this is at the end of an identifier.
-            (if (looking-at "\\>")
-                (backward-sexp))
-          (backward-sexp))
-        (if (looking-at "\\>")
-            ;; Move to beginning of identifier - must be an array or
-            ;; function expression.
-            (backward-sexp))
-        ;; Move to end of expression
-        (setq beg (point))
-        (forward-sexp)
-        (while (looking-at "\\>[[(]\\|\\.")
-          ;; an array
-          (forward-sexp))
-        (setq end (point)))))
-
-      ;; Get expression, but first move the begin mark if a
-      ;; process-mark is inside the region, to keep the overlay from
-      ;; wandering in the Shell.
-      (when (and beg end)
-       (if (and process-mark (> process-mark beg) (< process-mark end))
-           (setq beg (marker-position process-mark)))
-       (setq expr (buffer-substring beg end)))
-
-      ;; Show the overlay(s) and attach any necessary hooks and filters
-      (when (and beg end idlwave-shell-expression-overlay)
-       (move-overlay idlwave-shell-expression-overlay beg end
-                     (current-buffer))
-       (add-hook 'pre-command-hook
-                 #'idlwave-shell-delete-expression-overlay))
-      (add-hook 'pre-command-hook
-               #'idlwave-shell-delete-output-overlay)
-
-      ;; Remove empty or comment-only lines
-      (while (string-match "\n[ \t]*\\(;.*\\)?\r*\n" expr)
-       (setq expr (replace-match "\n" t t expr)))
-      ;; Concatenate continuation lines
-      (while (string-match "[ \t]*\\$[ \t]*\\(;.*\\)?\\(\n[ \t]*\\|$\\)" expr)
-       (setq expr (replace-match "" t t expr)))
-      ;; Remove final newline
-      (if (string-match "\n[ \t\r]*\\'" expr)
-         (setq expr (replace-match "" t t expr)))
-
-      (catch 'exit
-       ;; Pop-up or complete on the examine selection list, if appropriate
-       (if (or
-            complete-help-type
-            (and ev idlwave-shell-examine-alist)
-            (consp help))
-           (let ((help-cons
-                  (if (consp help) help
-                    (assoc
-                     ;; A cons from either a pop-up or mini-buffer completion
-                     (if complete-help-type
-                         (idlwave-one-key-select 'idlwave-shell-examine-alist
-                                                 "Examine with: " 1.5)
-;;                       (idlwave-completing-read
-;;                        "Examine with: "
-;;                        idlwave-shell-examine-alist nil nil nil
-;;                        'idlwave-shell-examine-completion-list
-;;                        "Print")
-                       (idlwave-popup-select
-                        ev
-                        (mapcar #'car idlwave-shell-examine-alist)
-                        "Examine with"))
-                     idlwave-shell-examine-alist))))
-             (setq help (cdr help-cons))
-             (if (null help) (throw 'exit nil))
-             (if idlwave-shell-separate-examine-output
-                 (setq idlwave-shell-examine-label
-                       (concat
-                        (format "==>%s<==\n%s:" expr (car help-cons))
-                        stack-label "\n"))))
-         ;; The regular help label (no popups, cons cells, etc.)
-         (setq idlwave-shell-examine-label
-               (concat
-                (format "==>%s<==\n%s:" expr
-                        (cond ((null help) "print")
-                              ((stringp help) help)
-                              (t (symbol-name help))))
-                stack-label "\n")))
-
-       ;; Send the command
-       (if stack-label
-           (setq expr (idlwave-retrieve-expression-from-level
-                       expr
-                       idlwave-shell-calling-stack-index)))
-       (setq cmd (idlwave-shell-help-statement help expr))
-       ;;(idlwave-shell-recenter-shell-window)
-       (idlwave-shell-send-command
-        cmd
-        'idlwave-shell-check-compiled-and-display
-        (if idlwave-shell-separate-examine-output 'hide))))))
-
-(defvar idlwave-shell-examine-window-alist nil
-  "Variable to hold the win/height pairs for all *Examine* windows.")
-
-(defvar idlwave-shell-examine-map (make-sparse-keymap))
-(define-key idlwave-shell-examine-map "q" #'idlwave-shell-examine-display-quit)
-(define-key idlwave-shell-examine-map "c" #'idlwave-shell-examine-display-clear)
-
-(defun idlwave-shell-check-compiled-and-display ()
-  "Check examine output for warning about undefined procedure/function."
-  (if (string-match "% Attempt to call undefined" idlwave-shell-command-output)
-      (idlwave-shell-compile-helper-routines))
-  (if idlwave-shell-separate-examine-output
-      (idlwave-shell-examine-display)
-    (idlwave-shell-examine-highlight)))
-
-(defun idlwave-shell-examine-display ()
-  "View the examine command output in a separate buffer."
-  (let (win cur-beg cur-end)
-    (with-current-buffer (get-buffer-create "*Examine*")
-      (use-local-map idlwave-shell-examine-map)
-      (setq buffer-read-only nil)
-      (goto-char (point-max))
-      (save-restriction
-       (narrow-to-region (point) (point))
-       (if (string-match "^% Syntax error." idlwave-shell-command-output)
-           (insert "% Syntax error.\n")
-         (insert idlwave-shell-command-output)
-         ;; Just take the last bit between the prompts (if more than one).
-         (let* ((end (or
-                      (re-search-backward idlwave-shell-prompt-pattern nil t)
-                      (point-max)))
-                (beg (progn
-                       (goto-char
-                        (or (progn (if (re-search-backward
-                                        idlwave-shell-prompt-pattern nil t)
-                                       (match-end 0)))
-                            (point-min)))
-                       (re-search-forward "\n")))
-                (str (buffer-substring beg end)))
-           (delete-region (point-min) (point-max))
-           (insert str)
-           (if idlwave-shell-examine-label
-               (progn (goto-char (point-min))
-                      (insert idlwave-shell-examine-label)
-                      (setq idlwave-shell-examine-label nil)))))
-       (setq cur-beg (point-min)
-             cur-end (point-max))
-       (setq buffer-read-only t)
-       (move-overlay idlwave-shell-output-overlay cur-beg cur-end
-                     (current-buffer))
-
-       ;; Look for the examine buffer in all windows.  If one is
-       ;; found in a frame all by itself, use that, otherwise, switch
-       ;; to or create an examine window in this frame, and resize if
-       ;; it's a newly created window
-       (let* ((winlist (get-buffer-window-list "*Examine*" nil 'visible)))
-         (setq win (idlwave-display-buffer
-                    "*Examine*"
-                    nil
-                    (let ((list winlist) thiswin)
-                      (catch 'exit
-                        (save-selected-window
-                          (while (setq thiswin (pop list))
-                            (select-window thiswin)
-                            (if (one-window-p)
-                                (throw 'exit (window-frame thiswin)))))))))
-         (set-window-start win (point-min)) ; Ensure the point is visible.
-         (save-selected-window
-           (select-window win)
-           (let ((elt (assoc win idlwave-shell-examine-window-alist)))
-             (when (and (not (one-window-p))
-                        (or (not (memq win winlist)) ;a newly created window
-                            (eq (window-height) (cdr elt))))
-               ;; Autosize it.
-               (enlarge-window (- (/ (frame-height) 2)
-                                  (window-height)))
-               (shrink-window-if-larger-than-buffer)
-               ;; Clean the window list of dead windows
-               (setq idlwave-shell-examine-window-alist
-                     (delq nil
-                           (mapcar (lambda (x) (if (window-live-p (car x)) x))
-                                   idlwave-shell-examine-window-alist)))
-               ;; And add the new value.
-               (if (setq elt (assoc win idlwave-shell-examine-window-alist))
-                   (setcdr elt (window-height))
-                 (add-to-list 'idlwave-shell-examine-window-alist
-                              (cons win (window-height)))))))))
-      ;; Recenter for maximum output, after widened
-      (save-selected-window
-       (select-window win)
-       (goto-char (point-max))
-       (skip-chars-backward "\n")
-       (recenter -1)))))
-
-(defun idlwave-shell-examine-display-quit ()
-  (interactive)
-  (let ((win (selected-window)))
-    (if (one-window-p)
-       (delete-frame (window-frame win))
-      (delete-window win))))
-
-(defun idlwave-shell-examine-display-clear ()
-  (interactive)
-  (let ((buf (get-buffer "*Examine*")))
-    (when (bufferp buf)
-      (with-current-buffer buf
-       (let ((inhibit-read-only t))
-          (erase-buffer))))))
-
-(defun idlwave-retrieve-expression-from-level (expr level)
-  "Return IDL command to print the expression EXPR from stack level LEVEL.
-
-It does not seem possible to evaluate an expression on a different
-level than the current.  Therefore, this function retrieves variables
-by reference from other levels, and then includes that variable in
-place of the chosen one.
-
-Since this function depends upon the undocumented IDL routine
-routine_names, there is no guarantee that this will work with future
-versions of IDL."
-  (let ((fetch (- 0 level))
-       (start 0)
-        var fetch-start fetch-end pre post)
-
-    ;; FIXME: In the following we try to find the variables in expression
-    ;; This is quite empirical - I don't know in what situations this will
-    ;; break.  We will look for identifiers and exclude cases where we
-    ;; know it is not a variable.  To distinguish array references from
-    ;; function calls, we require that arrays use [] instead of ()
-
-    (while (string-match
-           "\\(\\`\\|[^a-zA-Z0-9$_][ \t]*\\)\\([a-zA-Z][a-zA-Z0-9$_]*\\)\\([ \t]*[^a-zA-Z0-9$_]\\|\\'\\)" expr start)
-      (setq var (match-string 2 expr)
-           start (match-end 2)
-           pre (substring expr 0 (match-beginning 2))
-           post (substring expr (match-end 2)))
-      (cond
-       ((or
-       ;; Exclude identifiers which are not variables
-        (string-match ",[ \t$\n]*/\\'" pre)        ;; a `/' KEYWORD
-        (and (string-match "[,(][ \t\n]*\\'" pre)
-             (string-match "\\`[ \t]*=" post))  ;; a `=' KEYWORD
-        (string-match "\\`(" post)              ;; a function
-        (string-match "->[ \t]*\\'" pre)        ;; a method
-        (string-match "\\.\\'" pre)))             ;; structure member
-
-       ;; Skip over strings
-       ((and (string-match "\\([\"']\\)[^\1]*$" pre)
-            (string-match (concat "^[^" (match-string 1 pre) "]*"
-                                  (match-string 1 pre)) post))
-       (setq start (+ start (match-end 0))))
-
-
-       ;; seems to be a variable - delimit its name
-       (t
-       (put-text-property start (- start (length var)) 'fetch t expr))))
-
-    (setq start 0)
-    (while (setq fetch-start
-                (next-single-property-change start 'fetch expr))
-      (if (get-text-property start 'fetch expr) ; it's on in range
-         (setq fetch-end fetch-start ;it's off in range
-               fetch-start start)
-       (setq fetch-end (next-single-property-change fetch-start 'fetch expr)))
-      (unless fetch-end (setq fetch-end (length expr)))
-      (remove-text-properties fetch-start fetch-end '(fetch nil) expr)
-      (setq expr (concat (substring expr 0 fetch-start)
-                        (format "(routine_names('%s',fetch=%d))"
-                                (substring expr fetch-start fetch-end)
-                                fetch)
-                        (substring expr fetch-end)))
-      (setq start fetch-end))
-    (if (get-text-property 0 'fetch expr) ; Full expression, left over
-       (setq expr (format "(routine_names('%s',fetch=%d))" expr fetch)))
-    expr))
-
-
-(defun idlwave-shell-help-statement (help expr)
-  "Construct a help statement for printing expression EXPR.
-
-HELP can be non-nil for `help,', nil for `print,' or any string into which
-to insert expression in place of the marker ___, e.g.: print,
-size(___,/DIMENSIONS)"
-  (cond
-   ((null help)
-    (concat "idlwave_print_safe, " expr ","
-           (number-to-string idlwave-shell-max-print-length)))
-   ((stringp help)
-    (if (string-match "\\(^\\|[^_]\\)\\(___\\)\\([^_]\\|$\\)" help)
-       (concat (substring help 0 (match-beginning 2))
-               expr
-               (substring help (match-end 2)))))
-   (t
-    (concat "help, " expr))))
-
-
-(defun idlwave-shell-examine-highlight ()
-  "Highlight the most recent IDL output."
-  (let* ((buffer (get-buffer (idlwave-shell-buffer)))
-        (process (get-buffer-process buffer))
-        (process-mark (if process (process-mark process)))
-        output-begin output-end)
-    (with-current-buffer buffer
-      (goto-char process-mark)
-      (beginning-of-line)
-      (setq output-end (point))
-      (re-search-backward idlwave-shell-prompt-pattern nil t)
-      (beginning-of-line 2)
-      (setq output-begin (point)))
-
-    ;; First make sure the shell window is visible
-    (idlwave-display-buffer (idlwave-shell-buffer)
-                           nil (idlwave-shell-shell-frame))
-    (if (and idlwave-shell-output-overlay process-mark)
-       (move-overlay idlwave-shell-output-overlay
-                     output-begin output-end buffer))))
-
-(defun idlwave-shell-delete-output-overlay ()
-  (unless (memql this-command '(ignore handle-switch-frame))
-    (condition-case nil
-       (if idlwave-shell-output-overlay
-           (delete-overlay idlwave-shell-output-overlay))
-      (error nil))
-    (remove-hook 'pre-command-hook #'idlwave-shell-delete-output-overlay)))
-
-(defun idlwave-shell-delete-expression-overlay ()
-  (unless (memql this-command '(ignore handle-switch-frame))
-    (condition-case nil
-       (if idlwave-shell-expression-overlay
-           (delete-overlay idlwave-shell-expression-overlay))
-      (error nil))
-    (remove-hook 'pre-command-hook #'idlwave-shell-delete-expression-overlay)))
-
-(defvar idlwave-shell-bp-alist nil
-  "Alist of breakpoints.
-A breakpoint is a cons cell \((file line) . \((index module) data))
-
-The car is the `frame' for the breakpoint:
-file - full path file name.
-line - line number of breakpoint - integer.
-
-The first element of the cdr is a list of internal IDL data:
-index - the index number of the breakpoint internal to IDL.
-module - the module for breakpoint internal to IDL.
-
-Remaining elements of the cdr:
-data - Data associated with the breakpoint by `idlwave-shell' currently
-contains four items:
-
-count - number of times to execute breakpoint.  When count reaches 0
-  the breakpoint is cleared and removed from the alist.
-
-command - command to execute when breakpoint is reached, either a
-  Lisp function to be called with `funcall' with no arguments or a
-  list to be evaluated with `eval'.
-
-condition - any condition to apply to the breakpoint.
-
-disabled - whether the bp is disabled.")
-
-(defun idlwave-shell-run-region (beg end &optional n)
-  "Compile and run the region using the IDL process.
-Copies the region to a temporary file `idlwave-shell-temp-pro-file'
-and issues the IDL .run command for the file.  Because the region
-is compiled and run as a main program there is no problem with
-begin-end blocks extending over multiple lines - which would be
-a problem if `idlwave-shell-evaluate-region' was used.
-An END statement is appended to the region if necessary.
-
-If there is a prefix argument, display IDL process."
-  (interactive "r\nP")
-  (let ((oldbuf (current-buffer)))
-    (with-current-buffer (idlwave-find-file-noselect
-                          (idlwave-shell-temp-file 'pro) 'tmp)
-      (set (make-local-variable 'comment-start-skip) ";+[ \t]*")
-      (set (make-local-variable 'comment-start) ";")
-      (erase-buffer)
-      (insert-buffer-substring oldbuf beg end)
-      (if (not (save-excursion
-                 (idlwave-previous-statement)
-                 (idlwave-look-at "\\<end\\>")))
-          (insert "\nend\n"))
-      (save-buffer 0)))
-  (idlwave-shell-send-command (concat ".run \""
-                                     idlwave-shell-temp-pro-file "\"")
-                             nil
-                             (if (idlwave-shell-hide-p 'run) 'mostly)
-                             nil t)
-  (if n
-      (idlwave-display-buffer (idlwave-shell-buffer)
-                             nil (idlwave-shell-shell-frame))))
-
-(defun idlwave-shell-evaluate-region (beg end &optional n)
-  "Send region to the IDL process.
-If there is a prefix argument, display IDL process.
-Does not work for a region with multiline blocks - use
-`idlwave-shell-run-region' for this."
-  (interactive "r\nP")
-  (idlwave-shell-send-command (buffer-substring beg end))
-  (if n
-      (idlwave-display-buffer (idlwave-shell-buffer)
-                             nil (idlwave-shell-shell-frame))))
-
-(defun idlwave-shell-delete-temp-files ()
-  "Delete the temporary files and kill associated buffers."
-  (if (stringp idlwave-shell-temp-pro-file)
-      (condition-case nil
-          (let ((buf (find-buffer-visiting idlwave-shell-temp-pro-file)))
-           (if (buffer-live-p buf)
-               (kill-buffer buf))
-           (delete-file idlwave-shell-temp-pro-file))
-       (error nil)))
-  (if (stringp idlwave-shell-temp-rinfo-save-file)
-      (condition-case nil
-         (delete-file idlwave-shell-temp-rinfo-save-file)
-       (error nil))))
-
-(defun idlwave-display-buffer (buf not-this-window-p &optional frame)
-  ;; Force the frame ourselves.
-  (let ((this-frame (selected-frame)))
-    (save-excursion ;; make sure we end up in the same buffer
-      (if (frame-live-p frame)
-         (select-frame frame))
-      (if (eq this-frame (selected-frame))
-         ;; same frame:  use display buffer, to make sure the current
-         ;; window stays.
-         (display-buffer buf)
-       ;; different frame
-       (if (one-window-p)
-           ;; only window:  switch
-           (progn
-             (switch-to-buffer buf)
-             (selected-window))        ; must return the window.
-         ;; several windows - use display-buffer
-         (display-buffer buf not-this-window-p))))))
-
-(defvar idlwave-shell-bp-buffer " *idlwave-shell-bp*"
-  "Scratch buffer for parsing IDL breakpoint lists and other stuff.")
-
-(defun idlwave-shell-bp-query (&optional no-show)
-  "Reconcile idlwave-shell's breakpoint list with IDL's.
-Queries IDL using the string in `idlwave-shell-bp-query'."
-  (interactive)
-  (idlwave-shell-send-command idlwave-shell-bp-query
-                             `(progn
-                               (idlwave-shell-filter-bp (quote ,no-show)))
-                             'hide))
-
-(defun idlwave-shell-bp-get (bp &optional item)
-  "Get a value for a breakpoint.
-BP has the form of elements in `idlwave-shell-bp-alist'.
-Optional second arg ITEM is the particular value to retrieve.
-ITEM can be `file', `line', `index', `module', `count', `cmd',
-`condition', `disabled', `type', or `data'.  `data' returns a list
-of `count', `cmd' and `condition'.  Defaults to `index'."
-  (cond
-   ;; Frame
-   ((eq item 'line) (nth 1 (car bp)))
-   ((eq item 'file) (nth 0 (car bp)))
-   ;; idlwave-shell breakpoint data
-   ((eq item 'data) (cdr (cdr bp)))
-   ((eq item 'count) (nth 0 (cdr (cdr bp))))
-   ((eq item 'cmd) (nth 1 (cdr (cdr bp))))
-   ((eq item 'condition) (nth 2 (cdr (cdr bp))))
-   ((eq item 'disabled) (nth 3 (cdr (cdr bp))))
-   ;; IDL breakpoint info
-   ((eq item 'module)
-    (let ((module (nth 1 (car (cdr bp)))))
-      (if (listp module) (car module) module)))
-   ((eq item 'type)
-    (let ((module (nth 1 (car (cdr bp)))))
-      (if (listp module) (nth 1 module))))
-   ;;    index - default
-   (t (nth 0 (car (cdr bp))))))
-
-(defun idlwave-shell-filter-bp (&optional no-show)
-  "Get the breakpoints from `idlwave-shell-command-output'.
-Create `idlwave-shell-bp-alist' updating breakpoint count and command
-data from previous breakpoint list.  If NO-SHOW is set, don't update
-the breakpoint overlays."
-  (with-current-buffer (get-buffer-create idlwave-shell-bp-buffer)
-    (erase-buffer)
-    (insert idlwave-shell-command-output)
-    (goto-char (point-min))
-    (let ((old-bp-alist idlwave-shell-bp-alist)
-         ;; Searching the breakpoints
-         ;; In IDL 5.5, the breakpoint reporting format changed.
-         (bp-re54 "^[ \t]*\\([0-9]+\\)[ \t]+\\(\\S-+\\)?[ \t]+\\([0-9]+\\)[ \t]+\\(\\S-+\\)")
-         (bp-re55
-          (concat
-           "^\\s-*\\([0-9]+\\)"    ; 1 index
-           "\\s-+\\([0-9]+\\)"     ; 2 line number
-           "\\s-+\\(Uncompiled\\|" ; 3-6 either uncompiled or routine name
-           "\\(\\(Func=\\|Pro=\\)\\(\\$?[a-zA-Z][a-zA-Z0-9$_:]*\\$?\\)\\)\\)"
-           "\\(\\s-*,\\s-*After=[0-9]+/\\([0-9]+\\)?\\)?" ; 7-8 After part
-           "\\(\\s-*,\\s-*\\(BreakOnce\\)\\)?"            ; 9-10 BreakOnce
-           "\\(\\s-*,\\s-*\\(Condition='\\(.*\\)'\\)\n?\\)?" ; 11-13 Condition
-           "\\(\\s-*,\\s-*\\(Disabled\\)\n?\\)?"          ; 14-15 Disabled
-           "\\s-+\\(\\S-+\\)"))                           ; 16 File name
-         file line index module
-         count condition disabled
-         bp-re indmap)
-      (setq idlwave-shell-bp-alist (list nil))
-      ;; Search for either header type, and set the correct regexp
-      (when (or
-            (if (re-search-forward "^\\s-*Index.*\n\\s-*-" nil t)
-                (setq bp-re bp-re54    ; versions <= 5.4
-                      indmap '(1 2 3 4))) ;index module line file
-            (if (re-search-forward
-                 "^\\s-*Index\\s-*Line\\s-*Attributes\\s-*File" nil t)
-                (setq bp-re bp-re55    ; versions >= 5.5
-                      indmap '(1 6 2 16)))) ; index module line file
-       ;; There seems to be a breakpoint listing here, parse breakpoint lines.
-       (while (re-search-forward bp-re nil t)
-         (setq index (string-to-number (match-string (nth 0 indmap)))
-               module (match-string (nth 1 indmap))
-               line (string-to-number (match-string (nth 2 indmap)))
-               file (idlwave-shell-file-name (match-string (nth 3 indmap))))
-         (if (eq bp-re bp-re55)
-             (setq count (if (match-string 10) 1
-                           (if (match-string 8)
-                               (string-to-number (match-string 8))))
-                   condition (match-string 13)
-                   disabled (not (null (match-string 15)))))
-
-         ;; Add the breakpoint info to the list
-         (nconc idlwave-shell-bp-alist
-                (list (cons (list file line)
-                            (list
-                             (list index module)
-                             ;; bp data: count, command, condition, disabled
-                             count nil condition disabled))))))
-      (setq idlwave-shell-bp-alist (cdr idlwave-shell-bp-alist))
-      ;; Update breakpoint data
-      (mapc (if (eq bp-re bp-re54)
-               #'idlwave-shell-update-bp
-             #'idlwave-shell-update-bp-command-only)
-           old-bp-alist)))
-  ;; Update the breakpoint overlays
-  (unless no-show (idlwave-shell-update-bp-overlays))
-  ;; Return the new list
-  idlwave-shell-bp-alist)
-
-(defun idlwave-shell-update-bp-command-only (bp)
-  (idlwave-shell-update-bp bp t))
-
-(defun idlwave-shell-update-bp (bp &optional command-only)
-  "Update BP data in breakpoint list.
-If BP frame is in `idlwave-shell-bp-alist' updates the breakpoint data."
-  (let ((match (assoc (car bp) idlwave-shell-bp-alist)))
-    (if match
-       (if command-only
-           (setf (nth 1 (cdr (cdr match))) (nth 1 (cdr (cdr match))))
-         (setcdr (cdr match) (cdr (cdr bp)))))))
-
-(defun idlwave-shell-set-bp-data (bp data)
-  "Set the data of BP to DATA."
-  (setcdr (cdr bp) data))
-
-(defun idlwave-shell-bp (frame &optional data module)
-  "Create a breakpoint structure containing FRAME and DATA.
-Second and third args, DATA and MODULE, are optional.  Returns
-a breakpoint of the format used in `idlwave-shell-bp-alist'.
-Can be used in commands attempting match a breakpoint in
-`idlwave-shell-bp-alist'."
-  (cons frame ;; (file line)
-       (cons (list nil module) ;; (index_id (module type) | module)
-             data)))           ;; (count command condition disabled)
-
-(defvar idlwave-shell-old-bp nil
-  "List of breakpoints previous to setting a new breakpoint.")
-
-(defun idlwave-shell-sources-bp (bp)
-  "Check `idlwave-shell-sources-alist' for source of breakpoint using BP.
-If an equivalency is found, return the IDL internal source name.
-Otherwise return the filename in BP."
-  (let*
-      ((bp-file (idlwave-shell-bp-get bp 'file))
-       (bp-module (idlwave-shell-bp-get bp 'module))
-       (internal-file-list
-       (if bp-module
-           (cdr (assoc bp-module idlwave-shell-sources-alist)))))
-    (if (and internal-file-list
-            (equal bp-file (nth 0 internal-file-list)))
-        (nth 1 internal-file-list)
-      bp-file)))
-
-(defun idlwave-shell-set-bp (bp &optional no-show)
-  "Try to set a breakpoint BP.
-The breakpoint will be placed at the beginning of the statement on the
-line specified by BP or at the next IDL statement if that line is not
-a statement.  Determines IDL's internal representation for the
-breakpoint, which may have occurred at a different line than
-specified.  If NO-SHOW is non-nil, don't do any updating."
-  ;; Get and save the old breakpoints
-  (idlwave-shell-send-command
-   idlwave-shell-bp-query
-   `(progn
-     (idlwave-shell-filter-bp (quote ,no-show))
-     (setq idlwave-shell-old-bp idlwave-shell-bp-alist))
-   'hide)
-
-  ;; Get sources for this routine in the sources list
-  (idlwave-shell-module-source-query (idlwave-shell-bp-get bp 'module)
-                                    (idlwave-shell-bp-get bp 'type))
-  (let*
-      ((count (idlwave-shell-bp-get bp 'count))
-       (condition (idlwave-shell-bp-get bp 'condition))
-       (disabled (idlwave-shell-bp-get bp 'disabled))
-       (key (concat (if (and count (numberp count))
-                       (cond
-                        ((= count 1) ",/once")
-                        ((> count 1) (format ",after=%d" count))))
-                   (if condition (concat ",CONDITION=\"" condition "\""))
-                   ;; IDL can't simultaneously set a condition/count
-                   ;; and disable a breakpoint, but it does keep both
-                   ;; of these when resetting the same BP.  We assume
-                   ;; DISABLE and CONDITION/COUNT are not set
-                   ;; together for a newly created breakpoint.
-                   (if (and disabled (not condition) (not count))
-                           ",/DISABLE")))
-       (line (idlwave-shell-bp-get bp 'line)))
-    (idlwave-shell-send-command
-     (concat "breakpoint,'"
-            (idlwave-shell-sources-bp bp) "',"
-            (if (integerp line) (setq line (int-to-string line)))
-            key)
-     ;; Check for failure and adjust breakpoint to match IDL's list
-     `(progn
-       (if (idlwave-shell-set-bp-check (quote ,bp))
-           (idlwave-shell-set-bp-adjust (quote ,bp) (quote ,no-show))))
-     ;; hide output?
-     (idlwave-shell-hide-p 'breakpoint)
-     'preempt t)))
-
-(defun idlwave-shell-set-bp-adjust (bp &optional no-show)
-  "Find the breakpoint in IDL's internal list of breakpoints."
-  (idlwave-shell-send-command
-   idlwave-shell-bp-query
-   `(progn
-      (idlwave-shell-filter-bp 'no-show)
-      (idlwave-shell-new-bp (quote ,bp))
-      (unless (quote ,no-show)
-       (idlwave-shell-update-bp-overlays)))
-   'hide
-   'preempt))
-
-(defun idlwave-shell-find-bp (frame)
-  "Return breakpoint from `idlwave-shell-bp-alist' for frame.
-Returns nil if frame not found."
-  (assoc frame idlwave-shell-bp-alist))
-
-(defun idlwave-shell-find-current-bp ()
-  "Find breakpoint here, or at halt location."
-  (let ((bp (idlwave-shell-find-bp (idlwave-shell-current-frame))))
-    (when (not bp)
-      ;; Try moving to beginning of halted-at statement
-      (save-excursion
-       (idlwave-shell-goto-frame)
-       (idlwave-beginning-of-statement)
-       (setq bp (idlwave-shell-find-bp (idlwave-shell-current-frame))))
-      (unless bp
-       (beep)
-       (message "Cannot identify breakpoint for this line")))
-    bp))
-
-(defun idlwave-shell-new-bp (bp)
-  "Find the new breakpoint in IDL's list and update with DATA.
-The actual line number for a breakpoint in IDL may be different from
-the line number used with the IDL breakpoint command.
-Looks for a new breakpoint index number in the list.  This is
-considered the new breakpoint if the file name of frame matches."
-  (let ((obp-index (mapcar #'idlwave-shell-bp-get idlwave-shell-old-bp))
-        (bpl idlwave-shell-bp-alist))
-    (while (and (member (idlwave-shell-bp-get (car bpl)) obp-index)
-                (setq bpl (cdr bpl))))
-    (if (and
-         (not bpl)
-         ;; No additional breakpoint.
-         ;; Need to check if we are just replacing a breakpoint.
-         (setq bpl (assoc (car bp) idlwave-shell-bp-alist)))
-        (setq bpl (list bpl)))
-    (if (and bpl
-             (equal (idlwave-shell-bp-get (setq bpl (car bpl)) 'file)
-                    (idlwave-shell-bp-get bp 'file)))
-        ;; Got the breakpoint - add count, command to it.
-        ;; This updates `idlwave-shell-bp-alist' because a deep copy was
-        ;; not done for bpl.
-        (idlwave-shell-set-bp-data bpl (idlwave-shell-bp-get bp 'data))
-      (beep)
-      (message "Failed to identify breakpoint in IDL"))))
-
-(defvar idlwave-shell-bp-overlays nil
-  "Alist of overlays marking breakpoints.")
-(defvar idlwave-shell-bp-glyph)
-
-(defvar idlwave-shell-debug-line-map (make-sparse-keymap))
-(define-key idlwave-shell-debug-line-map [mouse-3]
-  #'idlwave-shell-mouse-active-bp)
-
-(defun idlwave-shell-update-bp-overlays ()
-  "Update the overlays which mark breakpoints in the source code.
-Existing overlays are recycled, in order to minimize consumption."
-  (when idlwave-shell-mark-breakpoints
-    (let ((ov-alist (copy-alist idlwave-shell-bp-overlays))
-         (bp-list idlwave-shell-bp-alist)
-         (use-glyph (and (memq idlwave-shell-mark-breakpoints '(t glyph))
-                         idlwave-shell-bp-glyph))
-         ov ov-list bp buf old-buffers)
-
-      ;; Delete the old overlays from their buffers
-      (if ov-alist
-         (while (setq ov-list (pop ov-alist))
-           (while (setq ov (pop (cdr ov-list)))
-             (cl-pushnew (overlay-buffer ov) old-buffers)
-             (delete-overlay ov))))
-
-      (setq ov-alist idlwave-shell-bp-overlays
-           idlwave-shell-bp-overlays
-           (if idlwave-shell-bp-glyph
-               (mapcar #'list (mapcar #'car idlwave-shell-bp-glyph))
-             (list (list 'bp))))
-      (while (setq bp (pop bp-list))
-       (save-excursion
-         (idlwave-shell-goto-frame (car bp))
-          (let* ((end (line-end-position))
-                (beg (progn (beginning-of-line 1) (point)))
-                (condition (idlwave-shell-bp-get bp 'condition))
-                (count (idlwave-shell-bp-get bp 'count))
-                (disabled (idlwave-shell-bp-get bp 'disabled))
-                (type (if idlwave-shell-bp-glyph
-                          (cond
-                           (condition 'bp-cond )
-                           (count
-                            (cond
-                             ((<= count 0) 'bp)
-                             ((<= count 4)
-                              (intern
-                               (concat "bp-" (number-to-string count))))
-                             (t 'bp-n)))
-                           (t 'bp))
-                        'bp))
-                (help-list
-                 (delq nil
-                       (list
-                        (if count
-                            (concat "after:" (int-to-string count)))
-                        (if condition
-                            (concat "condition:" condition))
-                        (if disabled "disabled"))))
-                (help-text (concat
-                            "BP "
-                            (int-to-string (idlwave-shell-bp-get bp))
-                            (if help-list
-                                (concat
-                                 " - "
-                                 (mapconcat #'identity help-list ", ")))
-                            (if (and (not count) (not condition))
-                                " (use mouse-3 for breakpoint actions)")))
-                (full-type (if disabled
-                               (intern (concat (symbol-name type)
-                                               "-disabled"))
-                             type))
-                (ov-existing (assq full-type ov-alist))
-                (ov (or (and (cdr ov-existing)
-                             (pop (cdr ov-existing)))
-                        (idlwave-shell-make-new-bp-overlay type disabled)))
-                match)
-           (if idlwave-shell-breakpoint-popup-menu
-               (overlay-put ov 'help-echo help-text))
-           (move-overlay ov beg end)
-           (if (setq match (assq full-type idlwave-shell-bp-overlays))
-               (push ov (cdr match))
-             (nconc idlwave-shell-bp-overlays
-                    (list (list full-type ov)))))
-         ;; Take care of margins if using a glyph
-         (when use-glyph
-           (if old-buffers
-               (setq old-buffers (delq (current-buffer) old-buffers)))
-            (if (< left-margin-width 2)
-                (setq left-margin-width 2))
-           (let ((window (get-buffer-window (current-buffer) 0)))
-             (if window
-                 (set-window-margins
-                  window left-margin-width right-margin-width))))))
-      (if use-glyph
-         (while (setq buf (pop old-buffers))
-           (with-current-buffer buf
-              (setq left-margin-width 0)
-             (let ((window (get-buffer-window buf 0)))
-               (if window
-                   (set-window-margins
-                    window left-margin-width right-margin-width)))))))))
-
-(defun idlwave-shell-make-new-bp-overlay (&optional type disabled)
-  "Make a new overlay for highlighting breakpoints.
-
-This stuff is strongly dependent upon the version of Emacs.  If TYPE
-is passed, make an overlay of that type (`bp' or `bp-cond', currently
-only for glyphs)."
-  (let ((ov (make-overlay 1 1))
-       (use-glyph (and (memq idlwave-shell-mark-breakpoints '(t glyph))
-                       idlwave-shell-bp-glyph))
-       (type (or type 'bp))
-       (face (if disabled
-                 idlwave-shell-disabled-breakpoint-face
-               idlwave-shell-breakpoint-face)))
-    (when idlwave-shell-breakpoint-popup-menu
-      (overlay-put ov 'mouse-face 'highlight)
-      (overlay-put ov 'keymap idlwave-shell-debug-line-map))
-    (cond
-     (window-system
-      (if use-glyph
-         (let ((image-props (cdr (assq type idlwave-shell-bp-glyph)))
-               string)
-
-           (if disabled (setq image-props
-                              (append image-props
-                                      (list :conversion 'disabled))))
-           (setq string
-                 (propertize "@"
-                             'display
-                             (list (list 'margin 'left-margin)
-                                   image-props)))
-           (overlay-put ov 'before-string string))
-       ;; just the face
-       (overlay-put ov 'face face)))
-
-     ;; use a face
-     (idlwave-shell-mark-breakpoints
-      (overlay-put ov 'face face))
-
-     ;; No marking
-     (t nil))
-    ov))
-
-(defun idlwave-shell-mouse-active-bp (ev)
-  "Does right-click mouse action on breakpoint lines."
-  (interactive "e")
-  (if ev (mouse-set-point ev))
-  (let ((bp (idlwave-shell-find-bp (idlwave-shell-current-frame)))
-       index condition count select cmd disabled)
-    (unless bp
-      (error "Breakpoint not found"))
-    (setq index (int-to-string (idlwave-shell-bp-get bp))
-         condition (idlwave-shell-bp-get bp 'condition)
-         cmd (idlwave-shell-bp-get bp 'cmd)
-         count (idlwave-shell-bp-get bp 'count)
-         disabled (idlwave-shell-bp-get bp 'disabled))
-    (setq select (idlwave-popup-select
-                 ev
-                 (delq nil
-                       (list (if disabled "Enable" "Disable")
-                             "Clear"
-                             "Clear All"
-                             (if condition "Remove Condition" "Add Condition")
-                             (if condition "Change Condition")
-                             (if count "Remove Repeat Count"
-                               "Add Repeat Count")
-                             (if count "Change Repeat Count")))
-                 (concat "BreakPoint " index)))
-    (if select
-       (cond
-        ((string-equal select "Clear All")
-         (idlwave-shell-clear-all-bp))
-        ((string-equal select "Clear")
-         (idlwave-shell-clear-current-bp))
-        ((string-match "Condition" select)
-         (idlwave-shell-break-here count cmd
-                                   (if (or (not condition)
-                                           (string-match "Change" select))
-                                     (read-string "Break Condition: "))
-                                   disabled))
-        ((string-match "Count" select)
-         (idlwave-shell-break-here (if (or (not count)
-                                           (string-match "Change" select))
-                                       (string-to-number
-                                        (read-string "Break After Count: ")))
-                                   cmd condition disabled))
-        ((string-match "able$" select)
-         (idlwave-shell-toggle-enable-current-bp))
-        (t
-         (message "Unimplemented: %s" select))))))
-
-(defun idlwave-shell-edit-default-command-line ()
-  "Edit the current execute command."
-  (interactive)
-  (setq idlwave-shell-command-line-to-execute
-       (read-string "IDL> " idlwave-shell-command-line-to-execute)))
-
-(defun idlwave-shell-execute-default-command-line (arg)
-  "Execute a command line.  On first use, ask for the command.
-Also with prefix arg, ask for the command.  You can also use the command
-`idlwave-shell-edit-default-command-line' to edit the line."
-  (interactive "P")
-  (cond
-   ((equal arg '(16))
-    (setq idlwave-shell-command-line-to-execute nil))
-   ((equal arg '(4))
-    (setq idlwave-shell-command-line-to-execute
-         (read-string "IDL> " idlwave-shell-command-line-to-execute))))
-  (idlwave-shell-reset 'hidden)
-  (idlwave-shell-send-command
-   (or idlwave-shell-command-line-to-execute
-       (with-current-buffer (idlwave-shell-buffer)
-        (ring-ref comint-input-ring 0)))
-   '(idlwave-shell-redisplay 'hide)))
-
-(defun idlwave-shell-save-and-run ()
-  "Save file and run it in IDL.
-Runs `save-buffer' and sends a '.RUN' command for the associated file to IDL.
-When called from the shell buffer, re-run the file which was last handled by
-one of the save-and-.. commands."
-  (interactive)
-  (idlwave-shell-save-and-action 'run))
-
-(defun idlwave-shell-save-and-compile ()
-  "Save file and run it in IDL.
-Runs `save-buffer' and sends '.COMPILE' command for the associated file to IDL.
-When called from the shell buffer, re-compile the file which was last handled by
-one of the save-and-.. commands."
-  (interactive)
-  (idlwave-shell-save-and-action 'compile))
-
-(defun idlwave-shell-save-and-batch ()
-  "Save file and batch it in IDL.
-Runs `save-buffer' and sends a '@file' command for the associated file to IDL.
-When called from the shell buffer, re-batch the file which was last handled by
-one of the save-and-.. commands."
-  (interactive)
-  (idlwave-shell-save-and-action 'batch))
-
-(defun idlwave-shell-save-and-action (action)
-  "Save file and compile it in IDL.
-Runs `save-buffer' and sends a '.RUN' command for the associated file to IDL.
-When called from the shell buffer, re-compile the file which was last
-handled by this command."
-  ;; Remove the stop overlay.
-  (if idlwave-shell-stop-line-overlay
-      (delete-overlay idlwave-shell-stop-line-overlay))
-  (if idlwave-shell-is-stopped
-      (idlwave-shell-electric-debug-all-off))
-  (setq idlwave-shell-is-stopped nil)
-  (setq overlay-arrow-string nil)
-  (let (buf)
-    (cond
-     ((derived-mode-p 'idlwave-mode)
-      (save-buffer)
-      (setq idlwave-shell-last-save-and-action-file (buffer-file-name)))
-     (idlwave-shell-last-save-and-action-file
-      (if (setq buf (find-buffer-visiting
-                    idlwave-shell-last-save-and-action-file))
-         (with-current-buffer buf
-           (save-buffer))))
-     (t (setq idlwave-shell-last-save-and-action-file
-             (read-file-name "File: ")))))
-  (if (file-regular-p idlwave-shell-last-save-and-action-file)
-      (progn
-       (idlwave-shell-send-command
-        (concat (cond ((eq action 'run)     ".run ")
-                      ((eq action 'compile) ".compile ")
-                      ((eq action 'batch)   "@")
-                      (t (error "Unknown action %s" action)))
-                "\""
-                idlwave-shell-last-save-and-action-file
-                "\"")
-        `(idlwave-shell-maybe-update-routine-info nil
-          ,idlwave-shell-last-save-and-action-file)
-        (if (idlwave-shell-hide-p 'run) 'mostly) nil t)
-       (idlwave-shell-bp-query))
-    (let ((msg (format "No such file %s"
-                      idlwave-shell-last-save-and-action-file)))
-      (setq idlwave-shell-last-save-and-action-file nil)
-      (error msg))))
-
-(defun idlwave-shell-maybe-update-routine-info (&optional wait file)
-  "Update the routine info if the shell is not stopped at an error."
-  (if (and (not idlwave-shell-is-stopped)
-          (or (eq t idlwave-auto-routine-info-updates)
-              (memq 'compile-buffer idlwave-auto-routine-info-updates))
-          idlwave-query-shell-for-routine-info
-          idlwave-routines)
-      (idlwave-shell-update-routine-info t nil wait file)))
-
-(defvar idlwave-shell-sources-query "help,/source,/full"
-  "IDL command to obtain source files for compiled procedures.")
-
-(defvar idlwave-shell-sources-alist nil
-  "Alist of IDL procedure names and compiled source files.
-Elements of the alist have the form:
-
-  (module name . (source-file-truename idlwave-internal-filename))")
-
-(defun idlwave-shell-module-source-query (module &optional type)
-  "Determine the source file for a given module.
-Query as a function if TYPE set to something beside `pro'."
-  (if module
-      (idlwave-shell-send-command
-       (format "print,(routine_info('%s',/SOURCE%s)).PATH" module
-              (if (eq type 'pro) "" ",/FUNCTIONS"))
-       `(idlwave-shell-module-source-filter ,module)
-       'hide 'wait)))
-
-(defun idlwave-shell-module-source-filter (module)
-  "Get module source, and update `idlwave-shell-sources-alist'."
-  (let ((old (assoc (upcase module) idlwave-shell-sources-alist))
-       filename)
-    (when (string-match ".PATH *[\n\r]\\([^%][^\r\n]+\\)[\n\r]"
-                       idlwave-shell-command-output)
-      (setq filename (substring idlwave-shell-command-output
-                               (match-beginning 1) (match-end 1)))
-      (if old
-         (setcdr old (list (idlwave-shell-file-name filename) filename))
-       (setq idlwave-shell-sources-alist
-             (append idlwave-shell-sources-alist
-                     (list (cons (upcase module)
-                                 (list (idlwave-shell-file-name filename)
-                                       filename)))))))))
-
-(defun idlwave-shell-sources-query ()
-  "Determine source files for all IDL compiled procedures.
-Queries IDL using the string in `idlwave-shell-sources-query'."
-  (interactive)
-  (idlwave-shell-send-command idlwave-shell-sources-query
-                             'idlwave-shell-sources-filter
-                             'hide))
-
-(defun idlwave-shell-sources-filter ()
-  "Get source files from `idlwave-shell-sources-query' output.
-Create `idlwave-shell-sources-alist' consisting of list elements
-of the form:
- (module name . (source-file-truename idlwave-internal-filename))"
-  (with-current-buffer (get-buffer-create idlwave-shell-bp-buffer)
-    (erase-buffer)
-    (insert idlwave-shell-command-output)
-    (goto-char (point-min))
-    (let (cpro cfun)
-      (if (re-search-forward "Compiled Procedures:" nil t)
-          (progn
-            (forward-line) ; Skip $MAIN$
-            (setq cpro (point))))
-      (if (re-search-forward "Compiled Functions:" nil t)
-          (progn
-            (setq cfun (point))
-            (setq idlwave-shell-sources-alist
-                  (append
-                   ;; compiled procedures
-                   (progn
-                     (narrow-to-region cpro (line-beginning-position))
-                     (goto-char (point-min))
-                     (idlwave-shell-sources-grep))
-                   ;; compiled functions
-                   (progn
-                     (widen)
-                     (goto-char cfun)
-                     (idlwave-shell-sources-grep)))))))))
-
-(defun idlwave-shell-sources-grep ()
-  (save-excursion
-    (let ((al (list nil)))
-      (while (and
-              (not (progn (forward-line) (eobp)))
-              (re-search-forward
-               "\\s-*\\(\\S-+\\)\\s-+\\(\\S-+\\)" nil t))
-        (nconc al
-               (list
-                (cons
-                 (buffer-substring      ; name
-                  (match-beginning 1) (match-end 1))
-                 (let ((internal-filename
-                        (buffer-substring       ; source
-                         (match-beginning 2) (match-end 2))))
-                   (list
-                    (idlwave-shell-file-name internal-filename)
-                    internal-filename))
-                ))))
-      (cdr al))))
-
-(defun idlwave-shell-clear-all-bp ()
-  "Remove all breakpoints in IDL."
-  (interactive)
-  (idlwave-shell-send-command
-   idlwave-shell-bp-query
-   '(progn
-      (idlwave-shell-filter-bp)
-      (mapcar (lambda (x) (idlwave-shell-clear-bp x 'no-query))
-             idlwave-shell-bp-alist)
-      (idlwave-shell-bp-query))
-   'hide))
-
-(defun idlwave-shell-list-all-bp ()
-  "List all breakpoints in IDL."
-  (interactive)
-  (idlwave-shell-send-command
-   idlwave-shell-bp-query))
-
-(defvar idlwave-shell-error-last 0
-  "Position of last syntax error in `idlwave-shell-error-buffer'.")
-
-(defun idlwave-shell-goto-next-error ()
-  "Move point to next IDL syntax error."
-  (interactive)
-  (let (frame col)
-    (with-current-buffer idlwave-shell-error-buffer
-      (goto-char idlwave-shell-error-last)
-      (if (or
-          (re-search-forward idlwave-shell-syntax-error nil t)
-          (re-search-forward idlwave-shell-other-error nil t))
-          (progn
-            (setq frame
-                  (list
-                   (save-match-data
-                     (idlwave-shell-file-name
-                      (buffer-substring (match-beginning 1 )
-                                       (match-end 1))))
-                   (string-to-number
-                    (buffer-substring (match-beginning 2)
-                                      (match-end 2)))))
-            ;; Try to find the column of the error
-            (save-excursion
-              (setq col
-                    (if (re-search-backward "\\^" nil t)
-                        (current-column)
-                      0)))))
-      (setq idlwave-shell-error-last (point)))
-    (if frame
-        (progn
-          (idlwave-shell-display-line frame col 'disable))
-      (beep)
-      (message "No more errors."))))
-
-(defun idlwave-shell-file-name (name)
-  "If `idlwave-shell-use-truename' is non-nil, convert file name to true name.
-Otherwise, just expand the file name."
-  (let ((def-dir (if (derived-mode-p 'idlwave-shell-mode)
-                    default-directory
-                  idlwave-shell-default-directory)))
-    (if idlwave-shell-use-truename
-       (file-truename name def-dir)
-      (expand-file-name name def-dir))))
-
-;; Keybindings ------------------------------------------------------------
-
-(defvar idlwave-shell-mode-map
-  (let ((map (make-sparse-keymap)))
-    (set-keymap-parent map comint-mode-map)
-
-    ;;(define-key map "\M-?" 'comint-dynamic-list-completions)
-    ;;(define-key map "\t" 'comint-dynamic-complete)
-
-    (define-key map "\C-w"     #'comint-kill-region)
-    (define-key map "\t"       #'idlwave-shell-complete)
-    (define-key map "\M-\t"    #'idlwave-shell-complete)
-    (define-key map "\C-c\C-s" #'idlwave-shell)
-    (define-key map "\C-c?"    #'idlwave-routine-info)
-    (define-key map "\C-g"     #'idlwave-keyboard-quit)
-    (define-key map "\M-?"     #'idlwave-context-help)
-    (define-key map [(control meta ?\?)]
-      #'idlwave-help-assistant-help-with-topic)
-    (define-key map "\C-c\C-i" #'idlwave-update-routine-info)
-    (define-key map "\C-c\C-y" #'idlwave-shell-char-mode-loop)
-    (define-key map "\C-c\C-x" #'idlwave-shell-send-char)
-    (define-key map "\C-c="    #'idlwave-resolve)
-    (define-key map "\C-c\C-v" #'idlwave-find-module)
-    (define-key map "\C-c\C-k" #'idlwave-kill-autoloaded-buffers)
-    (define-key map idlwave-shell-prefix-key
-      #'idlwave-shell-debug-map)
-    (define-key map [(up)]  #'idlwave-shell-up-or-history)
-    (define-key map [(down)] #'idlwave-shell-down-or-history)
-    (define-key idlwave-shell-mode-map [(shift mouse-3)]
-      #'idlwave-mouse-context-help)
-    map)
-  "Keymap for `idlwave-mode'.")
-
-(defvar idlwave-shell-electric-debug-mode-map
-  (let ((map (make-sparse-keymap)))
-    ;; A few extras in the electric debug map
-    (define-key map " " #'idlwave-shell-step)
-    (define-key map "+" #'idlwave-shell-stack-up)
-    (define-key map "=" #'idlwave-shell-stack-up)
-    (define-key map "-" #'idlwave-shell-stack-down)
-    (define-key map "_" #'idlwave-shell-stack-down)
-    (define-key map "e" (lambda () (interactive) (idlwave-shell-print '(16))))
-    (define-key map "q" #'idlwave-shell-retall)
-    (define-key map "t"
-      (lambda () (interactive) (idlwave-shell-send-command "help,/TRACE")))
-    (define-key map [(control ??)]  #'idlwave-shell-electric-debug-help)
-    (define-key map "x"
-      (lambda (arg) (interactive "P")
-        (idlwave-shell-print arg nil nil t)))
-    map))
-
-(defvar idlwave-shell-mode-prefix-map (make-sparse-keymap))
-(defalias 'idlwave-shell-mode-prefix-map idlwave-shell-mode-prefix-map)
-(defvar idlwave-mode-prefix-map (make-sparse-keymap))
-(defalias 'idlwave-mode-prefix-map idlwave-mode-prefix-map)
-
-(defun idlwave-shell-define-key-both (key hook)
-  "Define a key in both the shell and buffer mode maps."
-  (define-key idlwave-mode-map key hook)
-  (define-key idlwave-shell-mode-map key hook))
-(define-key idlwave-mode-map "\C-c\C-y" #'idlwave-shell-char-mode-loop)
-(define-key idlwave-mode-map "\C-c\C-x" #'idlwave-shell-send-char)
-
-;; The mouse bindings for PRINT and HELP
-(idlwave-shell-define-key-both [(shift down-mouse-2)]
-                               #'idlwave-shell-mouse-print)
-(idlwave-shell-define-key-both [(control meta down-mouse-2)]
-                               #'idlwave-shell-mouse-help)
-(idlwave-shell-define-key-both [(control shift down-mouse-2)]
-                               #'idlwave-shell-examine-select)
-
-;; We need to turn off the button release events.
-
-(idlwave-shell-define-key-both [(shift mouse-2)] #'ignore)
-(idlwave-shell-define-key-both [(shift control mouse-2)] #'ignore)
-(idlwave-shell-define-key-both [(control meta mouse-2)] #'ignore)
-
-
-;; The following set of bindings is used to bind the debugging keys.
-;; If `idlwave-shell-activate-prefix-keybindings' is non-nil, the
-;; first key in the list gets bound the C-c C-d prefix map.  If
-;; `idlwave-shell-debug-modifiers' is non-nil, the second key in the
-;; list gets bound with the specified modifiers in both
-;; `idlwave-mode-map' and `idlwave-shell-mode-map'.  The next list
-;; item, if non-nil, means to bind this as a single key in the
-;; electric-debug-mode-map.
-;;
-;; [C-c C-d]-binding   debug-modifier-key command bind-electric-debug buf-only
-;; Used keys:   abcdef hijklmnopqrstuvwxyz
-;; Unused keys:       g
-(let* ((specs
-       '(([(control ?b)]   ?b   idlwave-shell-break-here t t)
-         ([(control ?i)]   ?i   idlwave-shell-break-in t t)
-         ([(control ?j)]   ?j   idlwave-shell-break-this-module t t)
-         ([(control ?d)]   ?d   idlwave-shell-clear-current-bp t)
-         ([(control ?a)]   ?a   idlwave-shell-clear-all-bp t)
-         ([(control ?\\)]  ?\\  idlwave-shell-toggle-enable-current-bp t)
-         ([(control ?s)]   ?s   idlwave-shell-step t)
-         ([(control ?n)]   ?n   idlwave-shell-stepover t)
-         ([(control ?k)]   ?k   idlwave-shell-skip t)
-         ([(control ?u)]   ?u   idlwave-shell-up t)
-         ([(control ?o)]   ?o   idlwave-shell-out t)
-         ([(control ?m)]   ?m   idlwave-shell-return t)
-         ([(control ?h)]   ?h   idlwave-shell-to-here t t)
-         ([(control ?r)]   ?r   idlwave-shell-cont t)
-         ([(control ?y)]   ?y   idlwave-shell-execute-default-command-line)
-         ([(control ?z)]   ?z   idlwave-shell-reset t)
-         ([(control ?q)]   ?q   idlwave-shell-quit)
-         ([(control ?p)]   ?p   idlwave-shell-print t)
-         ([(        ??)]   ??   idlwave-shell-help-expression t)
-         ([(control ?v)]   ?v   idlwave-shell-toggle-electric-debug-mode t t)
-         ([(control ?x)]   ?x   idlwave-shell-goto-next-error)
-         ([(control ?c)]   ?c   idlwave-shell-save-and-run t)
-         ([(        ?@)]   ?@   idlwave-shell-save-and-batch)
-         ([(control ?e)]   ?e   idlwave-shell-run-region)
-         ([(control ?w)]   ?w   idlwave-shell-resync-dirs)
-         ([(control ?l)]   ?l   idlwave-shell-redisplay t)
-         ([(control ?t)]   ?t   idlwave-shell-toggle-toolbar)
-         ([(control up)]   up   idlwave-shell-stack-up)
-         ([(control down)] down idlwave-shell-stack-down)
-         ([(        ?\[)]  ?\[  idlwave-shell-goto-previous-bp t t)
-         ([(        ?\])]  ?\]  idlwave-shell-goto-next-bp t t)
-         ([(control ?f)]   ?f   idlwave-shell-window)))
-       (mod (and (listp idlwave-shell-debug-modifiers)
-                idlwave-shell-debug-modifiers))
-       (shift (memq 'shift mod))
-       (mod-noshift (delete 'shift (copy-sequence mod)))
-       s k1 c2 k2 cmd electric only-buffer cannotshift)
-  (while (setq s (pop specs))
-    (setq k1  (nth 0 s)
-         c2  (nth 1 s)
-         cmd (nth 2 s)
-         electric (nth 3 s)
-         only-buffer (nth 4 s)
-         cannotshift (and shift (characterp c2) (eq c2 (upcase c2))))
-
-    ;; The regular prefix keymap.
-    (when (and idlwave-shell-activate-prefix-keybindings k1)
-      (unless only-buffer
-       (define-key idlwave-shell-mode-prefix-map k1 cmd))
-      (define-key idlwave-mode-prefix-map k1 cmd))
-    ;; The debug modifier map
-    (when (and mod window-system)
-      (if (char-or-string-p c2)
-         (setq k2 (vector (append mod-noshift
-                                  (list (if shift (upcase c2) c2)))))
-       (setq k2 (vector (append mod (list c2)))))
-      (unless cannotshift
-       (define-key idlwave-mode-map k2 cmd)
-       (unless only-buffer (define-key idlwave-shell-mode-map k2 cmd))))
-    ;; The electric debug single-keystroke map
-    (if (and electric (char-or-string-p c2))
-       (define-key idlwave-shell-electric-debug-mode-map (char-to-string c2)
-         cmd))))
-
-; Enter the prefix map in two places.
-(defalias 'idlwave-debug-map       idlwave-mode-prefix-map)
-(defalias 'idlwave-shell-debug-map idlwave-shell-mode-prefix-map)
-
-;; The Electric Debug Minor Mode --------------------------------------------
-
-(defun idlwave-shell-toggle-electric-debug-mode ()
-  "Toggle electric-debug-mode, suppressing re-entry into mode if turned off."
-  (interactive)
-  ;; If turning it off, make sure it stays off throughout the debug
-  ;; session until we return or hit $MAIN$.  Cancel this suppression
-  ;; if it's explicitly turned on.
-  (if idlwave-shell-electric-debug-mode
-      (progn ;; Turn it off, and make sure it stays off.
-       (setq idlwave-shell-suppress-electric-debug t)
-       (idlwave-shell-electric-debug-mode 0))
-    (setq idlwave-shell-suppress-electric-debug nil)
-    (idlwave-shell-electric-debug-mode t)))
-
-(defvar idlwave-shell-electric-debug-read-only)
-(defvar idlwave-shell-electric-debug-buffers nil)
-
-(define-minor-mode idlwave-shell-electric-debug-mode
-  "Toggle Idlwave Shell Electric Debug mode.
-
-When Idlwave Shell Electric Debug mode is enabled, the Idlwave
-Shell debugging commands are available as single key sequences."
-  :lighter " *Debugging*"
-  (cond
-   (idlwave-shell-electric-debug-mode
-    (set (make-local-variable 'idlwave-shell-electric-debug-read-only)
-        buffer-read-only)
-    (setq buffer-read-only t)
-    (add-to-list 'idlwave-shell-electric-debug-buffers (current-buffer))
-    (if idlwave-shell-stop-line-overlay
-        (overlay-put idlwave-shell-stop-line-overlay 'face
-                    idlwave-shell-electric-stop-line-face))
-    (if (facep 'fringe)
-        (set-face-foreground 'fringe idlwave-shell-electric-stop-color
-                            (selected-frame)))
-    (message
-     "Electric Debugging mode entered.  Press [C-?] for help, [q] to quit"))
-   (t
-    ;; Return to previous read-only state
-    (setq buffer-read-only (if (boundp 'idlwave-shell-electric-debug-read-only)
-                              idlwave-shell-electric-debug-read-only))
-    (setq idlwave-shell-electric-debug-buffers
-         (delq (current-buffer) idlwave-shell-electric-debug-buffers))
-    (if idlwave-shell-stop-line-overlay
-        (overlay-put idlwave-shell-stop-line-overlay 'face
-                    idlwave-shell-stop-line-face)
-      (if (facep 'fringe)
-         (set-face-foreground 'fringe (face-foreground 'default)))))))
-
-;; Turn it off in all relevant buffers
-(defvar idlwave-shell-electric-debug-buffers nil)
-(defun idlwave-shell-electric-debug-all-off ()
-  (setq idlwave-shell-suppress-electric-debug nil)
-  (let ((buffers idlwave-shell-electric-debug-buffers)
-       buf)
-    (save-excursion
-      (while (setq buf (pop buffers))
-       (when (buffer-live-p buf)
-         (set-buffer buf)
-         (when (and (derived-mode-p 'idlwave-mode)
-                    buffer-file-name
-                    idlwave-shell-electric-debug-mode)
-           (idlwave-shell-electric-debug-mode 0))))))
-  (setq idlwave-shell-electric-debug-buffers nil))
-
-;; Show the help text
-(defun idlwave-shell-electric-debug-help ()
-  (interactive)
-  (with-output-to-temp-buffer "*IDLWAVE Electric Debug Help*"
-    (princ idlwave-shell-electric-debug-help))
-  (let* ((current-window (selected-window))
-        (window (get-buffer-window "*IDLWAVE Electric Debug Help*"))
-        (window-lines (window-height window)))
-    (select-window window)
-    (enlarge-window (1+ (- (count-lines 1 (point-max)) window-lines)))
-    (select-window current-window)))
-
-
-;; The Menus --------------------------------------------------------------
-(defvar idlwave-shell-menu-def
-  `("Debug"
-    ["Electric Debug Mode"
-     idlwave-shell-electric-debug-mode
-     :style toggle :selected idlwave-shell-electric-debug-mode
-     :included (derived-mode-p 'idlwave-mode) :keys "C-c C-d C-v"]
-    "--"
-    ("Compile & Run"
-     ["Save and .RUN" idlwave-shell-save-and-run
-      (or (derived-mode-p 'idlwave-mode)
-         idlwave-shell-last-save-and-action-file)]
-     ["Save and .COMPILE" idlwave-shell-save-and-compile
-      (or (derived-mode-p 'idlwave-mode)
-         idlwave-shell-last-save-and-action-file)]
-     ["Save and @Batch" idlwave-shell-save-and-batch
-      (or (derived-mode-p 'idlwave-mode)
-         idlwave-shell-last-save-and-action-file)]
-     "--"
-     ["Goto Next Error" idlwave-shell-goto-next-error t]
-     "--"
-     ["Compile and Run Region" idlwave-shell-run-region
-      (derived-mode-p 'idlwave-mode)]
-     ["Evaluate Region" idlwave-shell-evaluate-region
-      (derived-mode-p 'idlwave-mode)]
-     "--"
-     ["Execute Default Cmd" idlwave-shell-execute-default-command-line t]
-     ["Edit Default Cmd" idlwave-shell-edit-default-command-line t])
-    ("Breakpoints"
-     ["Set Breakpoint" idlwave-shell-break-here
-      :keys "C-c C-d C-b" :active (derived-mode-p 'idlwave-mode)]
-     ("Set Special Breakpoint"
-      ["Set After Count Breakpoint"
-       (progn
-       (let ((count (string-to-number (read-string "Break after count: "))))
-             (if (integerp count) (idlwave-shell-break-here count))))
-       :active (derived-mode-p 'idlwave-mode)]
-      ["Set Condition Breakpoint"
-       (idlwave-shell-break-here '(4))
-       :active (derived-mode-p 'idlwave-mode)])
-     ["Break in Module" idlwave-shell-break-in
-      :keys "C-c C-d C-i" :active (derived-mode-p 'idlwave-mode)]
-     ["Break in this Module" idlwave-shell-break-this-module
-      :keys "C-c C-d C-j" :active (derived-mode-p 'idlwave-mode)]
-     ["Clear Breakpoint" idlwave-shell-clear-current-bp t]
-     ["Clear All Breakpoints" idlwave-shell-clear-all-bp t]
-     ["Disable/Enable Breakpoint" idlwave-shell-toggle-enable-current-bp t]
-     ["Goto Previous Breakpoint" idlwave-shell-goto-previous-bp
-      :keys "C-c C-d [" :active (derived-mode-p 'idlwave-mode)]
-     ["Goto Next Breakpoint" idlwave-shell-goto-next-bp
-      :keys "C-c C-d ]" :active (derived-mode-p 'idlwave-mode)]
-     ["List All Breakpoints" idlwave-shell-list-all-bp t]
-     ["Resync Breakpoints" idlwave-shell-bp-query t])
-    ("Continue/Step"
-     ["Step (into)" idlwave-shell-step t]
-     ["Step (over)" idlwave-shell-stepover t]
-     ["Skip One Statement" idlwave-shell-skip t]
-     ["Continue" idlwave-shell-cont t]
-     ["... to End of Block" idlwave-shell-up t]
-     ["... to End of Subprog" idlwave-shell-return t]
-     ["... to End of Subprog+1" idlwave-shell-out t]
-     ["... to Here (Cursor Line)" idlwave-shell-to-here
-      :keys "C-c C-d C-h" :active (derived-mode-p 'idlwave-mode)])
-    ("Examine Expressions"
-     ["Print expression" idlwave-shell-print t]
-     ["Help on expression" idlwave-shell-help-expression t]
-     ("Examine nearby expression with"
-      ,@(mapcar (lambda(x)
-                 `[ ,(car x) (idlwave-shell-print nil ',x) t ])
-               idlwave-shell-examine-alist))
-     ("Examine region with"
-      ,@(mapcar (lambda(x)
-                 `[ ,(car x) (idlwave-shell-print '(4) ',x) t ])
-               idlwave-shell-examine-alist)))
-    ("Call Stack"
-     ["Stack Up" idlwave-shell-stack-up t]
-     ["Stack Down" idlwave-shell-stack-down t]
-     "--"
-     ["Redisplay and Sync" idlwave-shell-redisplay t])
-    ("Show Commands"
-     ["Everything" (if (eq idlwave-shell-show-commands 'everything)
-                      (progn
-                        (setq idlwave-shell-show-commands
-                              (get 'idlwave-shell-show-commands 'last-val))
-                        (put 'idlwave-shell-show-commands 'last-val nil))
-                    (put 'idlwave-shell-show-commands 'last-val
-                         idlwave-shell-show-commands)
-                    (setq idlwave-shell-show-commands 'everything))
-      :style toggle :selected (and (not (listp idlwave-shell-show-commands))
-                                  (eq idlwave-shell-show-commands
-                                      'everything))]
-     "--"
-     ["Compiling Commands" (idlwave-shell-add-or-remove-show 'run)
-      :style toggle
-      :selected (not (idlwave-shell-hide-p
-                     'run
-                     (get 'idlwave-shell-show-commands 'last-val)))
-      :active (not (eq idlwave-shell-show-commands 'everything))]
-     ["Breakpoint Commands" (idlwave-shell-add-or-remove-show 'breakpoint)
-      :style toggle
-      :selected (not (idlwave-shell-hide-p
-                     'breakpoint
-                     (get 'idlwave-shell-show-commands 'last-val)))
-      :active (not (eq idlwave-shell-show-commands 'everything))]
-     ["Debug Commands" (idlwave-shell-add-or-remove-show 'debug)
-      :style toggle
-      :selected (not (idlwave-shell-hide-p
-                     'debug
-                     (get 'idlwave-shell-show-commands 'last-val)))
-      :active (not (eq idlwave-shell-show-commands 'everything))]
-     ["Miscellaneous Commands" (idlwave-shell-add-or-remove-show 'misc)
-      :style toggle
-      :selected (not (idlwave-shell-hide-p
-                     'misc
-                     (get 'idlwave-shell-show-commands 'last-val)))
-      :active (not (eq idlwave-shell-show-commands 'everything))])
-    ("Input Mode"
-     ["Send one char" idlwave-shell-send-char t]
-     ["Temporary Character Mode" idlwave-shell-char-mode-loop t]
-     "--"
-     ["Use Input Mode Magic"
-      (setq idlwave-shell-use-input-mode-magic
-           (not idlwave-shell-use-input-mode-magic))
-      :style toggle :selected idlwave-shell-use-input-mode-magic])
-    "--"
-    ["Update Working Dir" idlwave-shell-resync-dirs t]
-    ["Save Path Info"
-     (idlwave-shell-send-command idlwave-shell-path-query
-                                'idlwave-shell-get-path-info
-                                'hide)
-     t]
-    ["Reset IDL" idlwave-shell-reset t]
-    "--"
-    ["Toggle Toolbar" idlwave-shell-toggle-toolbar t]
-    ["Exit IDL" idlwave-shell-quit t]))
-
-(easy-menu-define idlwave-mode-debug-menu idlwave-mode-map
-  "IDL debugging menus."
-  idlwave-shell-menu-def)
-(easy-menu-define idlwave-shell-mode-menu idlwave-shell-mode-map
-  "IDL shell menus."
-  idlwave-shell-menu-def)
-
-;; The Breakpoint Glyph -------------------------------------------------------
-
-(defvar idlwave-shell-bp-glyph nil
-  "The glyphs to mark breakpoint lines in the source code.")
-
-(let ((image-alist
-       '((bp . "/* XPM */
-static char * file[] = {
-\"14 12 3 1\",
-\"     c None s backgroundColor\",
-\".    c #4B4B4B4B4B4B\",
-\"R    c #FFFF00000000\",
-\"              \",
-\"     ....     \",
-\"    .RRRR.    \",
-\"   .RRRRRR.   \",
-\"  .RRRRRRRR.  \",
-\"  .RRRRRRRR.  \",
-\"  .RRRRRRRR.  \",
-\"  .RRRRRRRR.  \",
-\"   .RRRRRR.   \",
-\"    .RRRR.    \",
-\"     ....     \",
-\"              \"};")
-        (bp-cond . "/* XPM */
-static char * file[] = {
-\"14 12 4 1\",
-\"     c None s backgroundColor\",
-\".    c #4B4B4B4B4B4B\",
-\"R    c #FFFF00000000\",
-\"B     c #000000000000\",
-\"              \",
-\"     ....     \",
-\"    .RRRR.    \",
-\"   .RRRRRR.   \",
-\"  .RRRRRRRR.  \",
-\"  .RRBBBBRR.  \",
-\"  .RRRRRRRR.  \",
-\"  .RRBBBBRR.  \",
-\"   .RRRRRR.   \",
-\"    .RRRR.    \",
-\"     ....     \",
-\"              \"};")
-        (bp-1 . "/* XPM */
-static char * file[] = {
-\"14 12 4 1\",
-\"     c None s backgroundColor\",
-\".     c #4B4B4B4B4B4B\",
-\"X     c #FFFF00000000\",
-\"o     c #000000000000\",
-\"              \",
-\"     ....     \",
-\"    .XXXX.    \",
-\"   .XXooXX.   \",
-\"  .XXoooXXX.  \",
-\"  .XXXooXXX.  \",
-\"  .XXXooXXX.  \",
-\"  .XXooooXX.  \",
-\"   .XooooX.   \",
-\"    .XXXX.    \",
-\"     ....     \",
-\"              \"};")
-        (bp-2 . "/* XPM */
-static char * file[] = {
-\"14 12 4 1\",
-\"     c None s backgroundColor\",
-\".     c #4B4B4B4B4B4B\",
-\"X     c #FFFF00000000\",
-\"o     c #000000000000\",
-\"              \",
-\"     ....     \",
-\"    .XXXX.    \",
-\"   .XoooXX.   \",
-\"  .XXoXooXX.  \",
-\"  .XXXXooXX.  \",
-\"  .XXXooXXX.  \",
-\"  .XXooXXXX.  \",
-\"   .XooooX.   \",
-\"    .XXXX.    \",
-\"     ....     \",
-\"              \"};")
-        (bp-3 . "/* XPM */
-static char * file[] = {
-\"14 12 4 1\",
-\"     c None s backgroundColor\",
-\".     c #4B4B4B4B4B4B\",
-\"X     c #FFFF00000000\",
-\"o     c #000000000000\",
-\"              \",
-\"     ....     \",
-\"    .XXXX.    \",
-\"   .XoooXX.   \",
-\"  .XXXXooXX.  \",
-\"  .XXXooXXX.  \",
-\"  .XXXXooXX.  \",
-\"  .XXoXooXX.  \",
-\"   .XoooXX.   \",
-\"    .XXXX.    \",
-\"     ....     \",
-\"              \"};")
-        (bp-4 . "/* XPM */
-static char * file[] = {
-\"14 12 4 1\",
-\"     c None s backgroundColor\",
-\".     c #4B4B4B4B4B4B\",
-\"X     c #FFFF00000000\",
-\"o     c #000000000000\",
-\"              \",
-\"     ....     \",
-\"    .XXXX.    \",
-\"   .XoXXoX.   \",
-\"  .XXoXXoXX.  \",
-\"  .XXooooXX.  \",
-\"  .XXXXooXX.  \",
-\"  .XXXXooXX.  \",
-\"   .XXXooX.   \",
-\"    .XXXX.    \",
-\"     ....     \",
-\"              \"};")
-        (bp-n . "/* XPM */
-static char * file[] = {
-\"14 12 4 1\",
-\"     c None s backgroundColor\",
-\".     c #4B4B4B4B4B4B\",
-\"X     c #FFFF00000000\",
-\"o     c #000000000000\",
-\"              \",
-\"     ....     \",
-\"    .XXXX.    \",
-\"   .XXXXXX.   \",
-\"  .XXoXoXXX.  \",
-\"  .XXooXoXX.  \",
-\"  .XXoXXoXX.  \",
-\"  .XXoXXoXX.  \",
-\"   .XoXXoX.   \",
-\"    .XXXX.    \",
-\"     ....     \",
-\"              \"};"))) im-cons im)
-
-  (while (setq im-cons (pop image-alist))
-    (setq im (cond ((and (fboundp 'image-type-available-p)
-                        (image-type-available-p 'xpm))
-                   (list 'image :type 'xpm :data (cdr im-cons)
-                         :ascent 'center))
-                  (t nil)))
-    (if im (push (cons (car im-cons) im) idlwave-shell-bp-glyph))))
-
-(provide 'idlw-shell)
-(provide 'idlwave-shell)
-
-;; Load the toolbar when wanted by the user.
-
-(autoload 'idlwave-toolbar-toggle "idlw-toolbar"
-  "Toggle the IDLWAVE toolbar.")
-(autoload 'idlwave-toolbar-add-everywhere "idlw-toolbar"
-  "Add IDLWAVE toolbar.")
-(defun idlwave-shell-toggle-toolbar ()
-  "Toggle the display of the debugging toolbar."
-  (interactive)
-  (idlwave-toolbar-toggle))
-
-(if idlwave-shell-use-toolbar
-    (add-hook 'idlwave-shell-mode-hook #'idlwave-toolbar-add-everywhere))
-
-;;; idlw-shell.el ends here
diff --git a/lisp/progmodes/idlw-toolbar.el b/lisp/progmodes/idlw-toolbar.el
deleted file mode 100644 (file)
index c6cb47b..0000000
+++ /dev/null
@@ -1,931 +0,0 @@
-;;; idlw-toolbar.el --- a debugging toolbar for IDLWAVE  -*- lexical-binding: t; -*-
-
-;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
-
-;; Author: Carsten Dominik <dominik@astro.uva.nl>
-;; Maintainer: emacs-devel@gnu.org
-;; Keywords: processes
-;; Package: idlwave
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software: you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, either version 3 of the License, or
-;; (at your option) any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; This file implements a debugging toolbar for IDLWAVE.
-;; It requires toolbar and xpm support.
-
-;; New versions of IDLWAVE, documentation, and more information
-;; available from:
-;;                 https://github.com/jdtsmith/idlwave
-
-\f
-;;; Code:
-
-(defun idlwave-toolbar-make-button (image)
-  (list 'image :type 'xpm :data image))
-
-(defvar idlwave-toolbar)
-(defvar default-toolbar)
-(defvar idlwave-toolbar-is-possible)
-
-(if (not (and (boundp 'tool-bar-button-margin)   ; need toolbar
-             (fboundp 'image-type-available-p) ; need image stuff
-             (image-type-available-p 'xpm))    ; need xpm
-        )
-    ;; oops - cannot do the toolbar
-    (message "Sorry, IDLWAVE xpm toolbar cannot be used on this version of Emacs")
-;; OK, we can define a toolbar
-
-(defconst idlwave-toolbar-is-possible t
-  "When defined, indicates that a toolbar is possible with this Emacs.")
-(defvar idlwave-toolbar-compile-icon
-  (idlwave-toolbar-make-button
-   "/* XPM */
-static char * file[] = {
-\"28 28 2 1\",
-\"     c None s backgroundToolBarColor\",
-\".    c #000000000000\",
-\"                            \",
-\"                            \",
-\"                            \",
-\"             .              \",
-\"       ..   ...   ..        \",
-\"       .... ... ....        \",
-\"       .............        \",
-\"        ...........         \",
-\"    ...................     \",
-\"    ........   ........     \",
-\"     .....    ........      \",
-\"      ....  .........       \",
-\"    .....  .. ... .....     \",
-\"   ...... ..   .. ......    \",
-\"    ..... ... ..  .....     \",
-\"      .........  ....       \",
-\"     ........    .....      \",
-\"    ........   ........     \",
-\"    ...................     \",
-\"        ...........         \",
-\"       .............        \",
-\"       .... ... ....        \",
-\"       ..   ...   ..        \",
-\"             .              \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \"};")
-  "The compile icon.")
-
-(defvar idlwave-toolbar-next-error-icon
-  (idlwave-toolbar-make-button
-   "/* XPM */
-static char * file[] = {
-\"28 28 3 1\",
-\"     c None s backgroundToolBarColor\",
-\".    c #000000000000\",
-\"R    c #FFFF00000000\",
-\"                            \",
-\"                            \",
-\"             R              \",
-\"       RR   RRR   RR        \",
-\"       RRRR RRR RRRR        \",
-\"       RRRRRRRRRRRRR        \",
-\"        RRRRRRRRRRR         \",
-\"    RRRRRRRRRRRRRRRRRRR     \",
-\"    RRRRRRRR                \",
-\"     RRRRR                  \",
-\"      RRRR                  \",
-\"               ........     \",
-\"              ........      \",
-\"            .........       \",
-\"    .....  .. ... .....     \",
-\"   ...... ..   .. ......    \",
-\"    ..... ... ..  .....     \",
-\"      .........  ....       \",
-\"     ........    .....      \",
-\"    ........   ........     \",
-\"    ...................     \",
-\"        ...........         \",
-\"       .............        \",
-\"       .... ... ....        \",
-\"       ..   ...   ..        \",
-\"             .              \",
-\"                            \",
-\"                            \"};")
-  "The Next Error icon.")
-
-(defvar idlwave-toolbar-stop-at-icon
-  (idlwave-toolbar-make-button
-   "/* XPM */
-static char * file[] = {
-\"28 28 3 1\",
-\"     c None s backgroundToolBarColor\",
-\".    c #000000000000\",
-\"R    c #FFFF00000000\",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"          ........          \",
-\"         .RRRRRRRR.         \",
-\"        .RRRRRRRRRR.        \",
-\"       .RRRRRRRRRRRR.       \",
-\"      .RRRRRRRRRRRRRR.      \",
-\"     .RRRRRRRRRRRRRRRR.     \",
-\"    .RRRRRRRRRRRRRRRRRR.    \",
-\"    .RRRRRRRRRRRRRRRRRR.    \",
-\"    .RRRRRRRRRRRRRRRRRR.    \",
-\"    .RRRRRRRRRRRRRRRRRR.    \",
-\"    .RRRRRRRRRRRRRRRRRR.    \",
-\"    .RRRRRRRRRRRRRRRRRR.    \",
-\"    .RRRRRRRRRRRRRRRRRR.    \",
-\"    .RRRRRRRRRRRRRRRRRR.    \",
-\"     .RRRRRRRRRRRRRRRR.     \",
-\"      .RRRRRRRRRRRRRR.      \",
-\"       .RRRRRRRRRRRR.       \",
-\"        .RRRRRRRRRR.        \",
-\"         .RRRRRRRR.         \",
-\"          ........          \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \"};")
-  "The Stop At icon.")
-
-
-(defvar idlwave-toolbar-clear-at-icon
-  (idlwave-toolbar-make-button
-   "/* XPM */
-static char * file[] = {
-\"28 28 3 1\",
-\"     c None s backgroundToolBarColor\",
-\".    c #000000000000\",
-\"R    c #FFFF00000000\",
-\"                            \",
-\"                            \",
-\"                            \",
-\"  ...                  ...  \",
-\"   ...    ........    ...   \",
-\"    ...  .RRRRRRRR.  ...    \",
-\"     ....RRRRRRRRRR....     \",
-\"      ...RRRRRRRRRR...      \",
-\"      ....RRRRRRRR....      \",
-\"     .RR...RRRRRR...RR.     \",
-\"    .RRRR...RRRR...RRRR.    \",
-\"    .RRRRR...RR...RRRRR.    \",
-\"    .RRRRRR......RRRRRR.    \",
-\"    .RRRRRRR....RRRRRRR.    \",
-\"    .RRRRRRR....RRRRRRR.    \",
-\"    .RRRRRR......RRRRRR.    \",
-\"    .RRRRR...RR...RRRRR.    \",
-\"    .RRRR...RRRR...RRRR.    \",
-\"     .RR...RRRRRR...RR.     \",
-\"      ....RRRRRRRR....      \",
-\"      ...RRRRRRRRRR...      \",
-\"     ....RRRRRRRRRR....     \",
-\"    ...  .RRRRRRRR.  ...    \",
-\"   ...    ........    ...   \",
-\"  ...                  ...  \",
-\"                            \",
-\"                            \",
-\"                            \"};")
-  "The Clear At icon.")
-
-(defvar idlwave-toolbar-clear-all-icon
-  (idlwave-toolbar-make-button
-   "/* XPM */
-static char * file[] = {
-\"28 28 4 1\",
-\"     c None s backgroundToolBarColor\",
-\".    c #000000000000\",
-\"X    c #FFFFFFFFFFFF\",
-\"R    c #FFFF00000000\",
-\"                            \",
-\"                            \",
-\"                            \",
-\"  .. ....         .... ..   \",
-\"  ...RRRR.       .RRRR...   \",
-\"   ...RRRR.     .RRRR...    \",
-\"  .R...RRRR.   .RRRR...R.   \",
-\"  .RR...RRR.   .RRR...RR.   \",
-\"  .RRR...RR.   .RR...RRR.   \",
-\"  .RRRR...R.   .R...RRRR.   \",
-\"   .RRRR...     ...RRRR.    \",
-\"    .RRRR...   ...RRRR.     \",
-\"     .... ... ... ....      \",
-\"           .....            \",
-\"            ...             \",
-\"     ....  .....  ....      \",
-\"    .RRRR.... ....RRRR.     \",
-\"   .RRRRR...   ...RRRRR.    \",
-\"  .RRRRR....   ....RRRRR.   \",
-\"  .RRRR...R.   .R...RRRR.   \",
-\"  .RRR...RR.   .RR...RRR.   \",
-\"  .RR...RRR.   .RRR...RR.   \",
-\"   ....RRR.     .RRR....    \",
-\"   ...RRR.       .RRR...    \",
-\"  .......         .......   \",
-\"                            \",
-\"                            \",
-\"                            \"};")
-  "The Clear-All icon.")
-
-(defvar idlwave-toolbar-stop-beginning-icon
-  (idlwave-toolbar-make-button
-   "/* XPM */
-static char * file[] = {
-\"28 28 4 1\",
-\"     c None s backgroundToolBarColor\",
-\".    c #000000000000\",
-\"X    c #FFFF00000000\",
-\"_    c #FFFFFFFFFFFF\",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"          ........          \",
-\"         .XXXXXXXX.         \",
-\"        .XXXXXXXXXX.        \",
-\"       .XXXXXXXXXXXX.       \",
-\"      .XX..XXXXXXXXXX.      \",
-\"     .XX.XX.X______XXX.     \",
-\"    .XXX.XX.X______XXXX.    \",
-\"    .XXXX..XXXXXXXXXXXX.    \",
-\"    .XXXXXXXXXX____XXXX.    \",
-\"    .XXXXXXXXXX____XXXX.    \",
-\"    .XXXXXXXXXXXXXXXXXX.    \",
-\"    .XXXXXXXXXX____XXXX.    \",
-\"    .XXXXXXXXXX____XXXX.    \",
-\"    .XXXXXXXXXXXXXXXXXX.    \",
-\"     .XXXXXXXXX____XXX.     \",
-\"      .XXXXXXXX____XX.      \",
-\"       .XXXXXXXXXXXX.       \",
-\"        .XXXXXXXXXX.        \",
-\"         .XXXXXXXX.         \",
-\"          ........          \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \"};")
-  "The Stop at Beginning icon.")
-
-(defvar idlwave-toolbar-stop-in-icon
-  (idlwave-toolbar-make-button
-   "/* XPM */
-static char * file[] = {
-\"28 28 4 1\",
-\"     c None s backgroundToolBarColor\",
-\"_    c #FFFFFFFFFFFF\",
-\".    c #000000000000\",
-\"R    c #FFFF00000000\",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"          ........          \",
-\"         .RRRRRRRR.         \",
-\"        .RRRRRRRRRR.        \",
-\"       .RRRRRRRRRRRR.       \",
-\"      .RRR___RR___RRR.      \",
-\"     .RRRR__RRRR__RRRR.     \",
-\"    .RRRRR__RRRR__RRRRR.    \",
-\"    .RRRRR__RRRR__RRRRR.    \",
-\"    .RRRRR__RRRR__RRRRR.    \",
-\"    .RRRR__RRRRRR__RRRR.    \",
-\"    .RRRRR__RRRR__RRRRR.    \",
-\"    .RRRRR__RRRR__RRRRR.    \",
-\"    .RRRRR__RRRR__RRRRR.    \",
-\"    .RRRRR__RRRR__RRRRR.    \",
-\"     .RRRR___RR___RRRR.     \",
-\"      .RRRRRRRRRRRRRR.      \",
-\"       .RRRRRRRRRRRR.       \",
-\"        .RRRRRRRRRR.        \",
-\"         .RRRRRRRR.         \",
-\"          ........          \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \"};")
-  "The Stop in icon.")
-
-(defvar idlwave-toolbar-edit-cmd-icon
-  (idlwave-toolbar-make-button
-   "/* XPM */
-static char * file[] = {
-\"28 28 2 1\",
-\"     c None s backgroundToolBarColor\",
-\".    c #000000000000\",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"   ..                       \",
-\"    ..                      \",
-\"     ..                     \",
-\"    ..                      \",
-\"   ..                       \",
-\"                            \",
-\"                            \",
-\"        .................   \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \"};")
-  "The edit-cmd icon.")
-
-(defvar idlwave-toolbar-run-icon
-  (idlwave-toolbar-make-button
-   "/* XPM */
-static char * file[] = {
-\"28 28 3 1\",
-\"     c None s backgroundToolBarColor\",
-\".    s FgColor c #000000000000\",
-\"G    c #0000BBBB0000\",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"     .....                  \",
-\"     .GGG.                  \",
-\"     .GGG.                  \",
-\"     .GGG.       .......    \",
-\"     .GGG.                  \",
-\"     .GGG.                  \",
-\"     .GGG.       .......    \",
-\"     .GGG.                  \",
-\"  ....GGG....               \",
-\"   .GGGGGGG.     .......    \",
-\"    .GGGGG.                 \",
-\"     .GGG.                  \",
-\"      .G.        .......    \",
-\"       .                    \",
-\"                            \",
-\"                 .......    \",
-\"                            \",
-\"                            \",
-\"                 .......    \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \"};")
-  "The Run icon.")
-
-(defvar idlwave-toolbar-cont-icon
-  (idlwave-toolbar-make-button
-   "/* XPM */
-static char * file[] = {
-\"28 28 3 1\",
-\"     c None s backgroundToolBarColor\",
-\".    s FgColor c #000000000000\",
-\"G    c #0000BBBB0000\",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                 .......    \",
-\"                            \",
-\"       .......              \",
-\"      .GGGGGG.   .......    \",
-\"     .GGGGGGG.              \",
-\"     .GGG.....              \",
-\"     .GGG.       .......    \",
-\"     .GGG.                  \",
-\"     .GGG.                  \",
-\"     .GGG.       .......    \",
-\"     .GGG.                  \",
-\"  ....GGG....               \",
-\"   .GGGGGGG.     .......    \",
-\"    .GGGGG.                 \",
-\"     .GGG.                  \",
-\"      .G.        .......    \",
-\"       .                    \",
-\"                            \",
-\"                 .......    \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \"};")
-  "The Cont icon.")
-
-(defvar idlwave-toolbar-to-here-icon
-  (idlwave-toolbar-make-button
-   "/* XPM */
-static char * file[] = {
-\"28 28 4 1\",
-\"     c None s backgroundToolBarColor\",
-\".    c #000000000000\",
-\"G    c #0000BBBB0000\",
-\"R    c #FFFF00000000\",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"      .....   ........      \",
-\"     .GGGG.                 \",
-\"    .GGGGG.                 \",
-\"    .GG....   ........      \",
-\"    .GG.                    \",
-\"    .GG. .                  \",
-\"    .GG. ..                 \",
-\"    .GG. .G.    ......      \",
-\"    .GG...GG.               \",
-\"    .GGGGGGGG.  RRRRRR      \",
-\"    .GGGGGGGGG. RRRRRR      \",
-\"     .GGGGGGG.  RRRRRR      \",
-\"      ....GG.               \",
-\"         .G.    ......      \",
-\"         ..                 \",
-\"         .                  \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \"};")
-  "The Cont-to-here icon.")
-
-(defvar idlwave-toolbar-step-over-icon
-  (idlwave-toolbar-make-button
-   "/* XPM */
-static char * file[] = {
-\"28 28 3 1\",
-\"     c None s backgroundToolBarColor\",
-\".    c #000000000000\",
-\"G    c #0000BBBB0000\",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"      .....                 \",
-\"     .GGGG.      .......    \",
-\"    .GGGGG.                 \",
-\"    .GG....                 \",
-\"    .GG.         .......    \",
-\"    .GG. .                  \",
-\"    .GG. ..                 \",
-\"    .GG. .G.     .......    \",
-\"    .GG...GG.               \",
-\"    .GGGGGGGG.              \",
-\"    .GGGGGGGGG.  .......    \",
-\"     .GGGGGGG.              \",
-\"      ....GG.               \",
-\"         .G.     .......    \",
-\"         ..                 \",
-\"         .                  \",
-\"                 .......    \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \"};")
-  "The Step Over icon.")
-
-(defvar idlwave-toolbar-step-into-icon
-  (idlwave-toolbar-make-button
-   "/* XPM */
-static char * file[] = {
-\"28 28 3 1\",
-\"     c None s backgroundToolBarColor\",
-\".    c #000000000000\",
-\"G    c #0000BBBB0000\",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"      .....   .......       \",
-\"     .GGGG.                 \",
-\"    .GGGGG.                 \",
-\"    .GG....   ........      \",
-\"    .GG.                    \",
-\"    .GG. .                  \",
-\"    .GG. ..                 \",
-\"    .GG. .G.                \",
-\"    .GG...GG.    .......    \",
-\"    .GGGGGGGG.              \",
-\"    .GGGGGGGGG.             \",
-\"     .GGGGGGG.   .......    \",
-\"      ....GG.               \",
-\"         .G.                \",
-\"         ..      .......    \",
-\"         .                  \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \"};")
-  "The Step Into icon.")
-
-(defvar idlwave-toolbar-step-out-icon
-  (idlwave-toolbar-make-button
-   "/* XPM */
-static char * file[] = {
-\"28 28 3 1\",
-\"     c None s backgroundToolBarColor\",
-\".    c #000000000000\",
-\"G    c #0000BBBB0000\",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"         .                  \",
-\"         ..     ........    \",
-\"         .G.                \",
-\"      ....GG.               \",
-\"     .GGGGGGG.  ........    \",
-\"    .GGGGGGGGG.             \",
-\"    .GGGGGGGG.              \",
-\"    .GG...GG.   ........    \",
-\"    .GG. .G.                \",
-\"    .GG. ..                 \",
-\"    .GG. .                  \",
-\"    .GG.                    \",
-\"    .GG.......    .......   \",
-\"    .GGGGGGGG.              \",
-\"     .GGGGGGG.              \",
-\"      ........    .......   \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \"};")
-  "The Step up icon.")
-
-
-(defvar idlwave-toolbar-eval-icon
-  (idlwave-toolbar-make-button
-   "/* XPM */
-static char * file[] = {
-\"28 28 2 1\",
-\"     c None s backgroundToolBarColor\",
-\".    c #000000000000\",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"         ....               \",
-\"         .. ..  ......      \",
-\"         .. ..  ......      \",
-\"         .. ..              \",
-\"         .. ..  ......      \",
-\"         .. ..  ......      \",
-\"         ....               \",
-\"         ..                 \",
-\"         ..                 \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \"};")
-  "The Evaluate icon.")
-
-(defvar idlwave-toolbar-stack-up-icon
-  (idlwave-toolbar-make-button
-   "/* XPM */
-static char * file[] = {
-\"28 28 5 1\",
-\"     c None s backgroundToolBarColor\",
-\".    s FgColor c #000000000000\",
-\"_    c #FFFFFFFFFFFF\",
-\"G    c #0000BBBB0000\",
-\"R    c #FFFF00000000\",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"      ........     .        \",
-\"      .______.    ...       \",
-\"      .______.   .....      \",
-\"      .______.  .......     \",
-\"      .______.    ...       \",
-\"      .______.    ...       \",
-\"      ........    ...       \",
-\"      .GGGGGG.    ...       \",
-\"      .GGGGGG.    ...       \",
-\"      .GGGGGG.              \",
-\"      .GGGGGG.              \",
-\"      .GGGGGG.              \",
-\"      ........              \",
-\"      .RRRRRR.              \",
-\"      .RRRRRR.              \",
-\"      .RRRRRR.              \",
-\"      .RRRRRR.              \",
-\"      .RRRRRR.              \",
-\"      ........              \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \"};")
-  "The Stack Up icon.")
-
-(defvar idlwave-toolbar-stack-down-icon
-  (idlwave-toolbar-make-button
-   "/* XPM */
-static char * file[] = {
-\"28 28 5 1\",
-\"     c None s backgroundToolBarColor\",
-\".    s FgColor c #000000000000\",
-\"_    c #FFFFFFFFFFFF\",
-\"G    c #0000BBBB0000\",
-\"R    c #FFFF00000000\",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"      ........              \",
-\"      .______.              \",
-\"      .______.              \",
-\"      .______.              \",
-\"      .______.              \",
-\"      .______.              \",
-\"      ........              \",
-\"      .GGGGGG.              \",
-\"      .GGGGGG.              \",
-\"      .GGGGGG.              \",
-\"      .GGGGGG.    ...       \",
-\"      .GGGGGG.    ...       \",
-\"      ........    ...       \",
-\"      .RRRRRR.    ...       \",
-\"      .RRRRRR.    ...       \",
-\"      .RRRRRR.  .......     \",
-\"      .RRRRRR.   .....      \",
-\"      .RRRRRR.    ...       \",
-\"      ........     .        \",
-\"                            \",
-\"                            \",
-\"                            \",
-\"                            \"};")
-  "The Stack Down icon.")
-
-(defvar idlwave-toolbar-reset-icon
-  (idlwave-toolbar-make-button
-   "/* XPM */
-static char * file[] = {
-\"28 28 3 1\",
-\"     c None s backgroundToolBarColor\",
-\"G    c #0000BBBB0000\",
-\".    c #000000000000\",
-\"                            \",
-\"                            \",
-\"                            \",
-\"     .                      \",
-\"    .G.     .               \",
-\"   .GGG..  .G.              \",
-\"   .GGGGG..GG.              \",
-\"    ..GGGGGGGG.             \",
-\"      ..GGGGGG.             \",
-\"        ..GGGGG.            \",
-\"        .GGGGGG.            \",
-\"        .G......            \",
-\"                            \",
-\"                 .....      \",
-\"               .........    \",
-\"               .........    \",
-\"               .........    \",
-\"               . ..... .    \",
-\"               .       .    \",
-\"               .       .    \",
-\"               .       .    \",
-\"               .       .    \",
-\"               .       .    \",
-\"               ..     ..    \",
-\"                .......     \",
-\"                 .....      \",
-\"                            \",
-\"                            \"};")
-  "The Reset icon.")
-
-(defvar idlwave-toolbar-electric-debug-icon
-  (idlwave-toolbar-make-button
-   "/* XPM */
-static char * file[] = {
-\"28 28 8 1\",
-\"     c None s backgroundToolBarColor\",
-\".    c #CFC854\",
-\"+    c #EEDB0E\",
-\"@    c #D2C739\",
-\"#    c #A39C54\",
-\"$    c #CDC020\",
-\"%    c #020202\",
-\"&    c #D60E36\",
-\"                            \",
-\"                            \",
-\"      ..                    \",
-\"   +++++@                   \",
-\"   ++++++                   \",
-\"    +++++@                  \",
-\"     +++++                  \",
-\"     #++++@                 \",
-\"      $+++@       %% %%     \",
-\"     ++++++$       % %      \",
-\"     #+++++$       % %      \",
-\"      #++$#        %%%      \",
-\"      #+++       %%%%%%%    \",
-\"       .++     %%%%%%%%%%%  \",
-\"        ++$$   %%%%%%%%%%%  \",
-\"        .+@#   &&%%%%%%%&&  \",
-\"      .++++#  &&&&&%%%&&&&& \",
-\"      +++++$  &&%%&&&&&%%&& \",
-\"       $+++$  &&%%&&&&&%%&& \",
-\"        $++@  &&&&&&%&&&&&& \",
-\"         $+@  &&&&&&%&&&&&& \",
-\"          @+  &&%%&&&&&%%&& \",
-\"           ++. &%%&&%&&%%&  \",
-\"            +. &&&&%%%&&&&  \",
-\"            .+  &&%%%%%&&   \",
-\"             ++  %%%%%%%    \",
-\"              .    %%%      \",
-\"                            \"};")
-  "The electric debug icon.")
-
-(defvar idlwave-toolbar
-  '(
-    [idlwave-toolbar-compile-icon
-     idlwave-shell-save-and-compile
-     t
-     "Save and Compile this file (or recompile last)"]
-    [idlwave-toolbar-next-error-icon
-     idlwave-shell-goto-next-error
-     t
-     "Goto Next Error"]
-    [idlwave-toolbar-stop-at-icon
-     idlwave-shell-break-here
-     (derived-mode-p 'idlwave-mode)
-     "Set Breakpoint at selected position"]
-    [idlwave-toolbar-clear-at-icon
-     idlwave-shell-clear-current-bp
-     t
-     "Clear Breakpoint at selected position"]
-    [idlwave-toolbar-clear-all-icon
-     idlwave-shell-clear-all-bp
-     t
-     "Clear all Breakpoints"]
-    [idlwave-toolbar-stop-beginning-icon
-     idlwave-shell-break-this-module
-     (derived-mode-p 'idlwave-mode)
-     "Stop at beginning of enclosing Routine"]
-    [idlwave-toolbar-stop-in-icon
-     idlwave-shell-break-in
-     t
-     "Stop in Routine with name near point"]
-    [idlwave-toolbar-edit-cmd-icon
-     idlwave-shell-edit-default-command-line
-     t
-     "Edit Default Command Line"]
-    [idlwave-toolbar-run-icon
-     idlwave-shell-execute-default-command-line
-     t
-     "Reset, then Execute Default Command Line"]
-    [idlwave-toolbar-cont-icon
-     idlwave-shell-cont
-     t
-     "Continue Current Program"]
-    [idlwave-toolbar-to-here-icon
-     idlwave-shell-to-here
-     (derived-mode-p 'idlwave-mode)
-     "Continue to Here (cursor position)"]
-    [idlwave-toolbar-step-over-icon
-     idlwave-shell-stepover
-     t
-     "Step Over (aka next)"]
-    [idlwave-toolbar-step-into-icon
-     idlwave-shell-step
-     t
-     "Step Into (aka step)"]
-    [idlwave-toolbar-step-out-icon
-     idlwave-shell-out
-     t
-     "Step Out (of subroutine)"]
-    [idlwave-toolbar-eval-icon
-     idlwave-shell-print
-     t
-     "Print Expression at or before Point"]
-    [idlwave-toolbar-stack-up-icon
-     idlwave-shell-stack-up
-     t
-     "Stack Up (towards \"cooler\" - less recently visited - frames)"]
-    [idlwave-toolbar-stack-down-icon
-     idlwave-shell-stack-down
-     t
-     "Stack Down (towards \"warmer\" - more recently visited - frames)"]
-    [idlwave-toolbar-reset-icon
-     idlwave-shell-reset
-     t
-     "Reset IDL (RETALL & CLOSE,/ALL and more)"]
-    [idlwave-toolbar-electric-debug-icon
-     idlwave-shell-electric-debug-mode
-     (derived-mode-p 'idlwave-mode)
-     "Toggle Electric Debug Mode"]
-    ))
-
-;; When the shell exits, arrange to remove the special toolbar everywhere.
-(add-hook 'idlwave-shell-cleanup-hook
-         #'idlwave-toolbar-remove-everywhere)
-);; End can define toolbar
-
-(define-obsolete-function-alias 'idlwave-toolbar-add #'ignore "28.1")
-
-(define-obsolete-function-alias 'idlwave-toolbar-remove #'ignore "28.1")
-
-(defvar idlwave-shell-mode-map)
-(defvar idlwave-mode-map)
-(defvar idlwave-toolbar-visible nil)
-(defun idlwave-toolbar-add-everywhere ()
-  "Add the toolbar in all appropriate buffers."
-  (when (boundp 'idlwave-toolbar-is-possible)
-
-    ;; Then add it to all existing buffers
-    ;; For Emacs, add the key definitions to the mode maps
-    (mapc (lambda (x)
-           (let* ((icon (aref x 0))
-                  (func (aref x 1))
-                  (show (aref x 2))
-                  (help (aref x 3))
-                  (key (vector 'tool-bar func))
-                  (def (list 'menu-item
-                             ""
-                             func
-                             :image (symbol-value icon)
-                             :visible show
-                             :help help)))
-             (define-key idlwave-mode-map key def)
-             (define-key idlwave-shell-mode-map key def)))
-         (reverse idlwave-toolbar))
-    (setq idlwave-toolbar-visible t)))
-
-(defun idlwave-toolbar-remove-everywhere ()
-  "Remove the toolbar in all appropriate buffers."
-  ;; First make sure new buffers won't get the toolbar
-  (when idlwave-toolbar-is-possible
-    ;; Then remove it in all existing buffers.
-    ;; For Emacs, remove the key definitions from the mode maps
-    (mapc (lambda (x)
-           (let* (;;(icon (aref x 0))
-                  (func (aref x 1))
-                  ;;(show (aref x 2))
-                  ;;(help (aref x 3))
-                  (key (vector 'tool-bar func)))
-             (define-key idlwave-mode-map key nil)
-             (define-key idlwave-shell-mode-map key nil)))
-         idlwave-toolbar)
-    (setq idlwave-toolbar-visible nil)))
-
-(defun idlwave-toolbar-toggle (&optional force-on)
-  (interactive)
-  (if idlwave-toolbar-visible
-      (or force-on (idlwave-toolbar-remove-everywhere))
-    (idlwave-toolbar-add-everywhere))
-  ;; On Emacs, redraw the frame to make sure the Toolbar is updated.
-  (redraw-frame))
-
-(provide 'idlw-toolbar)
-(provide 'idlwave-toolbar)
-
-;;; idlw-toolbar.el ends here
diff --git a/lisp/progmodes/idlwave.el b/lisp/progmodes/idlwave.el
deleted file mode 100644 (file)
index 3628449..0000000
+++ /dev/null
@@ -1,9081 +0,0 @@
-;;; idlwave.el --- IDL editing mode for GNU Emacs  -*- lexical-binding: t; -*-
-
-;; Copyright (C) 1999-2024 Free Software Foundation, Inc.
-
-;; Authors: JD Smith <jd.smith@utoledo.edu>
-;;          Carsten Dominik <dominik@science.uva.nl>
-;;          Chris Chase <chase@att.com>
-;; Maintainer: emacs-devel@gnu.org
-;; Version: 6.1.22
-;; Keywords: languages
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software: you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, either version 3 of the License, or
-;; (at your option) any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; IDLWAVE enables feature-rich development and interaction with IDL,
-;; the Interactive Data Language.  It provides a compelling,
-;; full-featured alternative to the IDLDE development environment
-;; bundled with IDL.
-
-;; In the remotely distant past, based on pascal.el, though bears
-;; little resemblance to it now.
-;;
-;; Incorporates many ideas, such as abbrevs, action routines, and
-;; continuation line indenting, from wave.el.
-;; wave.el original written by Lubos Pochman, Precision Visuals, Boulder.
-;;
-;; See the mode description ("C-h m" in idlwave-mode or "C-h f idlwave-mode")
-;; for features, key bindings, and info.
-;; Also, Info format documentation is available with `M-x idlwave-info'
-;;
-;; New versions of IDLWAVE, documentation, and more information
-;; available from:
-;;                 https://github.com/jdtsmith/idlwave
-;;
-;; INSTALLATION
-;; ============
-;;
-;; Follow the instructions in the INSTALL file of the distribution.
-;; In short, put this file on your load path and add the following
-;; lines to your init file:
-;;
-;; (autoload 'idlwave-mode "idlwave" "IDLWAVE Mode" t)
-;; (autoload 'idlwave-shell "idlw-shell" "IDLWAVE Shell" t)
-;; (setq auto-mode-alist (cons '("\\.pro\\'" . idlwave-mode) auto-mode-alist))
-;;
-;;
-;; SOURCE
-;; ======
-;;
-;; The newest version of this file is available from the maintainer's
-;; Webpage:
-;;
-;;   https://github.com/jdtsmith/idlwave
-;;
-;; DOCUMENTATION
-;; =============
-;;
-;; IDLWAVE is documented online in info format.  A printable version
-;; of the documentation is available from the maintainers webpage (see
-;; SOURCE).
-;;
-;;
-;; ACKNOWLEDGMENTS
-;; ===============
-;;
-;;  Thanks to the following people for their contributions and comments:
-;;
-;;    Ulrik Dickow <dickow_at_nbi.dk>
-;;    Eric E. Dors <edors_at_lanl.gov>
-;;    Stein Vidar H. Haugan <s.v.h.haugan_at_astro.uio.no>
-;;    David Huenemoerder <dph_at_space.mit.edu>
-;;    Kevin Ivory <Kevin.Ivory_at_linmpi.mpg.de>
-;;    Dick Jackson <dick_at_d-jackson.com>
-;;    Xuyong Liu <liu_at_stsci.edu>
-;;    Simon Marshall <Simon.Marshall_at_esrin.esa.it>
-;;    Laurent Mugnier <mugnier_at_onera.fr>
-;;    Lubos Pochman <lubos_at_rsinc.com>
-;;    Bob Portmann <portmann_at_al.noaa.gov>
-;;    Patrick M. Ryan <pat_at_jaameri.gsfc.nasa.gov>
-;;    Marty Ryba <ryba_at_ll.mit.edu>
-;;    Paul Sorenson <aardvark62_at_msn.com>
-;;    Phil Sterne <sterne_at_dublin.llnl.gov>
-;;    Phil Williams <williams_at_irc.chmcc.org>
-;;
-;; CUSTOMIZATION:
-;; =============
-;;
-;; IDLWAVE has extensive customize support; to learn about the
-;; variables which control the mode's behavior, use `M-x
-;; idlwave-customize'.
-;;
-;; You can set your own preferred values with Customize, or with Lisp
-;; code in .emacs.  For an example of what to put into .emacs, check
-;; the TexInfo documentation or see a complete .emacs available at the
-;; website.
-;;
-;; KNOWN PROBLEMS:
-;; ==============
-;;
-;;   IDLWAVE support for the IDL-derived PV-WAVE CL language of Visual
-;;   Numerics, Inc. is growing less and less complete as the two
-;;   languages grow increasingly apart.  The mode probably shouldn't
-;;   even have "WAVE" in its title, but it's catchy, and was required
-;;   to avoid conflict with the CORBA idl.el mode.  Caveat WAVEor.
-;;
-;;   Moving the point backwards in conjunction with abbrev expansion
-;;   does not work as I would like it, but this is a problem with
-;;   Emacs abbrev expansion done by the self-insert-command.  It ends
-;;   up inserting the character that expanded the abbrev after moving
-;;   point backward, e.g., "\cl" expanded with a space becomes
-;;   "LONG( )" with point before the close paren.  This is solved by
-;;   using a temporary function in `post-command-hook' - not pretty,
-;;   but it works.
-;;
-;;   Tabs and spaces are treated equally as whitespace when filling a
-;;   comment paragraph.  To accomplish this, tabs are permanently
-;;   replaced by spaces in the text surrounding the paragraph, which
-;;   may be an undesirable side-effect.  Replacing tabs with spaces is
-;;   limited to comments only and occurs only when a comment
-;;   paragraph is filled via `idlwave-fill-paragraph'.
-;;
-;;   Multi-statement lines (using "&") on block begin and end lines can
-;;   ruin the formatting.  For example, multiple end statements on a
-;;   line: endif & endif.  Using "&" outside of block begin/end lines
-;;   should be okay.
-;;
-;;   Determining the expression at point for printing and other
-;;   examination commands is somewhat rough: currently only fairly
-;;   simple entities are found.  You can always drag-select or examine
-;;   a pre-selected region.
-;;
-;;   When forcing completion of method keywords, the initial
-;;   query for a method has multiple entries for some methods.  Would
-;;   be too difficult to fix this hardly used case.
-;;
-\f
-;;; Code:
-
-
-(eval-when-compile (require 'cl-lib))
-(require 'idlw-help)
-
-(declare-function idlwave-shell-get-path-info "idlw-shell")
-(declare-function idlwave-shell-temp-file "idlw-shell")
-(declare-function idlwave-shell-is-running "idlw-shell")
-(declare-function widget-value "wid-edit" (widget))
-(declare-function comint-dynamic-complete-filename "comint" ())
-
-(defgroup idlwave nil
-  "Major mode for editing IDL .pro files."
-  :tag "IDLWAVE"
-  :link '(url-link :tag "Website"
-                   "https://github.com/jdtsmith/idlwave")
-  :link '(emacs-commentary-link :tag "Commentary in idlw-shell.el"
-                               "idlw-shell.el")
-  :link '(emacs-commentary-link :tag "Commentary in idlwave.el" "idlwave.el")
-  :link '(custom-manual "(idlwave)Top")
-  :prefix "idlwave"
-  :group 'languages)
-
-
-;;; Variables for indentation behavior ---------------------------------------
-
-(defgroup idlwave-code-formatting nil
-  "Indentation and formatting options for IDLWAVE mode."
-  :group 'idlwave)
-
-(defcustom idlwave-main-block-indent 2
-  "Extra indentation for the main block of code.
-That is the block between the FUNCTION/PRO statement and the END
-statement for that program unit."
-  :group 'idlwave-code-formatting
-  :type 'integer)
-
-(defcustom idlwave-block-indent 3
-  "Extra indentation applied to block lines.
-If you change this, you probably also want to change `idlwave-end-offset'."
-  :group 'idlwave-code-formatting
-  :type 'integer)
-
-(defcustom idlwave-end-offset -3
-  "Extra indentation applied to block END lines.
-A value equal to negative `idlwave-block-indent' will make END lines
-line up with the block BEGIN lines."
-  :group 'idlwave-code-formatting
-  :type 'integer)
-
-(defcustom idlwave-continuation-indent 3
-  "Extra indentation applied to continuation lines.
-This extra offset applies to the first of a set of continuation lines.
-The following lines receive the same indentation as the first."
-  :group 'idlwave-code-formatting
-  :type 'integer)
-
-(defcustom idlwave-max-extra-continuation-indent 40
-  "Maximum additional indentation for special continuation indent.
-Several special indentations are tried to help line up continuation
-lines in routine calls or definitions, other statements with
-parentheses, or assignment statements.  This variable specifies a
-maximum amount by which this special indentation can exceed the
-standard continuation indentation, otherwise defaulting to a fixed
-offset.  Set to 0 to effectively disable all special continuation
-indentation, or to a large number (like 100) to enable it in all
-cases.  See also `idlwave-indent-to-open-paren', which can override
-this variable."
-  :group 'idlwave-code-formatting
-  :type 'integer)
-
-(defcustom idlwave-indent-to-open-paren t
-  "Non-nil means, indent continuation lines to innermost open parenthesis.
-This indentation occurs even if otherwise disallowed by
-`idlwave-max-extra-continuation-indent'.  Matching parens and the
-interleaving args are lined up.  Example:
-
-  x = function_a(function_b(function_c( a, b, [1,2,3, $
-                                               4,5,6 $
-                                              ], $
-                                        c, d $
-                                      )))
-
-When this variable is nil, paren alignment may still occur, based on
-the value of `idlwave-max-extra-continuation-indent', which, if zero,
-would yield:
-
-  x = function_a(function_b(function_c( a, b, [1,2,3, $
-     4,5,6 $
-     ], $
-     c, d $
-     )))"
-  :group 'idlwave-code-formatting
-  :type 'boolean)
-
-(defcustom idlwave-indent-parens-nested nil
-  "Non-nil means indent continuation lines with parens by nesting
-lines at consecutively deeper levels."
- :group 'idlwave-code-formatting
-  :type 'boolean)
-
-
-(defcustom idlwave-hanging-indent t
-  "If set non-nil then comment paragraphs are indented under the
-hanging indent given by `idlwave-hang-indent-regexp' match in the first line
-of the paragraph."
-  :group 'idlwave-code-formatting
-  :type 'boolean)
-
-(defcustom idlwave-hang-indent-regexp "- "
-  "Regular expression matching the position of the hanging indent
-in the first line of a comment paragraph.  The size of the indent
-extends to the end of the match for the regular expression."
-  :group 'idlwave-code-formatting
-  :type 'regexp)
-
-(defcustom idlwave-use-last-hang-indent nil
-  "If non-nil then use last match on line for `idlwave-hang-indent-regexp'."
-  :group 'idlwave-code-formatting
-  :type 'boolean)
-
-(defcustom idlwave-fill-comment-line-only t
-  "If non-nil then auto fill will only operate on comment lines."
-  :group 'idlwave-code-formatting
-  :type 'boolean)
-
-(defcustom idlwave-auto-fill-split-string t
-  "If non-nil then auto fill will split strings with the IDL `+' operator.
-When the line end falls within a string, string concatenation with the
-`+' operator will be used to distribute a long string over lines.
-If nil and a string is split then a terminal beep and warning are issued.
-
-This variable is ignored when `idlwave-fill-comment-line-only' is
-non-nil, since in this case code is not auto-filled."
-  :group 'idlwave-code-formatting
-  :type 'boolean)
-
-(defcustom idlwave-split-line-string t
-  "If non-nil then `idlwave-split-line' will split strings with `+'.
-When the splitting point of a line falls inside a string, split the string
-using the `+' string concatenation operator.  If nil and a string is
-split then a terminal beep and warning are issued."
-  :group 'idlwave-code-formatting
-  :type 'boolean)
-
-(defcustom idlwave-no-change-comment ";;;"
-  "The indentation of a comment that starts with this regular
-expression will not be changed.  Note that the indentation of a comment
-at the beginning of a line is never changed."
-  :group 'idlwave-code-formatting
-  :type 'regexp)
-
-(defcustom idlwave-begin-line-comment nil
-  "A comment anchored at the beginning of line.
-A comment matching this regular expression will not have its
-indentation changed.  If nil the default is \"^;\", i.e., any line
-beginning with a \";\".  Expressions for comments at the beginning of
-the line should begin with \"^\"."
-  :group 'idlwave-code-formatting
-  :type '(choice (const :tag "Any line beginning with `;'" nil)
-                 regexp))
-
-(defcustom idlwave-code-comment ";;[^;]"
-  "A comment that starts with this regular expression on a line by
-itself is indented as if it is a part of IDL code.  As a result if
-the comment is not preceded by whitespace it is unchanged."
-  :group 'idlwave-code-formatting
-  :type 'regexp)
-
-;; Comments not matching any of the above will be indented as a
-;; right-margin comment, i.e., to a minimum of `comment-column'.
-
-;;; Routine Info and Completion ---------------------------------------
-
-(defgroup idlwave-routine-info nil
-  "Routine Info options for IDLWAVE mode."
-  :group 'idlwave)
-
-(defcustom idlwave-use-library-catalogs t
-  "Non-nil means search the IDL path for library catalog files.
-
-These files, named .idlwave_catalog, document routine information for
-individual directories and libraries of IDL .pro files.  Many popular
-libraries come with catalog files by default, so leaving this on is
-usually a good idea."
-  :group 'idlwave-routine-info
-  :type 'boolean)
-
-(defcustom idlwave-init-rinfo-when-idle-after 10
-  "Seconds of idle time before routine info is automatically initialized.
-Initializing the routine info can take a long time, in particular if a
-large number of library catalogs are involved.  When Emacs is idle for
-more than the number of seconds specified by this variable, it starts
-the initialization.  The process is split into five steps, in order to
-keep work interruption as short as possible.  If one of the steps
-finishes, and no user input has arrived in the mean time, initialization
-proceeds immediately to the next step.  A good value for this variable
-is about 1/3 of the time initialization take in your 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.  A value of 0 means, don't
-initialize automatically, but instead wait until routine information is
-needed, and initialize then."
-  :group 'idlwave-routine-info
-  :type 'number)
-
-(defcustom idlwave-scan-all-buffers-for-routine-info t
-  "Non-nil means, scan buffers for IDL programs when updating info.
-The scanning is done by the command `idlwave-update-routine-info'.
-The following values are allowed:
-
-nil       Don't scan any buffers.
-t         Scan all `idlwave-mode' buffers in the current editing session.
-`current' Scan only the current buffer, but no other buffers."
-  :group 'idlwave-routine-info
-  :type '(choice
-         (const :tag "No buffer" nil)
-         (const :tag "All buffers" t)
-         (const :tag "Current buffer only" current)))
-
-(defcustom idlwave-query-shell-for-routine-info t
-  "Non-nil means query the shell for info about compiled routines.
-Querying the shell is useful to get information about compiled modules,
-and it is turned on by default.  However, when you have a complete library
-scan, this is not necessary."
-  :group 'idlwave-routine-info
-  :type 'boolean)
-
-(defcustom idlwave-auto-routine-info-updates
-  '(find-file save-buffer kill-buffer compile-buffer)
-  "Controls under what circumstances routine info is updated automatically.
-Possible values:
-nil       Never
-t         All available
-\(...)     A list of circumstances.  Allowed members are:
-           find-file       Add info for new IDLWAVE buffers.
-           save-buffer     Update buffer info when buffer is saved
-           kill-buffer     Remove buffer info when buffer gets killed
-           compile-buffer  Update shell info after `idlwave-shell-save-and...'"
-  :group 'idlwave-routine-info
-  :type '(choice
-         (const :tag "Never" nil)
-         (const :tag "As often as possible" t)
-         (set :tag "Checklist" :greedy t
-              (const :tag "When visiting a file" find-file)
-              (const :tag "When saving a buffer" save-buffer)
-              (const :tag "After a buffer was killed" kill-buffer)
-              (const :tag "After a buffer was compiled successfully, update shell info" compile-buffer))))
-
-(defcustom idlwave-rinfo-max-source-lines 5
-  "Maximum number of source files displayed in the Routine Info window.
-When an integer, it is the maximum number of source files displayed.
-A value of t means to show all source files."
-  :group 'idlwave-routine-info
-  :type 'integer)
-
-(defcustom idlwave-library-path nil
-  "Library path for Windows and Mac OS (OS9).  Not needed under UNIX.
-When selecting the directories to scan for IDL user catalog routine
-info, IDLWAVE can, under UNIX, query the shell for the exact search
-path (the value of !PATH).  However, under MS-Windows, the
-IDLWAVE shell does not work.  In this case, this variable can be
-set to specify the paths where IDLWAVE can find PRO files.  The
-shell will only be asked for a list of paths when this variable
-is nil.  The value is a list of directories.  A directory
-preceded by a `+' will be searched recursively.  If you set this
-variable on a UNIX system, the shell will not be queried.  See
-also `idlwave-system-directory'."
-  :group 'idlwave-routine-info
-  :type '(repeat (directory)))
-
-(defcustom idlwave-system-directory ""
-  "The IDL system directory for Windows and Mac OS.  Not needed under
-UNIX.  Set this to the value of the `!DIR' system variable in IDL.
-IDLWAVE uses this to find out which of the library routines belong to
-the official system library.  All files inside the `lib' subdirectory
-are considered system library files - so don't install private stuff
-in this directory.  On UNIX systems, IDLWAVE queries the shell for the
-value of `!DIR'.  See also `idlwave-library-path'."
-  :group 'idlwave-routine-info
-  :type 'directory)
-
-;; Configuration files
-(defcustom idlwave-config-directory
-  (locate-user-emacs-file "idlwave" ".idlwave")
-  "Directory for configuration files and user-library catalog."
-  :version "24.4"                      ; added locate-user-emacs-file
-  :group 'idlwave-routine-info
-  :type 'file)
-
-(defvar idlwave-user-catalog-file "idlusercat.el")
-(defvar idlwave-xml-system-rinfo-converted-file "idl_xml_rinfo.el")
-(defvar idlwave-path-file "idlpath.el")
-
-(defcustom idlwave-special-lib-alist nil
-  "Alist of regular expressions matching special library directories.
-When listing routine source locations, IDLWAVE gives a short hint where
-the file defining the routine is located.  By default it lists `SystemLib'
-for routines in the system library `!DIR/lib' and `Library' for anything
-else.  This variable can define additional types.  The car of each entry
-is a regular expression matching the file name (they normally will match
-on the path).  The cdr is the string to be used as identifier.  Max 10
-chars are allowed."
-  :group 'idlwave-routine-info
-  :type '(repeat
-         (cons regexp string)))
-
-(defcustom idlwave-auto-write-paths t
-  "Write out path (!PATH) and system directory (!DIR) info automatically.
-Path info is needed to locate library catalog files.  If non-nil,
-whenever the path-list changes as a result of shell-query, etc., it is
-written to file.  Otherwise, the menu option \"Write Paths\" can be
-used to force a write."
-  :group 'idlwave-routine-info
-  :type 'boolean)
-
-(defgroup idlwave-completion nil
-  "Completion options for IDLWAVE mode."
-  :prefix "idlwave"
-  :group 'idlwave)
-
-(eval-and-compile
-  (defconst idlwave-tmp
-    '(choice :tag "by applying the function"
-      (const upcase)
-      (const downcase)
-      (const capitalize)
-      (const preserve)
-      (symbol :tag "Other"))))
-
-(defcustom idlwave-completion-case '((routine . upcase)
-                                    (keyword . upcase)
-                                    (class   . preserve)
-                                    (method  . preserve))
-  "Association list setting the case of completed words.
-
-This variable determines the case (UPPER/lower/Capitalized...) of
-words inserted into the buffer by completion.  The preferred case can
-be specified separately for routine names, keywords, classes and
-methods.
-This alist should therefore have entries for `routine' (normal
-functions and procedures, i.e. non-methods), `keyword', `class', and
-`method'.  Plausible values are
-
-upcase      upcase whole word, like `BOX_CURSOR'
-downcase    downcase whole word, like `read_ppm'
-capitalize  capitalize each part, like `Widget_Control'
-preserve    preserve case as is, like `IDLgrView'
-
-The value can also be any Emacs Lisp function which transforms the
-case of characters in a string.
-
-A value of `preserve' means that the case of the completed word is
-identical to the way it was written in the definition statement of the
-routine.  This was implemented to allow for mixed-case completion, in
-particular of object classes and methods.
-If a completable word is defined in multiple locations, the meaning of
-`preserve' is not unique since the different definitions might be
-cased differently.  Therefore IDLWAVE always takes the case of the
-*first* definition it encounters during routine info collection and
-uses the case derived from it consistently.
-
-Note that a lowercase-only string in the buffer will always be completed in
-lower case (but see the variable `idlwave-completion-force-default-case').
-
-After changing this variable, you need to either restart Emacs or press
-`C-u C-c C-i' to update the internal lists."
-  :group 'idlwave-completion
-  :type `(repeat
-         (cons (symbol :tag "Derive completion case for")
-               ,idlwave-tmp)))
-
-(defcustom idlwave-completion-force-default-case nil
-  "Non-nil means, completion will always honor `idlwave-completion-case'.
-When nil, only the completion of a mixed case or upper case string
-will honor the default settings in `idlwave-completion-case', while
-the completion of lower case strings will be completed entirely in
-lower case."
-  :group 'idlwave-completion
-  :type 'boolean)
-
-(defcustom idlwave-complete-empty-string-as-lower-case nil
-  "Non-nil means, the empty string is considered downcase for completion.
-The case of what is already in the buffer determines the case of completions.
-When this variable is non-nil, the empty string is considered to be downcase.
-Completing on the empty string then offers downcase versions of the possible
-completions."
-  :group 'idlwave-completion
-  :type 'boolean)
-
-(defcustom idlwave-buffer-case-takes-precedence nil
-  "Non-nil means, the case of tokens in buffers dominates over system stuff.
-To make this possible, we need to re-case everything each time we update
-the routine info from the buffers.  This is slow.
-The default is to consider the case given in the system and library files
-first which makes updating much faster."
-  :group 'idlwave-completion
-  :type 'boolean)
-
-(defcustom idlwave-highlight-help-links-in-completion t
-  "Non-nil means, highlight completions for which system help is available.
-Help can then be accessed with mouse-3.
-This option is only effective when the online help system is installed."
-  :group 'idlwave-completion
-  :type 'boolean)
-
-(defcustom idlwave-support-inheritance t
-  "Non-nil means, treat inheritance with completion, online help etc.
-When nil, IDLWAVE only knows about the native methods and tags of a class,
-not about inherited ones."
-  :group 'idlwave-routine-info
-  :type 'boolean)
-
-(defcustom idlwave-keyword-class-inheritance '("^[gs]etproperty$" "^init$")
-  "List of regular expressions for class-driven keyword inheritance.
-Keyword inheritance is often tied to class inheritance by \"chaining\"
-up the class tree.  While it cannot be assumed that the presence of an
-_EXTRA or _REF_EXTRA symbol guarantees such chaining will occur, for
-certain methods this assumption is almost always true.  The methods
-for which to assume this can be set here."
-  :group 'idlwave-routine-info
-  :type '(repeat (regexp :tag "Match method:")))
-
-
-(defcustom idlwave-completion-show-classes 1
-  "Number of classes to show when completing object methods and keywords.
-When completing methods or keywords for an object with unknown class,
-the *Completions* buffer will show the valid classes for each completion
-like this:
-
-MyMethod <Class1,Class2,Class3>
-
-The value of this variable may be nil to inhibit display, or an integer to
-indicate the maximum number of classes to display."
-  :group 'idlwave-completion
-  :type '(choice (const :tag "Don't show" nil)
-                (integer :tag "Number of classes shown" 1)))
-
-(defcustom idlwave-completion-fontify-classes t
-  "Non-nil means, fontify the classes in completions buffer.
-This makes it easier to distinguish the completion items from the extra
-class info listed.  See `idlwave-completion-show-classes'."
-  :group 'idlwave-completion
-  :type 'boolean)
-
-(defcustom idlwave-query-class '((method-default . nil)
-                                (keyword-default . nil))
-  "Association list governing specification of object classes for completion.
-
-When IDLWAVE tries to complete object-oriented methods, it usually
-cannot determine the class of a given object from context.  In order
-to provide the user with a correct list of methods or keywords, it
-needs to determine the appropriate class.  IDLWAVE has two ways of
-doing this (well, three ways if you count the shell... see
-`idlwave-shell-query-for-class'):
-
-1. Combine the items of all available classes which contain this
-   method for the purpose of completion.  So when completing a method,
-   all methods of all known classes are available, and when completing
-   a keyword, all keywords allowed for this method in any class are
-   shown.  This behavior is very much like normal completion and is
-   therefore the default.  It works much better than one might think -
-   only for the INIT, GETPROPERTY and SETPROPERTY the keyword lists
-   become uncomfortably long.  See also
-   `idlwave-completion-show-classes'.
-
-2. The second possibility is to ask the user on each occasion.  To
-   make this less interruptive, IDLWAVE can store the class as a text
-   property on the object operator `->'.  For a given object in the
-   source code, class selection will then be needed only once
-   - for example to complete the method.  Keywords to the method can
-   then be completed directly, because the class is already known.
-   You will have to turn on the storage of the selected class
-   explicitly with the variable `idlwave-store-inquired-class'.
-
-This variable allows you to configure IDLWAVE's method and
-method-keyword completion behavior.  Its value is an alist, which
-should contain at least two elements: (method-default . VALUE) and
-\(keyword-default . VALUE), where VALUE is either t or nil.  These
-specify if the class should be found during method and keyword
-completion, respectively.
-
-The alist may have additional entries specifying exceptions from the
-keyword completion rule for specific methods, like INIT or
-GETPROPERTY.  In order to turn on class specification for the INIT
-method, add an entry (\"INIT\" . t).  The method name must be ALL-CAPS."
-  :group 'idlwave-completion
-  :type '(list
-         (cons (const method-default)
-               (boolean :tag "Determine class when completing METHODS    "))
-         (cons (const keyword-default)
-               (boolean :tag "Determine class when completing KEYWORDS   "))
-         (repeat
-          :tag "Exceptions to defaults"
-          :inline t
-          (cons (string  :tag "MODULE" :value "")
-                (boolean :tag "Determine class for this method")))))
-
-(defcustom idlwave-store-inquired-class t
-  "Non-nil means, store class of a method call as text property on `->'.
-IDLWAVE sometimes has to ask the user for the class associated with a
-particular object method call.  This happens during the commands
-`idlwave-routine-info' and `idlwave-complete', depending upon the
-value of the variable `idlwave-query-class'.
-
-When you specify a class, this information can be stored as a text
-property on the `->' arrow in the source code, so that during the same
-editing session, IDLWAVE will not have to ask again.  When this
-variable is non-nil, IDLWAVE will store and reuse the class information.
-The class stored can be checked and removed with \\[idlwave-routine-info]
-on the arrow.
-
-The default of this variable is nil, since the result of commands then
-is more predictable.  However, if you know what you are doing, it can
-be nice to turn this on.
-
-An arrow which knows the class will be highlighted with
-`idlwave-class-arrow-face'.  The command \\[idlwave-routine-info]
-displays (with prefix arg: deletes) the class stored on the arrow
-at point."
-  :group 'idlwave-completion
-  :type 'boolean)
-
-(defcustom idlwave-class-arrow-face 'bold
-  "Face to highlight object operator arrows `->' which carry a class property.
-When IDLWAVE stores a class name as text property on an object arrow
-\(see variable `idlwave-store-inquired-class', it highlights the arrow
-with this font in order to remind the user that this arrow is special."
-  :group 'idlwave-completion
-  :type 'symbol)
-
-(defcustom idlwave-resize-routine-help-window t
-  "Non-nil means, resize the Routine-info *Help* window to fit the content."
-  :group 'idlwave-completion
-  :type 'boolean)
-
-(defcustom idlwave-keyword-completion-adds-equal t
-  "Non-nil means, completion automatically adds `=' after completed keywords."
-  :group 'idlwave-completion
-  :type 'boolean)
-
-(defcustom idlwave-function-completion-adds-paren t
-  "Non-nil means, completion automatically adds `(' after completed function.
-nil means, don't add anything.
-A value of `2' means, also add the closing parenthesis and position cursor
-between the two."
-  :group 'idlwave-completion
-  :type '(choice (const :tag "Nothing" nil)
-                (const :tag "(" t)
-                (const :tag "()" 2)))
-
-(defcustom idlwave-completion-restore-window-configuration t
-  "Non-nil means, try to restore the window configuration after completion.
-When completion is not unique, Emacs displays a list of completions.
-This messes up your window configuration.  With this variable set, IDLWAVE
-restores the old configuration after successful completion."
-  :group 'idlwave-completion
-  :type 'boolean)
-
-;;; Variables for abbrev and action behavior -----------------------------
-
-(defgroup idlwave-abbrev-and-indent-action nil
-  "IDLWAVE performs actions when expanding abbreviations or indenting lines.
-The variables in this group govern this."
-  :group 'idlwave)
-
-(defcustom idlwave-do-actions nil
-  "Non-nil means performs actions when indenting.
-The actions that can be performed are listed in `idlwave-indent-action-table'."
-  :group 'idlwave-abbrev-and-indent-action
-  :type 'boolean)
-
-(defcustom idlwave-abbrev-start-char "\\"
-  "A single character string used to start abbreviations in abbrev mode.
-Possible characters to choose from: ~\\=`%
-or even `?'.  `.' is not a good choice because it can make structure
-field names act like abbrevs in certain circumstances.
-
-Changes to this in `idlwave-mode-hook' will have no effect.  Instead a user
-must set it directly using `setq' in the init file before idlwave.el
-is loaded."
-  :group 'idlwave-abbrev-and-indent-action
-  :type 'string)
-
-(defcustom idlwave-surround-by-blank nil
-  "Non-nil means, enable `idlwave-surround'.
-If non-nil, `=',`<',`>',`&',`,', `->' are surrounded with spaces by
-`idlwave-surround'.
-See help for `idlwave-indent-action-table' for symbols using `idlwave-surround'.
-
-Also see the default key bindings for keys using `idlwave-surround'.
-Keys are bound and made into actions calling `idlwave-surround' with
-`idlwave-action-and-binding'.
-See help for `idlwave-action-and-binding' for examples.
-
-Also see help for `idlwave-surround'."
-  :group 'idlwave-abbrev-and-indent-action
-  :type 'boolean)
-
-(defcustom idlwave-pad-keyword t
-  "Non-nil means pad `=' in keywords (routine calls or defs) like assignment.
-Whenever `idlwave-surround' is non-nil then this affects how `=' is
-padded for keywords and for variables.  If t, pad the same as for
-assignments.  If nil then spaces are removed.  With any other value,
-spaces are left unchanged."
-  :group 'idlwave-abbrev-and-indent-action
-  :type '(choice
-         (const :tag "Pad like assignments" t)
-         (const :tag "Remove space near `='" nil)
-         (other :tag "Keep space near `='" keep)))
-
-(defcustom idlwave-show-block t
-  "Non-nil means point blinks to block beginning for `idlwave-show-begin'."
-  :group 'idlwave-abbrev-and-indent-action
-  :type 'boolean)
-
-(defcustom idlwave-expand-generic-end nil
-  "Non-nil means expand generic END to ENDIF/ENDELSE/ENDWHILE etc."
-  :group 'idlwave-abbrev-and-indent-action
-  :type 'boolean)
-
-(defcustom idlwave-reindent-end t
-  "Non-nil means re-indent line after END was typed."
-  :group 'idlwave-abbrev-and-indent-action
-  :type 'boolean)
-
-(defcustom idlwave-abbrev-move t
-  "Non-nil means the abbrev hook can move point.
-Set to nil by `idlwave-expand-region-abbrevs'.  To see the abbrev
-definitions, use the command `list-abbrevs', for abbrevs that move
-point.  Moving point is useful, for example, to place point between
-parentheses of expanded functions.
-
-See `idlwave-modify-abbrev'."
-  :group 'idlwave-abbrev-and-indent-action
-  :type 'boolean)
-
-(defcustom idlwave-abbrev-change-case nil
-  "Non-nil means all abbrevs will be forced to either upper or lower case.
-If the value t, all expanded abbrevs will be upper case.
-If the value is `down' then abbrevs will be forced to lower case.
-If nil, the case will not change.
-If `idlwave-reserved-word-upcase' is non-nil, reserved words will always be
-upper case, regardless of this variable."
-  :group 'idlwave-abbrev-and-indent-action
-  :type 'boolean)
-
-(defcustom idlwave-reserved-word-upcase nil
-  "Non-nil means, reserved words will be made upper case via abbrev expansion.
-If nil case of reserved words is controlled by `idlwave-abbrev-change-case'.
-Has effect only if in `abbrev-mode'."
-  :group 'idlwave-abbrev-and-indent-action
-  :type 'boolean)
-
-;;; Action/Expand Tables.
-;;
-;; The average user may have difficulty modifying this directly.  It
-;; can be modified/set in idlwave-mode-hook, but it is easier to use
-;; idlwave-action-and-binding. See help for idlwave-action-and-binding for
-;; examples of how to add an action.
-;;
-;; The action table is used by `idlwave-indent-line' whereas both the
-;; action and expand tables are used by `idlwave-indent-and-action'.  In
-;; general, the expand table is only used when a line is explicitly
-;; indented.  Whereas, in addition to being used when the expand table
-;; is used, the action table is used when a line is indirectly
-;; indented via line splitting, auto-filling or a new line creation.
-;;
-;; Example actions:
-;;
-;;  Capitalize system vars
-;;   (idlwave-action-and-binding idlwave-sysvar
-;;                               (lambda (_) (capitalize-word 1)) t)
-;;
-;;  Capitalize procedure name
-;;   (idlwave-action-and-binding "\\<\\(pro\\|function\\)\\>[ \t]*\\<"
-;;                               (lambda (_) (capitalize-word 1)) t)
-;;
-;;  Capitalize common block name
-;;   (idlwave-action-and-binding "\\<common\\>[ \t]+\\<"
-;;                               (lambda (_) (capitalize-word 1)) t)
-;;  Capitalize label
-;;   (idlwave-action-and-binding (concat "^[ \t]*" idlwave-label)
-;;                               (lambda (_) (capitalize-word 1)) t)
-
-(defvar idlwave-indent-action-table nil
-  "Associated array containing action lists of search string (car),
-and function as a cdr.  This table is used by `idlwave-indent-line'.
-See documentation for `idlwave-do-action' for a complete description of
-the action lists.
-
-Additions to the table are made with `idlwave-action-and-binding' when a
-binding is not requested.
-See help on `idlwave-action-and-binding' for examples.")
-
-(defvar idlwave-indent-expand-table nil
-  "Associated array containing action lists of search string (car),
-and function as a cdr.  The table is used by the
-`idlwave-indent-and-action' function.  See documentation for
-`idlwave-do-action' for a complete description of the action lists.
-
-Additions to the table are made with `idlwave-action-and-binding' when a
-binding is requested.
-See help on `idlwave-action-and-binding' for examples.")
-
-;;; Documentation header and history keyword ---------------------------------
-
-(defgroup idlwave-documentation nil
-  "Options for documenting IDLWAVE files."
-  :group 'idlwave)
-
-;; FIXME: make defcustom?
-(defvar idlwave-file-header
-  (list nil
-        ";+
-; NAME:
-;
-;
-;
-; PURPOSE:
-;
-;
-;
-; CATEGORY:
-;
-;
-;
-; CALLING SEQUENCE:
-;
-;
-;
-; INPUTS:
-;
-;
-;
-; OPTIONAL INPUTS:
-;
-;
-;
-; KEYWORD PARAMETERS:
-;
-;
-;
-; OUTPUTS:
-;
-;
-;
-; OPTIONAL OUTPUTS:
-;
-;
-;
-; COMMON BLOCKS:
-;
-;
-;
-; SIDE EFFECTS:
-;
-;
-;
-; RESTRICTIONS:
-;
-;
-;
-; PROCEDURE:
-;
-;
-;
-; EXAMPLE:
-;
-;
-;
-; MODIFICATION HISTORY:
-;
-;-
-")
-  "A list (PATHNAME STRING) specifying the doc-header template to use for
-summarizing a file.  If PATHNAME is non-nil then this file will be included.
-Otherwise STRING is used.  If nil, the file summary will be omitted.
-For example you might set PATHNAME to the path for the
-lib_template.pro file included in the IDL distribution.")
-
-(defcustom idlwave-header-to-beginning-of-file t
-  "Non-nil means, the documentation header will always be at start of file.
-When nil, the header is positioned between the PRO/FUNCTION line of
-the current routine and the code, allowing several routine headers in
-a file."
-  :group 'idlwave-documentation
-  :type 'boolean)
-
-(defcustom idlwave-timestamp-hook 'idlwave-default-insert-timestamp
-  "The hook function used to update the timestamp of a function."
-  :group 'idlwave-documentation
-  :type 'function)
-
-(defcustom idlwave-doc-modifications-keyword "HISTORY"
-  "The modifications keyword to use with the log documentation commands.
-A `:' is added to the keyword end.
-Inserted by doc-header and used to position logs by doc-modification.
-If nil it will not be inserted."
-  :group 'idlwave-documentation
-  :type 'string)
-
-(defcustom idlwave-doclib-start "^;+\\+"
-  "Regexp matching the start of a document library header."
-  :group 'idlwave-documentation
-  :type 'regexp)
-
-(defcustom idlwave-doclib-end "^;+-"
-  "Regexp matching the end of a document library header."
-  :group 'idlwave-documentation
-  :type 'regexp)
-
-;;; External Programs -------------------------------------------------------
-
-(defgroup idlwave-external-programs nil
-  "Path locations of external commands used by IDLWAVE."
-  :group 'idlwave)
-
-(defcustom idlwave-shell-explicit-file-name "idl"
-  "If non-nil, this is the command to run IDL.
-Should be an absolute file path or path relative to the current environment
-execution search path.  If you want to specify command line switches
-for the IDL program, use `idlwave-shell-command-line-options'.
-
-I know the name of this variable is badly chosen, but I cannot change
-it without compromising backwards-compatibility."
-  :group 'idlwave-external-programs
-  :type 'string)
-
-(defcustom idlwave-shell-command-line-options nil
-  "A list of command line options for calling the IDL program.
-Since IDL is executed directly without going through a shell like /bin/sh,
-this should be a list of strings like (\"-rt=file\" \"-nw\") with a separate
-string for each argument.  But you may also give a single string which
-contains the options whitespace-separated.  Emacs will be kind enough to
-split it for you."
-  :type '(choice
-         string
-         (repeat (string :value "")))
-  :group 'idlwave-external-programs)
-
-(defcustom idlwave-help-application "idlhelp"
-  "The external application providing reference help for programming.
-Obsolete, if the IDL Assistant is being used for help."
-  :group 'idlwave-external-programs
-  :type 'string)
-
-;;; Some Shell variables which must be defined here.-----------------------
-
-(defcustom idlwave-shell-debug-modifiers '()
-  "List of modifiers to be used for the debugging commands.
-Will be used to bind debugging commands in the shell buffer and in all
-source buffers.  These are additional convenience bindings, the debugging
-commands are always available with the \\`C-c C-d' prefix.
-If you set this to (control shift), this means setting a breakpoint will
-be on \\`C-S-b', compiling a source file on \\`C-S-c' etc.  Possible modifiers
-are `control', `meta', `super', `hyper', `alt', and `shift'."
-  :group 'idlwave-shell-general-setup
-  :type '(set :tag "Specify modifiers"
-              (const control)
-              (const meta)
-              (const super)
-              (const hyper)
-              (const alt)
-              (const shift)))
-
-(defcustom idlwave-shell-automatic-start nil
-  "If non-nil attempt invoke `idlwave-shell' if not already running.
-This is checked when an attempt to send a command to an
-IDL process is made."
-  :group 'idlwave-shell-general-setup
-  :type 'boolean)
-
-;;; Miscellaneous variables -------------------------------------------------
-
-(defgroup idlwave-misc nil
-  "Miscellaneous options for IDLWAVE mode."
-  :link '(custom-group-link :tag "Font Lock Faces group" font-lock-faces)
-  :group 'idlwave)
-
-(defcustom idlwave-startup-message t
-  "Non-nil displays a startup message when `idlwave-mode' is first called."
-  :group 'idlwave-misc
-  :type 'boolean)
-
-(defcustom idlwave-default-font-lock-items
-  '(pros-and-functions batch-files idlwave-idl-keywords label goto
-                      common-blocks class-arrows)
-  "Items which should be fontified on the default fontification level 2.
-IDLWAVE defines 3 levels of fontification.  Level 1 is very little, level 3
-is everything and level 2 is specified by this list.
-This variable must be set before IDLWAVE gets loaded.
-It is a list of symbols; the following symbols are allowed:
-
-pros-and-functions   Procedure and Function definitions
-batch-files          Batch Files
-idlwave-idl-keywords IDL Keywords
-label                Statement Labels
-goto                 Goto Statements
-common-blocks        Common Blocks
-keyword-parameters   Keyword Parameters in routine definitions and calls
-system-variables     System Variables
-class-arrows         Object Arrows with class property"
-  :group 'idlwave-misc
-  :type '(set
-         :inline t :greedy t
-         (const :tag "Procedure and Function definitions" pros-and-functions)
-         (const :tag "Batch Files"                       batch-files)
-         (const :tag "IDL Keywords (reserved words)"     idlwave-idl-keywords)
-         (const :tag "Statement Labels"                  label)
-         (const :tag "Goto Statements"                   goto)
-         (const :tag "Tags in Structure Definition"      structtag)
-         (const :tag "Structure Name"                    structname)
-         (const :tag "Common Blocks"                     common-blocks)
-         (const :tag "Keyword Parameters"                keyword-parameters)
-         (const :tag "System Variables"                  system-variables)
-         (const :tag "Object Arrows with class property " class-arrows)))
-
-(defcustom idlwave-mode-hook nil
-  "Normal hook.  Executed when a buffer is put into `idlwave-mode'."
-  :group 'idlwave-misc
-  :type 'hook)
-
-(defcustom idlwave-load-hook nil
-  "Normal hook.  Executed when idlwave.el is loaded."
-  :group 'idlwave-misc
-  :type 'hook)
-(make-obsolete-variable 'idlwave-load-hook
-                        "use `with-eval-after-load' instead." "28.1")
-
-(defvar idlwave-experimental nil
-  "Non-nil means turn on a few experimental features.
-This variable is only for the maintainer, to test difficult stuff,
-while still distributing stable releases.
-As a user, you should not set this to t.")
-
-;;;
-;;; End customization variables section
-;;;
-
-;;; Non customization variables
-
-;;; font-lock mode - Additions by Phil Williams, Ulrik Dickow and
-;;; Simon Marshall <simon_at_gnu.ai.mit.edu>
-;;; and Carsten Dominik...
-
-;; The following are the reserved words in IDL.  Maybe we should
-;; highlight some more stuff as well?
-;; Procedure declarations.  Fontify keyword plus procedure name.
-(defvar idlwave-idl-keywords
-  ;; To update this regexp, update the list of keywords and
-  ;; evaluate the form.
-  ;;   (insert
-  ;;    (prin1-to-string
-  ;;     (concat
-  ;;      "\\<\\("
-  ;;      (regexp-opt
-  ;;       '("||" "&&" "and" "or" "xor" "not"
-  ;;         "eq" "ge" "gt" "le" "lt" "ne"
-  ;;         "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\\|||\\)\\>")
-
-
-(defmacro idlwave--dlet (binders &rest body)
-  "Like `dlet' but without warnings about non-prefixed var names."
-  (declare (indent 1) (debug let))
-  (let ((vars (mapcar (lambda (binder)
-                        (if (consp binder) (car binder) binder))
-                      binders)))
-    `(with-suppressed-warnings ((lexical ,@vars))
-       (dlet ,binders ,@body))))
-
-(idlwave--dlet
-    (;; Procedure declarations.  Fontify keyword plus procedure name.
-     ;; Function  declarations.  Fontify keyword plus function  name.
-     (pros-and-functions
-      '("\\<\\(function\\|pro\\)\\>[ \t]+\\(\\sw+\\(::\\sw+\\)?\\)"
-       (1 font-lock-keyword-face)
-       (2 font-lock-function-name-face nil t)))
-
-     ;; Common blocks
-     (common-blocks
-      '("\\<\\(common\\)\\>[ \t]*\\(\\sw+\\)?[ \t]*,?"
-       (1 font-lock-keyword-face)          ; "common"
-       (2 font-lock-constant-face nil t)   ; block name
-       ("[ \t]*\\(\\sw+\\)[ ,]*"
-        ;; Start with point after block name and comma
-        nil nil (1 font-lock-variable-name-face)))) ; variable names
-
-     ;; Batch files
-     (batch-files
-      '("^[ \t]*\\(@[^ \t\n]+\\)" (1 font-lock-string-face)))
-
-     ;; Labels
-     (label
-      '("^[ \t]*\\([a-zA-Z]\\sw*:\\)" (1 font-lock-constant-face)))
-
-     ;; The goto statement and its label
-     (goto
-      '("\\(goto\\)[ \t]*,[ \t]*\\([a-zA-Z]\\sw*\\)"
-       (1 font-lock-keyword-face)
-       (2 font-lock-constant-face)))
-
-     ;; Tags in structure definitions.  Note that this definition
-     ;; actually collides with labels, so we have to use the same
-     ;; face.  It also matches named subscript ranges,
-     ;; e.g. vec{bottom:top].  No good way around this.
-     (structtag
-      '("\\<\\([a-zA-Z][a-zA-Z0-9_]*:\\)[^:]" (1 font-lock-constant-face)))
-
-     ;; Structure names
-     (structname
-      '("\\({\\|\\<inherits\\s-\\)\\s-*\\([a-zA-Z][a-zA-Z0-9_]*\\)[},\t \n]"
-       (2 font-lock-function-name-face)))
-
-     ;; Keyword parameters, like /xlog or ,xrange=[]
-     ;; This is anchored to the comma preceding the keyword.
-     ;; Treats continuation lines, works only during whole buffer
-     ;; fontification.  Slow, use it only in fancy fontification.
-     (keyword-parameters
-      '("\\(,\\|[a-zA-Z0-9_](\\)[ \t]*\\(\\$[ \t]*\\(;.*\\)?\n\\([ \t]*\\(;.*\\)?\n\\)*[ \t]*\\)?\\(/[a-zA-Z_]\\sw*\\|[a-zA-Z_]\\sw*[ \t]*=\\)"
-       (6 font-lock-constant-face)))
-
-     ;; System variables start with a bang.
-     (system-variables
-      '("\\(![a-zA-Z_0-9]+\\(\\.\\sw+\\)?\\)"
-       (1 font-lock-variable-name-face)))
-
-     ;; Special and unusual operators (not used because too noisy)
-     ;; (special-operators
-     ;;  '("[<>#]" (0 font-lock-keyword-face)))
-
-     ;; All operators (not used because too noisy)
-     ;; (all-operators
-     ;;  '("[-*^#+<>/]" (0 font-lock-keyword-face)))
-
-     ;; Arrows with text property `idlwave-class'
-     (class-arrows
-      '(idlwave-match-class-arrows (0 idlwave-class-arrow-face))))
-
-  (defconst idlwave-font-lock-keywords-1
-    (list pros-and-functions batch-files)
-    "Subdued level highlighting for IDLWAVE mode.")
-
-  (defconst idlwave-font-lock-keywords-2
-    (mapcar #'symbol-value idlwave-default-font-lock-items)
-    "Medium level highlighting for IDLWAVE mode.")
-
-  (defconst idlwave-font-lock-keywords-3
-    (list pros-and-functions
-         batch-files
-         idlwave-idl-keywords
-         label goto
-         structtag
-         structname
-         common-blocks
-         keyword-parameters
-         system-variables
-         class-arrows)
-    "Gaudy level highlighting for IDLWAVE mode."))
-
-(defun idlwave-match-class-arrows (limit)
-  ;; Match an object arrow with class property
-  (and idlwave-store-inquired-class
-       (re-search-forward "->" limit 'limit)
-       (get-text-property (match-beginning 0) 'idlwave-class)))
-
-(defvar idlwave-font-lock-keywords idlwave-font-lock-keywords-2
-  "Default expressions to highlight in IDLWAVE mode.")
-
-(defvar idlwave-font-lock-defaults
-  '((idlwave-font-lock-keywords
-     idlwave-font-lock-keywords-1
-     idlwave-font-lock-keywords-2
-     idlwave-font-lock-keywords-3)
-    nil t
-    ((?$ . "w") (?_ . "w") (?. . "w") (?| . "w") (?& . "w"))
-    beginning-of-line))
-
-(defconst idlwave-comment-line-start-skip "^[ \t]*;"
-  "Regexp to match the start of a full-line comment.
-That is the _beginning_ of a line containing a comment delimiter `;' preceded
-only by whitespace.")
-
-(defconst idlwave-begin-block-reg
-  "\\<\\(pro\\|function\\|begin\\|case\\|switch\\)\\>"
-  "Regular expression to find the beginning of a block.
-The case does not matter.  The search skips matches in comments.")
-
-(defconst idlwave-begin-unit-reg "^\\s-*\\(pro\\|function\\)\\>\\|\\`"
-  "Regular expression to find the beginning of a unit.
-The case does not matter.")
-
-(defconst idlwave-end-unit-reg "^\\s-*\\(pro\\|function\\)\\>\\|\\'"
-  "Regular expression to find the line that indicates the end of unit.
-This line is the end of buffer or the start of another unit.
-The case does not matter.  The search skips matches in comments.")
-
-(defconst idlwave-continue-line-reg "\\<\\$"
-  "Regular expression to match a continued line.")
-
-(defconst idlwave-end-block-reg
-  "\\<end\\(\\|case\\|switch\\|else\\|for\\|if\\|rep\\|while\\)\\>"
-  "Regular expression to find the end of a block.
-The case does not matter.  The search skips matches in comments.")
-
-(defconst idlwave-block-matches
-  '(("pro"      . "end")
-    ("function" . "end")
-    ("case"     . "endcase")
-    ("else"     . "endelse")
-    ("for"      . "endfor")
-    ("then"     . "endif")
-    ("repeat"   . "endrep")
-    ("switch"   . "endswitch")
-    ("while"    . "endwhile"))
-  "Matches between statements and the corresponding END variant.
-The cars are the reserved words starting a block.  If the block really
-begins with BEGIN, the cars are the reserved words before the begin
-which can be used to identify the block type.
-This is used to check for the correct END type, to close blocks and
-to expand generic end statements to their detailed form.")
-
-(defconst idlwave-block-match-regexp
-  "\\<\\(else\\|for\\|then\\|repeat\\|while\\)\\>"
-"Regular expression matching reserved words which can stand before
-blocks starting with a BEGIN statement.  The matches must have associations
-`idlwave-block-matches'.")
-
-(defconst idlwave-identifier "[a-zA-Z_][a-zA-Z0-9$_]*"
-  "Regular expression matching an IDL identifier.")
-
-(defconst idlwave-sysvar (concat "!" idlwave-identifier)
-  "Regular expression matching IDL system variables.")
-
-(defconst idlwave-variable (concat idlwave-identifier "\\|" idlwave-sysvar)
-  "Regular expression matching IDL variable names.")
-
-(defconst idlwave-label (concat idlwave-identifier ":")
-  "Regular expression matching IDL labels.")
-
-(defconst idlwave-method-call (concat idlwave-identifier  "\\s *->"
-                                     "\\(\\s *" idlwave-identifier "::\\)?"
-))
-
-(defconst idlwave-statement-match
-  (list
-   ;; "endif else" is the only possible "end" that can be
-   ;; followed by a statement on the same line.
-   '(endelse . ("end\\(\\|if\\)\\s +else" "end\\(\\|if\\)\\s +else"))
-   ;; all other "end"s can not be followed by a statement.
-   (cons 'end (list idlwave-end-block-reg nil))
-   '(if . ("if\\>" "then"))
-   '(for . ("for\\>" "do"))
-   '(begin . ("begin\\>" nil))
-   '(pdef . ("pro\\>\\|function\\>" nil))
-   '(while . ("while\\>" "do"))
-   '(repeat . ("repeat\\>" "repeat"))
-   '(goto . ("goto\\>" nil))
-   '(case . ("case\\>" nil))
-   '(switch . ("switch\\>" nil))
-   (cons 'call (list (concat "\\(" idlwave-variable "\\) *= *"
-                            "\\(" idlwave-method-call "\\s *\\)?"
-                            idlwave-identifier
-                            "\\s *(")
-                    nil))
-   (cons 'call (list (concat
-                     "\\(" idlwave-method-call "\\s *\\)?"
-                     idlwave-identifier
-                     "\\( *\\($\\|\\$\\)\\|\\s *,\\)")
-                    nil))
-   (cons 'assign (list (concat
-                       "\\(" idlwave-variable "\\) *=")
-                      nil)))
-
-  "Associated list of statement matching regular expressions.
-Each regular expression matches the start of an IDL statement.
-The first element of each association is a symbol giving the statement
-type.  The associated value is a list.  The first element of this list
-is a regular expression matching the start of an IDL statement for
-identifying the statement type.  The second element of this list is a
-regular expression for finding a substatement for the type.  The
-substatement starts after the end of the found match modulo
-whitespace.  If it is nil then the statement has no substatement.  The
-list order matters since matching an assignment statement exactly is
-not possible without parsing.  Thus assignment statement become just
-the leftover unidentified statements containing an equal sign.")
-
-(defvar idlwave-comment-indent-function 'comment-indent-function
-  "IDL mode comment indent function.")
-
-;; Note that this is documented in the v18 manuals as being a string
-;; of length one rather than a single character.
-;; The code in this file accepts either format for compatibility.
-(defvar idlwave-comment-indent-char ?\s
-  "Character to be inserted for IDL comment indentation.
-Normally a space.")
-
-(defconst idlwave-continuation-char ?$
-  "Character which is inserted as a last character on previous line by
-\\[idlwave-split-line] to begin a continuation line.  Normally $.")
-
-(defconst idlwave-mode-version "6.1_em22")
-
-(defun idlwave-keyword-abbrev (&rest args)
-  "Create a function for abbrev hooks to call `idlwave-modify-abbrev' with args."
-  (lambda () (apply #'idlwave-modify-abbrev args)))
-
-(autoload 'idlwave-shell "idlw-shell"
-  "Run an inferior IDL, with I/O through buffer `(idlwave-shell-buffer)'." t)
-(autoload 'idlwave-shell-send-command "idlw-shell")
-(autoload 'idlwave-shell-recenter-shell-window "idlw-shell"
-  "Run `idlwave-shell' and switch back to current window" t)
-(autoload 'idlwave-shell-save-and-run "idlw-shell"
-  "Save and run buffer under the shell." t)
-(autoload 'idlwave-shell-break-here "idlw-shell"
-  "Set breakpoint in current line." t)
-(autoload 'idlwave-shell-run-region "idlw-shell"
-  "Compile and run the region." t)
-
-(defalias 'idlwave-debug-map (make-sparse-keymap))
-
-(defvar idlwave-mode-map
-  (let ((map (make-sparse-keymap)))
-    (define-key map "\C-c "    #'idlwave-hard-tab)
-    (define-key map [(control tab)] #'idlwave-hard-tab)
-    ;;(define-key map "\C-c\C- " #'idlwave-hard-tab)
-    (define-key map "'"        #'idlwave-show-matching-quote)
-    (define-key map "\""       #'idlwave-show-matching-quote)
-    (define-key map "\C-g"     #'idlwave-keyboard-quit)
-    (define-key map "\C-c;"    #'idlwave-toggle-comment-region)
-    (define-key map "\C-\M-a"  #'idlwave-beginning-of-subprogram)
-    (define-key map "\C-\M-e"  #'idlwave-end-of-subprogram)
-    (define-key map "\C-c{"    #'idlwave-beginning-of-block)
-    (define-key map "\C-c}"    #'idlwave-end-of-block)
-    (define-key map "\C-c]"    #'idlwave-close-block)
-    (define-key map [(meta control h)] #'idlwave-mark-subprogram)
-    (define-key map "\M-\C-n"  #'idlwave-forward-block)
-    (define-key map "\M-\C-p"  #'idlwave-backward-block)
-    (define-key map "\M-\C-d"  #'idlwave-down-block)
-    (define-key map "\M-\C-u"  #'idlwave-backward-up-block)
-    (define-key map "\M-\r"    #'idlwave-split-line)
-    (define-key map "\M-\C-q"  #'idlwave-indent-subprogram)
-    (define-key map "\C-c\C-p" #'idlwave-previous-statement)
-    (define-key map "\C-c\C-n" #'idlwave-next-statement)
-    ;; (define-key map "\r"       #'idlwave-newline)
-    ;; (define-key map "\t"       #'idlwave-indent-line)
-    (define-key map [(shift iso-lefttab)] #'idlwave-indent-statement)
-    (define-key map "\C-c\C-a" #'auto-fill-mode)
-    (define-key map "\M-q"     #'idlwave-fill-paragraph)
-    (define-key map "\M-s"     #'idlwave-edit-in-idlde)
-    (define-key map "\C-c\C-h" #'idlwave-doc-header)
-    (define-key map "\C-c\C-m" #'idlwave-doc-modification)
-    (define-key map "\C-c\C-c" #'idlwave-case)
-    (define-key map "\C-c\C-d" #'idlwave-debug-map)
-    (when (and (listp idlwave-shell-debug-modifiers)
-               (not (equal idlwave-shell-debug-modifiers '())))
-      ;; Bind the debug commands also with the special modifiers.
-      (let ((shift (memq 'shift idlwave-shell-debug-modifiers))
-            (mods-noshift
-             (delq 'shift (copy-sequence idlwave-shell-debug-modifiers))))
-        (define-key map
-          (vector (append mods-noshift (list (if shift ?C ?c))))
-          #'idlwave-shell-save-and-run)
-        (define-key map
-          (vector (append mods-noshift (list (if shift ?B ?b))))
-          #'idlwave-shell-break-here)
-        (define-key map
-          (vector (append mods-noshift (list (if shift ?E ?e))))
-          #'idlwave-shell-run-region)))
-    (define-key map "\C-c\C-d\C-c" #'idlwave-shell-save-and-run)
-    (define-key map "\C-c\C-d\C-b" #'idlwave-shell-break-here)
-    (define-key map "\C-c\C-d\C-e" #'idlwave-shell-run-region)
-    (define-key map "\C-c\C-f" #'idlwave-for)
-    ;;  (define-key map "\C-c\C-f" #'idlwave-function)
-    ;;  (define-key map "\C-c\C-p" #'idlwave-procedure)
-    (define-key map "\C-c\C-r" #'idlwave-repeat)
-    (define-key map "\C-c\C-w" #'idlwave-while)
-    (define-key map "\C-c\C-k" #'idlwave-kill-autoloaded-buffers)
-    (define-key map "\C-c\C-s" #'idlwave-shell)
-    (define-key map "\C-c\C-l" #'idlwave-shell-recenter-shell-window)
-    (define-key map "\C-c\C-b" #'idlwave-list-buffer-load-path-shadows)
-    (define-key map "\C-c\C-v"   #'idlwave-find-module)
-    (define-key map "\C-c\C-t"   #'idlwave-find-module-this-file)
-    (define-key map "\C-c?"      #'idlwave-routine-info)
-    (define-key map "\M-?"       #'idlwave-context-help)
-    (define-key map [(control meta ?\?)]
-      #'idlwave-help-assistant-help-with-topic)
-    ;; Pickup both forms of Esc/Meta binding
-    ;; FIXME: Use `completion-at-point'!
-    (define-key map [(meta tab)] #'idlwave-complete)
-    (define-key map [?\e?\t] #'idlwave-complete)
-    (define-key map "\M-\C-i" #'idlwave-complete)
-    (define-key map "\C-c\C-i" #'idlwave-update-routine-info)
-    (define-key map "\C-c="    #'idlwave-resolve)
-    (define-key map [(shift mouse-3)] #'idlwave-mouse-context-help)
-    map)
-  "Keymap used in IDL mode.")
-
-(defvar idlwave-mode-syntax-table
-  (let ((st (make-syntax-table)))
-    (modify-syntax-entry ?+   "."  st)
-    (modify-syntax-entry ?-   "."  st)
-    (modify-syntax-entry ?*   "."  st)
-    (modify-syntax-entry ?/   "."  st)
-    (modify-syntax-entry ?^   "."  st)
-    (modify-syntax-entry ?#   "."  st)
-    (modify-syntax-entry ?=   "."  st)
-    (modify-syntax-entry ?%   "."  st)
-    (modify-syntax-entry ?<   "."  st)
-    (modify-syntax-entry ?>   "."  st)
-    (modify-syntax-entry ?\'  "\"" st)
-    (modify-syntax-entry ?\"  "\"" st)
-    (modify-syntax-entry ?\\  "."  st)
-    (modify-syntax-entry ?_   "_"  st)
-    (modify-syntax-entry ?{   "(}" st)
-    (modify-syntax-entry ?}   "){" st)
-    (modify-syntax-entry ?$   "_"  st)
-    (modify-syntax-entry ?.   "."  st)
-    (modify-syntax-entry ?\;  "<"  st)
-    (modify-syntax-entry ?\n  ">"  st)
-    (modify-syntax-entry ?\f  ">"  st)
-    st)
-  "Syntax table in use in `idlwave-mode' buffers.")
-
-(defvar idlwave-find-symbol-syntax-table
-  (let ((st (copy-syntax-table idlwave-mode-syntax-table)))
-    (modify-syntax-entry ?$   "w"  st)
-    (modify-syntax-entry ?_   "w"  st)
-    (modify-syntax-entry ?!   "w"  st)
-    (modify-syntax-entry ?.   "w"  st)
-    st)
-  "Syntax table that treats symbol characters as word characters.")
-
-;;(defmacro idlwave-with-special-syntax (&rest body)
-;;  "Execute BODY with `idlwave-find-symbol-syntax-table'."
-;;  `(with-syntax-table idlwave-find-symbol-syntax-table
-;;     ,@body))
-
-(defun idlwave-action-and-binding (key cmd &optional select)
-  "KEY and CMD are made into a key binding and an indent action.
-KEY is a string - same as for the `define-key' function.  CMD is a
-function of one argument.  CMD is bound to
-KEY in `idlwave-mode-map' by defining an anonymous function calling
-`self-insert-command' followed by CMD.  If KEY contains more than one
-character a binding will only be set if SELECT is `both'.
-
-\(KEY . CMD) is also placed in the `idlwave-indent-expand-table',
-replacing any previous value for KEY.  If a binding is not set then it
-will instead be placed in `idlwave-indent-action-table'.
-
-If the optional argument SELECT is nil then an action and binding are
-created.  If SELECT is `noaction', then a binding is always set and no
-action is created.  If SELECT is `both' then an action and binding
-will both be created even if KEY contains more than one character.
-Otherwise, if SELECT is non-nil then only an action is created.
-
-Some examples:
-No spaces before and 1 after a comma
-   (idlwave-action-and-binding \",\"  (lambda (_) (idlwave-surround 0 1)))
-A minimum of 1 space before and after `=' (see `idlwave-expand-equal').
-   (idlwave-action-and-binding \"=\"  (lambda (_) (idlwave-expand-equal -1 -1)))
-Capitalize system variables - action only
-   (idlwave-action-and-binding idlwave-sysvar
-                               (lambda (_) (capitalize-word 1) t))"
-  (if (not (equal select 'noaction))
-      ;; Add action
-      (let* ((table (if select 'idlwave-indent-action-table
-                      'idlwave-indent-expand-table))
-            (table-key (regexp-quote key)))
-        (setf (alist-get table-key (symbol-value table) nil nil #'equal) cmd)))
-  ;; Make key binding for action
-  (if (if (null select) (= (length key) 1)
-        (memq select '(noaction both)))
-      ;; FIXME: Use `post-self-insert-hook'!
-      (define-key idlwave-mode-map key
-        (lambda ()
-          (interactive)
-          (self-insert-command 1)
-          (if (functionp cmd) (funcall cmd nil) (eval cmd t))))))
-
-;; Set action and key bindings.
-;; See description of the function `idlwave-action-and-binding'.
-;; Automatically add spaces for the following characters
-
-;; Actions for & are complicated by &&
-(idlwave-action-and-binding "&" #'idlwave-custom-ampersand-surround)
-
-;; Automatically add spaces to equal sign if not keyword.  This needs
-;; to go ahead of > and <, so >= and <= will be treated correctly
-(idlwave-action-and-binding "=" (lambda (_) (idlwave-expand-equal -1 -1)))
-
-;; Actions for > and < are complicated by >=, <=, and ->...
-(idlwave-action-and-binding "<" (lambda (a) (idlwave-custom-ltgtr-surround nil a)))
-(idlwave-action-and-binding ">" (lambda (a) (idlwave-custom-ltgtr-surround t a)))
-
-(idlwave-action-and-binding "," (lambda (a) (idlwave-surround 0 -1 1 a)))
-
-
-;;;
-;;; Abbrev Section
-;;;
-;; When expanding abbrevs and the abbrev hook moves backward, an extra
-;; space is inserted (this is the space typed by the user to expanded
-;; the abbrev).
-;; FIXME: This can be controlled with `no-self-insert' property.
-;;
-(define-abbrev-table 'idlwave-mode-abbrev-table ()
-  "Abbreviation table used for IDLWAVE mode."
-  :enable-function (lambda () (not (idlwave-quoted))))
-
-(defun idlwave-define-abbrev (name expansion hook &optional noprefix table)
-  ;; FIXME: `table' is never passed.
-  "Define-abbrev with backward compatibility.
-
-If NOPREFIX is non-nil, don't prepend prefix character.  Installs into
-`idlwave-mode-abbrev-table' unless TABLE is non-nil."
-  (let ((abbrevs-changed nil)  ;; mask the current value to avoid save
-       (args (list (or table idlwave-mode-abbrev-table)
-                   (if noprefix name (concat idlwave-abbrev-start-char name))
-                   expansion
-                   hook)))
-    (condition-case nil
-       (apply #'define-abbrev (append args '(0 t)))
-      (error (apply #'define-abbrev args)))))
-
-(condition-case nil
-    (modify-syntax-entry (string-to-char idlwave-abbrev-start-char)
-                        "w" idlwave-mode-syntax-table)
-  (error nil))
-
-;;
-;; Templates
-;;
-(idlwave-define-abbrev "c"    "" #'idlwave-case)
-(idlwave-define-abbrev "sw"   "" #'idlwave-switch)
-(idlwave-define-abbrev "f"    "" #'idlwave-for)
-(idlwave-define-abbrev "fu"   "" #'idlwave-function)
-(idlwave-define-abbrev "pr"   "" #'idlwave-procedure)
-(idlwave-define-abbrev "r"    "" #'idlwave-repeat)
-(idlwave-define-abbrev "w"    "" #'idlwave-while)
-(idlwave-define-abbrev "i"    "" #'idlwave-if)
-(idlwave-define-abbrev "elif" "" #'idlwave-elif)
-;;
-;; Keywords, system functions, conversion routines
-;;
-(idlwave-define-abbrev "ap" "arg_present()" (idlwave-keyword-abbrev 1))
-(idlwave-define-abbrev "b"  "begin"        (idlwave-keyword-abbrev 0 t))
-(idlwave-define-abbrev "co" "common"       (idlwave-keyword-abbrev 0 t))
-(idlwave-define-abbrev "cb" "byte()"       (idlwave-keyword-abbrev 1))
-(idlwave-define-abbrev "cx" "fix()"        (idlwave-keyword-abbrev 1))
-(idlwave-define-abbrev "cl" "long()"       (idlwave-keyword-abbrev 1))
-(idlwave-define-abbrev "cf" "float()"      (idlwave-keyword-abbrev 1))
-(idlwave-define-abbrev "cs" "string()"     (idlwave-keyword-abbrev 1))
-(idlwave-define-abbrev "cc" "complex()"    (idlwave-keyword-abbrev 1))
-(idlwave-define-abbrev "cd" "double()"     (idlwave-keyword-abbrev 1))
-(idlwave-define-abbrev "e"  "else"         (idlwave-keyword-abbrev 0 t))
-(idlwave-define-abbrev "ec" "endcase"      #'idlwave-show-begin)
-(idlwave-define-abbrev "es" "endswitch"    #'idlwave-show-begin)
-(idlwave-define-abbrev "ee" "endelse"      #'idlwave-show-begin)
-(idlwave-define-abbrev "ef" "endfor"       #'idlwave-show-begin)
-(idlwave-define-abbrev "ei" "endif else if" #'idlwave-show-begin)
-(idlwave-define-abbrev "el" "endif else"   #'idlwave-show-begin)
-(idlwave-define-abbrev "en" "endif"        #'idlwave-show-begin)
-(idlwave-define-abbrev "er" "endrep"       #'idlwave-show-begin)
-(idlwave-define-abbrev "ew" "endwhile"     #'idlwave-show-begin)
-(idlwave-define-abbrev "g"  "goto,"        (idlwave-keyword-abbrev 0 t))
-(idlwave-define-abbrev "h"  "help,"        (idlwave-keyword-abbrev 0))
-(idlwave-define-abbrev "k"  "keyword_set()" (idlwave-keyword-abbrev 1))
-(idlwave-define-abbrev "n"  "n_elements()" (idlwave-keyword-abbrev 1))
-(idlwave-define-abbrev "on" "on_error,"    (idlwave-keyword-abbrev 0))
-(idlwave-define-abbrev "oi" "on_ioerror,"  (idlwave-keyword-abbrev 0 1))
-(idlwave-define-abbrev "ow" "openw,"       (idlwave-keyword-abbrev 0))
-(idlwave-define-abbrev "or" "openr,"       (idlwave-keyword-abbrev 0))
-(idlwave-define-abbrev "ou" "openu,"       (idlwave-keyword-abbrev 0))
-(idlwave-define-abbrev "p"  "print,"       (idlwave-keyword-abbrev 0))
-(idlwave-define-abbrev "pt" "plot,"        (idlwave-keyword-abbrev 0))
-(idlwave-define-abbrev "re" "read,"        (idlwave-keyword-abbrev 0))
-(idlwave-define-abbrev "rf" "readf,"       (idlwave-keyword-abbrev 0))
-(idlwave-define-abbrev "ru" "readu,"       (idlwave-keyword-abbrev 0))
-(idlwave-define-abbrev "rt" "return"       (idlwave-keyword-abbrev 0))
-(idlwave-define-abbrev "sc" "strcompress()" (idlwave-keyword-abbrev 1))
-(idlwave-define-abbrev "sn" "strlen()"     (idlwave-keyword-abbrev 1))
-(idlwave-define-abbrev "sl" "strlowcase()" (idlwave-keyword-abbrev 1))
-(idlwave-define-abbrev "su" "strupcase()"  (idlwave-keyword-abbrev 1))
-(idlwave-define-abbrev "sm" "strmid()"     (idlwave-keyword-abbrev 1))
-(idlwave-define-abbrev "sp" "strpos()"     (idlwave-keyword-abbrev 1))
-(idlwave-define-abbrev "st" "strput()"     (idlwave-keyword-abbrev 1))
-(idlwave-define-abbrev "sr" "strtrim()"    (idlwave-keyword-abbrev 1))
-(idlwave-define-abbrev "t"  "then"         (idlwave-keyword-abbrev 0 t))
-(idlwave-define-abbrev "u"  "until"        (idlwave-keyword-abbrev 0 t))
-(idlwave-define-abbrev "wu" "writeu,"      (idlwave-keyword-abbrev 0))
-(idlwave-define-abbrev "iap" "if arg_present() then"     (idlwave-keyword-abbrev 6))
-(idlwave-define-abbrev "ik" "if keyword_set() then" (idlwave-keyword-abbrev 6))
-(idlwave-define-abbrev "ine" "if n_elements() eq 0 then" (idlwave-keyword-abbrev 11))
-(idlwave-define-abbrev "inn" "if n_elements() ne 0 then" (idlwave-keyword-abbrev 11))
-(idlwave-define-abbrev "np" "n_params()"   (idlwave-keyword-abbrev 0))
-(idlwave-define-abbrev "s"  "size()"       (idlwave-keyword-abbrev 1))
-(idlwave-define-abbrev "wi" "widget_info()" (idlwave-keyword-abbrev 1))
-(idlwave-define-abbrev "wc" "widget_control," (idlwave-keyword-abbrev 0))
-(idlwave-define-abbrev "pv" "ptr_valid()" (idlwave-keyword-abbrev 1))
-(idlwave-define-abbrev "ipv" "if ptr_valid() then" (idlwave-keyword-abbrev 6))
-
-;; This section is reserved words only. (From IDL user manual)
-;;
-(idlwave-define-abbrev "and"        "and"       (idlwave-keyword-abbrev 0 t) t)
-(idlwave-define-abbrev "begin"      "begin"     (idlwave-keyword-abbrev 0 t) t)
-(idlwave-define-abbrev "break"      "break"     (idlwave-keyword-abbrev 0 t) t)
-(idlwave-define-abbrev "case"       "case"      (idlwave-keyword-abbrev 0 t) t)
-(idlwave-define-abbrev "common"     "common"    (idlwave-keyword-abbrev 0 t) t)
-(idlwave-define-abbrev "continue"   "continue"  (idlwave-keyword-abbrev 0 t) t)
-(idlwave-define-abbrev "do"         "do"        (idlwave-keyword-abbrev 0 t) t)
-(idlwave-define-abbrev "else"       "else"      (idlwave-keyword-abbrev 0 t) t)
-(idlwave-define-abbrev "end"        "end"       #'idlwave-show-begin-check t)
-(idlwave-define-abbrev "endcase"    "endcase"   #'idlwave-show-begin-check t)
-(idlwave-define-abbrev "endelse"    "endelse"   #'idlwave-show-begin-check t)
-(idlwave-define-abbrev "endfor"     "endfor"    #'idlwave-show-begin-check t)
-(idlwave-define-abbrev "endif"      "endif"     #'idlwave-show-begin-check t)
-(idlwave-define-abbrev "endrep"     "endrep"    #'idlwave-show-begin-check t)
-(idlwave-define-abbrev "endswitch"  "endswitch" #'idlwave-show-begin-check t)
-(idlwave-define-abbrev "endwhi"     "endwhi"    #'idlwave-show-begin-check t)
-(idlwave-define-abbrev "endwhile"   "endwhile"  #'idlwave-show-begin-check t)
-(idlwave-define-abbrev "eq"         "eq"        (idlwave-keyword-abbrev 0 t) t)
-(idlwave-define-abbrev "for"        "for"       (idlwave-keyword-abbrev 0 t) t)
-(idlwave-define-abbrev "function"   "function"  (idlwave-keyword-abbrev 0 t) t)
-(idlwave-define-abbrev "ge"         "ge"        (idlwave-keyword-abbrev 0 t) t)
-(idlwave-define-abbrev "goto"       "goto"      (idlwave-keyword-abbrev 0 t) t)
-(idlwave-define-abbrev "gt"         "gt"        (idlwave-keyword-abbrev 0 t) t)
-(idlwave-define-abbrev "if"         "if"        (idlwave-keyword-abbrev 0 t) t)
-(idlwave-define-abbrev "le"         "le"        (idlwave-keyword-abbrev 0 t) t)
-(idlwave-define-abbrev "lt"         "lt"        (idlwave-keyword-abbrev 0 t) t)
-(idlwave-define-abbrev "mod"        "mod"       (idlwave-keyword-abbrev 0 t) t)
-(idlwave-define-abbrev "ne"         "ne"        (idlwave-keyword-abbrev 0 t) t)
-(idlwave-define-abbrev "not"        "not"       (idlwave-keyword-abbrev 0 t) t)
-(idlwave-define-abbrev "of"         "of"        (idlwave-keyword-abbrev 0 t) t)
-(idlwave-define-abbrev "on_ioerror" "on_ioerror" (idlwave-keyword-abbrev 0 t) t)
-(idlwave-define-abbrev "or"         "or"        (idlwave-keyword-abbrev 0 t) t)
-(idlwave-define-abbrev "pro"        "pro"       (idlwave-keyword-abbrev 0 t) t)
-(idlwave-define-abbrev "repeat"     "repeat"    (idlwave-keyword-abbrev 0 t) t)
-(idlwave-define-abbrev "switch"     "switch"    (idlwave-keyword-abbrev 0 t) t)
-(idlwave-define-abbrev "then"       "then"      (idlwave-keyword-abbrev 0 t) t)
-(idlwave-define-abbrev "until"      "until"     (idlwave-keyword-abbrev 0 t) t)
-(idlwave-define-abbrev "while"      "while"     (idlwave-keyword-abbrev 0 t) t)
-(idlwave-define-abbrev "xor"        "xor"       (idlwave-keyword-abbrev 0 t) t)
-
-(defvar imenu-create-index-function)
-(defvar extract-index-name-function)
-(defvar prev-index-position-function)
-(defvar imenu-extract-index-name-function)
-(defvar imenu-prev-index-position-function)
-;; defined later - so just make the compiler hush
-(defvar idlwave-mode-menu)
-(defvar idlwave-mode-debug-menu)
-
-;;;###autoload
-(define-derived-mode idlwave-mode prog-mode "IDLWAVE"
-  "Major mode for editing IDL source files (version 6.1_em22).
-
-The main features of this mode are
-
-1. Indentation and Formatting
-   --------------------------
-   Like other Emacs programming modes, C-j inserts a newline and indents.
-   TAB is used for explicit indentation of the current line.
-
-   To start a continuation line, use \\[idlwave-split-line].  This
-   function can also be used in the middle of a line to split the line
-   at that point.  When used inside a long constant string, the string
-   is split at that point with the `+' concatenation operator.
-
-   Comments are indented as follows:
-
-   `;;;' Indentation remains unchanged.
-   `;;'  Indent like the surrounding code
-   `;'   Indent to a minimum column.
-
-   The indentation of comments starting in column 0 is never changed.
-
-   Use \\[idlwave-fill-paragraph] to refill a paragraph inside a
-   comment.  The indentation of the second line of the paragraph
-   relative to the first will be retained.  Use
-   \\[auto-fill-mode] to toggle auto-fill mode for these
-   comments.  When the variable `idlwave-fill-comment-line-only' is
-   nil, code can also be auto-filled and auto-indented.
-
-   To convert pre-existing IDL code to your formatting style, mark the
-   entire buffer with \\[mark-whole-buffer] and execute
-   \\[idlwave-expand-region-abbrevs].  Then mark the entire buffer
-   again followed by \\[indent-region] (`indent-region').
-
-2. Routine Info
-   ------------
-   IDLWAVE displays information about the calling sequence and the
-   accepted keyword parameters of a procedure or function with
-   \\[idlwave-routine-info].  \\[idlwave-find-module] jumps to the
-   source file of a module.  These commands know about system
-   routines, all routines in idlwave-mode buffers and (when the
-   idlwave-shell is active) about all modules currently compiled under
-   this shell.  It also makes use of pre-compiled or custom-scanned
-   user and library catalogs many popular libraries ship with by
-   default.  Use \\[idlwave-update-routine-info] to update this
-   information, which is also used for completion (see item 4).
-
-3. Online IDL Help
-   ---------------
-
-   \\[idlwave-context-help] displays the IDL documentation relevant
-   for the system variable, keyword, or routines at point.  A single
-   key stroke gets you directly to the right place in the docs.  See
-   the manual to configure where and how the HTML help is displayed.
-
-4. Completion
-   ----------
-   \\[idlwave-complete] completes the names of procedures, functions
-   class names, keyword parameters, system variables and tags, class
-   tags, structure tags, filenames and much more.  It is context
-   sensitive and figures out what is expected at point.  Lower case
-   strings are completed in lower case, other strings in mixed or
-   upper case.
-
-5. Code Templates and Abbreviations
-   --------------------------------
-   Many Abbreviations are predefined to expand to code fragments and templates.
-   The abbreviations start generally with a `\\'.  Some examples:
-
-   \\pr        PROCEDURE template
-   \\fu        FUNCTION template
-   \\c         CASE statement template
-   \\sw        SWITCH statement template
-   \\f         FOR loop template
-   \\r         REPEAT Loop template
-   \\w         WHILE loop template
-   \\i         IF statement template
-   \\elif      IF-ELSE statement template
-   \\b         BEGIN
-
-   For a full list, use \\[idlwave-list-abbrevs].  Some templates also
-   have direct keybindings - see the list of keybindings below.
-
-   \\[idlwave-doc-header] inserts a documentation header at the
-   beginning of the current program unit (pro, function or main).
-   Change log entries can be added to the current program unit with
-   \\[idlwave-doc-modification].
-
-6. Automatic Case Conversion
-   -------------------------
-   The case of reserved words and some abbrevs is controlled by
-   `idlwave-reserved-word-upcase' and `idlwave-abbrev-change-case'.
-
-7. Automatic END completion
-   ------------------------
-   If the variable `idlwave-expand-generic-end' is non-nil, each END typed
-   will be converted to the specific version, like ENDIF, ENDFOR, etc.
-
-8. Hooks
-   -----
-   Turning on `idlwave-mode' runs `idlwave-mode-hook'.
-
-9. Documentation and Customization
-   -------------------------------
-   Info documentation for this package is available.  Use
-   \\[idlwave-info] to display (complain to your sysadmin if that does
-   not work).  For Postscript, PDF, and HTML versions of the
-   documentation, check IDLWAVE's website at URL
-   `https://github.com/jdtsmith/idlwave'.
-   IDLWAVE has customize support - see the group `idlwave'.
-
-10.Keybindings
-   -----------
-   Here is a list of all keybindings of this mode.
-   If some of the key bindings below show with ??, use \\[describe-key]
-   followed by the key sequence to see what the key sequence does.
-
-\\{idlwave-mode-map}"
-  :abbrev-table idlwave-mode-abbrev-table
-  (if idlwave-startup-message
-      (message "Emacs IDLWAVE mode version %s." idlwave-mode-version))
-  (setq idlwave-startup-message nil)
-
-  (set (make-local-variable 'indent-line-function) #'idlwave-indent-and-action)
-
-  (set (make-local-variable idlwave-comment-indent-function)
-       #'idlwave-comment-hook)
-
-  (set (make-local-variable 'comment-start-skip) ";+[ \t]*")
-  (set (make-local-variable 'comment-start) ";")
-  (set (make-local-variable 'comment-add) 1) ; ";;" for new and regions
-  (set (make-local-variable 'abbrev-all-caps) t)
-  (set (make-local-variable 'indent-tabs-mode) nil)
-  (set (make-local-variable 'completion-ignore-case) t)
-
-  (setq abbrev-mode t)
-
-  (set (make-local-variable 'normal-auto-fill-function) #'idlwave-auto-fill)
-  (setq comment-end "")
-  (set (make-local-variable 'comment-multi-line) nil)
-  (set (make-local-variable 'paragraph-separate)
-       "[ \t\f]*$\\|[ \t]*;+[ \t]*$\\|;+[+=-_*]+$")
-  (set (make-local-variable 'paragraph-start) "[ \t\f]\\|[ \t]*;+[ \t]")
-  (set (make-local-variable 'paragraph-ignore-fill-prefix) nil)
-  (set (make-local-variable 'parse-sexp-ignore-comments) t)
-
-  ;; ChangeLog
-  (set (make-local-variable 'add-log-current-defun-function)
-       #'idlwave-current-routine-fullname)
-
-  ;; Set tag table list to use IDLTAGS as file name.
-  (if (boundp 'tag-table-alist)
-      (add-to-list 'tag-table-alist '("\\.pro\\'" . "IDLTAGS")))
-
-  ;; Font-lock additions
-  (set (make-local-variable 'font-lock-defaults) idlwave-font-lock-defaults)
-  (set (make-local-variable 'font-lock-mark-block-function)
-       #'idlwave-mark-subprogram)
-  (set (make-local-variable 'font-lock-fontify-region-function)
-       #'idlwave-font-lock-fontify-region)
-
-  ;; Imenu setup
-  ;;(set (make-local-variable 'imenu-create-index-function)
-  ;;     ;; FIXME: Why set it explicitly to the value it already has?
-  ;;     #'imenu-default-create-index-function)
-  (set (make-local-variable 'imenu-extract-index-name-function)
-       #'idlwave-unit-name)
-  (set (make-local-variable 'imenu-prev-index-position-function)
-       #'idlwave-prev-index-position)
-
-  ;; HideShow setup
-  (add-to-list 'hs-special-modes-alist
-              (list 'idlwave-mode
-                    idlwave-begin-block-reg
-                    idlwave-end-block-reg
-                    ";"
-                    'idlwave-forward-block nil))
-
-  ;; Make a local post-command-hook and add our hook to it
-  (add-hook 'post-command-hook #'idlwave-command-hook nil 'local)
-
-  ;; Make local hooks for buffer updates
-  (add-hook 'kill-buffer-hook #'idlwave-kill-buffer-update nil 'local)
-  (add-hook 'after-save-hook #'idlwave-save-buffer-update nil 'local)
-  (add-hook 'after-save-hook #'idlwave-revoke-license-to-kill nil 'local)
-
-  ;; Setup directories and file, if necessary
-  (idlwave-setup)
-
-  ;; Update the routine info with info about current buffer?
-  (idlwave-new-buffer-update)
-
-  ;; Check help location
-  (idlwave-help-check-locations))
-
-(defvar idlwave-setup-done nil)
-(defun idlwave-setup ()
-  (unless idlwave-setup-done
-    (if (not (file-directory-p idlwave-config-directory))
-       (make-directory idlwave-config-directory))
-    (setq
-     idlwave-user-catalog-file (expand-file-name
-                               idlwave-user-catalog-file
-                               idlwave-config-directory)
-     idlwave-xml-system-rinfo-converted-file
-     (expand-file-name
-      idlwave-xml-system-rinfo-converted-file
-      idlwave-config-directory)
-     idlwave-path-file (expand-file-name
-                       idlwave-path-file
-                       idlwave-config-directory))
-    (idlwave-read-paths)  ; we may need these early
-    (setq idlwave-setup-done t)))
-
-(defun idlwave-font-lock-fontify-region (beg end &optional verbose)
-  "Fontify continuation lines correctly."
-  (let (pos)
-    (save-excursion
-      (goto-char beg)
-      (forward-line -1)
-      (when (setq pos (idlwave-is-continuation-line))
-       (goto-char pos)
-       (idlwave-beginning-of-statement)
-       (setq beg (point)))))
-  (font-lock-default-fontify-region beg end verbose))
-
-;;
-;; Code Formatting ----------------------------------------------------
-;;
-
-(defun idlwave-hard-tab ()
-  "Insert TAB in buffer in current position."
-  (interactive)
-  (insert "\t"))
-
-;;; This stuff is experimental
-
-(defvar idlwave--command-function nil
-  "If non-nil, a function called from `post-command-hook'.
-It is evaluated in the Lisp function `idlwave-command-hook' which is
-placed in `post-command-hook'.")
-
-(defun idlwave-command-hook ()
-  "Command run after every command.
-Evaluates a non-nil value of the *variable* `idlwave--command-function' and
-sets the variable to zero afterwards."
-  (and idlwave--command-function
-       (with-demoted-errors "idlwave-command-hook: %S"
-        (funcall (prog1 idlwave--command-function
-                   (setq idlwave--command-function nil))))))
-
-;;; End experiment
-
-;; It would be better to use expand.el for better abbrev handling and
-;; versatility.
-
-(defun idlwave-modify-abbrev (arg &optional reserved)
-  "Tweak the abbrev we just expanded.
-Argument ARG is the number of characters to move point
-backward if `idlwave-abbrev-move' is non-nil.
-If optional argument RESERVED is non-nil then the expansion
-consists of reserved words, which will be capitalized if
-`idlwave-reserved-word-upcase' is non-nil.
-Otherwise, the abbrev will be capitalized if `idlwave-abbrev-change-case'
-is non-nil, unless its value is `down' in which case the abbrev will be
-made into all lowercase.
-Returns non-nil if abbrev is left expanded."
-  (if (and reserved idlwave-reserved-word-upcase)
-      (upcase-region last-abbrev-location (point))
-    (cond
-     ((equal idlwave-abbrev-change-case 'down)
-      (downcase-region last-abbrev-location (point)))
-     (idlwave-abbrev-change-case
-      (upcase-region last-abbrev-location (point)))))
-  (if (and idlwave-abbrev-move (> arg 0))
-      (setq idlwave--command-function (lambda () (backward-char (1+ arg)))))
-  t)
-
-(defun idlwave-in-comment ()
-  "Return t if point is inside a comment, nil otherwise."
-  (save-excursion
-    (let ((here (point)))
-      (and (idlwave-goto-comment) (> here (point))))))
-
-(defun idlwave-goto-comment ()
-  "Move to start of comment delimiter on current line.
-Moves to end of line if there is no comment delimiter.
-Ignores comment delimiters in strings.
-Returns point if comment found and nil otherwise."
-  (let ((eos (line-end-position))
-        (data (match-data))
-        found)
-    ;; Look for first comment delimiter not in a string
-    (beginning-of-line)
-    (setq found (search-forward comment-start eos 'lim))
-    (while (and found (idlwave-in-quote))
-      (setq found (search-forward comment-start eos 'lim)))
-    (store-match-data data)
-    (and found (not (idlwave-in-quote))
-         (progn
-           (backward-char 1)
-           (point)))))
-
-(define-obsolete-function-alias 'idlwave-region-active-p #'use-region-p "28.1")
-
-(defun idlwave-show-matching-quote ()
-  "Insert quote and show matching quote if this is end of a string."
-  (interactive)
-  (let ((bq (idlwave-in-quote))
-        (inq last-command-event))
-    (if (and bq (not (idlwave-in-comment)))
-        (let ((delim (char-after bq)))
-          (insert inq)
-          (if (eq inq delim)
-              (save-excursion
-                (goto-char bq)
-                (sit-for 1))))
-      ;; Not the end of a string
-      (insert inq))))
-
-(defun idlwave-show-begin-check ()
-  "Ensure that the previous word was a token before `idlwave-show-begin'.
-An END token must be preceded by whitespace."
-  (if
-      (save-excursion
-       (backward-word-strictly 1)
-       (backward-char 1)
-       (looking-at "[ \t\n\f]"))
-      (idlwave-show-begin)))
-
-(defun idlwave-show-begin ()
-  "Find the start of current block and blinks to it for a second.
-Also checks if the correct END statement has been used."
-  ;; All end statements are reserved words
-  ;; Re-indent end line
-  ;;(insert-char ?\  1) ;; So indent, etc. work well
-  ;;(backward-char 1)
-  (let* ((pos (point-marker))
-        (last-abbrev-marker (copy-marker last-abbrev-location))
-         (eol-pos (line-end-position))
-        begin-pos end-pos end end1 )
-    (if idlwave-reindent-end  (idlwave-indent-line))
-    (setq last-abbrev-location (marker-position last-abbrev-marker))
-    (when (and (idlwave-modify-abbrev 0 t)
-              idlwave-show-block)
-      (save-excursion
-       ;; Move inside current block
-       (goto-char last-abbrev-marker)
-       (idlwave-block-jump-out -1 'nomark)
-       (setq begin-pos (point))
-       (idlwave-block-jump-out 1 'nomark)
-       (setq end-pos (point))
-       (if (> end-pos eol-pos)
-           (setq end-pos pos))
-       (goto-char end-pos)
-       (setq end (buffer-substring
-                  (progn
-                    (skip-chars-backward "a-zA-Z")
-                    (point))
-                  end-pos))
-       (goto-char begin-pos)
-       (when (setq end1 (cdr (idlwave-block-master)))
-         (cond
-          ((null end1)) ; no-operation
-          ((string= (downcase end) (downcase end1))
-           (sit-for 1))
-          ((string= (downcase end) "end")
-           ;; A generic end
-           (if idlwave-expand-generic-end
-               (save-excursion
-                 (goto-char pos)
-                 (backward-char 3)
-                 (insert (if (string= end "END") (upcase end1) end1))
-                 (delete-char 3)))
-           (sit-for 1))
-          (t
-           (beep)
-           (message "Warning: Shouldn't this be \"%s\" instead of \"%s\"?"
-                    end1 end)
-           (sit-for 1))))))))
-  ;;(delete-char 1))
-
-(defun idlwave-block-master ()
-  (let ((case-fold-search t))
-    (save-excursion
-      (cond
-       ((looking-at "pro\\|case\\|switch\\|function\\>")
-       (assoc (downcase (match-string 0)) idlwave-block-matches))
-       ((looking-at "begin\\>")
-       (let ((limit (save-excursion
-                      (idlwave-beginning-of-statement)
-                      (point))))
-         (cond
-          ((re-search-backward ":[ \t]*\\=" limit t)
-           ;; seems to be a case thing
-           '("begin" . "end"))
-          ((re-search-backward idlwave-block-match-regexp limit t)
-           (assoc (downcase (match-string 1))
-                  idlwave-block-matches))
-          (t
-           ;; Just a normal block
-           '("begin" . "end")))))
-       (t nil)))))
-
-(defun idlwave-close-block ()
-  "Terminate the current block with the correct END statement."
-  (interactive)
-  ;; Start new line if we are not in a new line
-  (unless (save-excursion
-           (skip-chars-backward " \t")
-           (bolp))
-    (let ((idlwave-show-block nil))
-      (newline-and-indent)))
-  (let ((last-abbrev-location (point)))  ; for upcasing
-    (insert "end")
-    (idlwave-show-begin)))
-
-(defun idlwave-custom-ampersand-surround (&optional is-action)
-  "Surround &, leaving room for && (which surround as well)."
-  (let* ((prev-char (char-after (- (point) 2)))
-        (next-char (char-after (point)))
-        (amp-left (eq prev-char ?&))
-        (amp-right (eq next-char ?&))
-        (len (if amp-left 2 1)))
-    (unless amp-right ;no need to do it twice, amp-left will catch it.
-      (idlwave-surround -1 (if (or is-action amp-left) -1) len))))
-
-(defun idlwave-custom-ltgtr-surround (gtr &optional is-action)
-  "Surround > and < by blanks, leaving room for >= and <=, and considering ->."
-  (let* ((prev-char (char-after (- (point) 2)))
-       (next-char (char-after (point)))
-       (method-invoke (and gtr (eq prev-char ?-)))
-       (len (if method-invoke 2 1)))
-    (unless (eq next-char ?=)
-      ;; Key binding: pad only on left, to save for possible >=/<=
-      (idlwave-surround -1 (if (or is-action method-invoke) -1) len))))
-
-(defun idlwave-surround (&optional before after length _is-action)
-  "Surround the LENGTH characters before point with blanks.
-LENGTH defaults to 1.
-Optional arguments BEFORE and AFTER affect the behavior before and
-after the characters (see also description of `idlwave-make-space'):
-
-nil            do nothing
-0              force no spaces
-integer > 0    force exactly n spaces
-integer < 0    at least |n| spaces
-
-The function does nothing if any of the following conditions is true:
-- `idlwave-surround-by-blank' is nil
-- the character before point is inside a string or comment"
-  (when (and idlwave-surround-by-blank (not (idlwave-quoted)))
-    (let ((length (or length 1))) ; establish a default for LENGTH
-      (backward-char length)
-      (save-restriction
-       (let ((here (point)))
-         (skip-chars-backward " \t")
-         (if (bolp)
-             ;; avoid clobbering indent
-             (progn
-               (move-to-column (idlwave-calculate-indent))
-               (if (<= (point) here)
-                   (narrow-to-region (point) here))
-               (goto-char here)))
-         (idlwave-make-space before))
-       (skip-chars-forward " \t"))
-      (forward-char length)
-      (idlwave-make-space after)
-      ;; Check to see if the line should auto wrap
-      (if (and (equal (char-after (1- (point))) ?\ )
-              (> (current-column) fill-column))
-         (funcall auto-fill-function)))))
-
-(defun idlwave-make-space (n)
-  "Make space at point.
-The space affected is all the spaces and tabs around point.
-If n is non-nil then point is left abs(n) spaces from the beginning of
-the contiguous space.
-The amount of space at point is determined by N.
-If the value of N is:
-nil   - do nothing.
-> 0   - exactly N spaces.
-< 0   - a minimum of -N spaces, i.e., do not change if there are
-        already -N spaces.
-0     - no spaces (i.e. remove any existing space)."
-  (if (integerp n)
-      (let
-          ((start-col (progn (skip-chars-backward " \t") (current-column)))
-           (left (point))
-           (end-col (progn (skip-chars-forward " \t") (current-column))))
-        (delete-horizontal-space)
-        (cond
-         ((> n 0)
-          (idlwave-indent-to (+ start-col n))
-          (goto-char (+ left n)))
-         ((< n 0)
-          (idlwave-indent-to end-col (- n))
-          (goto-char (- left n)))
-         ;; n = 0, done
-         ))))
-
-(defun idlwave-newline ()
-  "Insert a newline and indent the current and previous line."
-  (interactive)
-  ;;
-  ;; Handle unterminated single and double quotes
-  ;; If not in a comment and in a string then insertion of a newline
-  ;; will mean unbalanced quotes.
-  ;;
-  (if (and (not (idlwave-in-comment)) (idlwave-in-quote))
-      (progn (beep)
-             (message "Warning: unbalanced quotes?")))
-  (newline)
-  ;;
-  ;; The current line is being split, the cursor should be at the
-  ;; beginning of the new line skipping the leading indentation.
-  ;;
-  ;; The reason we insert the new line before indenting is that the
-  ;; indenting could be confused by keywords (e.g. END) on the line
-  ;; after the split point.  This prevents us from just using
-  ;; `indent-for-tab-command' followed by `newline-and-indent'.
-  ;;
-  (beginning-of-line 0)
-  (idlwave-indent-line)
-  (forward-line)
-  (idlwave-indent-line))
-
-;;
-;;  Use global variable 'comment-column' to set parallel comment
-;;
-;; Modeled on lisp.el
-;; Emacs Lisp and IDL (Wave CL) have identical comment syntax
-(defun idlwave-comment-hook ()
-  "Compute indent for the beginning of the IDL comment delimiter."
-  (if (or (looking-at idlwave-no-change-comment)
-          (looking-at (or idlwave-begin-line-comment "^;")))
-      (current-column)
-    (if (looking-at idlwave-code-comment)
-        (if (save-excursion (skip-chars-backward " \t") (bolp))
-            ;; On line by itself, indent as code
-            (let ((tem (idlwave-calculate-indent)))
-              (if (listp tem) (car tem) tem))
-          ;; after code - do not change
-          (current-column))
-      (skip-chars-backward " \t")
-      (max (if (bolp) 0 (1+ (current-column)))
-           comment-column))))
-
-(defun idlwave-split-line ()
-  "Continue line by breaking line at point and indent the lines.
-For a code line insert continuation marker.  If the line is a line comment
-then the new line will contain a comment with the same indentation.
-Splits strings with the IDL operator `+' if `idlwave-split-line-string' is
-non-nil."
-  (interactive)
-  ;; Expand abbreviation, just like normal RET would.
-  (and abbrev-mode (expand-abbrev))
-  (let (beg)
-    (if (not (idlwave-in-comment))
-        ;; For code line add continuation.
-        ;; Check if splitting a string.
-        (progn
-          (if (setq beg (idlwave-in-quote))
-              (if idlwave-split-line-string
-                  ;; Split the string.
-                  (progn (insert (setq beg (char-after beg)) " + "
-                                 idlwave-continuation-char beg)
-                         (backward-char 1)
-                        (newline-and-indent)
-                        (forward-char 1))
-                ;; Do not split the string.
-                (beep)
-                (message "Warning: continuation inside string!!")
-                (insert " " idlwave-continuation-char))
-            ;; Not splitting a string.
-           (if (not (member (char-before) '(?\  ?\t)))
-               (insert " "))
-            (insert idlwave-continuation-char)
-           (newline-and-indent)))
-      (indent-new-comment-line))
-    ;; Indent previous line
-    (setq beg (- (point-max) (point)))
-    (forward-line -1)
-    (idlwave-indent-line)
-    (goto-char (- (point-max) beg))
-    ;; Reindent new line
-    (idlwave-indent-line)))
-
-(defun idlwave-beginning-of-subprogram (&optional nomark)
-  "Move point to the beginning of the current program unit.
-If NOMARK is non-nil, do not push mark."
-  (interactive)
-  (idlwave-find-key idlwave-begin-unit-reg -1 nomark))
-
-(defun idlwave-end-of-subprogram (&optional nomark)
-  "Move point to the start of the next program unit.
-If NOMARK is non-nil, do not push mark."
-  (interactive)
-  (idlwave-end-of-statement)
-  (idlwave-find-key idlwave-end-unit-reg 1 nomark))
-
-(defun idlwave-mark-statement ()
-  "Mark current IDL statement."
-  (interactive)
-  (idlwave-end-of-statement)
-  (let ((end (point)))
-    (idlwave-beginning-of-statement)
-    (push-mark end nil t)))
-
-(defun idlwave-mark-block ()
-  "Mark containing block."
-  (interactive)
-  (idlwave-end-of-statement)
-  (idlwave-backward-up-block -1)
-  (idlwave-end-of-statement)
-  (let ((end (point)))
-    (idlwave-backward-block)
-    (idlwave-beginning-of-statement)
-    (push-mark end nil t)))
-
-
-(defun idlwave-mark-subprogram ()
-  "Put mark at beginning of program, point at end.
-The marks are pushed."
-  (interactive)
-  (idlwave-end-of-statement)
-  (idlwave-beginning-of-subprogram)
-  (let ((beg (point)))
-    (idlwave-forward-block)
-    (push-mark beg nil t))
-  (exchange-point-and-mark))
-
-(defun idlwave-backward-up-block (&optional arg)
-  "Move to beginning of enclosing block if prefix ARG >= 0.
-If prefix ARG < 0 then move forward to enclosing block end."
-  (interactive "p")
-  (idlwave-block-jump-out (- arg) 'nomark))
-
-(defun idlwave-beginning-of-block ()
-  "Go to the beginning of the current block."
-  (interactive)
-  (idlwave-block-jump-out -1 'nomark)
-  (forward-word-strictly 1))
-
-(defun idlwave-end-of-block ()
-  "Go to the beginning of the current block."
-  (interactive)
-  (idlwave-block-jump-out 1 'nomark)
-  (backward-word-strictly 1))
-
-(defun idlwave-forward-block (&optional arg)
-  "Move across next nested block."
-  (interactive)
-  (let ((arg (or arg 1)))
-    (if (idlwave-down-block arg)
-       (idlwave-block-jump-out arg 'nomark))))
-
-(defun idlwave-backward-block ()
-  "Move backward across previous nested block."
-  (interactive)
-  (if (idlwave-down-block -1)
-      (idlwave-block-jump-out -1 'nomark)))
-
-(defun idlwave-down-block (&optional arg)
-  "Go down a block.
-With ARG: ARG >= 0 go forwards, ARG < 0 go backwards.
-Returns non-nil if successful."
-  (interactive "p")
-  (let (status)
-    (if (< arg 0)
-        ;; Backward
-        (let ((eos (save-excursion
-                     (idlwave-block-jump-out -1 'nomark)
-                     (point))))
-          (if (setq status (idlwave-find-key
-                           idlwave-end-block-reg -1 'nomark eos))
-              (idlwave-beginning-of-statement)
-            (message "No nested block before beginning of containing block.")))
-      ;; Forward
-      (let ((eos (save-excursion
-                   (idlwave-block-jump-out 1 'nomark)
-                   (point))))
-        (if (setq status (idlwave-find-key
-                         idlwave-begin-block-reg 1 'nomark eos))
-            (idlwave-end-of-statement)
-          (message "No nested block before end of containing block."))))
-    status))
-
-(defun idlwave-mark-doclib ()
-  "Put point at beginning of doc library header, mark at end.
-The marks are pushed."
-  (interactive)
-  (let (beg
-        (here (point)))
-    (goto-char (point-max))
-    (if (re-search-backward idlwave-doclib-start nil t)
-        (progn
-         (setq beg (progn (beginning-of-line) (point)))
-         (if (re-search-forward idlwave-doclib-end nil t)
-             (progn
-               (forward-line 1)
-               (push-mark beg nil t)
-               (message "Could not find end of doc library header.")))
-         (message "Could not find doc library header start.")
-         (goto-char here)))))
-
-(defun idlwave-current-routine-fullname ()
-  (let ((name (idlwave-current-routine)))
-    (idlwave-make-full-name (nth 2 name) (car name))))
-
-(defun idlwave-current-routine ()
-  "Return (NAME TYPE CLASS) of current routine."
-  (idlwave-routines)
-  (save-excursion
-    (idlwave-beginning-of-subprogram 'nomark)
-    (if (looking-at "[ \t]*\\<\\(pro\\|function\\)\\>\\s-+\\(\\([a-zA-Z0-9$_]+\\)::\\)?\\([a-zA-Z0-9$_]+\\)")
-       (let* ((type (if (string= (downcase (match-string 1)) "pro")
-                        'pro 'function))
-              (class (idlwave-sintern-class (match-string 3)))
-              (name (idlwave-sintern-routine-or-method (match-string 4) class)))
-         (list name type class)))))
-
-(defvar idlwave-shell-prompt-pattern)
-(defun idlwave-beginning-of-statement ()
-  "Move to beginning of the current statement.
-Skips back past statement continuations.
-Point is placed at the beginning of the line whether or not this is an
-actual statement."
-  (interactive)
-  (cond
-   ((derived-mode-p 'idlwave-shell-mode)
-    (if (re-search-backward idlwave-shell-prompt-pattern nil t)
-       (goto-char (match-end 0))))
-   (t
-    (if (save-excursion (forward-line -1) (idlwave-is-continuation-line))
-       (idlwave-previous-statement)
-      (beginning-of-line)))))
-
-(defun idlwave-previous-statement ()
-  "Move point to beginning of the previous statement.
-Returns t if the current line before moving is the beginning of
-the first non-comment statement in the file, and nil otherwise."
-  (interactive)
-  (let (first-statement)
-    (if (not (= (forward-line -1) 0))
-        ;; first line in file
-        t
-      ;; skip blank lines, label lines, include lines and line comments
-      (while (and
-              ;; The current statement is the first statement until we
-              ;; reach another statement.
-              (setq first-statement
-                    (or
-                     (looking-at idlwave-comment-line-start-skip)
-                     (looking-at "[ \t]*$")
-                     (looking-at (concat "[ \t]*" idlwave-label "[ \t]*$"))
-                     (looking-at "^@")))
-              (= (forward-line -1) 0)))
-      ;; skip continuation lines
-      (while (and
-              (save-excursion
-                (forward-line -1)
-                (idlwave-is-continuation-line))
-              (= (forward-line -1) 0)))
-      first-statement)))
-
-(defun idlwave-end-of-statement ()
-  "Move point to the end of the current IDL statement.
-If not in a statement just moves to end of line.  Returns position."
-  (interactive)
-  (while (and (idlwave-is-continuation-line)
-              (= (forward-line 1) 0))
-    (while (and (idlwave-is-comment-or-empty-line)
-               (= (forward-line 1) 0))))
-  (end-of-line)
-  (point))
-
-(defun idlwave-end-of-statement0 ()
-  "Move point to the end of the current IDL statement.
-If not in a statement just moves to end of line.  Returns position."
-  (interactive)
-  (while (and (idlwave-is-continuation-line)
-              (= (forward-line 1) 0)))
-  (end-of-line)
-  (point))
-
-(defun idlwave-next-statement ()
-  "Move point to beginning of the next IDL statement.
-Returns t if that statement is the last non-comment IDL statement
-in the file, and nil otherwise."
-  (interactive)
-  (let (last-statement)
-    (idlwave-end-of-statement)
-    ;; skip blank lines, label lines, include lines and line comments
-    (while (and (= (forward-line 1) 0)
-                ;; The current statement is the last statement until
-                ;; we reach a new statement.
-                (setq last-statement
-                      (or
-                       (looking-at idlwave-comment-line-start-skip)
-                       (looking-at "[ \t]*$")
-                       (looking-at (concat "[ \t]*" idlwave-label "[ \t]*$"))
-                       (looking-at "^@")))))
-    last-statement))
-
-(defun idlwave-skip-multi-commands (&optional lim)
-  "Skip past multiple commands on a line (with `&')."
-  (let ((save-point (point)))
-    (when (re-search-forward ".*&" lim t)
-      (goto-char (match-end 0))
-      (if (idlwave-quoted)
-         (goto-char save-point)
-       (if (eq (char-after (- (point) 2)) ?&) (goto-char save-point))))
-    (point)))
-
-(defun idlwave-skip-label-or-case ()
-  "Skip label or case statement element.
-Returns position after label.
-If there is no label point is not moved and nil is returned."
-  ;; Case expressions and labels are terminated by a colon.
-  ;; So we find the first colon in the line and make sure
-  ;; - no `?' is before it (might be a ? b : c)
-  ;; - it is not in a comment
-  ;; - not in a string constant
-  ;; - not in parenthesis (like a[0:3])
-  ;; - not followed by another ":" in explicit class, ala a->b::c
-  ;; As many in this mode, this function is heuristic and not an exact
-  ;; parser.
-  (let* ((start (point))
-        (eos (save-excursion (idlwave-end-of-statement) (point)))
-        (end (idlwave-find-key ":" 1 'nomark eos)))
-    (if (and end
-             (= (nth 0 (parse-partial-sexp start end)) 0)
-            (not (string-search "?" (buffer-substring start end)))
-            (not (string-match "^::" (buffer-substring end eos))))
-        (progn
-          (forward-char)
-          (point))
-      (goto-char start)
-      nil)))
-
-(defun idlwave-start-of-substatement (&optional pre)
-  "Move to start of next IDL substatement after point.
-Uses the type of the current IDL statement to determine if the next
-statement is on a new line or is a subpart of the current statement.
-Returns point at start of substatement modulo whitespace.
-If optional argument is non-nil move to beginning of current
-substatement."
-  (let ((orig (point))
-        (eos (idlwave-end-of-statement))
-        (ifnest 0)
-        st nst last)
-    (idlwave-beginning-of-statement)
-    (idlwave-skip-label-or-case)
-    (if (< (point) orig)
-       (idlwave-skip-multi-commands orig))
-    (setq last (point))
-    ;; Continue looking for substatements until we are past orig
-    (while (and (<= (point) orig) (not (eobp)))
-      (setq last (point))
-      (setq nst (nth 1 (cdr (setq st (car (idlwave-statement-type))))))
-      (if (equal (car st) 'if) (setq ifnest (1+ ifnest)))
-      (cond ((and nst
-                  (idlwave-find-key nst 1 'nomark eos))
-             (goto-char (match-end 0)))
-            ((and (> ifnest 0) (idlwave-find-key "\\<else\\>" 1 'nomark eos))
-             (setq ifnest (1- ifnest))
-             (goto-char (match-end 0)))
-            (t (setq ifnest 0)
-               (idlwave-next-statement))))
-    (if pre (goto-char last))
-    ;; If a continuation line starts here, move to next line
-    (if (looking-at "[ \t]*\\$\\([ \t]*\\(;\\|$\\)\\)")
-       (beginning-of-line 2))
-    (point)))
-
-(defun idlwave-statement-type ()
-  "Return the type of the current IDL statement.
-Uses `idlwave-statement-match' to return a cons of (type . point) with
-point the ending position where the type was determined.  Type is the
-association from `idlwave-statement-match', i.e. the cons cell from the
-list not just the type symbol.  Returns nil if not an identifiable
-statement."
-  (save-excursion
-    ;; Skip whitespace within a statement which is spaces, tabs, continuations
-    ;; and possibly comments
-    (while (looking-at "[ \t]*\\$")
-      (forward-line 1))
-    (skip-chars-forward " \t")
-    (let ((st idlwave-statement-match)
-          (case-fold-search t))
-      (while (and (not (looking-at (nth 0 (cdr (car st)))))
-                  (setq st (cdr st))))
-      (if st
-          (append st (match-end 0))))))
-
-(defun idlwave-expand-equal (&optional before after _is-action)
-  "Pad `=' with spaces.
-Two cases: Assignment statement, and keyword assignment.
-Which case is determined using `idlwave-start-of-substatement' and
-`idlwave-statement-type'.  The equal sign will be surrounded by BEFORE
-and AFTER blanks.  If `idlwave-pad-keyword' is t then keyword assignment
-is treated just like assignment statements.  When nil, spaces are
-removed for keyword assignment.  Any other value keeps the current space
-around the `='.  Limits in for loops are treated as keyword assignment.
-
-Starting with IDL 6.0, a number of op= assignments are available.
-Since ambiguities of the form:
-
-r and= b
-rand= b
-
-can occur, alphanumeric operator assignment will never be pre-padded,
-only post-padded.  You must use a space before these to disambiguate
-\(not just for padding, but for proper parsing by IDL too!).  Other
-operators, such as ##=, ^=, etc., will be pre-padded.
-
-IS-ACTION is ignored.
-
-See `idlwave-surround'."
-  (if idlwave-surround-by-blank
-      (let
-         ((non-an-ops "\\(##\\|\\*\\|\\+\\|-\\|/\\|<\\|>\\|\\^\\)\\=")
-          (an-ops
-           "\\s-\\(AND\\|EQ\\|GE\\|GT\\|LE\\|LT\\|MOD\\|NE\\|OR\\|XOR\\)\\=")
-          (len 1))
-
-       (save-excursion
-         (let ((case-fold-search t))
-           (backward-char)
-           (if (or
-                (re-search-backward non-an-ops nil t)
-                ;; Why doesn't ##? work for both?
-                (re-search-backward "\\(#\\)\\=" nil t))
-               (setq len (1+ (length (match-string 1))))
-             (when (re-search-backward an-ops nil t)
-               ;(setq begin nil) ; won't modify begin
-               (setq len (1+ (length (match-string 1))))))))
-
-       (if (eq t idlwave-pad-keyword)
-           ;; Everything gets padded equally
-           (idlwave-surround before after len)
-         ;; Treating keywords/for variables specially...
-         (let ((st (save-excursion   ; To catch "for" variables
-                     (idlwave-start-of-substatement t)
-                     (idlwave-statement-type)))
-               (what (save-excursion ; To catch keywords
-                       (skip-chars-backward "= \t")
-                       (nth 2 (idlwave-where)))))
-           (cond ((or (memq what '(function-keyword procedure-keyword))
-                      (memq (caar st) '(for pdef)))
-                  (cond
-                   ((null idlwave-pad-keyword)
-                    (idlwave-surround 0 0)
-                    ) ; remove space
-                   (t))) ; leave any spaces alone
-                 (t (idlwave-surround before after len))))))))
-
-
-(defun idlwave-indent-and-action (&optional arg)
-  "Call `idlwave-indent-line' and do expand actions.
-With prefix ARG non-nil, indent the entire sub-statement."
-  (interactive "p")
-  (save-excursion
-    (if        (and idlwave-expand-generic-end
-            (re-search-backward "\\<\\(end\\)\\s-*\\="
-                                (max 0 (- (point) 10)) t)
-            (looking-at "\\(end\\)\\([ \n\t]\\|\\'\\)"))
-       (progn (goto-char (match-end 1))
-              ;;Expand the END abbreviation, just as RET or Space would have.
-              (if abbrev-mode (expand-abbrev)
-                (idlwave-show-begin)))))
-  (when (and (not arg) current-prefix-arg)
-    (setq arg current-prefix-arg)
-    (setq current-prefix-arg nil))
-  (if arg
-      (idlwave-indent-statement)
-    (idlwave-indent-line t)))
-
-(defun idlwave-indent-line (&optional expand)
-  "Indent current IDL line as code or as a comment.
-The actions in `idlwave-indent-action-table' are performed.
-If the optional argument EXPAND is non-nil then the actions in
-`idlwave-indent-expand-table' are performed."
-  (interactive)
-  ;; Move point out of left margin.
-  (if (save-excursion
-        (skip-chars-backward " \t")
-        (bolp))
-      (skip-chars-forward " \t"))
-  (let ((mloc (point-marker)))
-    (save-excursion
-      (beginning-of-line)
-      (if (looking-at idlwave-comment-line-start-skip)
-          ;; Indentation for a line comment
-          (progn
-            (skip-chars-forward " \t")
-            (idlwave-indent-left-margin (idlwave-comment-hook)))
-        ;;
-        ;; Code Line
-        ;;
-        ;; Before indenting, run action routines.
-        ;;
-        (if (and expand idlwave-do-actions)
-            (mapc #'idlwave-do-action idlwave-indent-expand-table))
-        ;;
-        (if idlwave-do-actions
-            (mapc #'idlwave-do-action idlwave-indent-action-table))
-        ;;
-        ;; No longer expand abbrevs on the line.  The user can do this
-        ;; manually using expand-region-abbrevs.
-        ;;
-        ;; Indent for code line
-        ;;
-        (beginning-of-line)
-        (if (or
-             ;; a label line
-             (looking-at (concat "^" idlwave-label "[ \t]*$"))
-             ;; a batch command
-             (looking-at "^[ \t]*@"))
-            ;; leave flush left
-            nil
-          ;; indent the line
-          (idlwave-indent-left-margin (idlwave-calculate-indent)))
-        ;; Adjust parallel comment
-       (end-of-line)
-       (if (idlwave-in-comment)
-            (let ((fill-column (1- (frame-width))))
-             (indent-for-comment)))))
-    (goto-char mloc)
-    ;; Get rid of marker
-    (set-marker mloc nil)))
-
-(defun idlwave-do-action (action)
-  "Perform an action repeatedly on a line.
-ACTION is a list (REG . FUNC).  REG is a regular expression.  FUNC is
-either a function which will be called with one argument `is-action' or
-a list to be evaluated with `eval'.
-The action performed by FUNC should leave point after the match for REG
-- otherwise an infinite loop may be entered.
-FUNC is always passed a final argument of `is-action', so it
-can discriminate between being run as an action, or a key binding."
-  (let ((action-key (car action))
-        (action-routine (cdr action)))
-    (beginning-of-line)
-    (while (idlwave-look-at action-key)
-      (if (functionp action-routine)
-          (funcall action-routine 'is-action)
-        (eval (append action-routine '('is-action)) t)))))
-
-(defun idlwave-indent-to (col &optional min)
-  "Indent from point with spaces until column COL.
-Inserts space before markers at point."
-  (if (not min) (setq min 0))
-  (insert-before-markers
-   (make-string (max min (- col (current-column))) ?\ )))
-
-(defun idlwave-indent-left-margin (col)
-  "Indent the current line to column COL.
-Indents such that first non-whitespace character is at column COL
-Inserts spaces before markers at point."
-  (save-excursion
-    (beginning-of-line)
-    (delete-horizontal-space)
-    (idlwave-indent-to col)))
-
-(defun idlwave-indent-subprogram ()
-  "Indent program unit which contains point."
-  (interactive)
-  (save-excursion
-    (idlwave-end-of-statement)
-    (idlwave-beginning-of-subprogram)
-    (let ((beg (point)))
-      (idlwave-forward-block)
-      (message "Indenting subprogram...")
-      (indent-region beg (point) nil))
-    (message "Indenting subprogram...done.")))
-
-(defun idlwave-indent-statement ()
-  "Indent current statement, including all continuation lines."
-  (interactive)
-  (save-excursion
-    (idlwave-beginning-of-statement)
-    (let ((beg (point)))
-      (idlwave-end-of-statement)
-      (indent-region beg (point) nil))))
-
-(defun idlwave-calculate-indent ()
-  "Return appropriate indentation for current line as IDL code."
-  (save-excursion
-    (beginning-of-line)
-    (cond
-     ;; Check for beginning of unit - main (beginning of buffer), pro, or
-     ;; function
-     ((idlwave-look-at idlwave-begin-unit-reg)
-      0)
-     ;; Check for continuation line
-     ((save-excursion
-        (and (= (forward-line -1) 0)
-             (idlwave-is-continuation-line)))
-      (idlwave-calculate-cont-indent))
-     ;; calculate indent based on previous and current statements
-     (t (let* (beg-prev-pos
-              (the-indent
-               ;; calculate indent based on previous statement
-               (save-excursion
-                 (cond
-                  ;; Beginning of file
-                  ((prog1
-                       (idlwave-previous-statement)
-                     (setq beg-prev-pos (point)))
-                   0)
-                  ;; Main block
-                  ((idlwave-look-at idlwave-begin-unit-reg t)
-                   (+ (idlwave-current-statement-indent)
-                      idlwave-main-block-indent))
-                  ;; Begin block
-                  ((idlwave-look-at idlwave-begin-block-reg t)
-                   (+ (idlwave-min-current-statement-indent)
-                      idlwave-block-indent))
-                  ;; End Block
-                  ((idlwave-look-at idlwave-end-block-reg t)
-                   (progn
-                     ;; Match to the *beginning* of the block opener
-                     (goto-char beg-prev-pos)
-                     (idlwave-block-jump-out -1 'nomark) ; go to begin block
-                     (idlwave-min-current-statement-indent)))
-                     ;;                      idlwave-end-offset
-                     ;;                      idlwave-block-indent))
-
-                  ;; Default to current indent
-                  ((idlwave-current-statement-indent))))))
-          ;; adjust the indentation based on the current statement
-          (cond
-           ;; End block
-           ((idlwave-look-at idlwave-end-block-reg)
-           (+ the-indent idlwave-end-offset))
-           (the-indent)))))))
-
-;;
-;; Parentheses indent
-;;
-
-(defun idlwave-calculate-paren-indent (beg-reg end-reg close-exp)
-  "Calculate the continuation indent inside a paren group.
-Returns a cons-cell with (open . indent), where open is the
-location of the open paren."
-  (let ((open (nth 1 (parse-partial-sexp beg-reg end-reg))))
-    ;; Found an innermost open paren.
-    (when open
-      (goto-char open)
-      ;; Line up with next word unless this is a closing paren.
-      (cons open
-           (cond
-            ;; Plain Kernighan-style nested indent
-            (idlwave-indent-parens-nested
-             (+ idlwave-continuation-indent (idlwave-current-indent)))
-
-            ;; This is a closed paren - line up under open paren.
-            (close-exp
-             (current-column))
-
-            ;; Empty (or just comment) follows -- revert to basic indent
-            ((progn
-               ;; Skip paren
-               (forward-char 1)
-               (looking-at "[ \t$]*\\(;.*\\)?$"))
-             nil)
-
-            ;; Line up with first word after any blank space
-            ((progn
-               (skip-chars-forward " \t")
-               (current-column))))))))
-
-(defun idlwave-calculate-cont-indent ()
-  "Calculates the IDL continuation indent column from the previous statement.
-Note that here previous statement usually means the beginning of the
-current statement if this statement is a continuation of the previous
-line.  Various special types of continuations, including assignments,
-routine definitions, and parenthetical groupings, are treated separately."
-  (save-excursion
-    (let* ((case-fold-search t)
-           (end-reg (progn (beginning-of-line) (point)))
-          (beg-last-statement (save-excursion (idlwave-previous-statement)
-                                              (point)))
-           (beg-reg (progn (idlwave-start-of-substatement 'pre)
-                          (if (eq (line-beginning-position) end-reg)
-                              (goto-char beg-last-statement)
-                            (point))))
-          (basic-indent (+ (idlwave-min-current-statement-indent end-reg)
-                           idlwave-continuation-indent))
-          fancy-nonparen-indent fancy-paren-indent)
-      (cond
-       ;; Align then with its matching if, etc.
-       ((let ((matchers '(("\\<if\\>" . "[ \t]*then")
-                         ("\\<\\(if\\|end\\(if\\)?\\)\\>" . "[ \t]*else")
-                         ("\\<\\(for\\|while\\)\\>" . "[ \t]*do")
-                         ("\\<\\(repeat\\|end\\(rep\\)?\\)\\>" .
-                          "[ \t]*until")
-                         ("\\<case\\>" . "[ \t]*of")))
-             match cont-re)
-         (goto-char end-reg)
-         (and
-          (setq cont-re
-                (catch 'exit
-                  (while (setq match (car matchers))
-                    (if (looking-at (cdr match))
-                        (throw 'exit (car match)))
-                    (setq matchers (cdr matchers)))))
-          (idlwave-find-key cont-re -1 'nomark beg-last-statement)))
-       (if (looking-at "end") ;; that one's special
-           (- (idlwave-current-indent)
-              (+ idlwave-block-indent idlwave-end-offset))
-         (idlwave-current-indent)))
-
-       ;; Indent in from the previous line for continuing statements
-       ((let ((matchers '("\\<then\\>"
-                         "\\<do\\>"
-                         "\\<repeat\\>"
-                         "\\<else\\>"))
-             match)
-         (catch 'exit
-           (goto-char end-reg)
-           (if (/= (forward-line -1) 0)
-               (throw 'exit nil))
-           (while (setq match (car matchers))
-             (if (looking-at (concat ".*" match "[ \t]*\\$[ \t]*"
-                                     "\\(;.*\\)?$"))
-                 (throw 'exit t))
-             (setq matchers (cdr matchers)))))
-       (+ idlwave-continuation-indent (idlwave-current-indent)))
-
-       ;; Parenthetical indent, either traditional or Kernighan style
-       ((setq fancy-paren-indent
-             (let* ((end-reg end-reg)
-                   (close-exp (progn
-                                (goto-char end-reg)
-                                (skip-chars-forward " \t")
-                                (looking-at "\\s)")))
-                   indent-cons)
-               (catch 'loop
-                 (while (setq indent-cons (idlwave-calculate-paren-indent
-                                           beg-reg end-reg close-exp))
-                   ;; First permitted containing paren
-                   (if (or
-                        idlwave-indent-to-open-paren
-                        idlwave-indent-parens-nested
-                         (null (cdr indent-cons))
-                        (< (- (cdr indent-cons) basic-indent)
-                           idlwave-max-extra-continuation-indent))
-                       (throw 'loop (cdr indent-cons)))
-                   (setq end-reg (car indent-cons))))))
-       fancy-paren-indent)
-
-       ;; A continued assignment, or procedure call/definition
-       ((and
-        (> idlwave-max-extra-continuation-indent 0)
-        (setq fancy-nonparen-indent
-              (progn
-                (goto-char beg-reg)
-                (while (idlwave-look-at "&"))  ; skip continued statements
-                (cond
-                 ;; A continued Procedure call or definition
-                 ((progn
-                    (idlwave-look-at "^[ \t]*\\(pro\\|function\\)") ;skip over
-                    (looking-at "[ \t]*\\([a-zA-Z0-9.$_]+[ \t]*->[ \t]*\\)?[a-zA-Z][:a-zA-Z0-9$_]*[ \t]*\\(,\\)[ \t]*"))
-                  (goto-char (match-end 0))
-                  ;; Comment only, or blank line with "$"?  Basic indent.
-                  (if (save-match-data (looking-at "[ \t$]*\\(;.*\\)?$"))
-                      nil
-                    (current-column)))
-
-                 ;; Continued assignment (with =):
-                 ((catch 'assign ;
-                    (while (looking-at "[^=\n\r]*\\(=\\)[ \t]*")
-                      (goto-char (match-end 0))
-                      (if (null (idlwave-what-function beg-reg))
-                          (throw 'assign t))))
-                  (unless (or
-                           (idlwave-in-quote)
-                           (looking-at "[ \t$]*\\(;.*\\)?$") ; use basic
-                           (save-excursion
-                             (goto-char beg-last-statement)
-                             (eq (caar (idlwave-statement-type)) 'for)))
-                    (current-column))))))
-        (< (- fancy-nonparen-indent basic-indent)
-           idlwave-max-extra-continuation-indent))
-       (if fancy-paren-indent ;calculated but disallowed paren indent
-           (+ fancy-nonparen-indent idlwave-continuation-indent)
-         fancy-nonparen-indent))
-
-       ;; Basic indent, by default
-       (t basic-indent)))))
-
-
-
-(defun idlwave-find-key (key-re &optional dir nomark limit)
-  "Move to next match of the regular expression KEY-RE.
-Matches inside comments or string constants will be ignored.
-If DIR is negative, the search will be backwards.
-At a successful match, the mark is pushed unless NOMARK is non-nil.
-Searches are limited to LIMIT.
-Searches are case-insensitive and use a special syntax table which
-treats `$' and `_' as word characters.
-Return value is the beginning of the match or (in case of failure) nil."
-  (setq dir (or dir 0))
-  (let ((case-fold-search t)
-       (search-func (if (> dir 0) 're-search-forward 're-search-backward))
-       found)
-    (with-syntax-table idlwave-find-symbol-syntax-table
-     (save-excursion
-       (catch 'exit
-        (while (funcall search-func key-re limit t)
-          (if (not (idlwave-quoted))
-              (throw 'exit (setq found (match-beginning 0)))
-            (if (or (and (> dir 0) (eobp))
-                    (and (< dir 0) (bobp)))
-                (throw 'exit nil)))))))
-    (if found
-       (progn
-         (if (not nomark) (push-mark))
-         (goto-char found)
-         found)
-      nil)))
-
-(defun idlwave-block-jump-out (&optional dir nomark)
-  "When optional argument DIR is non-negative, move forward to end of
-current block using the `idlwave-begin-block-reg' and `idlwave-end-block-reg'
-regular expressions.  When DIR is negative, move backwards to block beginning.
-Recursively calls itself to skip over nested blocks.  DIR defaults to
-forward.  Calls `push-mark' unless the optional argument NOMARK is
-non-nil.  Movement is limited by the start of program units because of
-possibility of unbalanced blocks."
-  (interactive "P")
-  (or dir (setq dir 0))
-  (let* ((here (point))
-         (case-fold-search t)
-         (limit (if (>= dir 0) (point-max) (point-min)))
-         (block-limit (if (>= dir 0)
-                         idlwave-begin-block-reg
-                       idlwave-end-block-reg))
-         found
-         (block-reg (concat idlwave-begin-block-reg "\\|"
-                           idlwave-end-block-reg))
-         (unit-limit (or (save-excursion
-                          (if (< dir 0)
-                              (idlwave-find-key
-                               idlwave-begin-unit-reg dir t limit)
-                            (end-of-line)
-                            (idlwave-find-key
-                             idlwave-end-unit-reg dir t limit)))
-                        limit)))
-    (if (>= dir 0) (end-of-line)) ;Make sure we are in current block
-    (if (setq found (idlwave-find-key  block-reg dir t unit-limit))
-        (while (and found (looking-at block-limit))
-          (if (>= dir 0) (forward-word-strictly 1))
-          (idlwave-block-jump-out dir t)
-          (setq found (idlwave-find-key block-reg dir t unit-limit))))
-    (if (not nomark) (push-mark here))
-    (if (not found) (goto-char unit-limit)
-      (if (>= dir 0) (forward-word-strictly 1)))))
-
-(defun idlwave-min-current-statement-indent (&optional end-reg)
-  "The minimum indent in the current statement."
-  (idlwave-beginning-of-statement)
-  (if (not (idlwave-is-continuation-line))
-      (idlwave-current-indent)
-    (let ((min (idlwave-current-indent)) comm-or-empty)
-      (while (and (= (forward-line 1) 0)
-                 (or (setq comm-or-empty (idlwave-is-comment-or-empty-line))
-                     (idlwave-is-continuation-line))
-                 (or (null end-reg) (< (point) end-reg)))
-       (unless comm-or-empty (setq min (min min (idlwave-current-indent)))))
-      (if (or comm-or-empty (and end-reg (>= (point) end-reg)))
-         min
-       (min min (idlwave-current-indent))))))
-
-(defun idlwave-current-statement-indent (&optional last-line)
-  "Return indentation of the current statement.
-If in a statement, moves to beginning of statement before finding indent."
-  (if last-line
-      (idlwave-end-of-statement)
-    (idlwave-beginning-of-statement))
-  (idlwave-current-indent))
-
-(defun idlwave-current-indent ()
-  "Return the column of the indentation of the current line.
-Skips any whitespace.  Returns 0 if the end-of-line follows the whitespace."
-  (save-excursion
-    (beginning-of-line)
-    (skip-chars-forward " \t")
-    ;; if we are at the end of blank line return 0
-    (cond ((eolp) 0)
-          ((current-column)))))
-
-(defun idlwave-is-continuation-line ()
-  "Test if current line is continuation line.
-Blank or comment-only lines following regular continuation lines (with
-`$') count as continuations too."
-  (let (p)
-    (save-excursion
-      (or
-       (idlwave-look-at "\\<\\$")
-       (catch 'loop
-        (while (and (looking-at "^[ \t]*\\(;.*\\)?$")
-                    (eq (forward-line -1) 0))
-          (if (setq p (idlwave-look-at "\\<\\$")) (throw 'loop p))))))))
-
-(defun idlwave-is-comment-line ()
-  "Test if the current line is a comment line."
-  (save-excursion
-    (beginning-of-line 1)
-    (looking-at "[ \t]*;")))
-
-(defun idlwave-is-comment-or-empty-line ()
-  "Test if the current line is a comment line."
-  (save-excursion
-    (beginning-of-line 1)
-    (looking-at "[ \t]*[;\n]")))
-
-(defun idlwave-look-at (regexp &optional cont beg)
-  "Search current line from current point for REGEXP.
-If optional argument CONT is non-nil, searches to the end of
-the current statement.
-If optional arg BEG is non-nil, search starts from the beginning of the
-current statement.
-Ignores matches that end in a comment or inside a string expression.
-Returns point if successful, nil otherwise.
-This function produces unexpected results if REGEXP contains quotes or
-a comment delimiter.  The search is case insensitive.
-If successful leaves point after the match, otherwise, does not move point."
-  (let ((here (point))
-        (case-fold-search t)
-        (eos (save-excursion
-              (if cont (idlwave-end-of-statement) (end-of-line))
-              (point)))
-        found)
-    (with-syntax-table idlwave-find-symbol-syntax-table
-     (if beg (idlwave-beginning-of-statement))
-     (while (and (setq found (re-search-forward regexp eos t))
-                (idlwave-quoted))))
-    (if (not found) (goto-char here))
-    found))
-
-(defun idlwave-fill-paragraph (&optional nohang)
-  "Fill paragraphs in comments.
-A paragraph is made up of all contiguous lines having the same comment
-leader (the leading whitespace before the comment delimiter and the
-comment delimiter).  In addition, paragraphs are separated by blank
-line comments.  The indentation is given by the hanging indent of the
-first line, otherwise by the minimum indentation of the lines after
-the first line.  The indentation of the first line does not change.
-Does not effect code lines.  Does not fill comments on the same line
-with code.  The hanging indent is given by the end of the first match
-matching `idlwave-hang-indent-regexp' on the paragraph's first line.
-If the optional argument NOHANG is non-nil then the hanging indent is
-ignored."
-  (interactive "P")
-  ;; check if this is a line comment
-  (if (save-excursion
-        (beginning-of-line)
-        (skip-chars-forward " \t")
-        (looking-at comment-start))
-      (let
-          ((indent 999)
-           pre here diff fill-prefix-reg bcl first-indent
-           hang start end)
-        ;; Change tabs to spaces in the surrounding paragraph.
-        ;; The surrounding paragraph will be the largest containing block of
-        ;; contiguous line comments. Thus, we may be changing tabs in
-        ;; a much larger area than is needed, but this is the easiest
-        ;; brute force way to do it.
-        ;;
-        ;; This has the undesirable side effect of replacing the tabs
-        ;; permanently without the user's request or knowledge.
-        (save-excursion
-          (backward-paragraph)
-          (setq start (point)))
-        (save-excursion
-          (forward-paragraph)
-          (setq end (point)))
-        (untabify start end)
-        ;;
-        (setq here (point))
-        (beginning-of-line)
-        (setq bcl (point))
-        (re-search-forward (concat "^[ \t]*" comment-start "+")
-                           (line-end-position) t)
-        ;; Get the comment leader on the line and its length
-        (setq pre (current-column))
-        ;; the comment leader is the indentation plus exactly the
-        ;; number of consecutive ";".
-        (setq fill-prefix-reg
-              (concat
-               (setq fill-prefix
-                     (regexp-quote (buffer-substring (line-beginning-position)
-                                                     (point))))
-               "[^;]"))
-
-        ;; Mark the beginning and end of the paragraph
-        (goto-char bcl)
-        (while (and (looking-at fill-prefix-reg)
-                    (not (looking-at paragraph-separate))
-                    (not (bobp)))
-          (forward-line -1))
-        ;; Move to first line of paragraph
-        (if (/= (point) bcl)
-            (forward-line 1))
-        (setq start (point))
-        (goto-char bcl)
-        (while (and (looking-at fill-prefix-reg)
-                    (not (looking-at paragraph-separate))
-                    (not (eobp)))
-          (forward-line 1))
-        (beginning-of-line)
-        (if (or (not (looking-at fill-prefix-reg))
-                (looking-at paragraph-separate))
-            (forward-line -1))
-        (end-of-line)
-        ;; if at end of buffer add a newline (need this because
-        ;; fill-region needs END to be at the beginning of line after
-        ;; the paragraph or it will add a line).
-        (if (eobp)
-            (progn (insert ?\n) (backward-char 1)))
-        ;; Set END to the beginning of line after the paragraph
-        ;; END is calculated as distance from end of buffer
-        (setq end (- (point-max) (point) 1))
-        ;;
-        ;; Calculate the indentation for the paragraph.
-        ;;
-        ;; In the following while statements, after one iteration
-        ;; point will be at the beginning of a line in which case
-        ;; the while will not be executed for the
-        ;; first paragraph line and thus will not affect the
-        ;; indentation.
-        ;;
-        ;; First check to see if indentation is based on hanging indent.
-        (if (and (not nohang) idlwave-hanging-indent
-                 (setq hang
-                       (save-excursion
-                         (goto-char start)
-                         (idlwave-calc-hanging-indent))))
-            ;; Adjust lines of paragraph by inserting spaces so that
-            ;; each line's indent is at least as great as the hanging
-            ;; indent. This is needed for fill-paragraph to work with
-            ;; a fill-prefix.
-            (progn
-              (setq indent hang)
-              (beginning-of-line)
-              (while (> (point) start)
-                (re-search-forward comment-start-skip (line-end-position) t)
-                (if (> (setq diff (- indent (current-column))) 0)
-                    (progn
-                      (if (>= here (point))
-                          ;; adjust the original location for the
-                          ;; inserted text.
-                          (setq here (+ here diff)))
-                      (insert (make-string diff ?\ ))))
-                (forward-line -1))
-              )
-
-          ;; No hang. Instead find minimum indentation of paragraph
-          ;; after first line.
-          ;; For the following while statement, since START is at the
-          ;; beginning of line and END is at the end of line
-          ;; point is greater than START at least once (which would
-          ;; be the case for a single line paragraph).
-          (while (> (point) start)
-            (beginning-of-line)
-            (setq indent
-                  (min indent
-                       (progn
-                         (re-search-forward comment-start-skip (line-end-position) t)
-                         (current-column))))
-            (forward-line -1)))
-        (setq fill-prefix (concat fill-prefix
-                                  (make-string (- indent pre)
-                                               ?\ )))
-        ;; first-line indent
-        (setq first-indent
-              (max
-               (progn
-                 (re-search-forward comment-start-skip (line-end-position) t)
-                 (current-column))
-               indent))
-
-        ;; try to keep point at its original place
-        (goto-char here)
-
-        ;; In place of the more modern fill-region-as-paragraph, a hack
-        ;; to keep whitespace untouched on the first line within the
-        ;; indent length and to preserve any indent on the first line
-        ;; (first indent).
-        (save-excursion
-          (setq diff
-                (buffer-substring start (+ start first-indent -1)))
-          (subst-char-in-region start (+ start first-indent -1) ?\  ?~ nil)
-          (fill-region-as-paragraph
-           start
-           (- (point-max) end)
-           (current-justification)
-           nil)
-          (delete-region start (+ start first-indent -1))
-          (goto-char start)
-          (insert diff))
-        ;; When we want the point at the beginning of the comment
-        ;; body fill-region will put it at the beginning of the line.
-        (if (bolp) (skip-chars-forward (concat " \t" comment-start)))
-        (setq fill-prefix nil))))
-
-(defun idlwave-calc-hanging-indent ()
-  "Calculate the position of the hanging indent for the comment paragraph.
-The hanging indent position is given by the first match with the
-`idlwave-hang-indent-regexp'.  If `idlwave-use-last-hang-indent' is
-non-nil then use last occurrence matching `idlwave-hang-indent-regexp'
-on the line.
-If not found returns nil."
-  (if idlwave-use-last-hang-indent
-      (save-excursion
-        (end-of-line)
-        (if (re-search-backward idlwave-hang-indent-regexp (line-beginning-position) t)
-            (+ (current-column) (length idlwave-hang-indent-regexp))))
-    (save-excursion
-      (beginning-of-line)
-      (if (re-search-forward idlwave-hang-indent-regexp (line-end-position) t)
-          (current-column)))))
-
-(defun idlwave-auto-fill ()
-  "Called to break lines in auto fill mode.
-Only fills non-comment lines if `idlwave-fill-comment-line-only' is
-non-nil.  Places a continuation character at the end of the line if
-not in a comment.  Splits strings with IDL concatenation operator `+'
-if `idlwave-auto-fill-split-string' is non-nil."
-  (if (<= (current-column) fill-column)
-      nil                             ; do not to fill
-    (if (or (not idlwave-fill-comment-line-only)
-           (save-excursion
-             ;; Check for comment line
-             (beginning-of-line)
-             (looking-at idlwave-comment-line-start-skip)))
-       (let (beg)
-         (idlwave-indent-line)
-         ;; Prevent actions do-auto-fill which calls indent-line-function.
-         (let (idlwave-do-actions
-               (paragraph-separate ".")
-               (fill-nobreak-predicate
-                (if (and (idlwave-in-quote)
-                         idlwave-auto-fill-split-string)
-                    (lambda () ;; We'll need 5 spaces for " ' + $"
-                      (<= (- fill-column (current-column)) 5)
-                      ))))
-           (do-auto-fill))
-         (save-excursion
-           (end-of-line 0)
-           ;; Indent the split line
-           (idlwave-indent-line))
-         (if (save-excursion
-               (beginning-of-line)
-               (looking-at idlwave-comment-line-start-skip))
-             ;; A continued line comment
-             ;; We treat continued line comments as part of a comment
-             ;; paragraph. So we check for a hanging indent.
-             (if idlwave-hanging-indent
-                 (let ((here (- (point-max) (point)))
-                       (indent
-                        (save-excursion
-                          (forward-line -1)
-                          (idlwave-calc-hanging-indent))))
-                   (when indent
-                     ;; Remove whitespace between comment delimiter and
-                     ;; text, insert spaces for appropriate indentation.
-                     (beginning-of-line)
-                      (re-search-forward comment-start-skip (line-end-position) t)
-                     (delete-horizontal-space)
-                     (idlwave-indent-to indent)
-                     (goto-char (- (point-max) here)))))
-           ;; Split code or comment?
-           (if (save-excursion
-                 (end-of-line 0)
-                 (idlwave-in-comment))
-               ;; Splitting a non-full-line comment.
-               ;; Insert the comment delimiter from split line
-               (progn
-                 (save-excursion
-                   (beginning-of-line)
-                   (skip-chars-forward " \t")
-                   ;; Insert blank to keep off beginning of line
-                   (insert " "
-                           (save-excursion
-                             (forward-line -1)
-                             (buffer-substring (idlwave-goto-comment)
-                                               (progn
-                                                 (skip-chars-forward "; ")
-                                                 (point))))))
-                 (idlwave-indent-line))
-             ;; Split code line - add continuation character
-             (save-excursion
-               (end-of-line 0)
-               ;; Check to see if we split a string
-               (if (and (setq beg (idlwave-in-quote))
-                        idlwave-auto-fill-split-string)
-                   ;; Split the string and concatenate.
-                   ;; The first extra space is for the space
-                   ;; the line was split. That space was removed.
-                   (insert " " (char-after beg) " +"))
-               (insert " $"))
-             (if beg
-                 (if idlwave-auto-fill-split-string
-                     ;; Make the second part of continued string
-                     (save-excursion
-                       (beginning-of-line)
-                       (skip-chars-forward " \t")
-                       (insert (char-after beg)))
-                   ;; Warning
-                   (beep)
-                   (message "Warning: continuation inside a string.")))
-             ;; Although do-auto-fill (via indent-new-comment-line) calls
-             ;; idlwave-indent-line for the new line, re-indent again
-             ;; because of the addition of the continuation character.
-             (idlwave-indent-line))
-           )))))
-
-(define-obsolete-function-alias 'idlwave-auto-fill-mode #'auto-fill-mode "28.1")
-
-(defun idlwave-doc-header (&optional nomark)
-  "Insert a documentation header at the beginning of the unit.
-Inserts the value of the variable `idlwave-file-header'.  Sets mark
-before moving to do insertion unless the optional prefix argument
-NOMARK is non-nil."
-  (interactive "P")
-  (or nomark (push-mark))
-  ;; make sure we catch the current line if it begins the unit
-  (if idlwave-header-to-beginning-of-file
-      (goto-char (point-min))
-    (end-of-line)
-    (idlwave-beginning-of-subprogram)
-    (beginning-of-line)
-    ;; skip function or procedure line
-    (if (idlwave-look-at "\\<\\(pro\\|function\\)\\>")
-       (progn
-         (idlwave-end-of-statement)
-         (if (> (forward-line 1) 0) (insert "\n")))))
-  (let ((pos (point)))
-    (if idlwave-file-header
-       (cond ((car idlwave-file-header)
-              (insert-file-contents (car idlwave-file-header)))
-             ((stringp (car (cdr idlwave-file-header)))
-              (insert (car (cdr idlwave-file-header))))))
-    (goto-char pos)))
-
-(defun idlwave-default-insert-timestamp ()
-  "Default timestamp insertion function."
-  (insert (current-time-string))
-  (insert ", " (user-full-name))
-  (if (boundp 'user-mail-address)
-      (insert " <" user-mail-address ">")
-    (insert " <" (user-login-name) "@" (system-name) ">"))
-  ;; Remove extra spaces from line
-  (idlwave-fill-paragraph)
-  ;; Insert a blank line comment to separate from the date entry -
-  ;; will keep the entry from flowing onto date line if re-filled.
-  (insert "\n;\n;\t\t"))
-
-(defun idlwave-doc-modification ()
-  "Insert a brief modification log at the beginning of the current program.
-Looks for an occurrence of the value of user variable
-`idlwave-doc-modifications-keyword' if non-nil.  Inserts time and user
-name and places the point for the user to add a log.  Before moving, saves
-location on mark ring so that the user can return to previous point."
-  (interactive)
-  (push-mark)
-  (let* (beg end)
-    (if (and (or (re-search-backward idlwave-doclib-start nil t)
-                (progn
-                  (goto-char (point-min))
-                  (re-search-forward idlwave-doclib-start nil t)))
-            (setq beg (match-beginning 0))
-            (re-search-forward idlwave-doclib-end nil t)
-            (setq end (match-end 0)))
-       (progn
-         (goto-char beg)
-         (if (re-search-forward
-              (concat idlwave-doc-modifications-keyword ":")
-              end t)
-             (end-of-line)
-           (goto-char end)
-           (end-of-line -1)
-           (insert "\n" comment-start "\n")
-           (insert comment-start " " idlwave-doc-modifications-keyword ":"))
-         (insert "\n;\n;\t")
-         (run-hooks 'idlwave-timestamp-hook))
-      (error "No valid DOCLIB header"))))
-
-
-;; CJC 3/16/93
-;; Interface to expand-region-abbrevs which did not work when the
-;; abbrev hook associated with an abbrev moves point backwards
-;; after abbrev expansion, e.g., as with the abbrev '.n'.
-;; The original would enter an infinite loop in attempting to expand
-;; .n (it would continually expand and unexpand the abbrev without expanding
-;; because the point would keep going back to the beginning of the
-;; abbrev instead of to the end of the abbrev). We now keep the
-;; abbrev hook from moving backwards.
-;;;
-(defun idlwave-expand-region-abbrevs (start end)
-  "Expand each abbrev occurrence in the region.
-Calling from a program, arguments are START END."
-  (interactive "r")
-  (save-excursion
-    (goto-char (min start end))
-    (let ((idlwave-show-block nil)          ;Do not blink
-          (idlwave-abbrev-move nil))        ;Do not move
-      (expand-region-abbrevs start end 'noquery))))
-
-(defun idlwave-quoted ()
-  "Return t if point is in a comment or quoted string.
-Returns nil otherwise."
-  ;; FIXME: Use (nth 8 (synx-ppss))!
-  (and (or (idlwave-in-comment) (idlwave-in-quote)) t))
-
-(defun idlwave-in-quote ()
-  "Return location of the opening quote
-if point is in a IDL string constant, nil otherwise.
-Ignores comment delimiters on the current line.
-Properly handles nested quotation marks and octal
-constants - a double quote followed by an octal digit."
-;; Treat an octal inside an apostrophe to be a normal string. Treat a
-;; double quote followed by an octal digit to be an octal constant
-;; rather than a string. Therefore, there is no terminating double
-;; quote.
-  (save-excursion
-    ;; Because single and double quotes can quote each other we must
-    ;; search for the string start from the beginning of line.
-    (let* ((start (point))
-           (eol (line-end-position))
-           (bq (progn (beginning-of-line) (point)))
-           (endq (point))
-           (data (match-data))
-           delim
-           found)
-      (while  (< endq start)
-       ;; Find string start
-       ;; Don't find an octal constant beginning with a double quote
-       (if (re-search-forward "[\"']" eol 'lim)
-           ;; Find the string end.
-           ;; In IDL, two consecutive delimiters after the start of a
-           ;; string act as an
-           ;; escape for the delimiter in the string.
-           ;; Two consecutive delimiters alone (i.e., not after the
-           ;; start of a string) is the null string.
-           (progn
-             ;; Move to position after quote
-             (goto-char (1+ (match-beginning 0)))
-             (setq bq (1- (point)))
-             ;; Get the string delimiter
-             (setq delim (char-to-string (preceding-char)))
-             ;; Check for null string
-             (if (looking-at delim)
-                 (progn (setq endq (point)) (forward-char 1))
-               ;; Look for next unpaired delimiter
-               (setq found (search-forward delim eol 'lim))
-               (while (looking-at delim)
-                 (forward-char 1)
-                 (setq found (search-forward delim eol 'lim)))
-               (setq endq (if found (1- (point)) (point)))
-               ))
-         (progn (setq bq (point)) (setq endq (point)))))
-      (store-match-data data)
-      ;; return string beginning position or nil
-      (if (> start bq) bq))))
-
-(defun idlwave-is-pointer-dereference (&optional limit)
-  "Determine if the character after point is a pointer dereference *."
-  (and
-   (eq (char-after) ?\*)
-   (not (idlwave-in-quote))
-   (save-excursion
-     (forward-char)
-     (re-search-backward (concat "\\(" idlwave-idl-keywords
-                                 "\\|[-[(*+/=,^><]\\)\\s-*\\*") limit t))))
-
-
-;; Statement templates
-
-;; Replace these with a general template function, something like
-;; expand.el (I think there was also something with a name similar to
-;; dmacro.el)
-
-(defun idlwave-template (s1 s2 &optional prompt noindent)
-  "Build a template with optional prompt expression.
-
-Opens a line if point is not followed by a newline modulo intervening
-whitespace.  S1 and S2 are strings.  S1 is inserted at point followed
-by S2.  Point is inserted between S1 and S2.  The case of S1 and S2 is
-adjusted according to `idlwave-abbrev-change-case'.  If optional
-argument PROMPT is a string then it is displayed as a message in the
-minibuffer.  The PROMPT serves as a reminder to the user of an
-expression to enter.
-
-The lines containing S1 and S2 are reindented using `indent-region'
-unless the optional second argument NOINDENT is non-nil."
-  (if (derived-mode-p 'idlwave-shell-mode)
-      ;; This is a gross hack to avoid template abbrev expansion
-      ;; in the shell.  FIXME: This is a dirty hack.
-      (if (and (eq this-command 'self-insert-command)
-              (equal last-abbrev-location (point)))
-         (insert last-abbrev-text)
-       (error "No templates in idlwave-shell"))
-    (cond ((eq idlwave-abbrev-change-case 'down)
-          (setq s1 (downcase s1) s2 (downcase s2)))
-         (idlwave-abbrev-change-case
-          (setq s1 (upcase s1) s2 (upcase s2))))
-    (let ((beg (line-beginning-position))
-         end)
-      (if (not (looking-at "\\s-*\n"))
-         (open-line 1))
-      (insert s1)
-      (save-excursion
-       (insert s2)
-       (setq end (point)))
-      (if (not noindent)
-         (indent-region beg end nil))
-      (if (stringp prompt)
-         (message "%s" prompt)))))
-
-(defun idlwave-rw-case (string)
-  "Make STRING have the case required by `idlwave-reserved-word-upcase'."
-  (if idlwave-reserved-word-upcase
-      (upcase string)
-    string))
-
-(defun idlwave-elif ()
-  "Build skeleton IDL if-else block."
-  (interactive)
-  (idlwave-template
-   (idlwave-rw-case "if")
-   (idlwave-rw-case " then begin\n\nendif else begin\n\nendelse")
-   "Condition expression"))
-
-(defun idlwave-case ()
-  "Build skeleton IDL case statement."
-  (interactive)
-  (idlwave-template
-   (idlwave-rw-case "case")
-   (idlwave-rw-case " of\n\nendcase")
-   "Selector expression"))
-
-(defun idlwave-switch ()
-  "Build skeleton IDL switch statement."
-  (interactive)
-  (idlwave-template
-   (idlwave-rw-case "switch")
-   (idlwave-rw-case " of\n\nendswitch")
-   "Selector expression"))
-
-(defun idlwave-for ()
-  "Build skeleton IDL loop statement."
-  (interactive)
-  (idlwave-template
-   (idlwave-rw-case "for")
-   (idlwave-rw-case " do begin\n\nendfor")
-   "Loop expression"))
-
-(defun idlwave-if ()
-  "Build skeleton IDL if statement."
-  (interactive)
-  (idlwave-template
-   (idlwave-rw-case "if")
-   (idlwave-rw-case " then begin\n\nendif")
-   "Scalar logical expression"))
-
-(defun idlwave-procedure ()
-  (interactive)
-  (idlwave-template
-   (idlwave-rw-case "pro")
-   (idlwave-rw-case "\n\nreturn\nend")
-   "Procedure name"))
-
-(defun idlwave-function ()
-  (interactive)
-  (idlwave-template
-   (idlwave-rw-case "function")
-   (idlwave-rw-case "\n\nreturn\nend")
-   "Function name"))
-
-(defun idlwave-repeat ()
-  (interactive)
-  (idlwave-template
-   (idlwave-rw-case "repeat begin\n\nendrep until")
-   (idlwave-rw-case "")
-   "Exit condition"))
-
-(defun idlwave-while ()
-  (interactive)
-  (idlwave-template
-   (idlwave-rw-case "while")
-   (idlwave-rw-case " do begin\n\nendwhile")
-   "Entry condition"))
-
-(defun idlwave-split-string (string &optional pattern)
-  "Return a list of substrings of STRING which are separated by PATTERN.
-If PATTERN is omitted, it defaults to \"[ \\f\\t\\n\\r\\v]+\"."
-  (or pattern
-      (setq pattern "[ \f\t\n\r\v]+"))
-  (let (parts (start 0))
-    (while (string-match pattern string start)
-      (setq parts (cons (substring string start (match-beginning 0)) parts)
-           start (match-end 0)))
-    (nreverse (cons (substring string start) parts))))
-
-(defun idlwave-replace-string (string replace_string replace_with)
-  (let* ((start 0)
-        (last (length string))
-        (ret_string "")
-        end)
-    (while (setq end (string-match replace_string string start))
-      (setq ret_string
-           (concat ret_string (substring string start end) replace_with))
-      (setq start (match-end 0)))
-    (setq ret_string (concat ret_string (substring string start last)))))
-
-(define-obsolete-function-alias 'idlwave-get-buffer-visiting
-  #'find-buffer-visiting "28.1")
-
-(defvar idlwave-outlawed-buffers nil
-  "List of buffers pulled up by IDLWAVE for special reasons.
-Buffers in this list may be killed by `idlwave-kill-autoloaded-buffers'.")
-
-(defun idlwave-find-file-noselect (file &optional why)
-  ;; Return a buffer visiting file.
-  (or (find-buffer-visiting file)
-      (let ((buf (find-file-noselect file)))
-       (if why (add-to-list 'idlwave-outlawed-buffers (cons buf why)))
-       buf)))
-
-(defun idlwave-kill-autoloaded-buffers ()
-  "Kill buffers created automatically by IDLWAVE.
-Function prompts for a letter to identify the buffers to kill.
-Possible letters are:
-
-f    Buffers created by the command \\[idlwave-find-module] or mouse
-     clicks in the routine info window.
-s    Buffers created by the IDLWAVE Shell to display where execution
-     stopped or an error was found.
-a    Both of the above.
-
-Buffers containing unsaved changes require confirmation before they are killed."
-  (interactive)
-  (if (null idlwave-outlawed-buffers)
-      (error "No IDLWAVE-created buffers available")
-    (princ (format "Kill IDLWAVE-created buffers: [f]ind source(%d), [s]hell display(%d), [a]ll ? "
-                  (idlwave-count-outlawed-buffers 'find)
-                  (idlwave-count-outlawed-buffers 'shell)))
-    (let ((c (read-char)))
-      (cond
-       ((member c '(?f ?\C-f))
-       (idlwave-do-kill-autoloaded-buffers 'find))
-       ((member c '(?s ?\C-s))
-       (idlwave-do-kill-autoloaded-buffers 'shell))
-       ((member c '(?a ?\C-a))
-       (idlwave-do-kill-autoloaded-buffers t))
-       (t (error "Abort"))))))
-
-(defun idlwave-count-outlawed-buffers (tag)
-  "How many outlawed buffers have tag TAG?"
-  (length (delq nil
-               (mapcar
-                (lambda (x) (eq (cdr x) tag))
-                idlwave-outlawed-buffers))))
-
-(defun idlwave-do-kill-autoloaded-buffers (&rest reasons)
-  "Kill all buffers pulled up by IDLWAVE matching REASONS."
-  (let* ((list (copy-sequence idlwave-outlawed-buffers))
-        (cnt 0)
-        entry)
-    (while (setq entry (pop list))
-      (if (buffer-live-p (car entry))
-         (and (or (memq t reasons)
-                  (memq (cdr entry) reasons))
-              (kill-buffer (car entry))
-              (cl-incf cnt)
-              (setq idlwave-outlawed-buffers
-                    (delq entry idlwave-outlawed-buffers)))
-       (setq idlwave-outlawed-buffers
-             (delq entry idlwave-outlawed-buffers))))
-    (message "%d buffer%s killed" cnt (if (= cnt 1) "" "s"))))
-
-(defun idlwave-revoke-license-to-kill ()
-  "Remove BUFFER from the buffers which may be killed.
-Killing would be done by `idlwave-do-kill-autoloaded-buffers'.
-Intended for `after-save-hook'."
-  (let* ((buf (current-buffer))
-        (entry (assq buf idlwave-outlawed-buffers)))
-    ;; Revoke license
-    (if entry
-       (setq idlwave-outlawed-buffers
-             (delq entry idlwave-outlawed-buffers)))
-    ;; Remove this function from the hook.
-    (remove-hook 'after-save-hook #'idlwave-revoke-license-to-kill 'local)))
-
-(defvar idlwave-path-alist)
-(defun idlwave-locate-lib-file (file)
-  ;; Find FILE on the scanned lib path and return a buffer visiting it
-  (let* ((dirs idlwave-path-alist)
-        dir efile)
-    (catch 'exit
-      (while (setq dir (car (pop dirs)))
-       (if (file-regular-p
-            (setq efile (expand-file-name file dir)))
-           (throw 'exit efile))))))
-
-(defun idlwave-expand-lib-file-name (file)
-  ;; Find FILE on the scanned lib path and return a buffer visiting it
-  ;; This is for, e.g., finding source with no user catalog
-  (cond
-   ((null file) nil)
-   ((file-name-absolute-p file) file)
-   (t (idlwave-locate-lib-file file))))
-
-(defun idlwave-make-tags ()
-  "Create the IDL tags file IDLTAGS in the current directory from
-the list of directories specified in the minibuffer.  Directories may be
-for example: . /usr/local/rsi/idl/lib.  All the subdirectories of the
-specified top directories are searched if the directory name is prefixed
-by @.  Specify @ directories with care, it may take a long, long time if
-you specify /."
-  (interactive)
-  (let (directory directories cmd append status numdirs dir getsubdirs
-                 buffer save_buffer files numfiles item errbuf)
-
-    ;;
-    ;; Read list of directories
-    (setq directory (read-string "Tag Directories: " "."))
-    (setq directories (idlwave-split-string directory "[ \t]+"))
-    ;;
-    ;; Set etags command, vars
-    (setq cmd "etags --output=IDLTAGS --language=none --regex='/[
-\\t]*[pP][Rr][Oo][ \\t]+\\([^ \\t,]+\\)/' --regex='/[
-\\t]*[Ff][Uu][Nn][Cc][Tt][Ii][Oo][Nn][ \\t]+\\([^ \\t,]+\\)/' ")
-    (setq append " ")
-    (setq status 0)
-    ;;
-    ;; For each directory
-    (setq numdirs 0)
-    (setq dir (nth numdirs directories))
-    (while (and dir)
-      ;;
-      ;; Find the subdirectories
-      (if (string-match "^[@]\\(.+\\)$" dir)
-         (setq getsubdirs t) (setq getsubdirs nil))
-      (if (and getsubdirs) (setq dir (substring dir 1 (length dir))))
-      (setq dir (expand-file-name dir))
-      (if (file-directory-p dir)
-         (progn
-           (if (and getsubdirs)
-               (progn
-                 (setq buffer (get-buffer-create "*idltags*"))
-                 (call-process "sh" nil buffer nil "-c"
-                               (concat "find " dir " -type d -print"))
-                 (setq save_buffer (current-buffer))
-                 (set-buffer buffer)
-                 (setq files (idlwave-split-string
-                              (idlwave-replace-string
-                               (buffer-substring 1 (point-max))
-                               "\n" "/*.pro ")
-                              "[ \t]+"))
-                 (set-buffer save_buffer)
-                 (kill-buffer buffer))
-             (setq files (list (concat dir "/*.pro"))))
-           ;;
-           ;; For each subdirectory
-           (setq numfiles 0)
-           (setq item (nth numfiles files))
-           (while (and item)
-             ;;
-             ;; Call etags
-             (if (not (string-match "^[ \t]*$" item))
-                 (progn
-                   (message "%s" (concat "Tagging " item "..."))
-                   (setq errbuf (get-buffer-create "*idltags-error*"))
-                   (setq status (+ status
-                                   (if (eq 0 (call-process
-                                              "sh" nil errbuf nil "-c"
-                                              (concat cmd append item)))
-                                       0
-                                       1)))
-                   ;;
-                   ;; Append additional tags
-                   (setq append " --append ")
-                   (setq numfiles (1+ numfiles))
-                   (setq item (nth numfiles files)))
-               (progn
-                 (setq numfiles (1+ numfiles))
-                 (setq item (nth numfiles files))
-                 )))
-
-           (setq numdirs (1+ numdirs))
-           (setq dir (nth numdirs directories)))
-       (progn
-         (setq numdirs (1+ numdirs))
-         (setq dir (nth numdirs directories)))))
-
-    (setq errbuf (get-buffer-create "*idltags-error*"))
-    (if (= status 0)
-       (kill-buffer errbuf))
-    (message "")
-    ))
-
-(defun idlwave-toggle-comment-region (beg end &optional n)
-  "Comment the lines in the region if the first non-blank line is
-commented, and conversely, uncomment region.  If optional prefix arg
-N is non-nil, then for N positive, add N comment delimiters or for N
-negative, remove N comment delimiters.
-Uses `comment-region' which does not place comment delimiters on
-blank lines."
-  (interactive "r\nP")
-  (if n
-      (comment-region beg end (prefix-numeric-value n))
-    (save-excursion
-      (goto-char beg)
-      (beginning-of-line)
-      ;; skip blank lines
-      (skip-chars-forward " \t\n")
-      (if (looking-at (concat "[ \t]*\\(" comment-start "+\\)"))
-          (uncomment-region beg end)
-       (comment-region beg end)))))
-
-
-;; ----------------------------------------------------------------------------
-;; ----------------------------------------------------------------------------
-;; ----------------------------------------------------------------------------
-;; ----------------------------------------------------------------------------
-;;
-;; Completion and Routine Info
-;;
-
-;; String "intern" functions
-
-;; For the completion and routine info function, we want to normalize
-;; the case of procedure names etc.  We do this by "interning" these
-;; string is a hand-crafted way.  Hashes are used to map the downcase
-;; version of the strings to the cased versions.  Most *-sint-*
-;; variables consist of *two* hashes, a buffer+shell, followed by a
-;; system hash.  The former is re-scanned, and the latter takes case
-;; precedence.
-;;
-;; Since these cased versions are really lisp objects, we can use `eq'
-;; to search, which is a large performance boost.  All new strings
-;; need to be "sinterned".  We do this as early as possible after
-;; getting these strings from completion or buffer substrings.  So
-;; most of the code can simply assume to deal with "sinterned"
-;; strings.  The only exception is that the functions which scan whole
-;; buffers for routine information do not intern the grabbed strings.
-;; This is only done afterwards.  Therefore in these functions it is
-;; *not* safe to assume the strings can be compared with `eq' and be
-;; fed into the routine assq functions.
-
-;; Here we define the hashing functions.
-
-;; The variables which hold the hashes.
-(defvar idlwave-sint-routines '(nil))
-(defvar idlwave-sint-keywords '(nil))
-(defvar idlwave-sint-methods  '(nil))
-(defvar idlwave-sint-classes  '(nil))
-(defvar idlwave-sint-dirs    '(nil))
-(defvar idlwave-sint-libnames '(nil))
-
-(defun idlwave-reset-sintern (&optional what)
-  "Reset all sintern hashes."
-  ;; Make sure the hash functions are accessible.
-  (let ((entries '((idlwave-sint-routines 1000 10)
-                  (idlwave-sint-keywords 1000 10)
-                  (idlwave-sint-methods   100 10)
-                  (idlwave-sint-classes    10 10))))
-
-    ;; Make sure these are lists
-    (cl-loop for entry in entries
-      for var = (car entry)
-      do (if (not (consp (symbol-value var))) (set var (list nil))))
-
-    ;; Reset the system & library hash
-    (when (or (eq what t) (eq what 'syslib)
-             (null (cdr idlwave-sint-routines)))
-      (cl-loop for entry in entries
-       for var = (car entry) for size = (nth 1 entry)
-       do (setcdr (symbol-value var)
-                  (make-hash-table ':size size ':test 'equal)))
-      (setq idlwave-sint-dirs nil
-           idlwave-sint-libnames nil))
-
-    ;; Reset the buffer & shell hash
-    (when (or (eq what t) (eq what 'bufsh)
-             (null (car idlwave-sint-routines)))
-      (cl-loop for entry in entries
-       for var = (car entry) for size = (nth 1 entry)
-       do (setcar (symbol-value var)
-                  (make-hash-table ':size size ':test 'equal))))))
-
-(defun idlwave-sintern-routine-or-method (name &optional class set)
-  (if class
-      (idlwave-sintern-method name set)
-    (idlwave-sintern-routine name set)))
-
-(defun idlwave-sintern (stype &rest args)
-  (apply (intern (concat "idlwave-sintern-" (symbol-name stype))) args))
-
-;;(defmacro idlwave-sintern (type var)
-;;  `(cond ((not (stringp name)) name)
-;;      ((gethash (downcase name) (cdr ,var)))
-;;      ((gethash (downcase name) (car ,var)))
-;;      (set (idlwave-sintern-set name ,type ,var set))
-;;      (name)))
-
-(defun idlwave-sintern-routine (name &optional set)
-  (cond ((not (stringp name)) name)
-       ((gethash (downcase name) (cdr idlwave-sint-routines)))
-       ((gethash (downcase name) (car idlwave-sint-routines)))
-       (set (idlwave-sintern-set name 'routine idlwave-sint-routines set))
-       (name)))
-(defun idlwave-sintern-keyword (name &optional set)
-  (cond ((not (stringp name)) name)
-       ((gethash (downcase name) (cdr idlwave-sint-keywords)))
-       ((gethash (downcase name) (car idlwave-sint-keywords)))
-       (set (idlwave-sintern-set name 'keyword idlwave-sint-keywords set))
-       (name)))
-(defun idlwave-sintern-method (name &optional set)
-  (cond ((not (stringp name)) name)
-       ((gethash (downcase name) (cdr idlwave-sint-methods)))
-       ((gethash (downcase name) (car idlwave-sint-methods)))
-       (set (idlwave-sintern-set name 'method idlwave-sint-methods set))
-       (name)))
-(defun idlwave-sintern-class (name &optional set)
-  (cond ((not (stringp name)) name)
-       ((gethash (downcase name) (cdr idlwave-sint-classes)))
-       ((gethash (downcase name) (car idlwave-sint-classes)))
-       (set (idlwave-sintern-set name 'class idlwave-sint-classes set))
-       (name)))
-
-(defun idlwave-sintern-dir (dir &optional _set)
-  (car (or (member dir idlwave-sint-dirs)
-          (setq idlwave-sint-dirs (cons dir idlwave-sint-dirs)))))
-(defun idlwave-sintern-libname (name &optional _set)
-  (car (or (member name idlwave-sint-libnames)
-          (setq idlwave-sint-libnames (cons name idlwave-sint-libnames)))))
-
-(defun idlwave-sintern-set (name type tables set)
-  (let* ((func (or (cdr (assq type idlwave-completion-case))
-                  'identity))
-        (iname (funcall (if (eq func 'preserve) 'identity func) name))
-        (table (if (eq set 'sys) (cdr tables) (car tables))))
-    (puthash (downcase name) iname table)
-    iname))
-
-(defun idlwave-sintern-keyword-list (kwd-list &optional set)
-  "Sintern a set of keywords (file (key . link) (key2 . link2) ...)."
-  (mapc (lambda(x)
-         (setcar x (idlwave-sintern-keyword (car x) set)))
-       (cdr kwd-list))
-  kwd-list)
-
-(defun idlwave-sintern-rinfo-list (list &optional set default-dir)
-  "Sintern all strings in the rinfo LIST.
-With optional parameter SET: also set new patterns.  Probably this
-will always have to be t.  If DEFAULT-DIR is passed, it is used as
-the base of the directory."
-  (let (entry name type class kwds res source call new)
-    (while list
-      (setq entry (car list)
-           list (cdr list)
-           name (car entry)
-           type (nth 1 entry)
-           class (nth 2 entry)
-           source (nth 3 entry)
-           call (nth 4 entry)
-           kwds (nthcdr 5 entry))
-
-      ;; The class and name
-      (if class
-         (progn
-           (if (symbolp class) (setq class (symbol-name class)))
-           (setq class (idlwave-sintern-class class set))
-           (setq name (idlwave-sintern-method name set)))
-       (setq name (idlwave-sintern-routine name set)))
-
-      ;; The source
-      (let ((source-type (car source))
-           (source-file  (nth 1 source))
-           (source-dir  (if default-dir
-                            (file-name-as-directory default-dir)
-                          (nth 2 source)))
-           (source-lib (nth 3 source)))
-       (if (stringp source-dir)
-           (setq source-dir (idlwave-sintern-dir source-dir set)))
-       (if (stringp source-lib)
-           (setq source-lib (idlwave-sintern-libname source-lib set)))
-       (setq source (list source-type source-file source-dir source-lib)))
-
-      ;; The keywords
-      (setq kwds (mapcar (lambda (x)
-                          (idlwave-sintern-keyword-list x set))
-                        kwds))
-
-      ;; Build a canonicalized list
-      (setq new (nconc (list name type class source call) kwds)
-           res (cons new res)))
-    (nreverse res)))
-
-;; Creating new sintern tables
-
-(defmacro idlwave-new-sintern-type (tag)
-  "Define a variable and a function to sintern the new type TAG.
-This defines the function `idlwave-sintern-TAG' and the variable
-`idlwave-sint-TAGs'."
-  (let* ((name (symbol-name tag))
-        (names (concat name "s"))
-        (var (intern (concat "idlwave-sint-" names)))
-        (func (intern (concat "idlwave-sintern-" name))))
-    `(progn
-       (defvar ,var nil)        ; initial value of the association list
-       (defun ,func (name &optional set)
-        (cond ((not (stringp name)) name)
-              ((cdr (assoc (downcase name) ,var)))
-              (set
-               (push (cons (downcase name) name) ,var)
-               name)
-              (name))))))
-
-(defun idlwave-reset-sintern-type (tag)
-  "Reset the sintern variable associated with TAG."
-  (set (intern (concat "idlwave-sint-" (symbol-name tag) "s")) nil))
-
-;;---------------------------------------------------------------------------
-
-
-;; The variables which hold the information
-(defvar idlwave-system-routines nil
-  "Holds the routine-info obtained by scanning buffers.")
-(defvar idlwave-buffer-routines nil
-  "Holds the routine-info obtained by scanning buffers.")
-(defvar idlwave-compiled-routines nil
-  "Holds the routine-info obtained by asking the shell.")
-(defvar idlwave-unresolved-routines nil
-  "Holds the unresolved routine-info obtained by asking the shell.")
-(defvar idlwave-user-catalog-routines nil
-  "Holds the procedure routine-info from the user scan.")
-(defvar idlwave-library-catalog-routines nil
-  "Holds the procedure routine-info from the .idlwave_catalog library files.")
-(defvar idlwave-library-catalog-libname nil
-  "Name of library catalog loaded from .idlwave_catalog files.")
-(defvar idlwave-path-alist nil
-  "Alist with !PATH directories and zero or more flags if the dir has
-been scanned in a user catalog ('user) or discovered in a library
-catalog \('lib).")
-(defvar idlwave-true-path-alist nil
-  "Like `idlwave-path-alist', but with true filenames.")
-(defvar idlwave-routines nil
-  "Holds the combined procedure/function/method routine-info.")
-(defvar idlwave-class-alist nil
-  "Holds the class names known to IDLWAVE.")
-(defvar idlwave-class-history nil
-  "The history of classes selected with the minibuffer.")
-(defvar idlwave-force-class-query nil)
-(defvar idlwave-before-completion-wconf nil
-  "The window configuration just before the completion buffer was displayed.")
-(defvar idlwave-last-system-routine-info-cons-cell nil
-  "The last cons cell in the system routine info.")
-
-;;
-;; The code to get routine info from different sources.
-
-(defvar idlwave-system-routines)
-(defvar idlwave-catalog-process nil
-  "The background process currently updating the catalog.")
-
-(defun idlwave-routines ()
-  "Provide a list of IDL routines.
-This routine loads the builtin routines on the first call.
-Later it only returns the value of the variable."
-  (if (and idlwave-catalog-process
-          (processp idlwave-catalog-process))
-      (progn
-       (cond
-        ((equal (process-status idlwave-catalog-process) 'exit)
-         (message "updating........")
-         (setq idlwave-catalog-process nil)
-         (idlwave-update-routine-info '(4)))
-        ((equal (process-status idlwave-catalog-process) 'run)
-         ;; Keep it running...
-         )
-        (t
-         ;; Something is wrong, get rid of the process
-         (message "Problem with catalog process") (beep)
-         (condition-case nil
-             (kill-process idlwave-catalog-process)
-           (error nil))
-         (setq idlwave-catalog-process nil)))))
-  (or idlwave-routines
-      (progn
-       (idlwave-update-routine-info)
-       ;; return the current value
-       idlwave-routines)))
-
-(defvar idlwave-update-rinfo-hook nil
-  "List of functions which should run after a global rinfo update.
-Does not run after automatic updates of buffer or the shell.")
-
-(defun idlwave-rescan-catalog-directories ()
-  "Rescan the previously selected directories.  For batch processing."
-  (idlwave-update-routine-info '(16)))
-
-(defun idlwave-rescan-asynchronously ()
-  "Dispatch another Emacs instance to update the idlwave catalog.
-After the process finishes normally, the first access to routine info
-will re-read the catalog."
-  (interactive)
-  (if (processp idlwave-catalog-process)
-      (if (eq (process-status idlwave-catalog-process) 'run)
-         (if (yes-or-no-p "A catalog-updating process is running.  Kill it? ")
-             (progn
-               (condition-case nil
-                   (kill-process idlwave-catalog-process)
-                 (error nil))
-               (error "Process killed, no new process started"))
-           (error "Quit"))
-       (condition-case nil
-           (kill-process idlwave-catalog-process)
-         (error nil))))
-  (if (or (not idlwave-user-catalog-file)
-         (not (stringp idlwave-user-catalog-file))
-         (not (file-regular-p idlwave-user-catalog-file)))
-      (error "No catalog has been produced yet"))
-  (let* ((emacs (concat invocation-directory invocation-name))
-        (args (list "-batch"
-                    "-l" (expand-file-name "~/.emacs")
-                    "-l" "idlwave"
-                    "-f" "idlwave-rescan-catalog-directories"))
-        (process (apply #'start-process "idlcat"
-                        nil emacs args)))
-    (setq idlwave-catalog-process process)
-    (set-process-sentinel
-     process
-     (lambda (_pro why)
-       (when (string-match "finished" why)
-        (setq idlwave-routines nil
-              idlwave-system-routines nil
-              idlwave-catalog-process nil)
-        (or (idlwave-start-load-rinfo-timer)
-            (idlwave-update-routine-info '(4))))))
-    (message "Background job started to update catalog file")))
-
-
-;; Format for all routine info user catalog, library catalogs, etc.:
-;;
-;; ("ROUTINE" type class
-;;  (system) | (lib pro_file dir "LIBNAME") | (user pro_file dir "USERLIB") |
-;;  (buffer pro_file dir) | (compiled pro_file dir)
-;;   "calling_string" ("HELPFILE" (("KWD1" . link1) ...))
-;;                    ("HELPFILE2" (("KWD2" . link) ...)) ...)
-;;
-;; DIR will be supplied dynamically while loading library catalogs,
-;; and is sinterned to save space, as is LIBNAME.  PRO_FILE can be a
-;; complete filepath, in which case DIR is unnecessary.  HELPFILE can
-;; be nil, as can LINK1, etc., if no HTML help is available.
-
-
-(defvar idlwave-load-rinfo-idle-timer)
-(defvar idlwave-shell-path-query)
-
-(defun idlwave-update-routine-info (&optional arg no-concatenate)
-  "Update the internal routine-info lists.
-These lists are used by `idlwave-routine-info' (\\[idlwave-routine-info])
-and by `idlwave-complete' (\\[idlwave-complete]) to provide information
-about individual routines.
-
-The information can come from 4 sources:
-1. IDL programs in the current editing session
-2. Compiled modules in an IDL shell running as Emacs subprocess
-3. A list which covers the IDL system routines.
-4. A list which covers the prescanned library files.
-
-Scans all IDLWAVE-mode buffers of the current editing session (see
-`idlwave-scan-all-buffers-for-routine-info').
-When an IDL shell is running, this command also queries the IDL program
-for currently compiled routines.
-
-With prefix ARG, also reload the system and library lists.
-With two prefix ARG's, also rescans the chosen user catalog tree.
-With three prefix args, dispatch asynchronous process to do the update.
-
-If NO-CONCATENATE is non-nil, don't pre-concatenate the routine info
-lists, but instead wait for the shell query to complete and
-asynchronously finish updating routine info.  This is set
-automatically when called interactively.  When you need routine
-information updated immediately, leave NO-CONCATENATE nil."
-  (interactive "P\np")
-  ;; Stop any idle processing
-  (if (timerp idlwave-load-rinfo-idle-timer)
-      (cancel-timer idlwave-load-rinfo-idle-timer))
-  (cond
-   ((equal arg '(64))
-    ;; Start a background process which updates the catalog.
-    (idlwave-rescan-asynchronously))
-   ((equal arg '(16))
-    ;; Update the user catalog now, and wait for them.
-    (idlwave-create-user-catalog-file t))
-   (t
-    (let* ((load (or arg
-                    idlwave-buffer-case-takes-precedence
-                    (null idlwave-routines)))
-          ;; The override-idle means, even if the idle timer has done some
-          ;; preparing work, load and renormalize everything anyway.
-          (override-idle (or arg idlwave-buffer-case-takes-precedence)))
-
-      (setq idlwave-buffer-routines nil
-           idlwave-compiled-routines nil
-           idlwave-unresolved-routines nil)
-      ;; Reset the appropriate hashes
-      (if (get 'idlwave-reset-sintern 'done-by-idle)
-         ;; reset was already done in idle time, so skip this step now once
-         (put 'idlwave-reset-sintern 'done-by-idle nil)
-       (idlwave-reset-sintern (cond (load t)
-                                    ((null idlwave-system-routines) t)
-                                    (t 'bufsh))))
-
-      (if idlwave-buffer-case-takes-precedence
-         ;; We can safely scan the buffer stuff first
-         (progn
-           (idlwave-update-buffer-routine-info)
-           (and load (idlwave-load-all-rinfo override-idle)))
-       ;; We first do the system info, and then the buffers
-       (and load (idlwave-load-all-rinfo override-idle))
-       (idlwave-update-buffer-routine-info))
-
-      ;; Let's see if there is a shell
-      (let* ((shell-is-running (and (fboundp 'idlwave-shell-is-running)
-                                   (idlwave-shell-is-running)))
-            (ask-shell (and shell-is-running
-                            idlwave-query-shell-for-routine-info)))
-
-       ;; Load the library catalogs again, first re-scanning the path
-       (when arg
-         (if shell-is-running
-             (idlwave-shell-send-command idlwave-shell-path-query
-                                         '(progn
-                                            (idlwave-shell-get-path-info)
-                                            (idlwave-scan-library-catalogs))
-                                         'hide)
-           (idlwave-scan-library-catalogs)))
-
-       (if (or (not ask-shell)
-               (not no-concatenate))
-           ;; 1. If we are not going to ask the shell, we need to do the
-           ;;    concatenation now.
-           ;; 2. When this function is called non-interactively, it
-           ;;    means that someone needs routine info *now*.  The
-           ;;    shell update causes the concatenation to be
-           ;;    *delayed*, so not in time for the current command.
-           ;;    Therefore, we do a concatenation now, even though
-           ;;    the shell might do it again.
-           (idlwave-concatenate-rinfo-lists nil 'run-hooks))
-
-       (when ask-shell
-         ;; Ask the shell about the routines it knows of.
-         (message "Querying the shell")
-         (idlwave-shell-update-routine-info nil t)))))))
-
-
-(defvar idlwave-load-rinfo-steps-done (make-vector 6 nil))
-(defvar idlwave-load-rinfo-idle-timer nil)
-(defun idlwave-start-load-rinfo-timer ()
-  (if (timerp idlwave-load-rinfo-idle-timer)
-      (cancel-timer idlwave-load-rinfo-idle-timer))
-  (setq idlwave-load-rinfo-steps-done (make-vector 6 nil))
-  (setq idlwave-load-rinfo-idle-timer nil)
-  (if (and idlwave-init-rinfo-when-idle-after
-          (numberp idlwave-init-rinfo-when-idle-after)
-          (not (equal 0 idlwave-init-rinfo-when-idle-after))
-          (not idlwave-routines))
-      (condition-case nil
-         (progn
-           (setq idlwave-load-rinfo-idle-timer
-                 (run-with-idle-timer
-                  idlwave-init-rinfo-when-idle-after
-                  nil #'idlwave-load-rinfo-next-step)))
-       (error nil))))
-
-;;------ XML Help routine info system
-(defun idlwave-load-system-routine-info ()
-  ;; Load the system routine info from the cached routine info file,
-  ;; which, if necessary, will be re-created from the XML file on
-  ;; disk.  As a last fallback, load the (likely outdated) idlw-rinfo
-  ;; file distributed with older IDLWAVE versions (<6.0)
-  (unless (and (load idlwave-xml-system-rinfo-converted-file
-                    'noerror 'nomessage)
-              (idlwave-xml-system-routine-info-up-to-date))
-    ;; See if we can create it from XML source
-    (condition-case nil
-       (idlwave-convert-xml-system-routine-info)
-      (error
-       (unless (load idlwave-xml-system-rinfo-converted-file
-                    'noerror 'nomessage)
-        (if idlwave-system-routines
-            (message
-             "Failed to load converted routine info, using old conversion.")
-          (message
-           "Failed to convert XML routine info, falling back on idlw-rinfo.")
-          (if (not (load "idlw-rinfo" 'noerror 'nomessage))
-              (message
-               "Could not locate any system routine information."))))))))
-
-(defun idlwave-xml-system-routine-info-up-to-date()
-  (let* ((dir (file-name-as-directory
-              (expand-file-name "help/online_help" (idlwave-sys-dir))))
-        (catalog-file (expand-file-name "idl_catalog.xml" dir)))
-    (file-newer-than-file-p ;converted file is newer than catalog
-     idlwave-xml-system-rinfo-converted-file
-     catalog-file)))
-
-(defvar idlwave-system-class-info nil) ; Gathered from idlw-rinfo
-(defvar idlwave-system-variables-alist nil
-  "Alist of system variables and the associated structure tags.
-Gets set in cached XML rinfo, or `idlw-rinfo.el'.")
-(defvar idlwave-executive-commands-alist nil
-  "Alist of system variables and their help files.")
-(defvar idlwave-help-special-topic-words nil)
-
-
-(defun idlwave-shorten-syntax (syntax name &optional class)
-  ;; From a list of syntax statements, shorten with %s and group with "or"
-  (let ((case-fold-search t))
-    (mapconcat
-     (lambda (x)
-       (while (string-match name x)
-        (setq x (replace-match "%s" t t x)))
-       (if class
-          (while (string-match class x)
-            (setq x (replace-match "%s" t t x))))
-       x)
-     (nreverse syntax)
-     " or ")))
-
-(defun idlwave-xml-create-class-method-lists (xml-entry)
-  ;; Create a class list entry from the xml parsed list., returning a
-  ;; cons of form (class-entry method-entries).
-  (let* ((nameblock (nth 1 xml-entry))
-        (class (cdr (assq 'name nameblock)))
-        (link (cdr (assq 'link nameblock)))
-        (params (cddr xml-entry))
-        (case-fold-search t)
-        class-entry
-        method methods-entry extra-kwds
-        props get-props set-props init-props inherits
-        pelem ptype)
-    (while params
-      (setq pelem (car params))
-      (when (listp pelem)
-       (setq ptype (car pelem)
-             props (car (cdr pelem)))
-       (cond
-        ((eq ptype 'SUPERCLASS)
-         (let ((pname (cdr (assq 'name props)))
-               (plink (cdr (assq 'link props))))
-           (unless (and (string= pname "None")
-                        (string= plink "None"))
-             (push pname inherits))))
-
-        ((eq ptype 'PROPERTY)
-         (let ((pname (cdr (assq 'name props)))
-               (plink (cdr (assq 'link props)))
-               (get (string= (cdr (assq 'get props)) "Yes"))
-               (set (string= (cdr (assq 'set props)) "Yes"))
-               (init (string= (cdr (assq 'init props)) "Yes")))
-           (if get (push (list pname plink) get-props))
-           (if set (push (list pname plink) set-props))
-           (if init (push (list pname plink) init-props))))
-
-        ((eq ptype 'METHOD)
-         (setq method (cdr (assq 'name props)))
-         (setq extra-kwds ;;Assume all property keywords are gathered already
-               (cond
-                ((string-match (concat class "::Init") method)
-                 (put 'init-props 'matched t)
-                 init-props)
-                ((string-match (concat class "::GetProperty") method)
-                 (put 'get-props 'matched t)
-                 get-props)
-                ((string-match (concat class "::SetProperty") method)
-                 (put 'set-props 'matched t)
-                 set-props)
-                (t nil)))
-         (setq methods-entry
-               (nconc (idlwave-xml-create-rinfo-list pelem class extra-kwds)
-                      methods-entry)))
-        (t)))
-      (setq params (cdr params)))
-    ;;(unless (get 'init-props 'matched)
-    ;;  (message "Failed to match Init in class %s" class))
-    ;;(unless (get 'get-props 'matched)
-    ;;  (message "Failed to match GetProperty in class %s" class))
-    ;;(unless (get 'set-props 'matched)
-    ;;  (message "Failed to match SetProperty in class %s" class))
-    (setq class-entry
-         (if inherits
-             (list class (append '(inherits) inherits) (list 'link link))
-           (list class (list 'link link))))
-    (cons class-entry methods-entry)))
-
-(defun idlwave-xml-create-rinfo-list (xml-entry &optional class extra-kws)
-  ;; Create correctly structured list elements from ROUTINE or METHOD
-  ;; XML list structures.  Return a list of list elements, with more
-  ;; than one sub-list possible if a routine can serve as both
-  ;; procedure and function (e.g. call_method).
-  (let* ((nameblock (nth 1 xml-entry))
-        (name (cdr (assq 'name nameblock)))
-        (link (cdr (assq 'link nameblock)))
-        (params (cddr xml-entry))
-        (syntax-vec (make-vector 3 nil)) ; procedure, function, exec command
-        (case-fold-search t)
-        syntax kwd klink pref-list kwds pelem ptype props result type)
-    (if class ;; strip out class name from class method name string
-       (if (string-match (concat class "::") name)
-           (setq name (substring name (match-end 0)))))
-    (while params
-      (setq pelem (car params))
-      (when (listp pelem)
-       (setq ptype (car pelem)
-             props (car (cdr pelem)))
-       (cond
-        ((eq ptype 'SYNTAX)
-         (setq syntax (cdr (assq 'name props)))
-         (if (string-match "-&gt;" syntax)
-             (setq syntax (replace-match "->" t nil syntax)))
-         (setq type (cdr (assq 'type props)))
-         (push syntax
-               (aref syntax-vec (cond
-                                 ((string-match "^pro" type) 0)
-                                 ((string-match "^fun" type) 1)
-                                 ((string-match "^exec" type) 2)))))
-        ((eq ptype 'KEYWORD)
-         (setq kwd (cdr (assq 'name props))
-               klink (cdr (assq 'link props)))
-         (if (string-match "^\\[XY\\(Z?\\)\\]" kwd)
-             (progn
-               (setq pref-list
-                     (if (match-string 1 kwd) '("X" "Y" "Z") '("X" "Y"))
-                     kwd (substring kwd (match-end 0)))
-               (cl-loop for x in pref-list do
-                     (push (list (concat x kwd) klink) kwds)))
-           (push (list kwd klink) kwds)))
-
-        (t))); Do nothing for the others
-      (setq params (cdr params)))
-
-    ;; Debug
-    ;; (if (and (null (aref syntax-vec 0))
-    ;;          (null (aref syntax-vec 1))
-    ;;          (null (aref syntax-vec 2)))
-    ;;   (with-current-buffer (get-buffer-create "IDL_XML_catalog_complaints")
-    ;;     (if class
-    ;;         (insert (format "Missing SYNTAX entry for %s::%s\n" class name))
-    ;;       (insert (message "Missing SYNTAX entry for %s\n" name)))))
-
-    ;; Executive commands are treated specially
-    (if (aref syntax-vec 2)
-       (cons (substring name 1) link)
-      (if extra-kws (setq kwds (nconc kwds extra-kws)))
-      (setq kwds (idlwave-rinfo-group-keywords kwds link))
-      (cl-loop for idx from 0 to 1 do
-           (if (aref syntax-vec idx)
-               (push (append (list name (if (eq idx 0) 'pro 'fun)
-                                   class '(system)
-                                   (idlwave-shorten-syntax
-                                    (aref syntax-vec idx) name class))
-                             kwds) result)))
-      result)))
-
-
-(defun idlwave-rinfo-group-keywords (kwds master-link)
-  ;; Group keywords by link file, as a list with elements
-  ;; (linkfile ( ("KWD1" . link1) ("KWD2" . link2))
-  (let (kwd link anchor linkfiles block master-elt)
-    (while kwds
-      (setq kwd (car kwds)
-           link (idlwave-split-link-target (nth 1 kwd))
-           anchor (cdr link)
-           link (car link)
-           kwd (car kwd))
-      (if (setq block (assoc link linkfiles))
-         (push (cons kwd anchor) (cdr block))
-       (push (list link (cons kwd anchor)) linkfiles))
-      (setq kwds (cdr kwds)))
-    ;; Ensure the master link is there
-    (if (setq master-elt (assoc master-link linkfiles))
-       (if (eq (car linkfiles) master-elt)
-           linkfiles
-         (cons master-elt (delq master-elt linkfiles)))
-      (push (list master-link) linkfiles))))
-
-(defun idlwave-convert-xml-clean-statement-aliases (aliases)
-  ;; Clean up the syntax of routines which are actually aliases by
-  ;; removing the "OR" from the statements
-  (let (syntax entry)
-    (cl-loop for x in aliases do
-         (setq entry (assoc x idlwave-system-routines))
-         (when entry
-           (while (string-match " +or +" (setq syntax (nth 4 entry)))
-             (setf (nth 4 entry) (replace-match ", " t t syntax)))))))
-
-(defun idlwave-convert-xml-clean-routine-aliases (aliases)
-  ;; Duplicate and trim original routine aliases from rinfo list
-  ;; This if for, e.g. OPENR/OPENW/OPENU
-  (let (alias remove-list new parts all-parts)
-    (cl-loop for x in aliases do
-         (when (setq parts (split-string (cdr x) "/"))
-           (setq new (assoc (cdr x) all-parts))
-           (unless new
-             (setq new (cons (cdr x) parts))
-             (push new all-parts))
-           (setcdr new (delete (car x) (cdr new)))))
-
-    ;; Add any missing aliases (separate by slashes)
-    (cl-loop for x in all-parts do
-         (if (cdr x)
-             (push (cons (nth 1 x) (car x)) aliases)))
-
-    (cl-loop for x in aliases do
-         (when (setq alias (assoc (cdr x) idlwave-system-routines))
-           (unless (memq alias remove-list) (push alias remove-list))
-           (setq alias (copy-sequence alias))
-           (setcar alias (car x))
-           (push alias idlwave-system-routines)))
-    (cl-loop for x in remove-list do
-            (setq idlwave-system-routines (delq x idlwave-system-routines)))))
-
-(defun idlwave-convert-xml-clean-sysvar-aliases (aliases)
-  ;; Duplicate and trim original routine aliases from rinfo list
-  ;; This if for, e.g. !X, !Y, !Z.
-  (let (alias remove-list)
-    (cl-loop for x in aliases do
-         (when (setq alias (assoc (cdr x) idlwave-system-variables-alist))
-           (unless (memq alias remove-list) (push alias remove-list))
-           (setq alias (copy-sequence alias))
-           (setcar alias (car x))
-           (push alias idlwave-system-variables-alist)))
-    (cl-loop for x in remove-list do
-            (setq idlwave-system-variables-alist
-                   (delq x idlwave-system-variables-alist)))))
-
-
-(defun idlwave-xml-create-sysvar-alist (xml-entry)
-  ;; Create a sysvar list entry from the xml parsed list.
-  (let* ((nameblock (nth 1 xml-entry))
-        (name (cdr (assq 'name nameblock)))
-        (sysvar (substring name (progn (string-match "^ *!" name)
-                                       (match-end 0))))
-        (link (cdr (assq 'link nameblock)))
-        (params (cddr xml-entry))
-        (case-fold-search t)
-        pelem ptype props tags)
-    (while params
-      (setq pelem (car params))
-      (when (listp pelem)
-       (setq ptype (car pelem)
-             props (car (cdr pelem)))
-       (cond
-        ((eq ptype 'FIELD)
-         (push (cons (cdr (assq 'name props))
-                     (cdr
-                      (idlwave-split-link-target (cdr (assq 'link props)))))
-               tags))))
-       (setq params (cdr params)))
-    (delq nil
-         (list sysvar (if tags (cons 'tags tags)) (list 'link link)))))
-
-
-(defvar idlwave-xml-routine-info-file nil)
-
-(defun idlwave-save-routine-info ()
-  (if idlwave-xml-routine-info-file
-      (with-temp-file idlwave-xml-system-rinfo-converted-file
-       (insert
-        (concat ";; *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
-;; IDLWAVE Routine Information File (IDLWAVE version " idlwave-mode-version ")
-;; Automatically generated from source file:
-;;  " idlwave-xml-routine-info-file "
-;; on " (current-time-string) "
-;; Do not edit."))
-       (insert (format "\n(setq idlwave-xml-routine-info-file \n    \"%s\")"
-                       idlwave-xml-routine-info-file))
-       (insert "\n(setq idlwave-system-routines\n    '")
-       (prin1 idlwave-system-routines (current-buffer))
-       (insert ")")
-       (insert "\n(setq idlwave-system-variables-alist\n    '")
-       (prin1 idlwave-system-variables-alist (current-buffer))
-       (insert ")")
-       (insert "\n(setq idlwave-system-class-info\n    '")
-       (prin1 idlwave-system-class-info (current-buffer))
-       (insert ")")
-       (insert "\n(setq idlwave-executive-commands-alist\n    '")
-       (prin1 idlwave-executive-commands-alist (current-buffer))
-       (insert ")")
-       (insert "\n(setq idlwave-help-special-topic-words\n    '")
-       (prin1 idlwave-help-special-topic-words (current-buffer))
-       (insert ")"))))
-
-(defun idlwave-convert-xml-system-routine-info ()
-  "Convert XML supplied IDL routine info into internal form.
-Cache to disk for quick recovery."
-  (interactive)
-  (let* ((dir (file-name-as-directory
-              (expand-file-name "help/online_help" (idlwave-sys-dir))))
-        (catalog-file (expand-file-name "idl_catalog.xml" dir))
-        (elem-cnt 0)
-        props rinfo msg-cnt elem type nelem class-result alias
-        routines routine-aliases statement-aliases sysvar-aliases)
-    (if (not (file-exists-p catalog-file))
-       (error "No such XML routine info file: %s" catalog-file)
-      (if (not (file-readable-p catalog-file))
-         (error "Cannot read XML routine info file: %s" catalog-file)))
-    (message "Reading XML routine info...")
-    (setq rinfo (xml-parse-file catalog-file))
-    (message "Reading XML routine info...done")
-    (setq rinfo (assq 'CATALOG rinfo))
-    (unless rinfo (error "Failed to parse XML routine info"))
-    ;;(setq rinfo (car rinfo)) ; Skip the catalog stuff.
-
-    (setq rinfo (cddr rinfo))
-
-    (setq nelem (length rinfo)
-         msg-cnt (/ nelem 20))
-
-    (setq idlwave-xml-routine-info-file nil)
-    (message "Converting XML routine info...")
-    (setq idlwave-system-routines nil
-         idlwave-system-variables-alist nil
-         idlwave-system-class-info nil
-         idlwave-executive-commands-alist nil
-         idlwave-help-special-topic-words nil)
-
-    (while rinfo
-      (setq elem (car rinfo)
-           rinfo (cdr rinfo))
-      (cl-incf elem-cnt)
-      (when (listp elem)
-       (setq type (car elem)
-             props (car (cdr elem)))
-       (if (= (mod elem-cnt msg-cnt) 0)
-           (message "Converting XML routine info...%2d%%"
-                    (floor (* elem-cnt 100.0) nelem)))
-       (cond
-        ((eq type 'ROUTINE)
-         (if (setq alias (assq 'alias_to props))
-             (push (cons (cdr (assq 'name props)) (cdr alias))
-                   routine-aliases)
-           (setq routines (idlwave-xml-create-rinfo-list elem))
-           (if (listp (cdr routines))
-               (setq idlwave-system-routines
-                     (nconc idlwave-system-routines routines))
-             ;; a cons cell is an executive commands
-             (push routines idlwave-executive-commands-alist))))
-
-        ((eq type 'CLASS)
-         (setq class-result (idlwave-xml-create-class-method-lists elem))
-         (push (car class-result) idlwave-system-class-info)
-         (setq idlwave-system-routines
-         (nconc idlwave-system-routines (cdr class-result))))
-
-        ((eq type 'STATEMENT)
-         (push (cons (cdr (assq 'name props))
-                     (cdr (assq 'link props)))
-         idlwave-help-special-topic-words)
-         ;; Save the links to those which are statement aliases (not routines)
-         (if (setq alias (assq 'alias_to props))
-             (unless (member (cdr alias) statement-aliases)
-               (push (cdr alias) statement-aliases))))
-
-        ((eq type 'SYSVAR)
-         (if (setq alias (cdr (assq 'alias_to props)))
-             (push (cons (substring (cdr (assq 'name props)) 1)
-                         (substring alias 1))
-                   sysvar-aliases)
-           (push (idlwave-xml-create-sysvar-alist elem)
-                 idlwave-system-variables-alist)))
-        (t))))
-    (idlwave-convert-xml-clean-routine-aliases routine-aliases)
-    (idlwave-convert-xml-clean-statement-aliases statement-aliases)
-    (idlwave-convert-xml-clean-sysvar-aliases sysvar-aliases)
-
-    (setq idlwave-xml-routine-info-file catalog-file)
-    (idlwave-save-routine-info)
-    (message "Converting XML routine info...done")))
-
-
-;; ("ROUTINE" type class
-;;  (system) | (lib pro_file dir "LIBNAME") | (user pro_file dir "USERLIB") |
-;;  (buffer pro_file dir) | (compiled pro_file dir)
-;;   "calling_string" ("HELPFILE" (("KWD1" . link1) ...))
-;;                    ("HELPFILE2" (("KWD2" . link) ...)) ...)
-
-
-(defun idlwave-load-rinfo-next-step ()
-  (let ((inhibit-quit t)
-       (arr idlwave-load-rinfo-steps-done))
-    (if (catch 'exit
-         (when (not (aref arr 0))
-           (message "Loading system routine info in idle time...")
-           (idlwave-load-system-routine-info)
-           ;;(load "idlw-rinfo" 'noerror 'nomessage)
-           (message "Loading system routine info in idle time...done")
-           (aset arr 0 t)
-           (throw 'exit t))
-
-         (when (not (aref arr 1))
-           (message "Normalizing idlwave-system-routines in idle time...")
-           (idlwave-reset-sintern t)
-           (put 'idlwave-reset-sintern 'done-by-idle t)
-           (setq idlwave-system-routines
-                 (idlwave-sintern-rinfo-list idlwave-system-routines 'sys))
-           (message "Normalizing idlwave-system-routines in idle time...done")
-           (aset arr 1 t)
-           (throw 'exit t))
-
-         (when (not (aref arr 2))
-           (when (and (stringp idlwave-user-catalog-file)
-                      (file-regular-p idlwave-user-catalog-file))
-             (message "Loading user catalog in idle time...")
-             (condition-case nil
-                 (load-file idlwave-user-catalog-file)
-               (error (throw 'exit nil)))
-             ;; Check for the old style catalog and warn
-             (if (and
-                  (boundp 'idlwave-library-routines)
-                  idlwave-library-routines)
-                 (progn
-                   (setq idlwave-library-routines nil)
-                   (ding)
-                   (message "Outdated user catalog: %s... recreate"
-                            idlwave-user-catalog-file))
-               (message "Loading user catalog in idle time...done")))
-           (aset arr 2 t)
-           (throw 'exit t))
-
-         (when (not (aref arr 3))
-           (when idlwave-user-catalog-routines
-             (message "Normalizing user catalog routines in idle time...")
-             (setq idlwave-user-catalog-routines
-                   (idlwave-sintern-rinfo-list
-                    idlwave-user-catalog-routines 'sys))
-             (message
-              "Normalizing user catalog routines in idle time...done"))
-           (aset arr 3 t)
-           (throw 'exit t))
-
-         (when (not (aref arr 4))
-           (idlwave-scan-library-catalogs
-            "Loading and normalizing library catalogs in idle time...")
-           (aset arr 4 t)
-           (throw 'exit t))
-         (when (not (aref arr 5))
-           (message "Finishing initialization in idle time...")
-           (idlwave-routines)
-           (message "Finishing initialization in idle time...done")
-           (aset arr 5 t)
-           (throw 'exit nil)))
-       ;; restart the timer
-       (if (sit-for 1)
-           (idlwave-load-rinfo-next-step)
-         (setq idlwave-load-rinfo-idle-timer
-               (run-with-idle-timer
-                idlwave-init-rinfo-when-idle-after
-                nil #'idlwave-load-rinfo-next-step))))))
-
-(defvar idlwave-after-load-rinfo-hook nil)
-
-(defun idlwave-load-all-rinfo (&optional force)
-  ;; Load and case-treat the system, user catalog, and library routine
-  ;; info files.
-
-  ;; System
-  (when (or force (not (aref idlwave-load-rinfo-steps-done 0)))
-    ;;(load "idlw-rinfo" 'noerror 'nomessage))
-    (idlwave-load-system-routine-info))
-  (when (or force (not (aref idlwave-load-rinfo-steps-done 1)))
-    (message "Normalizing idlwave-system-routines...")
-    (setq idlwave-system-routines
-         (idlwave-sintern-rinfo-list idlwave-system-routines 'sys))
-    (message "Normalizing idlwave-system-routines...done"))
-  (when idlwave-system-routines
-    (setq idlwave-routines (copy-sequence idlwave-system-routines))
-    (setq idlwave-last-system-routine-info-cons-cell
-         (nthcdr (1- (length idlwave-routines)) idlwave-routines)))
-
-  ;; User catalog
-  (when (and (stringp idlwave-user-catalog-file)
-            (file-regular-p idlwave-user-catalog-file))
-    (condition-case nil
-       (when (or force (not (aref idlwave-load-rinfo-steps-done 2)))
-         (load-file idlwave-user-catalog-file))
-      (error nil))
-    (when (and
-          (boundp 'idlwave-library-routines)
-          idlwave-library-routines)
-      (setq idlwave-library-routines nil)
-      (error "Outdated user catalog: %s... recreate"
-            idlwave-user-catalog-file))
-    (setq idlwave-true-path-alist nil)
-    (when (or force (not (aref idlwave-load-rinfo-steps-done 3)))
-      (message "Normalizing user catalog routines...")
-      (setq idlwave-user-catalog-routines
-           (idlwave-sintern-rinfo-list
-            idlwave-user-catalog-routines 'sys))
-      (message "Normalizing user catalog routines...done")))
-
-  ;; Library catalog
-  (when (or force (not (aref idlwave-load-rinfo-steps-done 4)))
-    (idlwave-scan-library-catalogs
-     "Loading and normalizing library catalogs..."))
-  (run-hooks 'idlwave-after-load-rinfo-hook))
-
-
-(defun idlwave-update-buffer-routine-info ()
-  (let (res)
-    (cond
-     ((eq idlwave-scan-all-buffers-for-routine-info t)
-      ;; Scan all buffers, current buffer last
-      (message "Scanning all buffers...")
-      (setq res (idlwave-get-routine-info-from-buffers
-                (reverse (buffer-list)))))
-     ((null idlwave-scan-all-buffers-for-routine-info)
-      ;; Don't scan any buffers
-      (setq res nil))
-     (t
-      ;; Just scan this buffer
-      (if (derived-mode-p 'idlwave-mode)
-         (progn
-           (message "Scanning current buffer...")
-           (setq res (idlwave-get-routine-info-from-buffers
-                      (list (current-buffer))))))))
-    ;; Put the result into the correct variable
-    (setq idlwave-buffer-routines
-         (idlwave-sintern-rinfo-list res 'set))))
-
-(defun idlwave-concatenate-rinfo-lists (&optional quiet run-hook)
-  "Put the different sources for routine information together."
-  ;; The sequence here is important because earlier definitions shadow
-  ;; later ones.  We assume that if things in the buffers are newer
-  ;; then in the shell of the system, they are meant to be different.
-  (let ((temp (append idlwave-buffer-routines
-                     idlwave-compiled-routines
-                     idlwave-library-catalog-routines
-                     idlwave-user-catalog-routines)))
-    ;; Not actually used for anything?
-    (if idlwave-last-system-routine-info-cons-cell
-       (setcdr idlwave-last-system-routine-info-cons-cell temp)
-      (setq idlwave-last-system-routine-info-cons-cell (cons temp nil))))
-  (setq idlwave-class-alist nil)
-
-  ;; Give a message with information about the number of routines we have.
-  (unless quiet
-    (message
-     "Routines Found: buffer(%d) compiled(%d) library(%d) user(%d) system(%d)"
-     (length idlwave-buffer-routines)
-     (length idlwave-compiled-routines)
-     (length idlwave-library-catalog-routines)
-     (length idlwave-user-catalog-routines)
-     (length idlwave-system-routines)))
-  (if run-hook
-      (run-hooks 'idlwave-update-rinfo-hook)))
-
-(defun idlwave-class-alist ()
-  "Return the class alist - make it if necessary."
-  (or idlwave-class-alist
-      (let (class)
-       (cl-loop for x in idlwave-routines do
-         (when (and (setq class (nth 2 x))
-                    (not (assq class idlwave-class-alist)))
-           (push (list class) idlwave-class-alist)))
-       idlwave-class-alist)))
-
-;; Three functions for the hooks
-(defun idlwave-save-buffer-update ()
-  (idlwave-update-current-buffer-info 'save-buffer))
-(defun idlwave-kill-buffer-update ()
-  (idlwave-update-current-buffer-info 'kill-buffer))
-(defun idlwave-new-buffer-update ()
-  (idlwave-update-current-buffer-info 'find-file))
-
-(defun idlwave-update-current-buffer-info (why)
-  "Update `idlwave-routines' for current buffer.
-Can run from `after-save-hook'."
-  (when (and (derived-mode-p 'idlwave-mode)
-            (or (eq t idlwave-auto-routine-info-updates)
-                (memq why idlwave-auto-routine-info-updates))
-            idlwave-scan-all-buffers-for-routine-info
-            idlwave-routines)
-    (condition-case nil
-       (let (routines)
-         (idlwave-replace-buffer-routine-info
-          (buffer-file-name)
-          (if (eq why 'kill-buffer)
-              nil
-            (setq routines
-                  (idlwave-sintern-rinfo-list
-                   (idlwave-get-routine-info-from-buffers
-                    (list (current-buffer))) 'set))))
-         (idlwave-concatenate-rinfo-lists 'quiet)
-         routines)
-      (error nil))))
-
-(defun idlwave-replace-buffer-routine-info (file new)
-  "Cut the part from FILE out of `idlwave-buffer-routines' and add NEW."
-  (let ((list idlwave-buffer-routines)
-       found)
-    (while list
-      ;; The following test uses eq to make sure it works correctly
-      ;; when two buffers visit the same file.  Then the file names
-      ;; will be equal, but not eq.
-      (if (eq (idlwave-routine-source-file (nth 3 (car list))) file)
-         (progn
-           (setcar list nil)
-           (setq found t))
-       (if found
-           ;; End of that section reached. Jump.
-           (setq list nil)))
-      (setq list (cdr list)))
-    (setq idlwave-buffer-routines
-         (append new (delq nil idlwave-buffer-routines)))))
-
-;;----- Scanning buffers -------------------
-
-(defun idlwave-get-routine-info-from-buffers (buffers)
-  "Call `idlwave-get-buffer-routine-info' on `idlwave-mode' buffers in BUFFERS."
-  (let (buf routine-lists res)
-    (save-excursion
-      (while (setq buf (pop buffers))
-       (set-buffer buf)
-       (if (and (derived-mode-p 'idlwave-mode)
-                buffer-file-name)
-           ;; yes, this buffer has the right mode.
-           (progn (setq res (condition-case nil
-                                (idlwave-get-buffer-routine-info)
-                              (error nil)))
-                  (push res routine-lists)))))
-    ;; Concatenate the individual lists and return the result
-    (apply #'nconc routine-lists)))
-
-(defun idlwave-get-buffer-routine-info ()
-  "Scan the current buffer for routine info.  Return (PRO-LIST FUNC-LIST)."
-  (let* ((case-fold-search t)
-        routine-list string entry)
-    (save-excursion
-      (save-restriction
-       (widen)
-       (goto-char (point-min))
-       (while (re-search-forward
-               "^[ \t]*\\(pro\\|function\\)[ \t]" nil t)
-         (setq string (buffer-substring-no-properties
-                       (match-beginning 0)
-                       (progn
-                         (idlwave-end-of-statement)
-                         (point))))
-         (setq entry (idlwave-parse-definition string))
-         (push entry routine-list))))
-    routine-list))
-
-(defvar idlwave-scanning-lib-dir)
-(defvar idlwave-scanning-lib)
-(defun idlwave-parse-definition (string)
-  "Parse a module definition."
-  (let ((case-fold-search t)
-       start name args type keywords class)
-    ;; Remove comments
-    (while (string-match ";.*" string)
-      (setq string (replace-match "" t t string)))
-    ;; Remove the continuation line stuff
-    (while (string-match "\\([^a-zA-Z0-9$_]\\)\\$[ \t]*\n" string)
-      (setq string (replace-match "\\1 " t nil string)))
-    (while (string-match "\n" string)
-      (setq string (replace-match " " t nil string)))
-    ;; Match the name and type.
-    (when (string-match
-          "\\<\\(pro\\|function\\)\\>\\s-+\\(\\([a-zA-Z0-9$_]+\\)::\\)?\\([a-zA-Z0-9$_]+\\)" string)
-      (setq start (match-end 0))
-      (setq type (downcase (match-string 1 string)))
-      (if (match-beginning 3)
-         (setq class (match-string 3 string)))
-      (setq name (match-string 4 string)))
-    ;; Match normal args and keyword args
-    (while (string-match
-           ",\\s-*\\([a-zA-Z][a-zA-Z0-9$_]*\\|\\(_ref\\)?_extra\\)\\s-*\\(=\\)?"
-           string start)
-      (setq start (match-end 0))
-      (if (match-beginning 3)
-         (push (match-string 1 string) keywords)
-       (push (match-string 1 string) args)))
-    ;; Normalize and sort.
-    (setq args (nreverse args))
-    (setq keywords (sort keywords (lambda (a b)
-                                   (string< (downcase a) (downcase b)))))
-    ;; Make and return the entry
-    ;; We don't know which argument are optional, so this information
-    ;; will not be contained in the calling sequence.
-    (list name
-         (if (equal type "pro") 'pro 'fun)
-         class
-         (cond ((not (boundp 'idlwave-scanning-lib))
-                (list  'buffer (buffer-file-name)))
-;              ((string= (downcase (file-name-base (buffer-file-name))
-;                        (downcase name))
-;               (list 'lib))
-;              (t (cons 'lib (file-name-nondirectory (buffer-file-name))))
-               (t (list 'user (file-name-nondirectory (buffer-file-name))
-                        idlwave-scanning-lib-dir "UserLib")))
-         (concat
-          (if (string= type "function") "Result = " "")
-          (if class "Obj ->[%s::]" "")
-          "%s"
-          (if args
-              (concat
-               (if (string= type "function") "(" ", ")
-               (mapconcat #'identity args ", ")
-               (if (string= type "function") ")" ""))))
-         (if keywords
-             (cons nil (mapcar #'list keywords)) ;No help file
-           nil))))
-
-
-;;----- Scanning the user catalog -------------------
-
-(defun idlwave-sys-dir ()
-  "Return the syslib directory, or a dummy that never matches."
-  (cond
-   ((and idlwave-system-directory
-        (not (string= idlwave-system-directory "")))
-    idlwave-system-directory)
-   ((getenv "IDL_DIR"))
-   (t "@@@@@@@@")))
-
-
-(defun idlwave-create-user-catalog-file (&optional arg)
-  "Scan all files on selected dirs of IDL search path for routine information.
-
-A widget checklist will allow you to choose the directories.  Write
-the result as a file `idlwave-user-catalog-file'.  When this file
-exists, it will be automatically loaded to give routine information
-about library routines.  With ARG, just rescan the same directories
-as last time - so no widget will pop up."
-  (interactive "P")
-  ;; Make sure the file is loaded if it exists.
-  (if (and (stringp idlwave-user-catalog-file)
-          (file-regular-p idlwave-user-catalog-file))
-      (condition-case nil
-         (load-file idlwave-user-catalog-file)
-       (error nil)))
-  ;; Make sure the file name makes sense
-  (unless (and (stringp idlwave-user-catalog-file)
-              (> (length idlwave-user-catalog-file) 0)
-              (file-accessible-directory-p
-               (file-name-directory idlwave-user-catalog-file))
-              (not (string= "" (file-name-nondirectory
-                                idlwave-user-catalog-file))))
-    (error "`idlwave-user-catalog-file' does not point to a file in an accessible directory"))
-
-  (cond
-    ;; Rescan the known directories
-   ((and arg idlwave-path-alist
-        (consp (car idlwave-path-alist)))
-    (idlwave-scan-user-lib-files idlwave-path-alist))
-
-   ;; Expand the directories from library-path and run the widget
-   (idlwave-library-path
-    (idlwave-display-user-catalog-widget
-     (if idlwave-true-path-alist
-        ;; Propagate any flags on the existing path-alist
-        (mapcar (lambda (x)
-                  (let ((path-entry (assoc (file-truename x)
-                                           idlwave-true-path-alist)))
-                    (if path-entry
-                        (cons x (cdr path-entry))
-                      (list x))))
-                (idlwave-expand-path idlwave-library-path))
-       (mapcar #'list (idlwave-expand-path idlwave-library-path)))))
-
-   ;; Ask the shell for the path and then run the widget
-   (t
-    (message "Asking the shell for IDL path...")
-    (require 'idlw-shell)
-    (idlwave-shell-send-command idlwave-shell-path-query
-                               '(idlwave-user-catalog-command-hook nil)
-                               'hide))))
-
-
-;; Parse shell path information and select among it.
-(defun idlwave-user-catalog-command-hook (&optional arg)
-  ;; Command hook used by `idlwave-create-user-catalog-file'.
-  (if arg
-      ;; Scan immediately
-      (idlwave-scan-user-lib-files idlwave-path-alist)
-    ;; Set the path and display the widget
-    (idlwave-shell-get-path-info 'no-write) ; set to something path-alist
-    (idlwave-scan-library-catalogs "Locating library catalogs..." 'no-load)
-    (idlwave-display-user-catalog-widget idlwave-path-alist)))
-
-(defconst idlwave-user-catalog-widget-help-string
-  "This is the front-end to the creation of the IDLWAVE user catalog.
-Please select the directories on IDL's search path from which you
-would like to extract routine information, to be stored in the file:
-
-             %s
-
-If this is not the correct file, first set variable
-`idlwave-user-catalog-file', and call this command again.
-
-N.B. Many libraries include pre-scanned catalog files
-\(\".idlwave_catalog\").  These are marked with \"[LIB]\", and need
-not be scanned.  You can scan your own libraries off-line using the
-perl script `idlwave_catalog'.
-
-After selecting the directories, choose [Scan & Save] to scan the library
-directories and save the routine info.
-\n")
-
-(defvar idlwave-widget)
-(defvar widget-keymap)
-(defun idlwave-display-user-catalog-widget (dirs-list)
-  "Create the widget to select IDL search path directories for scanning."
-  (interactive)
-  (require 'widget)
-  (require 'wid-edit)
-  (unless dirs-list
-      (error "Don't know IDL's search path"))
-
-  (kill-buffer (get-buffer-create "*IDLWAVE Widget*"))
-  (switch-to-buffer (get-buffer-create "*IDLWAVE Widget*"))
-  (kill-all-local-variables)
-  (make-local-variable 'idlwave-widget)
-  (widget-insert (format idlwave-user-catalog-widget-help-string
-                        idlwave-user-catalog-file))
-
-  (widget-create 'push-button
-                :notify 'idlwave-widget-scan-user-lib-files
-                "Scan & Save")
-  (widget-insert "  ")
-  (widget-create 'push-button
-                :notify 'idlwave-delete-user-catalog-file
-                "Delete File")
-  (widget-insert "  ")
-  (widget-create 'push-button
-                :notify
-                (lambda (&rest _ignore)
-                   (let ((path-list (widget-get idlwave-widget :path-dirs)))
-                     (dolist (x path-list)
-                       (unless (memq 'lib (cdr x))
-                         (idlwave-path-alist-add-flag x 'user)))
-                     (idlwave-display-user-catalog-widget path-list)))
-                "Select All Non-Lib")
-  (widget-insert "  ")
-  (widget-create 'push-button
-                :notify
-                (lambda (&rest _ignore)
-                   (let ((path-list (widget-get idlwave-widget :path-dirs)))
-                     (dolist (x path-list)
-                       (idlwave-path-alist-remove-flag x 'user))
-                     (idlwave-display-user-catalog-widget path-list)))
-                "Deselect All")
-  (widget-insert "  ")
-  (widget-create 'push-button
-                :notify (lambda (&rest _ignore)
-                          (kill-buffer (current-buffer)))
-                "Quit")
-  (widget-insert "\n\n")
-
-  (widget-insert "Select Directories: \n")
-
-  (setq idlwave-widget
-       (apply #'widget-create
-              'checklist
-              :value  (delq nil (mapcar (lambda (x)
-                                          (if (memq 'user (cdr x))
-                                              (car x)))
-                                        dirs-list))
-              :greedy t
-              :tag "List of directories"
-              (mapcar (lambda (x)
-                        (list 'item
-                              (if (memq 'lib (cdr x))
-                                  (concat "[LIB] " (car x) )
-                                (car x))))
-                      dirs-list)))
-  (widget-put idlwave-widget :path-dirs dirs-list)
-  (widget-insert "\n")
-  (use-local-map widget-keymap)
-  (widget-setup)
-  (goto-char (point-min))
-  (delete-other-windows))
-
-(defun idlwave-delete-user-catalog-file (&rest _ignore)
-  (if (yes-or-no-p
-       (format "Delete file %s?" idlwave-user-catalog-file))
-      (progn
-       (delete-file idlwave-user-catalog-file)
-       (message "%s has been deleted" idlwave-user-catalog-file))))
-
-(defun idlwave-widget-scan-user-lib-files (&rest _ignore)
-  ;; Call `idlwave-scan-user-lib-files' with data taken from the widget.
-  (let* ((widget idlwave-widget)
-        (selected-dirs (widget-value widget))
-        (path-alist (widget-get widget :path-dirs))
-        (this-path-alist path-alist)
-        dir-entry)
-    (while (setq dir-entry (pop this-path-alist))
-      (if (member
-          (if (memq 'lib (cdr dir-entry))
-              (concat "[LIB] " (car dir-entry))
-            (car dir-entry))
-          selected-dirs)
-         (idlwave-path-alist-add-flag dir-entry 'user)
-       (idlwave-path-alist-remove-flag dir-entry 'user)))
-    (idlwave-scan-user-lib-files path-alist)))
-
-(defun idlwave-scan-user-lib-files (path-alist)
-  ;; Scan the PRO files in PATH-ALIST and store the info in the user catalog
-  (let* ((idlwave-scanning-lib t)
-        (idlwave-scanning-lib-dir "")
-        (idlwave-completion-case nil)
-        dirs-alist dir files file)
-    (setq idlwave-user-catalog-routines nil
-         idlwave-path-alist path-alist ; for library-path instead
-         idlwave-true-path-alist nil)
-    (if idlwave-auto-write-paths (idlwave-write-paths))
-    (with-current-buffer (get-buffer-create "*idlwave-scan.pro*")
-      (idlwave-mode)
-      (setq dirs-alist (reverse path-alist))
-      (while (setq dir (pop dirs-alist))
-       (when (memq 'user (cdr dir))    ; Has it marked for scan?
-         (setq dir (car dir))
-         (setq idlwave-scanning-lib-dir dir)
-         (when (file-directory-p dir)
-           (setq files (directory-files dir 'full "\\.[pP][rR][oO]\\'"))
-           (while (setq file (pop files))
-             (when (file-regular-p file)
-               (if (not (file-readable-p file))
-                   (message "Skipping %s (no read permission)" file)
-                 (message "Scanning %s..." file)
-                 (erase-buffer)
-                 (insert-file-contents file 'visit)
-                 (setq idlwave-user-catalog-routines
-                       (append (idlwave-get-routine-info-from-buffers
-                                (list (current-buffer)))
-                               idlwave-user-catalog-routines)))))))))
-    (message "Creating user catalog file...")
-    (kill-buffer "*idlwave-scan.pro*")
-    (kill-buffer (get-buffer-create "*IDLWAVE Widget*"))
-    (with-temp-buffer
-      (insert ";; IDLWAVE user catalog file\n")
-      (insert (format ";; Created %s\n\n" (current-time-string)))
-
-      ;; Define the routine info list
-      (insert "\n(setq idlwave-user-catalog-routines\n    '(")
-      (let ((standard-output (current-buffer)))
-       (mapc (lambda (x)
-               (insert "\n    ")
-               (prin1 x)
-               (goto-char (point-max)))
-             idlwave-user-catalog-routines))
-      (insert (format "))\n\n;;; %s ends here\n"
-                     (file-name-nondirectory idlwave-user-catalog-file)))
-      (write-region nil nil idlwave-user-catalog-file)))
-  (message "Creating user catalog file...done")
-  (message "Info for %d routines saved in %s"
-          (length idlwave-user-catalog-routines)
-          idlwave-user-catalog-file)
-  (sit-for 2)
-  (idlwave-update-routine-info t))
-
-(defun idlwave-read-paths ()
-  (if (and (stringp idlwave-path-file)
-          (file-regular-p idlwave-path-file))
-      (condition-case nil
-         (load idlwave-path-file t t t)
-       (error nil))))
-
-(defun idlwave-write-paths ()
-  (interactive)
-  (when (and idlwave-path-alist idlwave-system-directory)
-    (with-temp-buffer
-      (insert ";; IDLWAVE paths\n")
-      (insert (format ";; Created %s\n\n" (current-time-string)))
-    ;; Define the variable which knows the value of "!DIR"
-      (insert (format "\n(setq idlwave-system-directory \"%s\")\n"
-                     idlwave-system-directory))
-
-      ;; Define the variable which contains a list of all scanned directories
-      (insert "\n(setq idlwave-path-alist\n    '(")
-      (let ((standard-output (current-buffer)))
-       (mapc (lambda (x)
-               (insert "\n      ")
-               (prin1 x)
-               (goto-char (point-max)))
-             idlwave-path-alist))
-      (insert "))\n")
-      (write-region nil nil idlwave-path-file))))
-
-(defun idlwave-expand-path (path &optional default-dir)
-  ;; Expand parts of path starting with '+' recursively into directory list.
-  ;; Relative recursive path elements are expanded relative to DEFAULT-DIR.
-  (message "Expanding path...")
-  (let (path1 dir recursive)
-    (while (setq dir (pop path))
-      (if (setq recursive (string= (substring dir 0 1) "+"))
-         (setq dir (substring dir 1)))
-      (if (and recursive
-              (not (file-name-absolute-p dir)))
-         (setq dir (expand-file-name dir default-dir)))
-      (if recursive
-         ;; Expand recursively
-         (setq path1 (append (idlwave-recursive-directory-list dir) path1))
-       ;; Keep unchanged
-       (push dir path1)))
-    (message "Expanding path...done")
-    (nreverse path1)))
-
-(defun idlwave-recursive-directory-list (dir)
-  ;; Return a list of all directories below DIR, including DIR itself
-  (let ((path (list dir)) path1 file files)
-    (while (setq dir (pop path))
-      (when (file-directory-p dir)
-       (setq files (nreverse (directory-files dir t "[^.]")))
-       (while (setq file (pop files))
-         (if (file-directory-p file)
-             (push (file-name-as-directory file) path)))
-       (push dir path1)))
-    path1))
-
-
-;;----- Scanning the library catalogs ------------------
-
-
-
-
-(defun idlwave-scan-library-catalogs (&optional message-base no-load)
-  "Scan for library catalog files (.idlwave_catalog) and ingest.
-
-All directories on `idlwave-path-alist' (or `idlwave-library-path'
-instead, if present) are searched.  Print MESSAGE-BASE along with the
-libraries being loaded, if passed, and skip loading/normalizing if
-NO-LOAD is non-nil.  The variable `idlwave-use-library-catalogs' can
-be set to nil to disable library catalog scanning."
-  (when idlwave-use-library-catalogs
-    (let ((dirs
-          (if idlwave-library-path
-              (idlwave-expand-path idlwave-library-path)
-            (mapcar #'car idlwave-path-alist)))
-         (old-libname "")
-         dir-entry dir catalog all-routines)
-      (if message-base (message "%s" message-base))
-      (while (setq dir (pop dirs))
-       (catch 'continue
-         (when (file-readable-p
-                (setq catalog (expand-file-name ".idlwave_catalog" dir)))
-           (unless no-load
-             (setq idlwave-library-catalog-routines nil)
-             ;; Load the catalog file
-             (condition-case nil
-                 (load catalog t t t)
-               (error (throw 'continue t)))
-             (when (and
-                    message-base
-                    (not (string= idlwave-library-catalog-libname
-                                  old-libname)))
-               (message "%s%s" message-base idlwave-library-catalog-libname)
-               (setq old-libname idlwave-library-catalog-libname))
-             (when idlwave-library-catalog-routines
-               (setq all-routines
-                     (append
-                      (idlwave-sintern-rinfo-list
-                       idlwave-library-catalog-routines 'sys dir)
-                      all-routines))))
-
-           ;;  Add a 'lib flag if on path-alist
-           (when (and idlwave-path-alist
-                      (setq dir-entry (assoc dir idlwave-path-alist)))
-             (idlwave-path-alist-add-flag dir-entry 'lib)))))
-      (unless no-load (setq idlwave-library-catalog-routines all-routines))
-      (if message-base (message "%sdone" message-base)))))
-
-;;----- Communicating with the Shell -------------------
-
-;; First, here is the idl program which can be used to query IDL for
-;; defined routines.
-(defconst idlwave-routine-info.pro
-  "
-;; START OF IDLWAVE SUPPORT ROUTINES
-pro idlwave_print_safe,item,limit
-  catch,err
-  if err ne 0 then begin
-     print,'Could not print item.'
-     return
-  endif
-  if n_elements(item) gt limit then $
-     print,item[0:limit-1],'<... truncated at ',strtrim(limit,2),' elements>' $
-  else print,item
-end
-
-pro idlwave_print_info_entry,name,func=func,separator=sep
-  ;; See if it's an object method
-  if name eq '' then return
-  func    = keyword_set(func)
-  methsep = strpos(name,'::')
-  meth    = methsep ne -1
-
-  ;; Get routine info
-  pars   = routine_info(name,/parameters,functions=func)
-  source = routine_info(name,/source,functions=func)
-  nargs  = pars.num_args
-  nkw    = pars.num_kw_args
-  if nargs gt 0 then args = pars.args
-  if nkw   gt 0 then kwargs = pars.kw_args
-
-  ;; Trim the class, and make the name
-  if meth then begin
-      class = strmid(name,0,methsep)
-      name  = strmid(name,methsep+2,strlen(name)-1)
-      if nargs gt 0 then begin
-          ;; remove the self argument
-          wh = where(args ne 'SELF',nargs)
-          if nargs gt 0 then args = args[wh]
-      endif
-  endif else begin
-      ;; No class, just a normal routine.
-      class = \"\"
-  endelse
-
-  ;; Calling sequence
-  cs = \"\"
-  if func then cs = 'Result = '
-  if meth then cs = cs + 'Obj -> [' + '%s' + '::]'
-  cs = cs + '%s'
-  if func then cs = cs + '(' else if nargs gt 0 then cs = cs + ', '
-  if nargs gt 0 then begin
-      for j=0,nargs-1 do begin
-          cs = cs + args[j]
-          if j lt nargs-1 then cs = cs + ', '
-      endfor
-  end
-  if func then cs = cs + ')'
-  ;; Keyword arguments
-  kwstring = ''
-  if nkw gt 0 then begin
-      for j=0,nkw-1 do begin
-          kwstring = kwstring + ' ' + kwargs[j]
-      endfor
-  endif
-
-  ret=(['IDLWAVE-PRO','IDLWAVE-FUN'])[func]
-
-  print,ret + ': ' + name + sep + class + sep + source[0].path  $
-    + sep + cs + sep + kwstring
-end
-
-pro idlwave_routine_info,file
-  on_error,1
-  sep = '<@>'
-  print,'>>>BEGIN OF IDLWAVE ROUTINE INFO (\"' + sep + '\" IS THE SEPARATOR)'
-  all = routine_info()
-  fileQ=n_elements(file) ne 0
-  if fileQ then file=strtrim(file,2)
-  for i=0L,n_elements(all)-1L do begin
-     if fileQ then begin
-        if (routine_info(all[i],/SOURCE)).path eq file then $
-           idlwave_print_info_entry,all[i],separator=sep
-     endif else idlwave_print_info_entry,all[i],separator=sep
-  endfor
-  all = routine_info(/functions)
-  for i=0L,n_elements(all)-1L do begin
-     if fileQ then begin
-        if (routine_info(all[i],/FUNCTIONS,/SOURCE)).path eq file then $
-           idlwave_print_info_entry,all[i],separator=sep,/FUNC
-     endif else idlwave_print_info_entry,all[i],separator=sep,/FUNC
-  endfor
-  print,'>>>END OF IDLWAVE ROUTINE INFO'
-end
-
-pro idlwave_get_sysvars
-  on_error,1
-  catch,error_status
-  if error_status ne 0 then begin
-      print, 'Cannot get info about system variables'
-  endif else begin
-      help,/brief,output=s,/system_variables  ; ? unsafe use of OUTPUT=
-      s = strtrim(strjoin(s,' ',/single),2)   ; make one line
-      v = strsplit(s,' +',/regex,/extract)    ; get variables
-      for i=0L,n_elements(v)-1 do begin
-          t = ['']                            ; get tag list
-          a=execute('if n_tags('+v[i]+') gt 0 then t=tag_names('+v[i]+')')
-          print, 'IDLWAVE-SYSVAR: '+v[i]+' '+strjoin(t,' ',/single)
-      endfor
-  endelse
-end
-
-pro idlwave_get_class_tags, class
-  res = execute('tags=tag_names({'+class+'})')
-  if res then print,'IDLWAVE-CLASS-TAGS: '+class+' '+strjoin(tags,' ',/single)
-end
-;; END OF IDLWAVE SUPPORT ROUTINES
-"
-  "The IDL programs to get info from the shell.")
-
-(defvar idlwave-idlwave_routine_info-compiled nil
-  "Remember if the routine info procedure is already compiled.")
-
-(defvar idlwave-shell-temp-pro-file)
-(defvar idlwave-shell-temp-rinfo-save-file)
-
-(defun idlwave-shell-compile-helper-routines (&optional wait)
-  (unless (and idlwave-idlwave_routine_info-compiled
-              (file-readable-p (idlwave-shell-temp-file 'rinfo)))
-    (with-current-buffer (idlwave-find-file-noselect
-                          (idlwave-shell-temp-file 'pro))
-      (erase-buffer)
-      (insert idlwave-routine-info.pro)
-      (save-buffer 0))
-    (idlwave-shell-send-command
-     (concat ".run \"" idlwave-shell-temp-pro-file "\"")
-     nil 'hide wait)
-    (idlwave-shell-send-command
-     (format "save,'idlwave_print_safe','idlwave_routine_info','idlwave_print_info_entry','idlwave_get_class_tags','idlwave_get_sysvars',FILE='%s',/ROUTINES"
-            (idlwave-shell-temp-file 'rinfo))
-     nil 'hide)
-    (setq idlwave-idlwave_routine_info-compiled t))
-
-  ;; Restore if necessary.  Must use execute to hide lame routine_info
-  ;; errors on undefined routine
-  (idlwave-shell-send-command
-   (format "if execute(\"_v=routine_info('idlwave_routine_info',/SOURCE)\") eq 0 then restore,'%s' else if _v.path eq '' then restore,'%s'"
-          idlwave-shell-temp-rinfo-save-file
-          idlwave-shell-temp-rinfo-save-file)
-   nil 'hide))
-
-
-(defun idlwave-shell-update-routine-info (&optional quiet run-hooks wait file)
-  "Query the shell for routine_info of compiled modules and update the lists."
-  ;; Save and compile the procedure.  The compiled procedure is then
-  ;; saved into an IDL SAVE file, to allow for fast RESTORE.  We may
-  ;; need to test for and possibly RESTORE the procedure each time we
-  ;; use it, since the user may have killed or redefined it.  In
-  ;; particular, .RESET_SESSION will kill all user procedures.  If
-  ;; FILE is set, only update routine info for routines in that file.
-
-  (idlwave-shell-compile-helper-routines wait)
-  ; execute the routine_info procedure, and analyze the output
-  (idlwave-shell-send-command
-   (format "idlwave_routine_info%s" (if file (concat ",'" file "'") ""))
-   `(progn
-      (idlwave-shell-routine-info-filter)
-      (idlwave-concatenate-rinfo-lists ,quiet ,run-hooks))
-   'hide wait))
-
-;; ---------------------------------------------------------------------------
-;;
-;; Completion and displaying routine calling sequences
-
-(defvar idlwave-completion-help-info nil)
-(defvar idlwave-completion-help-links nil)
-(defvar idlwave-current-obj_new-class nil)
-(defvar idlwave--method-selector)
-(defvar idlwave--class-selector)
-(defvar idlwave--type-selector)
-(defvar idlwave--super-classes)
-
-(defun idlwave-complete (&optional arg module class)
-  "Complete a function, procedure or keyword name at point.
-This function is smart and figures out what can be completed
-at this point.
-- At the beginning of a statement it completes procedure names.
-- In the middle of a statement it completes function names.
-- After a `(' or `,' in the argument list of a function or procedure,
-  it completes a keyword of the relevant function or procedure.
-- In the first arg of `OBJ_NEW', it completes a class name.
-
-When several completions are possible, a list will be displayed in
-the *Completions* buffer.  If this list is too long to fit into the
-window, scrolling can be achieved by repeatedly pressing
-\\[idlwave-complete].
-
-The function also knows about object methods.  When it needs a class
-name, the action depends upon `idlwave-query-class', which see.  You
-can force IDLWAVE to ask you for a class name with a
-\\[universal-argument] prefix argument to this command.
-
-See also the variables `idlwave-keyword-completion-adds-equal' and
-`idlwave-function-completion-adds-paren'.
-
-The optional ARG can be used to specify the completion type in order
-to override IDLWAVE's idea of what should be completed at point.
-Possible values are:
-
-0  <=>  query for the completion type
-1  <=>  `procedure'
-2  <=>  `procedure-keyword'
-3  <=>  `function'
-4  <=>  `function-keyword'
-5  <=>  `procedure-method'
-6  <=>  `procedure-method-keyword'
-7  <=>  `function-method'
-8  <=>  `function-method-keyword'
-9  <=>  `class'
-
-As a special case, the universal argument \\[universal-argument] forces completion of
-function names in places where the default would be a keyword.
-
-For Lisp programmers only:
-When we force a keyword, optional argument MODULE can contain the module name.
-When we force a method or a method keyword, CLASS can specify the class."
-  (interactive "P")
-  (idlwave-routines)
-  (let* ((where-list
-         (if (and arg
-                  (or (and (integerp arg) (not (equal arg '(16))))
-                      (symbolp arg)))
-             (idlwave-make-force-complete-where-list arg module class)
-           (idlwave-where)))
-        (what (nth 2 where-list))
-        (idlwave-force-class-query (equal arg '(4))))
-
-    (if (and module (string-match "::" module))
-       (setq class (substring module 0 (match-beginning 0))
-             module (substring module (match-end 0))))
-
-    (cond
-
-     ((and (null arg)
-          (eq (car-safe last-command) 'idlwave-display-completion-list)
-          (get-buffer-window "*Completions*"))
-      (setq this-command last-command)
-      (idlwave-scroll-completions))
-
-     ;; Complete a filename in quotes
-     ((and (idlwave-in-quote)
-          (not (eq what 'class)))
-      (idlwave-complete-filename))
-
-     ;; Check for any special completion functions
-     ((run-hook-with-args-until-success 'idlwave-complete-functions))
-
-     ((null what)
-      (error "Nothing to complete here"))
-
-     ;; Complete a class
-     ((eq what 'class)
-      (setq idlwave-completion-help-info '(class))
-      (idlwave-complete-class))
-
-     ((eq what 'procedure)
-      ;; Complete a procedure name
-      (let* ((cw-list (nth 3 where-list))
-            (idlwave--class-selector (idlwave-determine-class cw-list 'pro))
-            (idlwave--super-classes
-             (unless (idlwave-explicit-class-listed cw-list)
-               (idlwave-all-class-inherits idlwave--class-selector)))
-            (isa (concat "procedure"
-                         (if idlwave--class-selector "-method" "")))
-            (idlwave--type-selector 'pro))
-       (setq idlwave-completion-help-info
-             (list 'routine nil
-                   idlwave--type-selector idlwave--class-selector
-                   nil idlwave--super-classes))
-       (idlwave-complete-in-buffer
-        'procedure (if idlwave--class-selector 'method 'routine)
-        (idlwave-routines) 'idlwave-selector
-        (format "Select a %s name%s"
-                isa
-                (if idlwave--class-selector
-                    (format " (class is %s)"
-                            (if (eq idlwave--class-selector t)
-                                "unknown" idlwave--class-selector))
-                  ""))
-        isa
-        'idlwave-attach-method-classes 'idlwave-add-file-link-selector)))
-
-     ((eq what 'function)
-      ;; Complete a function name
-      (let* ((cw-list (nth 3 where-list))
-            (idlwave--class-selector (idlwave-determine-class cw-list 'fun))
-            (idlwave--super-classes
-             (unless (idlwave-explicit-class-listed cw-list)
-               (idlwave-all-class-inherits idlwave--class-selector)))
-            (isa (concat "function" (if idlwave--class-selector "-method" "")))
-            (idlwave--type-selector 'fun))
-       (setq idlwave-completion-help-info
-             (list 'routine nil
-                   idlwave--type-selector idlwave--class-selector
-                   nil idlwave--super-classes))
-       (idlwave-complete-in-buffer
-        'function (if idlwave--class-selector 'method 'routine)
-        (idlwave-routines) 'idlwave-selector
-        (format "Select a %s name%s"
-                isa
-                (if idlwave--class-selector
-                    (format " (class is %s)"
-                            (if (eq idlwave--class-selector t)
-                                "unknown" idlwave--class-selector))
-                  ""))
-        isa
-        'idlwave-attach-method-classes 'idlwave-add-file-link-selector)))
-
-     ((and (memq what '(procedure-keyword function-keyword)) ; Special Case
-          (equal arg '(4)))
-      (idlwave-complete 3))
-
-     ((eq what 'procedure-keyword)
-      ;; Complete a procedure keyword
-      (let* ((where (nth 3 where-list))
-            (name  (car where))
-            (idlwave--method-selector name)
-            (idlwave--type-selector 'pro)
-            (class (idlwave-determine-class where 'pro))
-            (idlwave--class-selector class)
-            (idlwave--super-classes (idlwave-all-class-inherits
-                                     idlwave--class-selector))
-            (isa (format "procedure%s-keyword" (if class "-method" "")))
-            (entry (idlwave-best-rinfo-assq
-                    name 'pro class (idlwave-routines)))
-            (system (if entry (eq (car (nth 3 entry)) 'system)))
-            (list (idlwave-entry-keywords entry 'do-link)))
-       (unless (or entry (eq class t))
-         (error "Nothing known about procedure %s"
-                (idlwave-make-full-name class name)))
-       (setq list (idlwave-fix-keywords name 'pro class list
-                                        idlwave--super-classes system))
-       (unless list (error "No keywords available for procedure %s"
-                           (idlwave-make-full-name class name)))
-       (setq idlwave-completion-help-info
-             (list 'keyword name
-                   idlwave--type-selector idlwave--class-selector
-                   entry idlwave--super-classes))
-       (idlwave-complete-in-buffer
-        'keyword 'keyword list nil
-        (format "Select keyword for procedure %s%s"
-                (idlwave-make-full-name class name)
-                (if (or (member '("_EXTRA") list)
-                        (member '("_REF_EXTRA") list))
-                    " (note _EXTRA)" ""))
-        isa
-        'idlwave-attach-keyword-classes)))
-
-     ((eq what 'function-keyword)
-      ;; Complete a function keyword
-      (let* ((where (nth 3 where-list))
-            (name  (car where))
-            (idlwave--method-selector name)
-            (idlwave--type-selector 'fun)
-            (class (idlwave-determine-class where 'fun))
-            (idlwave--class-selector class)
-            (idlwave--super-classes (idlwave-all-class-inherits
-                                     idlwave--class-selector))
-            (isa (format "function%s-keyword" (if class "-method" "")))
-            (entry (idlwave-best-rinfo-assq
-                    name 'fun class (idlwave-routines)))
-            (system (if entry (eq (car (nth 3 entry)) 'system)))
-            (list (idlwave-entry-keywords entry 'do-link))
-            msg-name)
-       (unless (or entry (eq class t))
-         (error "Nothing known about function %s"
-                (idlwave-make-full-name class name)))
-       (setq list (idlwave-fix-keywords name 'fun class list
-                                        idlwave--super-classes system))
-       ;; OBJ_NEW: Messages mention the proper Init method
-       (setq msg-name (if (and (null class)
-                               (string= (upcase name) "OBJ_NEW"))
-                          (concat idlwave-current-obj_new-class
-                                  "::Init (via OBJ_NEW)")
-                        (idlwave-make-full-name class name)))
-       (unless list (error "No keywords available for function %s"
-                           msg-name))
-       (setq idlwave-completion-help-info
-             (list 'keyword name
-                   idlwave--type-selector idlwave--class-selector
-                   nil idlwave--super-classes))
-       (idlwave-complete-in-buffer
-        'keyword 'keyword list nil
-        (format "Select keyword for function %s%s" msg-name
-                (if (or (member '("_EXTRA") list)
-                        (member '("_REF_EXTRA") list))
-                    " (note _EXTRA)" ""))
-        isa
-        'idlwave-attach-keyword-classes)))
-
-     (t (error "This should not happen (idlwave-complete)")))))
-
-(define-obsolete-variable-alias 'idlwave-complete-special
-  'idlwave-complete-functions "28.1")
-(defvar idlwave-complete-functions nil
-  "List of special completion functions.
-These functions are called for each completion.  Each function must
-check if its own special completion context is present.  If yes, it
-should use `idlwave-complete-in-buffer' to do some completion and
-return t.  If such a function returns t, *no further* attempts to
-complete other contexts will be done.  If the function returns nil,
-other completions will be tried.")
-
-(defun idlwave-call-special (functions &rest args)
-  (declare (obsolete run-hook-with-args-until-success "28.1"))
-  (let ((funcs functions)
-       fun ret)
-    (catch 'exit
-      (while (setq fun (pop funcs))
-       (if (setq ret (apply fun args))
-           (throw 'exit ret)))
-      nil)))
-
-(defun idlwave-make-force-complete-where-list (what &optional module class)
-  ;; Return an artificial WHERE specification to force the completion
-  ;; routine to complete a specific item independent of context.
-  ;; WHAT is the prefix arg of `idlwave-complete', see there for details.
-  ;; MODULE and CLASS can be used to specify the routine name and class.
-  ;; The class name will also be found in MODULE if that is like "class::mod".
-  (let* ((what-list '(("procedure") ("procedure-keyword")
-                     ("function") ("function-keyword")
-                     ("procedure-method") ("procedure-method-keyword")
-                     ("function-method") ("function-method-keyword")
-                     ("class")))
-        (module (idlwave-sintern-routine-or-method module class))
-        (class (idlwave-sintern-class class))
-        (what (cond
-               ((equal what 0)
-                (setq what
-                      (intern (completing-read
-                               "Complete what? " what-list nil t))))
-               ((integerp what)
-                (setq what (intern (car (nth (1- what) what-list)))))
-               ((and what
-                     (symbolp what)
-                     (assoc (symbol-name what) what-list))
-                what)
-               (t (error "Invalid WHAT"))))
-        (nil-list '(nil nil nil nil))
-        (class-list (list nil nil (or class t) nil)))
-
-    (cond
-
-     ((eq what 'procedure)
-      (list nil-list nil-list 'procedure nil-list nil))
-
-     ((eq what 'procedure-keyword)
-      (let* ((idlwave--class-selector nil)
-            (idlwave--super-classes nil)
-            (idlwave--type-selector 'pro)
-            (pro (or module
-                     (idlwave-completing-read
-                      "Procedure: " (idlwave-routines) 'idlwave-selector))))
-       (setq pro (idlwave-sintern-routine pro))
-       (list nil-list nil-list 'procedure-keyword
-             (list pro nil nil nil) nil)))
-
-     ((eq what 'function)
-      (list nil-list nil-list 'function nil-list nil))
-
-     ((eq what 'function-keyword)
-      (let* ((idlwave--class-selector nil)
-            (idlwave--super-classes nil)
-            (idlwave--type-selector 'fun)
-            (func (or module
-                      (idlwave-completing-read
-                       "Function: " (idlwave-routines) 'idlwave-selector))))
-       (setq func (idlwave-sintern-routine func))
-       (list nil-list nil-list 'function-keyword
-             (list func nil nil nil) nil)))
-
-     ((eq what 'procedure-method)
-      (list nil-list nil-list 'procedure class-list nil))
-
-     ((eq what 'procedure-method-keyword)
-      (let* ((class (idlwave-determine-class class-list 'pro))
-            (idlwave--class-selector class)
-            (idlwave--super-classes (idlwave-all-class-inherits
-                                     idlwave--class-selector))
-            (idlwave--type-selector 'pro)
-            (pro (or module
-                     (idlwave-completing-read
-                      (format "Procedure in %s class: "
-                              idlwave--class-selector)
-                      (idlwave-routines) 'idlwave-selector))))
-       (setq pro (idlwave-sintern-method pro))
-       (list nil-list nil-list 'procedure-keyword
-             (list pro nil class nil) nil)))
-
-     ((eq what 'function-method)
-      (list nil-list nil-list 'function class-list nil))
-
-     ((eq what 'function-method-keyword)
-      (let* ((class (idlwave-determine-class class-list 'fun))
-            (idlwave--class-selector class)
-            (idlwave--super-classes (idlwave-all-class-inherits
-                                     idlwave--class-selector))
-            (idlwave--type-selector 'fun)
-            (func (or module
-                      (idlwave-completing-read
-                       (format "Function in %s class: "
-                               idlwave--class-selector)
-                       (idlwave-routines) 'idlwave-selector))))
-       (setq func (idlwave-sintern-method func))
-       (list nil-list nil-list 'function-keyword
-             (list func nil class nil) nil)))
-
-     ((eq what 'class)
-      (list nil-list nil-list 'class nil-list nil))
-
-     (t (error "Invalid value for WHAT")))))
-
-(defun idlwave-completing-read (&rest args)
-  ;; Completing read, case insensitive
-  (let ((old-value (default-value 'completion-ignore-case)))
-    (unwind-protect
-       (progn
-         (setq-default completion-ignore-case t)
-         (apply #'completing-read args))
-      (setq-default completion-ignore-case old-value))))
-
-(defvar idlwave-shell-default-directory)
-(defun idlwave-complete-filename ()
-  "Use the comint stuff to complete a file name."
-  (require 'comint)
-  (dlet ((comint-file-name-chars "~/A-Za-z0-9+@:_.$#%={}\\-")
-        (comint-completion-addsuffix nil)
-        (default-directory
-          (if (and (boundp 'idlwave-shell-default-directory)
-                   (stringp idlwave-shell-default-directory)
-                   (file-directory-p idlwave-shell-default-directory))
-              idlwave-shell-default-directory
-            default-directory)))
-    (comint-dynamic-complete-filename)))
-
-(defun idlwave-make-full-name (class name)
-  ;; Make a fully qualified module name including the class name
-  (concat (if class (format "%s::" class) "") name))
-
-(defun idlwave-rinfo-assoc (name type class list)
-  "Like `idlwave-rinfo-assq', but sintern strings first."
-  (idlwave-rinfo-assq
-   (idlwave-sintern-routine-or-method name class)
-   type (idlwave-sintern-class class) list))
-
-(defun idlwave-rinfo-assq (name type class list)
-  ;; Works like assq, but also checks type and class
-  (catch 'exit
-    (let (match)
-      (while (setq match (assq name list))
-       (and (or (eq type t)
-                (eq (nth 1 match) type))
-            (eq (nth 2 match) class)
-            (throw 'exit match))
-       (setq list (cdr (memq match list)))))))
-
-(defun idlwave-rinfo-assq-any-class (name type class list)
-  ;; Return the first matching method on the inheritance list
-  (let* ((classes (cons class (idlwave-all-class-inherits class)))
-        rtn) ;; class
-    (while classes
-      (if (setq rtn (idlwave-rinfo-assq name type (pop classes) list))
-         (setq classes nil)))
-    rtn))
-
-(defun idlwave-best-rinfo-assq (name type class list &optional with-file
-                                    keep-system)
-  "Like `idlwave-rinfo-assq', but get all twins and sort, then return first.
-If WITH-FILE is passed, find the best rinfo entry with a file
-included.  If KEEP-SYSTEM is set, don't prune system for compiled
-syslib files."
-  (let ((twins (idlwave-routine-twins
-               (idlwave-rinfo-assq-any-class name type class list)
-               list))
-       syslibp)
-    (when (> (length twins) 1)
-      (setq twins (sort twins #'idlwave-routine-entry-compare-twins))
-      (if (and (null keep-system)
-              (eq 'system (car (nth 3 (car twins))))
-              (setq syslibp (idlwave-any-syslib (cdr twins)))
-              (not (equal 1 syslibp)))
-         ;; Its a compiled syslib, so we need to remove the system entry
-         (setq twins (cdr twins)))
-      (if with-file
-         (setq twins (delq nil
-                           (mapcar (lambda (x)
-                                     (if (nth 1 (nth 3 x)) x))
-                                   twins)))))
-    (car twins)))
-
-(defun idlwave-best-rinfo-assoc (name type class list &optional with-file
-                                    keep-system)
-  "Like `idlwave-best-rinfo-assq', but sintern strings first."
-  (idlwave-best-rinfo-assq
-   (idlwave-sintern-routine-or-method name class)
-   type (idlwave-sintern-class class) list with-file keep-system))
-
-(defun idlwave-any-syslib (entries)
-  "Does the entry list ENTRIES contain a syslib entry?
-If yes, return the index (>=1)."
-  (let (file (cnt 0))
-    (catch 'exit
-      (while entries
-       (cl-incf cnt)
-       (setq file (idlwave-routine-source-file (nth 3 (car entries))))
-       (if (and file (idlwave-syslib-p file))
-           (throw 'exit cnt)
-         (setq entries (cdr entries))))
-      nil)))
-
-(defun idlwave-all-assq (key list)
-  "Return a list of all associations of Key in LIST."
-  (let (rtn elt)
-    (while (setq elt (assq key list))
-      (push elt rtn)
-      (setq list (cdr (memq elt list))))
-    (nreverse rtn)))
-
-(defun idlwave-all-method-classes (method &optional type)
-  "Return all classes which have a method METHOD.
-TYPE is `fun' or `pro'.
-When TYPE is not specified, both procedures and functions will be considered."
-  (if (null method)
-      (mapcar #'car (idlwave-class-alist))
-    (let (rtn)
-      (mapc (lambda (x)
-             (and (nth 2 x)
-                  (or (not type)
-                      (eq type (nth 1 x)))
-                  (push (nth 2 x) rtn)))
-           (idlwave-all-assq method (idlwave-routines)))
-      (idlwave-uniquify rtn))))
-
-(defun idlwave-all-method-keyword-classes (method keyword &optional type)
-  "Return all classes which have a method METHOD with keyword KEYWORD.
-TYPE is `fun' or `pro'.
-When TYPE is not specified, both procedures and functions will be considered."
-  (if (or (null method)
-         (null keyword))
-      nil
-    (let (rtn)
-      (mapc (lambda (x)
-             (and (nth 2 x)            ; non-nil class
-                  (or (not type)       ; correct or unspecified type
-                      (eq type (nth 1 x)))
-                  (assoc keyword (idlwave-entry-keywords x))
-                  (push (nth 2 x) rtn)))
-           (idlwave-all-assq method (idlwave-routines)))
-      (idlwave-uniquify rtn))))
-
-(defun idlwave-members-only (list club)
-  "Return list of all elements in LIST which are also in CLUB."
-  (let (rtn)
-    (while list
-      (if (member (car list) club)
-         (setq rtn (cons (car list) rtn)))
-      (setq list (cdr list)))
-    (nreverse rtn)))
-
-(defun idlwave-nonmembers-only (list club)
-  "Return list of all elements in LIST which are not in CLUB."
-  (let (rtn)
-    (while list
-      (if (member (car list) club)
-         nil
-       (setq rtn (cons (car list) rtn)))
-      (setq list (cdr list)))
-    (nreverse rtn)))
-
-(defun idlwave-explicit-class-listed (info)
-  "Return whether or not the class is listed explicitly, ala a->b::c.
-INFO is as returned by `idlwave-what-function' or `-procedure'."
-  (let ((apos (nth 3 info)))
-    (if apos
-       (save-excursion (goto-char apos)
-                       (looking-at "->[a-zA-Z][a-zA-Z0-9$_]*::")))))
-
-(define-obsolete-variable-alias 'idlwave-determine-class-special
-  'idlwave-determine-class-functions "28.1")
-(defvar idlwave-determine-class-functions nil
-  "Special hook to determine a class.
-The functions should accept one argument, APOS.")
-
-(defun idlwave-determine-class (info type)
-  ;; Determine the class of a routine call.
-  ;; INFO is the `cw-list' structure as returned by idlwave-where.
-  ;; The second element in this structure is the class.  When nil, we
-  ;; return nil.  When t, try to get the class from text properties at
-  ;; the arrow.  When the object is "self", we use the class of the
-  ;; current routine.  otherwise prompt the user for a class name.
-  ;; Also stores the selected class as a text property at the arrow.
-  ;; TYPE is 'fun or 'pro.
-  (let* ((class (nth 2 info))
-        (apos (nth 3 info))
-        (nassoc (assoc (if (stringp (car info))
-                           (upcase (car info))
-                         (car info))
-                       idlwave-query-class))
-        (dassoc (assq (if (car info) 'keyword-default 'method-default)
-                      idlwave-query-class))
-        (query (cond (nassoc (cdr nassoc))
-                     (dassoc (cdr dassoc))
-                     (t t)))
-        (arrow (and apos (string= (buffer-substring apos (+ 2 apos)) "->")))
-        (is-self
-         (and arrow
-              (save-excursion (goto-char apos)
-                              (forward-word-strictly -1)
-                              (let ((case-fold-search t))
-                                (looking-at "self\\>")))))
-        (force-query idlwave-force-class-query)
-        store special-class class-alist)
-    (cond
-     ((null class) nil)
-     ((eq t class)
-      ;; There is an object which would like to know its class
-      (if (and arrow (get-text-property apos 'idlwave-class)
-              idlwave-store-inquired-class
-              (not force-query))
-         (setq class (get-text-property apos 'idlwave-class)
-               class (idlwave-sintern-class class)))
-      (if (and (eq t class) is-self)
-         (setq class (or (nth 2 (idlwave-current-routine)) class)))
-
-      ;; Before prompting, try any special class determination routines
-      (when (and (eq t class)
-                (not force-query))
-       (setq special-class
-             (run-hook-with-args-until-success
-              'idlwave-determine-class-functions apos))
-       (if special-class
-           (setq class (idlwave-sintern-class special-class)
-                 store idlwave-store-inquired-class)))
-
-      ;; Prompt for a class, if we need to
-      (when (and (eq class t)
-                (or force-query query))
-       (setq class-alist
-             (mapcar #'list (idlwave-all-method-classes (car info) type)))
-       (setq class
-             (idlwave-sintern-class
-              (cond
-               ((and (= (length class-alist) 0) (not force-query))
-                (error "No classes available with method %s" (car info)))
-               ((and (= (length class-alist) 1) (not force-query))
-                (car (car class-alist)))
-               (t
-                (setq store idlwave-store-inquired-class)
-                (idlwave-completing-read
-                 (format "Class%s: " (if (stringp (car info))
-                                         (format " for %s method %s"
-                                                 type (car info))
-                                       ""))
-                 class-alist nil nil nil 'idlwave-class-history))))))
-
-      ;; Store it, if requested
-      (when (and class (not (eq t class)))
-       ;; We have a real class here
-       (when (and store arrow)
-         (condition-case ()
-             (add-text-properties
-              apos (+ apos 2)
-              `(idlwave-class ,class face ,idlwave-class-arrow-face
-                              rear-nonsticky t))
-           (error nil)))
-       (setf (nth 2 info) class))
-      ;; Return the class
-      class)
-     ;; Default as fallback
-     (t class))))
-
-(defun idlwave-selector (a)
-  (and (eq (nth 1 a) idlwave--type-selector)
-       (or (and (nth 2 a) (eq idlwave--class-selector t))
-          (eq (nth 2 a) idlwave--class-selector)
-          (memq (nth 2 a) idlwave--super-classes))))
-
-(defun idlwave-add-file-link-selector (a)
-  ;; Record a file link, if any, for the tested names during selection.
-  (let ((sel (idlwave-selector a)) file)
-    (if (and sel (setq file (idlwave-entry-has-help a)))
-       (push (cons (car a) file) idlwave-completion-help-links))
-    sel))
-
-
-(defun idlwave-where ()
-  "Find out where we are.
-The return value is a list with the following stuff:
-\(PRO-LIST FUNC-LIST COMPLETE-WHAT CW-LIST LAST-CHAR)
-
-PRO-LIST       (PRO POINT CLASS ARROW)
-FUNC-LIST      (FUNC POINT CLASS ARROW)
-COMPLETE-WHAT  a symbol indicating what kind of completion makes sense here
-CW-LIST        (PRO-OR-FUNC POINT CLASS ARROW)  Like PRO-LIST, for what can
-               be completed here.
-LAST-CHAR      last relevant character before point (non-white non-comment,
-               not part of current identifier or leading slash).
-
-In the lists, we have these meanings:
-PRO:    Procedure name
-FUNC:   Function name
-POINT:  Where is this
-CLASS:  What class has the routine (nil=no, t=is method, but class unknown)
-ARROW:  Location of the arrow"
-  (idlwave-routines)
-  (let* (;(bos (save-excursion (idlwave-beginning-of-statement) (point)))
-         (bos (save-excursion (idlwave-start-of-substatement 'pre) (point)))
-        (func-entry (idlwave-what-function bos))
-         (func (car func-entry))
-         (func-class (nth 1 func-entry))
-         (func-arrow (nth 2 func-entry))
-        (func-point (or (nth 3 func-entry) 0))
-        (func-level (or (nth 4 func-entry) 0))
-        (pro-entry (idlwave-what-procedure bos))
-        (pro (car pro-entry))
-         (pro-class (nth 1 pro-entry))
-         (pro-arrow (nth 2 pro-entry))
-        (pro-point (or (nth 3 pro-entry) 0))
-        (last-char (idlwave-last-valid-char))
-         (case-fold-search t)
-        (match-string (buffer-substring bos (point)))
-        cw cw-mod cw-arrow cw-class cw-point)
-    (if (< func-point pro-point) (setq func nil))
-    (cond
-     ((string-match "\\`[ \t]*\\(pro\\|function\\)[ \t]+[a-zA-Z0-9_]*\\'"
-                    match-string)
-      (setq cw 'class))
-     ((string-match
-       "\\`[ \t]*\\([a-zA-Z][a-zA-Z0-9$_]*\\)?\\'"
-       (if (> pro-point 0)
-          (buffer-substring pro-point (point))
-        match-string))
-      (setq cw 'procedure cw-class pro-class cw-point pro-point
-           cw-arrow pro-arrow))
-     ((string-match "\\`[ \t]*\\(pro\\|function\\)\\>"
-                   match-string)
-      nil)
-     ((string-match "OBJ_NEW([ \t]*['\"][a-zA-Z0-9$_]*\\'"
-                   match-string)
-      (setq cw 'class))
-     ((string-match "\\<inherits\\s-+[a-zA-Z0-9$_]*\\'"
-                   match-string)
-      (setq cw 'class))
-     ((and func
-          (> func-point pro-point)
-          (= func-level 1)
-          (memq last-char '(?\( ?,)))
-      (setq cw 'function-keyword cw-mod func cw-point func-point
-           cw-class func-class cw-arrow func-arrow))
-     ((and pro (eq last-char ?,))
-      (setq cw 'procedure-keyword cw-mod pro cw-point pro-point
-           cw-class pro-class cw-arrow pro-arrow))
-;     ((member last-char '(?\' ?\) ?\] ?!))
-;      ;; after these chars, a function makes no sense
-;      ;; FIXME: I am sure there can be more in this list
-;      ;; FIXME: Do we want to do this at all?
-;      nil)
-     ;; Everywhere else we try a function.
-     (t
-      (setq cw 'function)
-      (save-excursion
-       (if (re-search-backward "->[ \t]*\\(\\$[ \t]*\\(;.*\\)?\n\\s-*\\)?\\(\\([$a-zA-Z0-9_]+\\)::\\)?[$a-zA-Z0-9_]*\\=" bos t)
-           (setq cw-arrow (copy-marker (match-beginning 0))
-                 cw-class (if (match-end 4)
-                              (idlwave-sintern-class (match-string 4))
-                            t))))))
-    (list (list pro pro-point pro-class pro-arrow)
-          (list func func-point func-class func-arrow)
-          cw
-         (list cw-mod cw-point cw-class cw-arrow)
-         last-char)))
-
-(defun idlwave-this-word (&optional class)
-  ;; Grab the word around point.  CLASS is for the `skip-chars=...' functions
-  (setq class (or class "a-zA-Z0-9$_."))
-  (save-excursion
-    (buffer-substring
-     (progn (skip-chars-backward class) (point))
-     (progn (skip-chars-forward  class) (point)))))
-
-(defun idlwave-what-function (&optional bound)
-  ;; Find out if point is within the argument list of a function.
-  ;; The return value is ("function-name" class arrow-start (point) level).
-  ;; Level is 1 on the top level parentheses, higher further down.
-
-  ;; If the optional BOUND is an integer, bound backwards directed
-  ;;    searches to this point.
-
-  (catch 'exit
-    (let (pos
-         func-point
-         (cnt 0)
-         func arrow-start class)
-      (with-syntax-table idlwave-find-symbol-syntax-table
-       (save-restriction
-        (save-excursion
-          (narrow-to-region (max 1 (or bound 0)) (point-max))
-          ;; move back out of the current parenthesis
-          (while (condition-case nil
-                     (progn (up-list -1) t)
-                   (error nil))
-            (setq pos (point))
-            (cl-incf cnt)
-            (when (and (= (following-char) ?\()
-                       (re-search-backward
-                        "\\(::\\|\\<\\)\\([a-zA-Z][a-zA-Z0-9$_]*\\)[ \t]*\\="
-                        bound t))
-              (setq func (match-string 2)
-                    func-point (goto-char (match-beginning 2))
-                    pos func-point)
-              (if (re-search-backward
-                   "->[ \t]*\\(\\([a-zA-Z][a-zA-Z0-9$_]*\\)::\\)?\\=" bound t)
-                  (setq arrow-start (copy-marker (match-beginning 0))
-                        class (or (match-string 2) t)))
-              (throw
-               'exit
-               (list
-                (idlwave-sintern-routine-or-method func class)
-                (idlwave-sintern-class class)
-                arrow-start func-point cnt)))
-            (goto-char pos))
-          (throw 'exit nil)))))))
-
-(defun idlwave-what-procedure (&optional _bound)
-  ;; Find out if point is within the argument list of a procedure.
-  ;; The return value is ("procedure-name" class arrow-pos (point)).
-
-  ;; If the optional BOUND is an integer, bound backwards directed
-  ;;    searches to this point.
-  (let ((pos (point)) pro-point
-       pro class arrow-start string)
-    (save-excursion
-      ;;(idlwave-beginning-of-statement)
-      (idlwave-start-of-substatement 'pre)
-      (setq string (buffer-substring (point) pos))
-      (if (string-match
-          "\\`[ \t]*\\([a-zA-Z][a-zA-Z0-9$_]*\\)[ \t]*\\(,\\|\\'\\)" string)
-         (setq pro (match-string 1 string)
-               pro-point (+ (point) (match-beginning 1)))
-       (if (and (idlwave-skip-object)
-                (setq string (buffer-substring (point) pos))
-                (string-match
-                 "\\`[ \t]*\\(->\\)[ \t]*\\(\\([a-zA-Z][a-zA-Z0-9$_]*\\)::\\)?\\([a-zA-Z][a-zA-Z0-9$_]*\\)?[ \t]*\\(,\\|\\(\\$\\s *\\(;.*\\)?\\)?$\\)"
-                 string))
-           (setq pro (if (match-beginning 4)
-                         (match-string 4 string))
-                 pro-point (if (match-beginning 4)
-                               (+ (point) (match-beginning 4))
-                       pos)
-                 arrow-start (copy-marker (+ (point) (match-beginning 1)))
-                 class (or (match-string 3 string) t)))))
-    (list (idlwave-sintern-routine-or-method pro class)
-         (idlwave-sintern-class class)
-         arrow-start
-         pro-point)))
-
-(defun idlwave-skip-object ()
-  ;; If there is an object at point, move over it and return t.
-  (let ((pos (point)))
-    (if (catch 'exit
-         (save-excursion
-           (skip-chars-forward "       ")  ; white space
-           (skip-chars-forward "*")        ; de-reference
-           (cond
-            ((looking-at idlwave-identifier)
-             (goto-char (match-end 0)))
-            ((eq (following-char) ?\()
-             nil)
-            (t (throw 'exit nil)))
-           (catch 'endwhile
-             (while t
-               (cond ((eq (following-char) ?.)
-                      (forward-char 1)
-                      (if (not (looking-at idlwave-identifier))
-                          (throw 'exit nil))
-                      (goto-char (match-end 0)))
-                     ((memq (following-char) '(?\( ?\[))
-                      (condition-case nil
-                          (forward-list 1)
-                        (error (throw 'exit nil))))
-                     (t (throw 'endwhile t)))))
-           (if (looking-at "[ \t]*->")
-               (throw 'exit (setq pos (match-beginning 0)))
-             (throw 'exit nil))))
-       (goto-char pos)
-      nil)))
-
-(defun idlwave-last-valid-char ()
-  "Return the last character before point which is not white or a comment
-and also not part of the current identifier.  Since we do this in
-order to identify places where keywords are, we consider the initial
-`/' of a keyword as part of the identifier.
-This function is not general, can only be used for completion stuff."
-  (catch 'exit
-    (save-excursion
-      ;; skip the current identifier
-      (skip-chars-backward "a-zA-Z0-9_$")
-      ;; also skip a leading slash which might be belong to the keyword
-      (if (eq (preceding-char) ?/)
-         (backward-char 1))
-      ;; FIXME: does not check if this is a valid identifier
-      (while t
-       (skip-chars-backward " \t")
-       (cond
-        ((memq (preceding-char) '(?\; ?\$)) (throw 'exit nil))
-        ((eq (preceding-char) ?\n)
-         (beginning-of-line 0)
-         (if (looking-at "\\([^\n]*\\)\\$[ \t]*\\(;[^\n]*\\)?\n")
-             ;; continuation line
-             (goto-char (match-end 1))
-           (throw 'exit nil)))
-        (t (throw 'exit (preceding-char))))))))
-
-(defvar idlwave--complete-after-success-function #'ignore
-  "A function to evaluate after successful completion.")
-(defvar idlwave--complete-after-success-force-function #'ignore
-  "A function to evaluate after completion selection in *Completions* buffer.")
-(defconst idlwave-completion-mark (make-marker)
-  "A mark pointing to the beginning of the completion string.")
-
-(defun idlwave-complete-in-buffer (type stype list selector prompt isa
-                                       &optional prepare-display-function
-                                       special-selector)
-  "Perform TYPE completion of word before point against LIST.
-SELECTOR is the PREDICATE argument for the completion function.  Show
-PROMPT in echo area.  TYPE is one of the intern types, e.g., `function',
-`procedure', `class-tag', `keyword', `sysvar'.  SPECIAL-SELECTOR is
-used only once, for `all-completions', and can be used to, e.g.,
-accumulate information on matching completions."
-  (let* ((completion-ignore-case t)
-        beg (end (point)) slash part spart completion all-completions
-        dpart dcompletion)
-
-    (unless list
-      (error (concat prompt ": No completions available")))
-
-    ;; What is already in the buffer?
-    (save-excursion
-      (skip-chars-backward "a-zA-Z0-9_$")
-      (setq slash (eq (preceding-char) ?/)
-           beg (point)
-           idlwave--complete-after-success-function
-           (lambda () (idlwave-after-successful-completion
-                  type slash beg))
-           idlwave--complete-after-success-force-function
-           (lambda () (idlwave-after-successful-completion
-                  type slash 'force))))
-
-    ;; Try a completion
-    (setq part (buffer-substring beg end)
-         dpart (downcase part)
-         spart (idlwave-sintern stype part)
-         completion (try-completion part list selector)
-         dcompletion (if (stringp completion) (downcase completion))
-         idlwave-completion-help-links nil)
-    (cond
-     ((null completion)
-      ;; nothing available.
-      (error (concat prompt ": no completion for \"%s\"") part))
-     ((and (not (equal dpart dcompletion))
-          (not (eq t completion)))
-      ;; We can add something
-      (delete-region beg end)
-      (insert (if (and (string= part dpart)
-                       (or (not (string= part ""))
-                           idlwave-complete-empty-string-as-lower-case)
-                       (not idlwave-completion-force-default-case))
-                  dcompletion
-                completion))
-      (if (eq t (try-completion completion list selector))
-         ;; Now this is a unique match
-         (idlwave-after-successful-completion type slash beg))
-      t)
-     ((or (eq completion t)
-         (and (= 1 (length (setq all-completions
-                                 (idlwave-uniquify
-                                  (all-completions part list
-                                                   (or special-selector
-                                                       selector))))))
-              (equal dpart dcompletion)))
-      ;; This is already complete
-      (idlwave-after-successful-completion type slash beg)
-      (message "%s is already the complete %s" part isa)
-      nil)
-     (t
-      ;; We cannot add something - offer a list.
-      (message "Making completion list...")
-
-      (unless idlwave-completion-help-links ; already set somewhere?
-       (mapc (lambda (x)  ; Pass link prop through to highlight-linked
-               (let ((link (get-text-property 0 'link (car x))))
-                 (if link
-                     (push (cons (car x) link)
-                           idlwave-completion-help-links))))
-             list))
-      (let* ((list all-completions)
-            ;; "complete" means, this is already a valid completion
-            (complete (memq spart all-completions)))
-       (setq list (sort list (lambda (a b)
-                               (string< (downcase a) (downcase b)))))
-       (if prepare-display-function
-           (setq list (funcall prepare-display-function list)))
-       (if (and (string= part dpart)
-                (or (not (string= part ""))
-                    idlwave-complete-empty-string-as-lower-case)
-                (not idlwave-completion-force-default-case))
-           (setq list (mapcar (lambda (x)
-                                (if (listp x)
-                                    (setcar x (downcase (car x)))
-                                  (setq x (downcase x)))
-                                x)
-                              list)))
-       (idlwave-display-completion-list list prompt beg complete))
-      t))))
-
-(defun idlwave-complete-class ()
-  "Complete a class at point."
-  (interactive)
-  ;; Call `idlwave-routines' to make sure the class list will be available
-  (idlwave-routines)
-  ;; Check for the special case of completing empty string after pro/function
-  (if (let ((case-fold-search t))
-       (save-excursion
-         (and
-          (re-search-backward "\\<\\(pro\\|function\\)[ \t]+\\="
-                              (- (point) 15) t)
-          (goto-char (point-min))
-          (re-search-forward
-           "^[ \t]*\\(pro\\|function\\)[ \t]+\\([a-zA-Z0-9_]+::\\)" nil t))))
-      ;; Yank the full class specification
-      (insert (match-string 2))
-    ;; Do the completion, using list gathered from `idlwave-routines'
-    (idlwave-complete-in-buffer
-     'class 'class (idlwave-class-alist) nil
-     "Select a class" "class"
-     (lambda (list) ;; Push it to help-links if system help available
-       (mapcar (lambda (x)
-                 (let* ((entry (idlwave-class-info x))
-                        (link (nth 1 (assq 'link entry))))
-                   (if link (push (cons x link)
-                                  idlwave-completion-help-links))
-                   x))
-               list)))))
-
-(defun idlwave-attach-classes (list type show-classes)
-  ;; Attach the proper class list to a LIST of completion items.
-  ;; TYPE, when 'kwd, shows classes for method keywords, when
-  ;; 'class-tag, for class tags, and otherwise for methods.
-  ;; SHOW-CLASSES is the value of `idlwave-completion-show-classes'.
-  (if (or (null show-classes)           ; don't want to see classes
-         (null idlwave--class-selector)         ; not a method call
-         (and
-          (stringp idlwave--class-selector) ; the class is already known
-          (not idlwave--super-classes)))    ; no possibilities for inheritance
-      ;; In these cases, we do not have to do anything
-      list
-    (let* ((do-prop (>= show-classes 0))
-          (do-buf (not (= show-classes 0)))
-          ;; (do-dots t)
-          (inherit (if (and (not (eq type 'class-tag)) idlwave--super-classes)
-                       (cons idlwave--class-selector idlwave--super-classes)))
-          (max (abs show-classes))
-          (lmax ;; (if do-dots
-                    (apply #'max (mapcar #'length list))) ;;)
-         classes nclasses class-info space)
-      (mapcar
-       (lambda (x)
-        ;; get the classes
-        (if (eq type 'class-tag)
-            ;; Just one class for tags
-            (setq classes
-                  (list
-                   (idlwave-class-or-superclass-with-tag
-                    idlwave--class-selector x)))
-          ;; Multiple classes for method or method-keyword
-          (setq classes
-                (if (eq type 'kwd)
-                    (idlwave-all-method-keyword-classes
-                     idlwave--method-selector x idlwave--type-selector)
-                  (idlwave-all-method-classes x idlwave--type-selector)))
-          (if inherit
-              (setq classes
-                    (delq nil
-                          (mapcar (lambda (x) (if (memq x inherit) x nil))
-                                  classes)))))
-        (setq nclasses (length classes))
-        ;; Make the separator between item and class-info
-        ;; (if do-dots
-        (setq space (concat " " (make-string (- lmax (length x)) ?.)))
-        ;; (setq space " "))
-        (if  do-buf
-            ;; We do want info in the buffer
-            (if (<= nclasses max)
-                (setq class-info (concat
-                                  space
-                                  "<" (mapconcat #'identity classes ",") ">"))
-              (setq class-info (format "%s<%d classes>" space nclasses)))
-          (setq class-info nil))
-        (when do-prop
-          ;; We do want properties
-          (setq x (copy-sequence x))
-          (put-text-property 0 (length x)
-                              'help-echo (mapconcat #'identity classes " ")
-                              x))
-        (if class-info
-            (list x class-info)
-          x))
-       list))))
-
-(defun idlwave-attach-method-classes (list)
-  ;; Call idlwave-attach-classes with method parameters
-  (idlwave-attach-classes list 'method idlwave-completion-show-classes))
-(defun idlwave-attach-keyword-classes (list)
-  ;; Call idlwave-attach-classes with keyword parameters
-  (idlwave-attach-classes list 'kwd idlwave-completion-show-classes))
-(defun idlwave-attach-class-tag-classes (list)
-  ;; Call idlwave-attach-classes with class structure tags
-  (idlwave-attach-classes list 'class-tag idlwave-completion-show-classes))
-
-
-;;----------------------------------------------------------------------
-;;----------------------------------------------------------------------
-;;----------------------------------------------------------------------
-;;----------------------------------------------------------------------
-;;----------------------------------------------------------------------
-
-(defun idlwave-popup-select (ev list title &optional sort)
-  "Select an item in LIST with a popup menu.
-TITLE is the title to put atop the popup.  If SORT is non-nil,
-sort the list before displaying."
-  (let ((maxpopup idlwave-max-popup-menu-items)
-       rtn menu)
-    (cond ((null list))
-         ((= 1 (length list))
-          (setq rtn (car list)))
-         (t
-          (if sort (setq list (sort list (lambda (a b)
-                                           (string< (upcase a) (upcase b))))))
-          (setq menu (cons title
-                           (list
-                            (append (list "")
-                                    (mapcar (lambda(x) (cons x x)) list)))))
-          (setq menu (idlwave-split-menu menu maxpopup))
-          (setq rtn (x-popup-menu ev menu))))
-    rtn))
-
-(define-obsolete-function-alias 'idlwave-split-menu-emacs
-  #'idlwave-split-menu "28.1")
-
-(defun idlwave-split-menu (menu N)
-  "Split the MENU into submenus of maximum length N."
-  (if (<= (length (nth 1 menu)) (1+ N))
-      ;; No splitting needed
-      menu
-    (let* ((title (car menu))
-          (entries (cdr (nth 1 menu)))
-          (menu nil)
-          (cnt 0)
-          (nextmenu nil))
-      (while entries
-       (while (and entries (< cnt N))
-         (setq cnt (1+ cnt)
-               nextmenu (cons (car entries) nextmenu)
-               entries (cdr entries)))
-       (setq nextmenu (nreverse nextmenu))
-       (prin1 nextmenu)
-       (setq nextmenu (cons (format "%s...%s"
-                                    (car (car nextmenu))
-                                    (car (nth (1- cnt) nextmenu)))
-                            nextmenu))
-       (setq menu (cons nextmenu menu)
-             nextmenu nil
-             cnt 0))
-      (setq menu (nreverse menu))
-      (setq menu (cons title menu))
-      menu)))
-
-(defvar idlwave-completion-setup-hook nil)
-
-(defun idlwave-scroll-completions (&optional message)
-  "Scroll the completion window on this frame."
-  (let ((cwin (get-buffer-window "*Completions*" 'visible))
-       (win (selected-window)))
-    (unwind-protect
-       (progn
-         (select-window cwin)
-         (condition-case nil
-             (scroll-up)
-           (error (if (and (listp last-command)
-                           (nth 2 last-command))
-                      (progn
-                        (select-window win)
-                        (funcall idlwave--complete-after-success-function))
-                    (set-window-start cwin (point-min)))))
-         (and message (message "%s" message)))
-      (select-window win))))
-
-(defun idlwave-display-completion-list (list &optional message beg complete)
-  "Display the completions in LIST in the completions buffer and echo MESSAGE."
-  (unless (and (get-buffer-window "*Completions*")
-              (idlwave-local-value 'idlwave-completion-p "*Completions*"))
-    (move-marker idlwave-completion-mark beg)
-    (setq idlwave-before-completion-wconf (current-window-configuration)))
-
-  (idlwave-display-completion-list-1 list)
-
-  ;; Store a special value in `this-command'.  When `idlwave-complete'
-  ;; finds this in `last-command', it will scroll the *Completions* buffer.
-  (setq this-command (list 'idlwave-display-completion-list message complete))
-
-  ;; Mark the completions buffer as created by cib
-  (idlwave-set-local 'idlwave-completion-p t "*Completions*")
-
-  ;; Fontify the classes
-  (if (and idlwave-completion-fontify-classes
-           (consp (car list)))
-      (idlwave-completion-fontify-classes))
-
-  ;; Run the hook
-  (run-hooks 'idlwave-completion-setup-hook)
-
-  ;; Display the message
-  (message "%s" (or message "Making completion list...done")))
-
-(defun idlwave-choose (function &rest args)
-  "Call FUNCTION as a completion chooser and pass ARGS to it."
-  (let ((completion-ignore-case t))        ; install correct value
-    (apply function args))
-  (if (and (derived-mode-p 'idlwave-shell-mode)
-          (not font-lock-mode))
-      ;; For the shell, remove the fontification of the word before point
-      (let ((beg (save-excursion
-                  (skip-chars-backward "a-zA-Z0-9_")
-                  (point))))
-       (remove-text-properties beg (point) '(face nil))))
-  (funcall idlwave--complete-after-success-force-function))
-
-(defun idlwave-keyboard-quit ()
-  (interactive)
-  (unwind-protect
-      (if (eq (car-safe last-command) 'idlwave-display-completion-list)
-         (idlwave-restore-wconf-after-completion))
-    (keyboard-quit)))
-
-(defun idlwave-restore-wconf-after-completion ()
-  "Restore the old (before completion) window configuration."
-  (and idlwave-completion-restore-window-configuration
-       idlwave-before-completion-wconf
-       (set-window-configuration idlwave-before-completion-wconf)))
-
-(defun idlwave-one-key-select (sym prompt delay)
-  "Make the user select an element from the alist in the variable SYM.
-The keys of the alist are expected to be strings.  The function returns the
-car of the selected association.
-To do this, PROMPT is displayed and the user must hit a letter key to
-select an entry.  If the user does not reply within DELAY seconds, a help
-window with the options is displayed automatically.
-The key which is associated with each option is generated automatically.
-First, the strings are checked for preselected keys, like in \"[P]rint\".
-If these don't exist, a letter in the string is automatically selected."
-  (let* ((alist (symbol-value sym))
-         (temp-buffer-show-hook '(fit-window-to-buffer))
-         keys-alist char)
-    ;; First check the cache
-    (if (and (eq (symbol-value sym) (get sym :one-key-alist-last)))
-        (setq keys-alist (get sym :one-key-alist-cache))
-      ;; Need to make new list
-      (setq keys-alist (idlwave-make-one-key-alist alist))
-      (put sym :one-key-alist-cache keys-alist)
-      (put sym :one-key-alist-last alist))
-    ;; Display prompt and wait for quick reply
-    (message "%s[%s]" prompt
-             (mapconcat (lambda(x) (char-to-string (car x)))
-                        keys-alist))
-    (if (sit-for delay)
-        ;; No quick reply: Show help
-        (save-window-excursion
-          (with-output-to-temp-buffer "*Completions*"
-           (dolist (x keys-alist)
-             (princ (nth 1 x))
-             (princ "\n")))
-          (setq char (read-char)))
-      (setq char (read-char)))
-    (message nil)
-    ;; Return the selected result
-    (nth 2 (assoc char keys-alist))))
-
-;; Used for, e.g., electric debug super-examine.
-(defun idlwave-make-one-key-alist (alist)
-  "Make an alist for single key selection."
-  (let ((l alist) keys-alist name start char help
-        (cnt 0)
-        (case-fold-search nil))
-    (while l
-      (setq name (car (car l))
-            l (cdr l))
-      (catch 'exit
-        ;; First check if the configuration predetermined a key
-        (if (string-match "\\[\\(.\\)\\]" name)
-            (progn
-              (setq char (string-to-char (downcase (match-string 1 name)))
-                    help (format "%c:  %s" char name)
-                    keys-alist (cons (list char help name) keys-alist))
-              (throw 'exit t)))
-        ;; Then check for capital letters
-        (setq start 0)
-        (while (string-match "[A-Z]" name start)
-          (setq start (match-end 0)
-                char (string-to-char (downcase (match-string 0 name))))
-          (if (not (assoc char keys-alist))
-              (progn
-                (setq help (format "%c:  %s" char
-                                   (replace-match
-                                    (concat "[" (match-string 0 name) "]")
-                                          t t name))
-                      keys-alist (cons (list char help name) keys-alist))
-                (throw 'exit t))))
-        ;; Now check for lowercase letters
-        (setq start 0)
-        (while (string-match "[a-z]" name start)
-          (setq start (match-end 0)
-                char (string-to-char (match-string 0 name)))
-          (if (not (assoc char keys-alist))
-              (progn
-                (setq help (format "%c:  %s" char
-                                   (replace-match
-                                    (concat "[" (match-string 0 name) "]")
-                                    t t name))
-                      keys-alist (cons (list char help name) keys-alist))
-                (throw 'exit t))))
-        ;; Bummer, nothing found!  Use a stupid number
-        (setq char (string-to-char (int-to-string (setq cnt (1+ cnt))))
-              help (format "%c:  %s" char name)
-              keys-alist (cons (list char help name) keys-alist))))
-    (nreverse keys-alist)))
-
-(defun idlwave-set-local (var value &optional buffer)
-  "Set the buffer-local value of VAR in BUFFER to VALUE."
-  (with-current-buffer (or buffer (current-buffer))
-    (set (make-local-variable var) value)))
-
-(defun idlwave-local-value (var &optional buffer)
-  "Return the value of VAR in BUFFER, but only if VAR is local to BUFFER."
-  (when (local-variable-p var buffer)
-    (buffer-local-value var (or buffer (current-buffer)))))
-
-(defvar idlwave-completion-map nil
-  "Keymap for `completion-list-mode' with `idlwave-complete'.")
-
-;; (defun idlwave-default-choose-completion (&rest args)
-;;   "Execute `default-choose-completion' and then restore the win-conf."
-;;   (apply #'idlwave-choose #'default-choose-completion args))
-
-(define-obsolete-function-alias 'idlwave-display-completion-list-emacs
-  #'idlwave-display-completion-list-1 "28.1")
-
-(defun idlwave-display-completion-list-1 (list)
-  "Display completion list and install the choose wrappers."
-  (with-output-to-temp-buffer "*Completions*"
-    (display-completion-list list))
-  (with-current-buffer "*Completions*"
-    (use-local-map
-     (or idlwave-completion-map
-        (setq idlwave-completion-map
-              (idlwave-make-modified-completion-map (current-local-map)))))))
-
-(define-obsolete-function-alias 'idlwave-make-modified-completion-map-emacs
-  #'idlwave-make-modified-completion-map "28.1")
-
-(defun idlwave-make-modified-completion-map (old-map)
-  "Replace `choose-completion' in OLD-MAP."
-  (let ((new-map (copy-keymap old-map)))
-    (substitute-key-definition
-     #'choose-completion #'idlwave-choose-completion new-map)
-    (define-key new-map [mouse-3] #'idlwave-mouse-completion-help)
-    new-map))
-
-(defun idlwave-choose-completion (&rest args)
-  "Choose the completion that point is in or next to."
-  (interactive (list last-nonmenu-event))
-  (apply #'idlwave-choose #'choose-completion args))
-
-(define-obsolete-function-alias 'idlwave-mouse-choose-completion
-  #'idlwave-choose-completion "28.1")
-
-;;----------------------------------------------------------------------
-;;----------------------------------------------------------------------
-
-;;; ------------------------------------------------------------------------
-;;; Structure parsing code, and code to manage class info
-
-;;
-;; - Go again over the documentation how to write a completion
-;;   plugin.  It is in self.el, but currently still very bad.
-;;   This could be in a separate file in the distribution, or
-;;   in an appendix for the manual.
-
-(defvar idlwave-struct-skip
-  "[ \t]*\\(\\$.*\n\\(^[ \t]*\\(\\$[ \t]*\\)?\\(;.*\\)?\n\\)*\\)?[ \t]*"
-  "Regexp for skipping continued blank or comment-only lines in structures.")
-
-(defvar idlwave-struct-tag-regexp
-  (concat "[{,]" ;leading comma/brace
-         idlwave-struct-skip ; 4 groups
-         "\\([a-zA-Z][a-zA-Z0-9_]*\\)" ;the tag itself, group 5
-         "[ \t]*:") ; the final colon
-  "Regexp for structure tags.")
-
-(defun idlwave-struct-tags ()
-  "Return a list of all tags in the structure defined at point.
-Point is expected just before the opening `{' of the struct definition."
-  (save-excursion
-    (let* ((borders (idlwave-struct-borders))
-          (beg (car borders))
-          (end (cdr borders))
-          tags)
-      (goto-char beg)
-      (save-restriction
-       (narrow-to-region beg end)
-       (while (re-search-forward idlwave-struct-tag-regexp end t)
-         ;; Check if we are still on the top level of the structure.
-         (if (and (condition-case nil (progn (up-list -1) t) (error nil))
-                  (= (point) beg))
-             (push (match-string-no-properties 5) tags))
-         (goto-char (match-end 0))))
-       (nreverse tags))))
-
-(defun idlwave-find-struct-tag (tag)
-  "Find a given TAG in the structure defined at point."
-  (let* ((borders (idlwave-struct-borders))
-        (end (cdr borders))
-        (case-fold-search t))
-    (re-search-forward (concat "\\(^[ \t]*\\|[,{][ \t]*\\)" tag "[ \t]*:")
-                      end t)))
-
-(defun idlwave-struct-inherits ()
-  "Return a list of all `inherits' names in the struct at point.
-Point is expected just before the opening `{' of the struct definition."
-  (save-excursion
-    (let* ((borders (idlwave-struct-borders))
-          (beg (car borders))
-          (end (cdr borders))
-          (case-fold-search t)
-          names)
-      (goto-char beg)
-      (save-restriction
-       (narrow-to-region beg end)
-       (while (re-search-forward
-               (concat "[{,]"  ;leading comma/brace
-                       idlwave-struct-skip ; 4 groups
-                       "inherits"    ; The INHERITS tag
-                       idlwave-struct-skip ; 4 more
-                       "\\([a-zA-Z][a-zA-Z0-9_]*\\)") ; The super-group, #9
-               end t)
-         ;; Check if we are still on the top level of the structure.
-         (if (and (condition-case nil (progn (up-list -1) t) (error nil))
-                  (= (point) beg))
-             (push (match-string-no-properties 9) names))
-         (goto-char (match-end 0))))
-      (nreverse names))))
-
-(defun idlwave-in-structure ()
-  "Return t if point is inside an IDL structure definition."
-  (let ((beg (point)))
-    (save-excursion
-      (if (not (or (idlwave-in-comment) (idlwave-in-quote)))
-         (if (idlwave-find-structure-definition nil nil 'back)
-             (let ((borders (idlwave-struct-borders)))
-               (or (= (car borders) (cdr borders)) ;; struct not yet closed...
-                   (and (> beg (car borders)) (< beg (cdr borders))))))))))
-
-(defun idlwave-struct-borders ()
-  "Return the borders of the {...} after point as a cons cell."
-  (let (beg)
-    (save-excursion
-      (skip-chars-forward "^{")
-      (setq beg (point))
-      (condition-case nil (forward-list 1)
-       (error (goto-char beg)))
-      (cons beg (point)))))
-
-(defun idlwave-find-structure-definition (&optional var name bound)
-  "Search forward for a structure definition.
-If VAR is non-nil, search for a structure assigned to variable VAR.
-If NAME is non-nil, search for a named structure NAME, if a string,
-or a generic named structure otherwise.  If BOUND is an integer, limit
-the search.  If BOUND is the symbol `all', we search first back and
-then forward through the entire file.  If BOUND is the symbol `back'
-we search only backward."
-  (let* ((ws "[ \t]*\\(\\$.*\n[ \t]*\\)*")
-        (case-fold-search t)
-        (lim (if (integerp bound) bound nil))
-        (re (concat
-             (if var
-                 (concat "\\<" (regexp-quote (downcase var)) "\\>" ws)
-               "\\(\\)")
-             "=" ws "\\({\\)"
-             (if name
-                 (if (stringp name)
-                     (concat ws "\\(\\<" (downcase name) "\\)[^a-zA-Z0-9_$]")
-                   ;; Just a generic name
-                   (concat ws "\\<\\([a-zA-Z_0-9$]+\\)" ws ","))
-               ""))))
-    (if (or (and (or (eq bound 'all) (eq bound 'back))
-                (re-search-backward re nil t))
-           (and (not (eq bound 'back)) (re-search-forward re lim t)))
-       (progn
-         (goto-char (match-beginning 3))
-         (match-string-no-properties 5)))))
-
-(defvar idlwave-class-info nil)
-(defvar idlwave-class-reset nil) ; to reset buffer-local classes
-
-(add-hook 'idlwave-update-rinfo-hook
-         (lambda () (setq idlwave-class-reset t)))
-(add-hook 'idlwave-after-load-rinfo-hook
-         (lambda () (setq idlwave-class-info nil)))
-
-(defun idlwave-class-info (class)
-  (let (list entry)
-    (if idlwave-class-info
-       (if idlwave-class-reset
-           (setq
-            idlwave-class-reset nil
-            idlwave-class-info ; Remove any visited in a buffer
-            (delq nil (mapcar
-                       (lambda (x)
-                         (let ((filebuf
-                                (idlwave-class-file-or-buffer
-                                 (or (cdr (assq 'found-in x)) (car x)))))
-                           (if (cdr filebuf)
-                               nil
-                             x)))
-                       idlwave-class-info))))
-      ;; Info is nil, put in the system stuff to start.
-      (setq idlwave-class-info idlwave-system-class-info)
-      (setq list idlwave-class-info)
-      (while (setq entry (pop list))
-       (idlwave-sintern-class-info entry)))
-    (setq class (idlwave-sintern-class class))
-    (or (assq class idlwave-class-info)
-       (progn (idlwave-scan-class-info class)
-              (assq class idlwave-class-info)))))
-
-(defun idlwave-sintern-class-info (entry)
-  "Sintern the class names in a class-info entry."
-  (let ((inherits (assq 'inherits entry)))
-    (setcar entry (idlwave-sintern-class (car entry) 'set))
-    (if inherits
-       (setcdr inherits (mapcar (lambda (x) (idlwave-sintern-class x 'set))
-                                (cdr inherits))))))
-
-(defun idlwave-find-class-definition (class &optional all-hook alt-class)
-  "Find class structure definition(s).
-If ALL-HOOK is set, find all named structure definitions in a given
-class__define routine, on which ALL-HOOK will be run.  If ALT-CLASS is
-set, look for the name__define pro, and inside of it, for the ALT-CLASS
-class/struct definition."
-  (let ((case-fold-search t) end-lim name)
-    (when (re-search-forward
-          (concat "^[ \t]*pro[ \t]+" (downcase class) "__define" "\\>") nil t)
-      (if all-hook
-         (progn
-           ;; For everything there
-           (setq end-lim (save-excursion (idlwave-end-of-subprogram) (point)))
-           (while (setq name
-                        (idlwave-find-structure-definition nil t end-lim))
-             (funcall all-hook name)))
-       (idlwave-find-structure-definition nil (or alt-class class))))))
-
-
-(defun idlwave-class-file-or-buffer (class)
-  "Find buffer visiting CLASS definition."
-  (let* ((pro (concat (downcase class) "__define"))
-        (file (idlwave-routine-source-file
-               (nth 3 (idlwave-rinfo-assoc pro 'pro nil
-                                           (idlwave-routines))))))
-    (cons file (if file (find-buffer-visiting file)))))
-
-
-(defun idlwave-scan-class-info (class)
-  "Scan all class and named structure info in the class__define pro."
-  (let* ((idlwave-auto-routine-info-updates nil)
-        (filebuf (idlwave-class-file-or-buffer class))
-        (file (car filebuf))
-        (buf (cdr filebuf))
-        (class (idlwave-sintern-class class)))
-    (if (or
-        (not file)
-        (and ;; neither a regular file nor a visited buffer
-         (not buf)
-         (not (file-regular-p file))))
-       nil ; Cannot find the file/buffer to get any info
-      (save-excursion
-       (if buf (set-buffer buf)
-         ;; Read the file in temporarily
-         (set-buffer (get-buffer-create " *IDLWAVE-tmp*"))
-         (erase-buffer)
-         (unless (derived-mode-p 'idlwave-mode)
-           (idlwave-mode))
-         (insert-file-contents file))
-       (save-excursion
-         (goto-char 1)
-         (idlwave-find-class-definition class
-          ;; Scan all of the structures found there
-          (lambda (name)
-            (let* ((this-class (idlwave-sintern-class name))
-                   (entry
-                    (list this-class
-                          (cons 'tags (idlwave-struct-tags))
-                          (cons 'inherits (idlwave-struct-inherits)))))
-              (if (not (eq this-class class))
-                  (setq entry (nconc entry (list (cons 'found-in class)))))
-              (idlwave-sintern-class-info entry)
-              (push entry idlwave-class-info)))))))))
-
-(defun idlwave-class-found-in (class)
-  "Return the FOUND-IN property of the CLASS."
-  (cdr (assq 'found-in (idlwave-class-info class))))
-(defun idlwave-class-tags (class)
-  "Return the native tags in CLASS."
-  (cdr (assq 'tags (idlwave-class-info class))))
-(defun idlwave-class-inherits (class)
-  "Return the direct superclasses of CLASS."
-  (cdr (assq 'inherits (idlwave-class-info class))))
-
-
-(defun idlwave-all-class-tags (class)
-  "Return a list of native and inherited tags in CLASS."
-  (condition-case err
-      (apply #'append (mapcar #'idlwave-class-tags
-                             (cons class (idlwave-all-class-inherits class))))
-    (error
-     (idlwave-class-tag-reset)
-     (error "%s" (error-message-string err)))))
-
-
-(defun idlwave-all-class-inherits (class)
-  "Return a list of all superclasses of CLASS (recursively expanded).
-The list is cached in `idlwave-class-info' for faster access."
-  (cond
-   ((not idlwave-support-inheritance) nil)
-   ((eq class nil) nil)
-   ((eq class t) nil)
-   (t
-    (let ((info (idlwave-class-info class))
-         entry)
-      (if (setq entry (assq 'all-inherits info))
-         (cdr entry)
-       ;; Save the depth of inheritance scan to check for circular references
-       (let ((inherits (mapcar (lambda (x) (cons x 0))
-                               (idlwave-class-inherits class)))
-             rtn all-inherits cl)
-         (while inherits
-           (setq cl (pop inherits)
-                 rtn (cons (car cl) rtn)
-                 inherits (append (mapcar (lambda (x)
-                                            (cons x (1+ (cdr cl))))
-                                          (idlwave-class-inherits (car cl)))
-                                  inherits))
-           (if (> (cdr cl) 999)
-             (error
-               "Class scan: inheritance depth exceeded.  Circular inheritance?")))
-         (setq all-inherits (nreverse rtn))
-         (nconc info (list (cons 'all-inherits all-inherits)))
-         all-inherits))))))
-
-(defun idlwave-entry-keywords (entry &optional record-link)
-  "Return the flat entry keywords alist from routine-info entry.
-If RECORD-LINK is non-nil, the keyword text is copied and a text
-property indicating the link is added."
-  (let (kwds)
-    (mapc
-     (lambda (key-list)
-       (let ((file (car key-list)))
-        (mapcar (lambda (key-cons)
-                  (let ((key (car key-cons))
-                        (link (cdr key-cons)))
-                    (when (and record-link file)
-                        (setq key (copy-sequence key))
-                        (put-text-property
-                         0 (length key)
-                         'link
-                         (concat
-                          file
-                          (if link
-                              (concat idlwave-html-link-sep
-                                      (number-to-string link))))
-                         key))
-                    (push (list key) kwds)))
-                (cdr key-list))))
-     (nthcdr 5 entry))
-    (nreverse kwds)))
-
-(defun idlwave-entry-find-keyword (entry keyword)
-  "Find keyword KEYWORD in entry ENTRY, and return (with link) if set."
-  (catch 'exit
-    (mapc
-     (lambda (key-list)
-       (let ((file (car key-list))
-            (kwd (assoc keyword (cdr key-list))))
-        (when kwd
-          (setq kwd (cons (car kwd)
-                          (if (and file (cdr kwd))
-                              (concat file
-                                      idlwave-html-link-sep
-                                      (number-to-string (cdr kwd)))
-                            (cdr kwd))))
-          (throw 'exit kwd))))
-     (nthcdr 5 entry))))
-
-;;==========================================================================
-;;
-;; Completing class structure tags.  This is a completion plugin.
-;; The necessary taglist is constructed dynamically
-
-(defvar idlwave-current-tags-class nil)
-(defvar idlwave-current-class-tags nil)
-(defvar idlwave-current-native-class-tags nil)
-(defvar idlwave-sint-class-tags nil)
-(idlwave-new-sintern-type class-tag)
-(add-hook 'idlwave-complete-functions #'idlwave-complete-class-structure-tag)
-(add-hook 'idlwave-update-rinfo-hook #'idlwave-class-tag-reset)
-
-(defun idlwave-complete-class-structure-tag ()
-  "Complete a structure tag on a `self' argument in an object method."
-  (interactive)
-  (let ((pos (point))
-       (case-fold-search t))
-    (if (save-excursion
-         ;; Check if the context is right
-         (skip-chars-backward "a-zA-Z0-9._$")
-         (and (< (point) (- pos 4))
-              (looking-at "self\\.")))
-       (let* ((idlwave--class-selector (nth 2 (idlwave-current-routine)))
-              (idlwave--super-classes (idlwave-all-class-inherits
-                                       idlwave--class-selector)))
-         ;; Check if we are in a class routine
-         (unless idlwave--class-selector
-           (error "Not in a method procedure or function"))
-         ;; Check if we need to update the "current" class
-         (if (not (equal idlwave--class-selector idlwave-current-tags-class))
-             (idlwave-prepare-class-tag-completion idlwave--class-selector))
-         (setq idlwave-completion-help-info
-               (list 'idlwave-complete-class-structure-tag-help
-                     (idlwave-sintern-routine
-                      (concat idlwave--class-selector "__define"))
-                     nil))
-          ;; FIXME: idlwave-cpl-bold doesn't seem used anywhere.
-         (let  ((_idlwave-cpl-bold idlwave-current-native-class-tags))
-           (idlwave-complete-in-buffer
-            'class-tag 'class-tag
-            idlwave-current-class-tags nil
-            (format "Select a tag of class %s" idlwave--class-selector)
-            "class tag"
-            'idlwave-attach-class-tag-classes))
-         t) ; return t to skip other completions
-      nil)))
-
-(defun idlwave-class-tag-reset ()
-  (setq idlwave-current-tags-class nil))
-
-(defun idlwave-prepare-class-tag-completion (class)
-  "Find and parse the necessary class definitions for class structure tags."
-  (setq idlwave-sint-class-tags nil)
-  (setq idlwave-current-tags-class class)
-  (setq idlwave-current-class-tags
-       (mapcar (lambda (x)
-                 (list (idlwave-sintern-class-tag x 'set)))
-               (idlwave-all-class-tags class)))
-  (setq idlwave-current-native-class-tags
-       (mapcar #'downcase (idlwave-class-tags class))))
-
-;===========================================================================
-;;
-;; Completing system variables and their structure fields
-;; This is also a plugin.
-
-(defvar idlwave-sint-sysvars nil)
-(defvar idlwave-sint-sysvartags nil)
-(idlwave-new-sintern-type sysvar)
-(idlwave-new-sintern-type sysvartag)
-(add-hook 'idlwave-complete-functions #'idlwave-complete-sysvar-or-tag)
-(add-hook 'idlwave-update-rinfo-hook #'idlwave-sysvars-reset)
-(add-hook 'idlwave-after-load-rinfo-hook #'idlwave-sintern-sysvar-alist)
-
-
-(defun idlwave-complete-sysvar-or-tag ()
-  "Complete a system variable."
-  (interactive)
-  (let ((pos (point))
-       (case-fold-search t))
-    (cond ((save-excursion
-            ;; Check if the context is right for system variable
-            (skip-chars-backward "a-zA-Z0-9_$")
-            (equal (char-before) ?!))
-          (setq idlwave-completion-help-info '(idlwave-complete-sysvar-help))
-          (idlwave-complete-in-buffer 'sysvar 'sysvar
-                                      idlwave-system-variables-alist nil
-                                      "Select a system variable"
-                                      "system variable")
-          t)  ; return t to skip other completions
-         ((save-excursion
-            ;; Check if the context is right for sysvar tag
-            (skip-chars-backward "a-zA-Z0-9_$.")
-            (and (equal (char-before) ?!)
-                 (looking-at "\\([a-zA-Z][a-zA-Z0-9_$]*\\)\\.")
-                 (<= (match-end 0) pos)))
-          ;; Complete a system variable tag
-          (let* ((var (idlwave-sintern-sysvar (match-string 1)))
-                 (entry (assq var idlwave-system-variables-alist))
-                 (tags (cdr (assq 'tags entry))))
-            (or entry (error "!%s is not a known system variable" var))
-            (or tags (error "System variable !%s is not a structure" var))
-            (setq idlwave-completion-help-info
-                  (list 'idlwave-complete-sysvar-tag-help var))
-            (idlwave-complete-in-buffer 'sysvartag 'sysvartag
-                                        tags nil
-                                        "Select a system variable tag"
-                                        "system variable tag")
-            t)) ; return t to skip other completions
-         (t nil))))
-
-(defvar idlw-help-link) ;dynamic variables set by help callback
-(defun idlwave-complete-sysvar-help (mode word)
-  (let ((word (or (nth 1 idlwave-completion-help-info) word))
-       (entry (assoc word idlwave-system-variables-alist)))
-    (cond
-     ((eq mode 'test)
-      (and (stringp word) entry (nth 1 (assq 'link entry))))
-     ((eq mode 'set)
-      ;; Setting dynamic!!!
-      (if entry (setq idlw-help-link (nth 1 (assq 'link entry)))))
-     (t (error "This should not happen")))))
-
-(defun idlwave-complete-sysvar-tag-help (mode word)
-  (let* ((var (nth 1 idlwave-completion-help-info))
-       (entry (assoc var idlwave-system-variables-alist))
-       (tags (cdr (assq 'tags entry)))
-       (main (nth 1 (assq 'link entry)))
-       target)
-    (cond
-     ((eq mode 'test) ; we can at least link the main
-      (and (stringp word) entry main))
-     ((eq mode 'set)
-      (if entry
-         (setq idlw-help-link
-               (if (setq target (cdr (assoc-string word tags t)))
-                   (idlwave-substitute-link-target main target)
-                 main)))) ;; setting dynamic!!!
-     (t (error "This should not happen")))))
-
-(defun idlwave-split-link-target (link)
-  "Split a given LINK into link file and anchor."
-  (if (string-match idlwave-html-link-sep link)
-      (cons (substring link 0 (match-beginning 0))
-           (string-to-number (substring link (match-end 0))))))
-
-(defun idlwave-substitute-link-target (link target)
-  "Substitute the TARGET anchor for the given LINK."
-  (let (main-base)
-    (setq main-base (if (string-match "#" link)
-                       (substring link 0 (match-beginning 0))
-                     link))
-    (if target
-       (concat main-base idlwave-html-link-sep (number-to-string target))
-      link)))
-
-;; Fake help in the source buffer for class structure tags.
-;; IDLW-HELP-LINK AND IDLW-HELP-NAME ARE GLOBAL-VARIABLES HERE.
-;; (from idlwave-do-mouse-completion-help)
-(defvar idlw-help-name)
-(defvar idlw-help-link)
-(defvar idlwave-help-do-class-struct-tag nil)
-(defun idlwave-complete-class-structure-tag-help (mode word)
-  (cond
-   ((eq mode 'test) ; nothing gets fontified for class tags
-    nil)
-   ((eq mode 'set)
-    (let (class-with found-in)
-      (when (setq class-with
-               (idlwave-class-or-superclass-with-tag
-                idlwave-current-tags-class
-                word))
-       (if (assq (idlwave-sintern-class class-with)
-                 idlwave-system-class-info)
-           (error "No help available for system class tags"))
-       (if (setq found-in (idlwave-class-found-in class-with))
-           (setq idlw-help-name (cons (concat found-in "__define") class-with))
-         (setq idlw-help-name (concat class-with "__define")))))
-    (setq idlw-help-link word
-         idlwave-help-do-class-struct-tag t))
-   (t (error "This should not happen"))))
-
-(defun idlwave-class-or-superclass-with-tag (class tag)
-  "Find and return the CLASS or one of its superclass with the
-associated TAG, if any."
-  (let ((sclasses (cons class (idlwave-all-class-inherits class)))
-       cl)
-   (catch 'exit
-     (while sclasses
-       (setq cl (pop sclasses))
-       (let ((tags (idlwave-class-tags cl)))
-        (while tags
-          (if (string-equal-ignore-case tag (car tags))
-            (throw 'exit cl))
-          (setq tags (cdr tags))))))))
-
-
-(defun idlwave-sysvars-reset ()
-  (if (and (fboundp 'idlwave-shell-is-running)
-          (idlwave-shell-is-running)
-          idlwave-idlwave_routine_info-compiled)
-      (idlwave-shell-send-command "idlwave_get_sysvars"
-                                 'idlwave-process-sysvars 'hide)))
-
-(defun idlwave-process-sysvars ()
-  (idlwave-shell-filter-sysvars)
-  (setq idlwave-sint-sysvars nil
-       idlwave-sint-sysvartags nil)
-  (idlwave-sintern-sysvar-alist))
-
-(defun idlwave-sintern-sysvar-alist ()
-  (let ((list idlwave-system-variables-alist) entry tags)
-    (while (setq entry (pop list))
-      (setcar entry (idlwave-sintern-sysvar (car entry) 'set))
-      (setq tags (assq 'tags entry))
-      (if tags
-         (setcdr tags
-                 (mapcar (lambda (x)
-                           (cons (idlwave-sintern-sysvartag (car x) 'set)
-                                 (cdr x)))
-                         (cdr tags)))))))
-
-(defvar idlwave-shell-command-output)
-(defun idlwave-shell-filter-sysvars ()
-  "Get any new system variables and tags."
-  (let ((text idlwave-shell-command-output)
-       (start 0)
-       (old idlwave-system-variables-alist)
-       var tags link old-entry) ;; type name class
-    (setq idlwave-system-variables-alist nil)
-    (while (string-match "^IDLWAVE-SYSVAR: !\\([a-zA-Z0-9_$]+\\)\\( \\(.*\\)\\)?"
-                        text start)
-      (setq start (match-end 0)
-           var (match-string 1 text)
-           tags (if (match-end 3)
-                    (idlwave-split-string (match-string 3 text))))
-      ;; Maintain old links, if present
-      (setq old-entry (assq (idlwave-sintern-sysvar var) old))
-      (setq link (assq 'link old-entry))
-      (setq idlwave-system-variables-alist
-           (cons (list var
-                       (cons
-                        'tags
-                        (mapcar (lambda (x)
-                                  (cons x
-                                        (cdr (assq
-                                              (idlwave-sintern-sysvartag x)
-                                              (cdr (assq 'tags old-entry))))))
-                                tags))
-                       link)
-                 idlwave-system-variables-alist)))
-    ;; Keep the old value if query was not successful
-    (setq idlwave-system-variables-alist
-         (or idlwave-system-variables-alist old))))
-
-(defun idlwave-completion-fontify-classes ()
-  "Goto the *Completions* buffer and fontify the class info."
-  (with-current-buffer "*Completions*"
-    (save-excursion
-      (goto-char (point-min))
-      (let ((buffer-read-only nil))
-        (while (re-search-forward "\\.*<[^>]+>" nil t)
-          (put-text-property (match-beginning 0) (match-end 0)
-                             'face 'font-lock-string-face))))))
-
-(defun idlwave-after-successful-completion (type slash &optional verify)
-  "Add `=' or `(' after successful completion of keyword and function.
-Restore the pre-completion window configuration if possible."
-  (cond
-   ((eq type 'procedure)
-    nil)
-   ((eq type 'function)
-    (cond
-     ((equal idlwave-function-completion-adds-paren nil) nil)
-     ((or (equal idlwave-function-completion-adds-paren t)
-         (equal idlwave-function-completion-adds-paren 1))
-      (insert "("))
-     ((equal idlwave-function-completion-adds-paren 2)
-      (insert "()")
-      (backward-char 1))
-     (t nil)))
-   ((eq type 'keyword)
-    (if (and idlwave-keyword-completion-adds-equal
-            (not slash))
-       (progn (insert "=") t)
-      nil)))
-
-  ;; Restore the pre-completion window configuration if this is safe.
-
-  (if (or (eq verify 'force)                                    ; force
-         (and
-          (get-buffer-window "*Completions*")                  ; visible
-          (idlwave-local-value 'idlwave-completion-p
-                               "*Completions*")                ; cib-buffer
-          (eq (marker-buffer idlwave-completion-mark)
-              (current-buffer))                                ; buffer OK
-          (equal (marker-position idlwave-completion-mark)
-                 verify)))                                     ; pos OK
-      (idlwave-restore-wconf-after-completion))
-  (move-marker idlwave-completion-mark nil)
-  (setq idlwave-before-completion-wconf nil))
-
-(defun idlwave-mouse-context-help (ev &optional arg)
-  "Call `idlwave-context-help' on the clicked location."
-  (interactive "eP")
-  (mouse-set-point ev)
-  (idlwave-context-help arg))
-
-(defvar idlwave-last-context-help-pos nil)
-(defun idlwave-context-help (&optional arg)
-  "Display IDL Online Help on context.
-If point is on a keyword, help for that keyword will be shown.  If
-point is on a routine name or in the argument list of a routine, help
-for that routine will be displayed.  Works for system routines and
-keywords, it pulls up text help.  For other routines and keywords,
-visits the source file, finding help in the header (if
-`idlwave-help-source-try-header' is non-nil) or the routine definition
-itself."
-  (interactive "P")
-  (idlwave-do-context-help arg))
-
-(defun idlwave-mouse-completion-help (ev)
-  "Display online help about the completion at point."
-  (interactive "eP")
-  ;; Restore last-command for next command, to make
-  ;; scrolling/canceling of completions work.
-  (setq this-command last-command)
-  (idlwave-do-mouse-completion-help ev))
-
-(defun idlwave-routine-info (&optional arg _external)
-  "Display a routines calling sequence and list of keywords.
-When point is on the name a function or procedure, or in the argument
-list of a function or procedure, this command displays a help buffer with
-the information.  When called with prefix arg, enforce class query.
-
-When point is on an object operator `->', display the class stored in
-this arrow, if any (see `idlwave-store-inquired-class').  With a prefix
-arg, the class property is cleared out."
-
-  (interactive "P")
-  (idlwave-routines)
-  (if (string-search "->" (buffer-substring
-                          (max (point-min) (1- (point)))
-                          (min (+ 2 (point)) (point-max))))
-      ;; Cursor is on an arrow
-      (if (get-text-property (point) 'idlwave-class)
-         ;; arrow has class property
-         (if arg
-             ;; Remove property
-             (save-excursion
-               (backward-char 1)
-               (when (looking-at ".?\\(->\\)")
-                 (remove-text-properties (match-beginning 1) (match-end 1)
-                                         '(idlwave-class nil face nil))
-                 (message "Class property removed from arrow")))
-           ;; Echo class property
-           (message "Arrow has text property identifying object to be class %s"
-                    (get-text-property (point) 'idlwave-class)))
-       ;; No property found
-       (message "Arrow has no class text property"))
-
-    ;; Not on an arrow...
-    (let* ((idlwave-query-class nil)
-          (idlwave-force-class-query (equal arg '(4)))
-          (module (idlwave-what-module)))
-      (if (car module)
-         (apply #'idlwave-display-calling-sequence
-                (idlwave-fix-module-if-obj_new module))
-       (error "Don't know which calling sequence to show")))))
-
-(defun idlwave-resolve (&optional arg)
-  "Call RESOLVE_ROUTINE on the module name at point.
-Like `idlwave-routine-info', this looks for a routine call at point.
-After confirmation in the minibuffer, it will use the shell to issue
-a RESOLVE call for this routine, to attempt to make it defined and its
-routine info available for IDLWAVE.  If the routine is a method call,
-both `class__method' and `class__define' will be tried.
-With ARG, enforce query for the class of object methods."
-  (interactive "P")
-  (let* ((idlwave-query-class nil)
-        (idlwave-force-class-query (equal arg '(4)))
-        (module (idlwave-what-module))
-        (name (idlwave-make-full-name (nth 2 module) (car module)))
-        (type (if (eq (nth 1 module) 'pro) "pro" "function"))
-        (resolve (read-string "Resolve: " (format "%s %s" type name)))
-        (kwd "")
-        class)
-    (if (string-match "\\(pro\\|function\\)[ \t]+\\(\\(.*\\)::\\)?\\(.*\\)"
-                     resolve)
-       (setq type (match-string 1 resolve)
-             class (if (match-beginning 2)
-                       (match-string 3 resolve)
-                     nil)
-             name (match-string 4 resolve)))
-    (if (string= (downcase type) "function")
-       (setq kwd ",/is_function"))
-
-    (cond
-     ((null class)
-      (idlwave-shell-send-command
-       (format "resolve_routine,'%s'%s" (downcase name) kwd)
-       'idlwave-update-routine-info
-       nil t))
-     (t
-      (idlwave-shell-send-command
-       (format "resolve_routine,'%s__define'%s" (downcase class) kwd)
-       (list 'idlwave-shell-send-command
-            (format "resolve_routine,'%s__%s'%s"
-                    (downcase class) (downcase name) kwd)
-            '(idlwave-update-routine-info)
-            nil t))))))
-
-(defun idlwave-find-module-this-file ()
-  (interactive)
-  (idlwave-find-module '(4)))
-
-(defun idlwave-find-module (&optional arg)
-  "Find the source code of an IDL module.
-Works for modules for which IDLWAVE has routine info available.
-The function offers as default the module name `idlwave-routine-info'
-would use.  With ARG limit to this buffer.  With two prefix ARG's
-force class query for object methods."
-  (interactive "P")
-  (let* ((idlwave-query-class nil)
-        (idlwave-force-class-query (equal arg '(16)))
-        (this-buffer (equal arg '(4)))
-        (module (idlwave-fix-module-if-obj_new (idlwave-what-module)))
-        (default (if module
-                     (concat (idlwave-make-full-name
-                              (nth 2 module) (car module))
-                             (if (eq (nth 1 module) 'pro) "<p>" "<f>"))
-                   "none"))
-        (list
-         (idlwave-uniquify
-          (delq nil
-                (mapcar (lambda (x)
-                          (if (eq 'system (car-safe (nth 3 x)))
-                              ;; Take out system routines with no source.
-                              nil
-                            (list
-                             (concat (idlwave-make-full-name
-                                      (nth 2 x) (car x))
-                                     (if (eq (nth 1 x) 'pro) "<p>" "<f>")))))
-                        (if this-buffer
-                            (idlwave-save-buffer-update)
-                          (idlwave-routines))))))
-        (name (idlwave-completing-read
-               (if (or (not this-buffer)
-                       (assoc default list))
-                   (format-prompt "Module" default)
-                 "Module in this file: ")
-               list))
-        type class)
-    (if (string-match "\\`\\s-*\\'" name)
-       ;; Nothing, use the default.
-       (setq name default))
-    (if (string-match "<[fp]>" name)
-       (setq type (substring name -2 -1)
-             name (substring name 0 -3)))
-    (if (string-match "\\(.*\\)::\\(.*\\)" name)
-       (setq class (match-string 1 name)
-             name (match-string 2 name)))
-    (setq name (idlwave-sintern-routine-or-method name class)
-         class (idlwave-sintern-class class)
-         type (cond ((equal type "f") 'fun)
-                    ((equal type "p") 'pro)
-                    (t t)))
-    (idlwave-do-find-module name type class nil this-buffer)))
-
-(defun idlwave-do-find-module (name type class
-                                   &optional force-source this-buffer)
-  (let ((name1 (idlwave-make-full-name class name))
-       source buf1 entry
-       (buf (current-buffer))
-       (pos (point))
-       file name2)
-    (setq entry (idlwave-best-rinfo-assq name type class (idlwave-routines)
-                                        'WITH-FILE)
-         source (or force-source (nth 3 entry))
-         name2 (if (nth 2 entry)
-                   (idlwave-make-full-name (nth 2 entry) name)
-                 name1))
-    (if source
-       (setq file (idlwave-routine-source-file source)))
-    (unless file  ; Try to find it on the path.
-      (setq file
-           (idlwave-expand-lib-file-name
-            (if class
-                (format "%s__define.pro" (downcase class))
-              (format "%s.pro" (downcase name))))))
-    (cond
-     ((or (null name) (equal name ""))
-      (error "Abort"))
-     ((eq (car source) 'system)
-      (error "Source code for system routine %s is not available"
-            name2))
-     ((or (not file) (not (file-regular-p file)))
-      (error "Source code for routine %s is not available"
-            name2))
-     (t
-      (when (not this-buffer)
-       (setq buf1
-             (idlwave-find-file-noselect file 'find))
-       (pop-to-buffer buf1 t))
-      (goto-char (point-max))
-      (let ((case-fold-search t))
-       (if (re-search-backward
-            (concat "^[ \t]*\\<"
-                    (cond ((eq type 'fun) "function")
-                          ((eq type 'pro) "pro")
-                          (t "\\(pro\\|function\\)"))
-                    "\\>[ \t]+"
-                    (regexp-quote (downcase name2))
-                    "[^a-zA-Z0-9_$]")
-            nil t)
-           (goto-char (match-beginning 0))
-         (pop-to-buffer buf)
-         (goto-char pos)
-         (error "Could not find routine %s" name2)))))))
-
-(defun idlwave-what-module ()
-  "Return a default module for stuff near point.
-Used by `idlwave-routine-info' and `idlwave-find-module'."
-  (idlwave-routines)
-  (if (let ((case-fold-search t))
-       (save-excursion
-         (idlwave-beginning-of-statement)
-         (looking-at "[ \t]*\\(pro\\|function\\)[ \t]+\\(\\([a-zA-Z0-9_$]+\\)::\\)?\\([a-zA-Z0-9$_]+\\)\\([, \t\n]\\|$\\)")))
-      ;; This is a function or procedure definition statement
-      ;; We return the defined routine as module.
-      (list
-       (idlwave-sintern-routine-or-method (match-string-no-properties 4)
-                                         (match-string-no-properties 2))
-       (if (equal (downcase (match-string 1)) "pro") 'pro 'fun)
-       (idlwave-sintern-class (match-string 3)))
-
-    ;; Not a definition statement - analyze precise position.
-    (let* ((where (idlwave-where))
-          (cw (nth 2 where))
-          (pro (car (nth 0 where)))
-          (func (car (nth 1 where)))
-          (this-word (idlwave-this-word "a-zA-Z0-9$_"))
-          (next-char (save-excursion (skip-chars-forward "a-zA-Z0-9$_")
-                                     (following-char)))
-          )
-      (cond
-       ((and (eq cw 'procedure)
-            (not (equal this-word "")))
-       (setq this-word (idlwave-sintern-routine-or-method
-                        this-word (nth 2 (nth 3 where))))
-       (list this-word 'pro
-             (idlwave-determine-class
-              (cons this-word (cdr (nth 3 where)))
-              'pro)))
-       ((and (eq cw 'function)
-            (not (equal this-word ""))
-            (or (eq next-char ?\()     ; exclude arrays, vars.
-                (looking-at "[a-zA-Z0-9_]*[ \t]*(")))
-       (setq this-word (idlwave-sintern-routine-or-method
-                        this-word (nth 2 (nth 3 where))))
-       (list this-word 'fun
-             (idlwave-determine-class
-              (cons this-word (cdr (nth 3 where)))
-              'fun)))
-       ((and (memq cw '(function-keyword procedure-keyword))
-            (not (equal this-word ""))
-            (eq next-char ?\())        ; A function!
-       (setq this-word (idlwave-sintern-routine this-word))
-       (list this-word 'fun nil))
-       (func
-       (list func 'fun (idlwave-determine-class (nth 1 where) 'fun)))
-       (pro
-       (list pro 'pro (idlwave-determine-class (nth 0 where) 'pro)))
-       (t nil)))))
-
-(defun idlwave-what-module-find-class ()
-  "Call `idlwave-what-module' and find the inherited class if necessary."
-  (let* ((module (idlwave-what-module))
-        (class (nth 2 module)))
-    (if (and (= (length module) 3)
-            (stringp class))
-       (list (car module)
-             (nth 1 module)
-             (apply #'idlwave-find-inherited-class module))
-      module)))
-
-(defun idlwave-find-inherited-class (name type class)
-  "Find the class which defines TYPE NAME and is CLASS or inherited by CLASS."
-  (let ((entry (idlwave-best-rinfo-assoc name type class (idlwave-routines))))
-    (if entry
-       (nth 2 entry)
-      class)))
-
-(defun idlwave-fix-module-if-obj_new (module)
-  "Check if MODULE points to obj_new.
-If yes, and if the cursor is in the keyword region, change to the
-appropriate Init method."
-  (let* ((name (car module))
-        (pos (point))
-        (case-fold-search t)
-        string)
-    (if (and (stringp name)
-            (equal (downcase name) "obj_new")
-            (save-excursion
-              (idlwave-beginning-of-statement)
-              (setq string (buffer-substring (point) pos))
-              (string-match "obj_new([^'\"]*['\"]\\([a-zA-Z0-9_]+\\)"
-                            string)))
-       (let (;; (name "Init")
-             (class (match-string 1 string)))
-         (setq module (list (idlwave-sintern-method "Init")
-                            'fun
-                            (idlwave-sintern-class class)))))
-    module))
-
-(defun idlwave-fix-keywords (name type class keywords
-                                 &optional super-classes system)
-  "Update a list of keywords.
-Translate OBJ_NEW, adding all super-class keywords, or all keywords
-from all classes if CLASS equals t.  If SYSTEM is non-nil, don't
-demand _EXTRA in the keyword list."
-  (let ((case-fold-search t)
-        (idlwave--super-classes super-classes))
-
-    ;; If this is the OBJ_NEW function, try to figure out the class and use
-    ;; the keywords from the corresponding INIT method.
-    (if (and (equal (upcase name) "OBJ_NEW")
-            (derived-mode-p '(idlwave-mode idlwave-shell-mode)))
-       (let* ((bos (save-excursion (idlwave-beginning-of-statement) (point)))
-              (string (buffer-substring bos (point)))
-              (case-fold-search t)
-              class)
-         (and (string-match "obj_new([^'\"]*['\"]\\([a-zA-Z0-9_]+\\)"
-                            string)
-              (setq class (idlwave-sintern-class (match-string 1 string)))
-              (setq idlwave-current-obj_new-class class)
-              (setq keywords
-                    (append keywords
-                            (idlwave-entry-keywords
-                             (idlwave-rinfo-assq
-                              (idlwave-sintern-method "INIT")
-                              'fun
-                              class
-                              (idlwave-routines))
-                             'do-link))))))
-
-    ;; If the class is t, combine all keywords of all methods NAME
-    (when (eq class t)
-      (mapc (lambda (entry)
-             (and
-              (nth 2 entry)             ; non-nil class
-              (eq (nth 1 entry) type)   ; correct type
-              (setq keywords
-                    (append keywords
-                            (idlwave-entry-keywords entry 'do-link)))))
-           (idlwave-all-assq name (idlwave-routines)))
-      (setq keywords (idlwave-uniquify keywords)))
-
-    ;; If we have inheritance, add all keywords from superclasses, if
-    ;; the user indicated that method in `idlwave-keyword-class-inheritance'
-    (when (and
-          idlwave--super-classes
-          idlwave-keyword-class-inheritance
-          (stringp class)
-          (or
-           system
-           (assq (idlwave-sintern-keyword "_extra") keywords)
-           (assq (idlwave-sintern-keyword "_ref_extra") keywords))
-          ;; Check if one of the keyword-class regexps matches the name
-          (let ((regexps idlwave-keyword-class-inheritance) re)
-            (catch 'exit
-              (while (setq re (pop regexps))
-                (if (string-match re name) (throw 'exit t))))))
-
-      (cl-loop for entry in (idlwave-routines) do
-           (and (nth 2 entry)                           ; non-nil class
-                (memq (nth 2 entry) idlwave--super-classes) ;an inherited class
-                (eq (nth 1 entry) type)                 ; correct type
-                (eq (car entry) name)                   ; correct name
-                (mapc (lambda (k) (add-to-list 'keywords k))
-                      (idlwave-entry-keywords entry 'do-link))))
-      (setq keywords (idlwave-uniquify keywords)))
-
-    ;; Return the final list
-    keywords))
-
-(defun idlwave-expand-keyword (keyword module)
-  "Expand KEYWORD to one of the valid keyword parameters of MODULE.
-KEYWORD may be an exact match or an abbreviation of a keyword.
-If the match is exact, KEYWORD itself is returned, even if there may be other
-keywords of which KEYWORD is an abbreviation.  This is necessary because some
-system routines have keywords which are prefixes of other keywords.
-If KEYWORD is an abbreviation of several keywords, a list of all possible
-completions is returned.
-If the abbreviation was unique, the correct keyword is returned.
-If it cannot be a keyword, the function return nil.
-If we do not know about MODULE, just return KEYWORD literally."
-  (let* ((name (car module))
-        (type (nth 1 module))
-        (class (nth 2 module))
-        (kwd (idlwave-sintern-keyword keyword))
-        (entry (idlwave-best-rinfo-assoc name type class (idlwave-routines)))
-        (kwd-alist (idlwave-entry-keywords entry))
-        (extra (or (assq (idlwave-sintern-keyword "_EXTRA") kwd-alist)
-                   (assq (idlwave-sintern-keyword "_REF_EXTRA") kwd-alist)))
-        (completion-ignore-case t)
-        candidates)
-    (cond ((assq kwd kwd-alist)
-          kwd)
-         ((setq candidates (all-completions kwd kwd-alist))
-          (if (= (length candidates) 1)
-              (car candidates)
-            candidates))
-         ((and entry extra)
-          ;; Inheritance may cause this keyword to be correct
-          keyword)
-         (entry
-          ;; We do know the function, which does not have the keyword.
-          nil)
-         (t
-          ;; We do not know the function, so this just might be a correct
-          ;; keyword - return it as it is.
-          keyword))))
-
-(defvar idlwave-rinfo-mouse-map
-  (let ((map (make-sparse-keymap)))
-    (define-key map [mouse-2] #'idlwave-mouse-active-rinfo)
-    (define-key map [(shift mouse-2)] #'idlwave-mouse-active-rinfo-shift)
-    (define-key map [mouse-3] #'idlwave-mouse-active-rinfo-right)
-    (define-key map " " #'idlwave-active-rinfo-space)
-    (define-key map "q" #'idlwave-quit-help)
-    map))
-
-(defvar idlwave-rinfo-map
-  (let ((map (make-sparse-keymap)))
-    (define-key map "q" #'idlwave-quit-help)
-    map))
-
-(defvar idlwave-popup-source nil)
-(defvar idlwave-rinfo-marker (make-marker))
-
-(defun idlwave-quit-help ()
-  (interactive)
-  (let ((ri-window (get-buffer-window "*Help*"))
-       (olh-window (get-buffer-window "*IDLWAVE Help*")))
-    (when (and olh-window
-              (fboundp 'idlwave-help-quit))
-      (select-window olh-window)
-      (idlwave-help-quit))
-    (when (window-live-p ri-window)
-      (quit-window nil ri-window))))
-
-(defun idlwave-display-calling-sequence (name type class
-                                             &optional initial-class)
-  ;; Display the calling sequence of module NAME, type TYPE in class CLASS.
-  (let* ((initial-class (or initial-class class))
-        (entry (or (idlwave-best-rinfo-assq name type class
-                                            (idlwave-routines))
-                   (idlwave-rinfo-assq name type class
-                                       idlwave-unresolved-routines)))
-        (name (or (car entry) name))
-        (class (or (nth 2 entry) class))
-        (superclasses (idlwave-all-class-inherits initial-class))
-        (twins (idlwave-routine-twins entry))
-        (dtwins (idlwave-study-twins twins))
-        (all dtwins)
-        (system (eq (car (nth 3 entry)) 'system))
-        (calling-seq (nth 4 entry))
-        (keywords (idlwave-entry-keywords entry 'do-link))
-        (html-file (car (nth 5 entry)))
-        (help-echo-kwd
-         "Button2: Insert KEYWORD (SHIFT=`/KEYWORD') | Button3: Online Help ")
-        (help-echo-use
-         "Button2/3: Online Help")
-        (help-echo-src
-         "Button2: Jump to source and back | Button3: Source in Help window.")
-        (help-echo-class
-         "Button2: Display info about same method in superclass")
-        (col 0)
-        (data (list name type class (current-buffer) nil initial-class))
-        (face 'idlwave-help-link)
-        beg props win cnt total)
-    ;; Fix keywords, but don't add chained idlwave--super-classes, since these
-    ;; are shown separately for that super-class
-    (setq keywords (idlwave-fix-keywords name type class keywords))
-    (cond
-     ((null entry)
-      (error "No %s %s known %s" type name
-            (if initial-class (concat "in class " initial-class) "")))
-     ((or (null name) (equal name ""))
-      (error "No function or procedure call at point"))
-     ((null calling-seq)
-      (error "Calling sequence of %s %s not available" type name))
-     (t
-      (move-marker idlwave-rinfo-marker (point))
-      (with-current-buffer (get-buffer-create "*Help*")
-       (use-local-map idlwave-rinfo-map)
-       (setq buffer-read-only nil)
-       (erase-buffer)
-       (set (make-local-variable 'idlwave-popup-source) nil)
-       (set (make-local-variable 'idlwave-current-obj_new-class)
-                                 idlwave-current-obj_new-class)
-       (when superclasses
-         (setq props (list 'mouse-face 'highlight
-                           'local-map idlwave-rinfo-mouse-map
-                           'help-echo help-echo-class
-                           'data (cons 'class data)))
-         (let ((classes (cons initial-class superclasses)) c)
-           (insert "Classes: ")
-           (while (setq c (pop classes))
-             (insert " ")
-             (setq beg (point))
-             (insert c)
-             (if (equal (downcase c) (downcase class))
-                 (add-text-properties beg (point) (list 'face 'bold))
-               ;; If Method exists in a different class link it
-               (if (idlwave-rinfo-assq name type c (idlwave-routines))
-                   (add-text-properties beg (point) props))))
-           (insert "\n")))
-       (setq props (list 'mouse-face 'highlight
-                         'local-map idlwave-rinfo-mouse-map
-                         'help-echo help-echo-use
-                         'data (cons 'usage data)))
-       (if html-file (setq props (append (list 'face face 'link html-file)
-                                         props)))
-       (insert "Usage:    ")
-       (setq beg (point))
-       (insert (if class
-                   (format calling-seq class name class name class name)
-                 (format calling-seq name name name name))
-               "\n")
-       (add-text-properties beg (point) props)
-
-       (insert "Keywords:")
-       (if (null keywords)
-           (insert " No keywords accepted.")
-         (setq col 9)
-         (mapc
-          (lambda (x)
-            (if (>= (+ col 1 (length (car x)))
-                    (window-width))
-                (progn
-                  (insert "\n         ")
-                  (setq col 9)))
-            (insert " ")
-            (setq beg (point)
-                  ;; Relevant keywords already have link property attached
-                  props (list 'mouse-face 'highlight
-                              'local-map idlwave-rinfo-mouse-map
-                              'data (cons 'keyword data)
-                              'help-echo help-echo-kwd
-                              'keyword (car x)))
-            (if system (setq props (append (list 'face face) props)))
-            (insert (car x))
-            (add-text-properties beg (point) props)
-            (setq col (+ col 1 (length (car x)))))
-          keywords))
-
-       (setq cnt 1 total (length all))
-       ;; Here entry is (key file (list of type-conses))
-       (while (setq entry (pop all))
-         (setq props (list 'mouse-face 'highlight
-                           'local-map idlwave-rinfo-mouse-map
-                           'help-echo help-echo-src
-                           'source (list (car (car (nth 2 entry))) ;type
-                                         (nth 1 entry)
-                                         nil
-                                         (cdr (car (nth 2 entry))))
-                           'data (cons 'source data)))
-         (idlwave-insert-source-location
-          (format "\n%-8s  %s"
-                  (if (equal cnt 1)
-                      (if (> total 1) "Sources:" "Source:")
-                    "")
-                  (if (> total 1) "- " ""))
-          entry props)
-         (cl-incf cnt)
-         (when (and all (> cnt idlwave-rinfo-max-source-lines))
-           ;; No more source lines, please
-           (insert (format
-                    "\n          Source information truncated to %d entries."
-                    idlwave-rinfo-max-source-lines))
-           (setq all nil)))
-       (goto-char (point-min))
-       (setq buffer-read-only t))
-      (display-buffer "*Help*")
-      (if (and (setq win (get-buffer-window "*Help*"))
-              idlwave-resize-routine-help-window)
-         (progn
-           (let ((ww (selected-window)))
-             (unwind-protect
-                 (progn
-                   (select-window win)
-                   (enlarge-window (- (/ (frame-height) 2)
-                                      (window-height)))
-                   (shrink-window-if-larger-than-buffer))
-               (select-window ww)))))))))
-
-(defun idlwave-insert-source-location (prefix entry &optional file-props)
-  "Insert a source location into the routine info buffer.
-Start line with PREFIX.  If a file name is inserted, add FILE-PROPS
-to it."
-  (let* ((key (car entry))
-        (file (nth 1 entry))
-        (types (nth 2 entry))
-        (shell-flag (assq 'compiled types))
-        (buffer-flag (assq 'buffer types))
-        (user-flag (assq 'user types))
-        (lib-flag (assq 'lib types))
-        (ndupl (or (and buffer-flag (idlwave-count-memq 'buffer types))
-                   (and user-flag (idlwave-count-memq 'user types))
-                   (and lib-flag (idlwave-count-memq 'lib types))
-                   1))
-        (doflags t)
-        beg special)
-
-    (insert prefix)
-
-    (cond
-     ((eq key 'system)
-      (setq doflags nil)
-      (insert "System    "))
-
-     ((eq key 'builtin)
-      (setq doflags nil)
-      (insert "Builtin   "))
-
-     ((and (not file) shell-flag)
-      (insert "Unresolved"))
-
-     ((null file)
-      (insert "ERROR"))
-
-     ((idlwave-syslib-p file)
-      (if (string-match "obsolete" (file-name-directory file))
-         (insert "Obsolete  ")
-       (insert "SystemLib ")))
-
-     ;; New special syntax: taken directly from routine-info for
-     ;; library catalog routines
-     ((setq special (or (cdr lib-flag) (cdr user-flag)))
-      (insert (format "%-10s" special)))
-
-     ;; Old special syntax: a matching regexp
-     ((setq special (idlwave-special-lib-test file))
-      (insert (format "%-10s" special)))
-
-     ;; Catch-all with file
-     ((idlwave-lib-p file)      (insert "Library   "))
-
-     ;; Sanity catch all
-     (t                         (insert "Other     ")))
-
-    (when doflags
-      (insert (concat
-              "  ["
-              (if lib-flag "L" "-")
-              (if user-flag "C" "-")
-              (if shell-flag "S" "-")
-              (if buffer-flag "B" "-")
-              "] ")))
-    (when (> ndupl 1)
-      (setq beg (point))
-      (insert (format "(%dx) " ndupl))
-      (add-text-properties beg (point) (list 'face 'bold)))
-    (when (and file (not (equal file "")))
-      (setq beg (point))
-      (insert (apply #'abbreviate-file-name (list file)))
-      (if file-props
-         (add-text-properties beg (point) file-props)))))
-
-(defun idlwave-special-lib-test (file)
-  "Check the path of FILE against the regexps which define special libs.
-Return the name of the special lib if there is a match."
-  (let ((alist idlwave-special-lib-alist)
-       entry rtn)
-    (cond
-     ((stringp file)
-      (while (setq entry (pop alist))
-       (if (string-match (car entry) file)
-           (setq rtn (cdr entry)
-                 alist nil)))
-      rtn)
-     (t nil))))
-
-(defun idlwave-mouse-active-rinfo-right (ev)
-  (interactive "e")
-  (idlwave-mouse-active-rinfo ev 'right))
-
-(defun idlwave-mouse-active-rinfo-shift (ev)
-  (interactive "e")
-  (idlwave-mouse-active-rinfo ev nil 'shift))
-
-(defun idlwave-active-rinfo-space ()
-  (interactive)
-  (idlwave-mouse-active-rinfo nil 'right))
-
-(defun idlwave-mouse-active-rinfo (ev &optional right shift)
-  "Do the mouse actions in the routine info buffer.
-Optional args RIGHT and SHIFT indicate, if mouse-3 was used, and if SHIFT
-was pressed."
-  (interactive "e")
-  (if ev (mouse-set-point ev))
-  (let (data id name type class buf bufwin source link keyword
-            word initial-class)
-    (setq data (get-text-property (point) 'data)
-         source (get-text-property (point) 'source)
-         keyword (get-text-property (point) 'keyword)
-         link (get-text-property (point) 'link)
-         id (car data)
-         name (nth 1 data) type (nth 2 data) class (nth 3 data)
-         buf (nth 4 data)
-         initial-class (nth 6 data)
-         word (idlwave-this-word)
-         bufwin (get-buffer-window buf t))
-
-    (cond ((eq id 'class) ; Switch class being displayed
-          (if (window-live-p bufwin) (select-window bufwin))
-          (idlwave-display-calling-sequence
-           (idlwave-sintern-method name)
-           type (idlwave-sintern-class word)
-           initial-class))
-         ((eq id 'usage) ; Online help on this routine
-          (idlwave-online-help link name type class))
-         ((eq id 'source) ; Source in help or buffer
-          (if right ; In help
-              (let ((idlwave-extra-help-function 'idlwave-help-with-source)
-                    (idlwave-help-source-try-header nil)
-                    ;; Fake idlwave-routines so help will find the right entry
-                    (idlwave-routines
-                     (list (list name type class source ""))))
-                (idlwave-help-get-special-help name type class nil))
-            ;; Otherwise just pop to the source
-            (setq idlwave-popup-source (not idlwave-popup-source))
-            (if idlwave-popup-source
-                (condition-case err
-                    (idlwave-do-find-module name type class source)
-                  (error
-                   (setq idlwave-popup-source nil)
-                   (if (window-live-p bufwin) (select-window bufwin))
-                   (error (nth 1 err))))
-              (if bufwin
-                  (select-window bufwin)
-                (pop-to-buffer buf))
-              (goto-char (marker-position idlwave-rinfo-marker)))))
-         ((eq id 'keyword)
-          (if right
-              (idlwave-online-help link name type class keyword)
-            (idlwave-rinfo-insert-keyword keyword buf shift))))))
-
-(defun idlwave-rinfo-insert-keyword (keyword buffer &optional shift)
-  "Insert KEYWORD in BUFFER.  Make sure buffer is displayed in a window."
-  (let ((bwin (get-buffer-window buffer)))
-    (if idlwave-complete-empty-string-as-lower-case
-       (setq keyword (downcase keyword)))
-    (if bwin
-       (select-window bwin)
-      (pop-to-buffer buffer)
-      (setq bwin (get-buffer-window buffer)))
-    (if (eq (preceding-char) ?/)
-       (insert keyword)
-      (unless (save-excursion
-               (re-search-backward
-                "[(,][ \t]*\\(\\$[ \t]*\\(;.*\\)?\n\\)?[ \t]*\\="
-                (min (- (point) 100) (point-min)) t))
-       (insert ", "))
-      (if shift (insert "/"))
-      (insert keyword)
-      (if (and (not shift)
-              idlwave-keyword-completion-adds-equal)
-         (insert "=")))))
-
-(defun idlwave-list-buffer-load-path-shadows (&optional _arg)
-  "List the load path shadows of all routines defined in current buffer."
-  (interactive)
-  (idlwave-routines)
-  (if (derived-mode-p 'idlwave-mode)
-      (idlwave-list-load-path-shadows
-       nil (idlwave-update-current-buffer-info 'save-buffer)
-       "in current buffer")
-    (error "Current buffer is not in idlwave-mode")))
-
-(defun idlwave-list-shell-load-path-shadows (&optional _arg)
-  "List the load path shadows of all routines compiled under the shell.
-This is very useful for checking an IDL application.  Just compile the
-application, do RESOLVE_ALL, and \\`C-c C-i' to compile all referenced
-routines and update IDLWAVE internal info.  Then check for shadowing
-with this command."
-  (interactive)
-  (cond
-   ((or (not (fboundp 'idlwave-shell-is-running))
-       (not (idlwave-shell-is-running)))
-    (error "Shell is not running"))
-   ((null idlwave-compiled-routines)
-    (error "No compiled routines.  Maybe you need to update with `C-c C-i'"))
-   (t
-    (idlwave-list-load-path-shadows nil idlwave-compiled-routines
-                                   "in the shell"))))
-
-(defun idlwave-list-all-load-path-shadows (&optional _arg)
-  "List the load path shadows of all routines known to IDLWAVE."
-  (interactive)
-  (idlwave-list-load-path-shadows nil nil "globally"))
-
-(defvar idlwave-sort-prefer-buffer-info t
-  "Internal variable used to influence `idlwave-routine-twin-compare'.")
-
-(defun idlwave-list-load-path-shadows (_arg &optional special-routines loc)
-  "List the routines which are defined multiple times.
-Search the information IDLWAVE has about IDL routines for multiple
-definitions.
-When SPECIAL-ROUTINES in non-nil, only look for shadows of these routines.
-
-When IDL hits a routine call which is not defined, it will search on
-the load path in order to find a definition.  The output of this command
-can be used to detect possible name clashes during this process."
-  (idlwave-routines)  ; Make sure everything is loaded.
-  (unless (or idlwave-user-catalog-routines idlwave-library-catalog-routines)
-    (or (y-or-n-p
-        "You don't have any user or library catalogs.  Continue anyway? ")
-       (error "Abort")))
-  (let* ((routines (append idlwave-system-routines
-                          idlwave-compiled-routines
-                          idlwave-library-catalog-routines
-                          idlwave-user-catalog-routines
-                          idlwave-buffer-routines
-                          nil))
-        (keymap (make-sparse-keymap))
-        (props (list 'mouse-face 'highlight
-                     'local-map keymap
-                     'help-echo "Mouse2: Find source"))
-        (nroutines (length (or special-routines routines)))
-        (step (/ nroutines 100))
-        (n 0)
-        (cnt 0)
-        (idlwave-sort-prefer-buffer-info nil)
-        routine twins dtwins twin done props1 lroutines)
-
-    (if special-routines
-       ;; Just looking for shadows of a few special routines
-       (setq lroutines routines
-             routines special-routines))
-
-    (message "Sorting routines...")
-    (setq routines (sort routines
-                        (lambda (a b)
-                          (string< (downcase (idlwave-make-full-name
-                                              (nth 2 a) (car a)))
-                                   (downcase (idlwave-make-full-name
-                                              (nth 2 b) (car b)))))))
-    (message "Sorting routines...done")
-
-    (define-key keymap [(mouse-2)]
-      (lambda (ev)
-       (interactive "e")
-       (mouse-set-point ev)
-       (apply #'idlwave-do-find-module
-              (get-text-property (point) 'find-args))))
-    (define-key keymap [(return)]
-      (lambda ()
-       (interactive)
-       (apply #'idlwave-do-find-module
-              (get-text-property (point) 'find-args))))
-    (message "Compiling list...( 0%%)")
-    (with-current-buffer (get-buffer-create "*Shadows*")
-      (setq buffer-read-only nil)
-      (erase-buffer)
-      (while (setq routine (pop routines))
-       (if (= (mod (setq n (1+ n)) step) 0)
-           (message "Compiling list...(%2d%%)" (floor (* n 100.0) nroutines)))
-
-       ;; Get a list of all twins
-       (setq twins (idlwave-routine-twins routine (or lroutines routines)))
-       (if (memq routine done)
-           (setq dtwins nil)
-         (setq dtwins (idlwave-study-twins twins)))
-       ;; Mark all twins as dealt with
-       (setq done (append twins done))
-       (when (or (> (length dtwins) 1)
-                 (> (idlwave-count-memq 'lib (nth 2 (car dtwins))) 1)
-                 (> (idlwave-count-memq 'user (nth 2 (car dtwins))) 1)
-                 (> (idlwave-count-memq 'buffer (nth 2 (car dtwins))) 1))
-         (cl-incf cnt)
-         (insert (format "\n%s%s"
-                         (idlwave-make-full-name (nth 2 routine)
-                                                 (car routine))
-                         (if (eq (nth 1 routine) 'fun) "()" "")))
-         (while (setq twin (pop dtwins))
-           (setq props1 (append (list 'find-args
-                                      (list (nth 0 routine)
-                                            (nth 1 routine)
-                                            (nth 2 routine)))
-                                props))
-           (idlwave-insert-source-location "\n   - " twin props1))))
-      (goto-char (point-min))
-      (setq buffer-read-only t))
-    (setq loc (or loc ""))
-    (if (> cnt 0)
-       (progn
-         (display-buffer (get-buffer "*Shadows*"))
-         (message "%d case%s of shadowing found %s"
-                  cnt (if (= cnt 1) "" "s") loc))
-      (message "No shadowing conflicts found %s" loc))))
-
-(defun idlwave-print-source (routine)
-  (let* ((source (nth 3 routine))
-        (stype (car source))
-        (sfile (idlwave-routine-source-file source)))
-    (if (idlwave-syslib-p sfile) (setq stype 'syslib))
-    (if (and (eq stype 'compiled)
-            (or (not (stringp sfile))
-                (not (string-match "\\S-" sfile))))
-       (setq stype 'unresolved))
-    (princ (format "      %-10s %s\n"
-                  stype
-                  (if sfile sfile "No source code available")))))
-
-(defun idlwave-routine-twins (entry &optional list)
-  "Return all twin entries of ENTRY in LIST.
-LIST defaults to `idlwave-routines'.
-Twin entries are those which have the same name, type, and class.
-ENTRY will also be returned, as the first item of this list."
-  (let* ((name (car entry))
-        (type (nth 1 entry))
-        (class (nth 2 entry))
-        (candidates (idlwave-all-assq name (or list (idlwave-routines))))
-        twins candidate)
-    (while (setq candidate (pop candidates))
-      (if (and (not (eq candidate entry))
-              (eq type (nth 1 candidate))
-              (eq class (nth 2 candidate)))
-         (push candidate twins)))
-    (if (setq candidate (idlwave-rinfo-assq name type class
-                                           idlwave-unresolved-routines))
-       (push candidate twins))
-    (cons entry (nreverse twins))))
-
-;; Bound in idlwave-study-twins,idlwave-routine-entry-compare-twins.
-(defvar idlwave-twin-class)
-(defvar idlwave-twin-name)
-
-(defun idlwave-study-twins (entries)
-  "Return dangerous twins of first entry in ENTRIES.
-Dangerous twins are routines with same name, but in different files on
-the load path.  If a file is in the system library and has an entry in
-the `idlwave-system-routines' list, we omit the latter as
-non-dangerous because many IDL routines are implemented as library
-routines, and may have been scanned."
-  (let* ((entry (car entries))
-        (idlwave-twin-name (car entry))      ;
-        (type (nth 1 entry))    ; Must be bound for
-        (idlwave-twin-class (nth 2 entry)) ;  idlwave-routine-twin-compare
-        (cnt 0)
-        source type-cons file alist syslibp key)
-    (while (setq entry (pop entries))
-      (cl-incf cnt)
-      (setq source (nth 3 entry)
-           type (car source)
-           type-cons (cons type (nth 3 source))
-           file (idlwave-routine-source-file source))
-
-      ;; Make KEY to index entry properly
-      (setq key (cond ((eq type 'system) type)
-                     (file (file-truename file))
-                     (t 'unresolved)))
-
-      ;; Check for an entry in the system library
-      (if (and file
-              (not syslibp)
-              (idlwave-syslib-p file))
-         (setq syslibp t))
-
-      ;; If there's more than one matching entry for the same file, just
-      ;; append the type-cons to the type list.
-      (if (setq entry (assoc key alist))
-         (push type-cons (nth 2 entry))
-       (push (list key file (list type-cons)) alist)))
-
-    (setq alist (nreverse alist))
-
-    (when syslibp
-      ;; File is in system *library* - remove any 'system entry
-      (setq alist (delq (assq 'system alist) alist)))
-
-    ;; If 'system remains and we've scanned the syslib, it's a builtin
-    ;; (rather than a !DIR/lib/.pro file bundled as source).
-    (when (and (idlwave-syslib-scanned-p)
-              (setq entry (assoc 'system alist)))
-      (setcar entry 'builtin))
-    (sort alist #'idlwave-routine-twin-compare)))
-
-;; FIXME: Dynamically scoped vars need to use the `idlwave-' prefix.
-;; (defvar type)
-
-(define-obsolete-function-alias 'idlwave-xor #'xor "27.1")
-
-(defun idlwave-routine-entry-compare (a b)
-  "Compare two routine info entries for sorting.
-This is the general case.  It first compares class, names, and type.
-If it turns out that A and B are twins (same name, class, and type),
-calls another routine which compares twins on the basis of their file
-names and path locations."
-  (let ((name (car a)) (type (nth 1 a)) (class (nth 2 a)))
-    (cond
-     ((not (equal (idlwave-downcase-safe class)
-                 (idlwave-downcase-safe (nth 2 b))))
-      ;; Class decides
-      (cond ((null (nth 2 b)) nil)
-           ((null class) t)
-           (t (string< (downcase class) (downcase (nth 2 b))))))
-     ((not (equal (downcase name) (downcase (car b))))
-      ;; Name decides
-      (string< (downcase name) (downcase (car b))))
-     ((not (eq type (nth 1 b)))
-      ;; Type decides
-      (< (if (eq type 'fun) 1 0) (if (eq (nth 1 b) 'fun) 1 0)))
-     (t
-      ;; A and B are twins - so the decision is more complicated.
-      ;; Call twin-compare with the proper arguments.
-      (idlwave-routine-entry-compare-twins a b)))))
-
-(defun idlwave-routine-entry-compare-twins (a b)
-  "Compare two routine entries, under the assumption that they are twins.
-This basically calls `idlwave-routine-twin-compare' with the correct args."
-  (let* ((idlwave-twin-name (car a))
-        ;; (type (nth 1 a))
-        (idlwave-twin-class (nth 2 a)) ; used in idlwave-routine-twin-compare
-        (asrc (nth 3 a))
-        (atype (car asrc))
-        (bsrc (nth 3 b))
-        (btype (car bsrc))
-        (afile (idlwave-routine-source-file asrc))
-        (bfile (idlwave-routine-source-file bsrc)))
-    (idlwave-routine-twin-compare
-     (if (stringp afile)
-        (list (file-truename afile) afile (list atype))
-       (list atype afile (list atype)))
-     (if (stringp bfile)
-        (list (file-truename bfile) bfile (list btype))
-       (list btype bfile (list btype))))))
-
-(defun idlwave-routine-twin-compare (a b)
-  "Compare two routine twin entries for sorting.
-In here, A and B are not normal routine info entries, but special
-lists (KEY FILENAME (TYPES...)).
-This expects NAME TYPE IDLWAVE-TWIN-CLASS to be bound to the right values."
-  (let* (;; Dis-assemble entries
-        (akey (car a))      (bkey (car b))
-        (afile (nth 1 a))   (bfile (nth 1 b))
-        (atypes (nth 2 a))  (btypes (nth 2 b))
-        ;; System routines?
-        (asysp (memq akey '(builtin system)))
-        (bsysp (memq bkey '(builtin system)))
-        ;; Compiled routines?
-        (acompp (memq 'compiled atypes))
-        (bcompp (memq 'compiled btypes))
-        ;; Unresolved?
-        (aunresp (or (eq akey 'unresolved)
-                     (and acompp (not afile))))
-        (bunresp (or (eq bkey 'unresolved)
-                     (and bcompp (not bfile))))
-        ;; Buffer info available?
-        (abufp (memq 'buffer atypes))
-        (bbufp (memq 'buffer btypes))
-        ;; On search path?
-        (tpath-alist (idlwave-true-path-alist))
-        (apathp (and (stringp akey)
-                     (assoc (file-name-directory akey) tpath-alist)))
-        (bpathp (and (stringp bkey)
-                     (assoc (file-name-directory bkey) tpath-alist)))
-        ;; How early on search path?  High number means early since we
-        ;; measure the tail of the path list
-        (anpath (length (memq apathp tpath-alist)))
-        (bnpath (length (memq bpathp tpath-alist)))
-        ;; Look at file names
-        (aname (if (stringp afile) (downcase (file-name-nondirectory afile)) ""))
-        (bname (if (stringp bfile) (downcase (file-name-nondirectory bfile)) ""))
-        (fname-re (if idlwave-twin-class
-                      (format "\\`%s__\\(%s\\|define\\)\\.pro\\'"
-                              (regexp-quote (downcase idlwave-twin-class))
-                              (regexp-quote (downcase idlwave-twin-name)))
-                    (format "\\`%s\\.pro" (regexp-quote (downcase idlwave-twin-name)))))
-        ;; Is file name derived from the routine name?
-        ;; Method file or class definition file?
-        (anamep (string-match fname-re aname))
-        (adefp (and idlwave-twin-class anamep
-                    (string= "define" (match-string 1 aname))))
-        (bnamep (string-match fname-re bname))
-        (bdefp (and idlwave-twin-class bnamep
-                    (string= "define" (match-string 1 bname)))))
-
-    ;; Now: follow JD's ideas about sorting.  Looks really simple now,
-    ;; doesn't it?  The difficult stuff is hidden above...
-    (cond
-     ((xor asysp   bsysp)     asysp)        ; System entries first
-     ((xor aunresp bunresp)   bunresp)      ; Unresolved last
-     ((and idlwave-sort-prefer-buffer-info
-           (xor abufp bbufp)) abufp)        ; Buffers before non-buffers
-     ((xor acompp bcompp)     acompp)       ; Compiled entries
-     ((xor apathp bpathp)     apathp)       ; Library before non-library
-     ((xor anamep bnamep)     anamep)       ; Correct file names first
-     ((and idlwave-twin-class anamep bnamep ; both file names match ->
-           (xor adefp bdefp)) bdefp)        ; __define after __method
-     ((> anpath bnpath)       t)            ; Who is first on path?
-     (t                       nil))))       ; Default
-
-(defun idlwave-routine-source-file (source)
-  (if (nth 2 source)
-      (expand-file-name (nth 1 source) (nth 2 source))
-    (nth 1 source)))
-
-(defun idlwave-downcase-safe (string)
-  "Downcase if string, else return unchanged."
-  (if (stringp string)
-      (downcase string)
-    string))
-
-(defun idlwave-count-eq (elt list)
-  "How often is ELT in LIST?"
-  (declare (obsolete nil "30.1"))
-  (seq-count (lambda (x) (eq x elt)) list))
-
-(defun idlwave-count-memq (elt alist)
-  "How often is ELT a key in ALIST?"
-  (seq-count (lambda (x) (eq (car x) elt)) alist))
-
-(defun idlwave-syslib-p (file)
-  "Non-nil if FILE is in the system library."
-  (let* ((true-syslib (file-name-as-directory
-                      (file-truename
-                       (expand-file-name "lib" (idlwave-sys-dir)))))
-        (true-file (file-truename file)))
-    (string-match (concat "^" (regexp-quote true-syslib)) true-file)))
-
-(defun idlwave-lib-p (file)
-  "Non-nil if FILE is in the library."
-  (let ((true-dir (file-name-directory (file-truename file))))
-    (assoc true-dir (idlwave-true-path-alist))))
-
-(defun idlwave-path-alist-add-flag (list-entry flag)
-  "Add a flag to the path list entry, if not set."
-  (cl-pushnew flag (cdr list-entry) :test #'equal))
-
-(defun idlwave-path-alist-remove-flag (list-entry flag)
-  "Remove a flag to the path list entry, if set."
-  (let ((flags (delq flag (cdr list-entry))))
-    (setcdr list-entry flags)))
-
-(defun idlwave-true-path-alist ()
-  "Return `idlwave-path-alist' alist with true-names.
-Info is cached, but relies on the functions setting `idlwave-path-alist'
-to reset the variable `idlwave-true-path-alist' to nil."
-  (or idlwave-true-path-alist
-      (setq idlwave-true-path-alist
-           (mapcar (lambda(x) (cons
-                               (file-name-as-directory
-                                (file-truename
-                                 (directory-file-name
-                                  (car x))))
-                               (cdr x)))
-                   idlwave-path-alist))))
-
-(defun idlwave-syslib-scanned-p ()
-  "Non-nil if the system lib file !DIR/lib has been scanned."
-  (let* ((true-syslib (file-name-as-directory
-                      (file-truename
-                       (expand-file-name "lib" (idlwave-sys-dir))))))
-    (cdr (assoc true-syslib (idlwave-true-path-alist)))))
-
-;; ----------------------------------------------------------------------------
-;;
-;; Online Help display
-
-
-;; ----------------------------------------------------------------------------
-;;
-;; Additions for use with imenu.el
-;; (pop-up a list of IDL units in the current file).
-;;
-
-(defun idlwave-prev-index-position ()
-  "Search for the previous procedure or function.
-Return nil if not found.  For use with imenu.el."
-  (save-match-data
-    (cond
-     ((idlwave-find-key "\\<\\(pro\\|function\\)\\>" -1 'nomark))
-     ;;   ((idlwave-find-key idlwave-begin-unit-reg 1 'nomark)
-     (t nil))))
-
-(defun idlwave-unit-name ()
-  "Return the unit name.
-Assumes that point is at the beginning of the unit as found by
-`idlwave-prev-index-position'."
-  (forward-sexp 2)
-  (forward-sexp -1)
-  (let ((begin (point)))
-    (re-search-forward
-     "[a-zA-Z_][a-zA-Z0-9$_]+\\(::[a-zA-Z_][a-zA-Z0-9$_]+\\)?")
-    (buffer-substring-no-properties begin (point))))
-
-(define-obsolete-function-alias 'idlwave-function-menu #'imenu "29.1")
-
-(defun idlwave-edit-in-idlde ()
-  "Edit the current file in IDL Development environment."
-  (interactive)
-  (start-process "idldeclient" nil
-                idlwave-shell-explicit-file-name "-c" "-e"
-                 (buffer-file-name)))
-
-(defvar idlwave-help-use-assistant)
-(defun idlwave-launch-idlhelp ()
-  "Start the IDLhelp application."
-  (interactive)
-  (if idlwave-help-use-assistant
-      (idlwave-help-assistant-raise)
-    (start-process "idlhelp" nil idlwave-help-application)))
-
-;; Menus - using easymenu.el
-(defvar idlwave-mode-menu-def
-  '("IDLWAVE"
-    ["PRO/FUNC menu" imenu t]
-    ("Motion"
-     ["Subprogram Start" idlwave-beginning-of-subprogram t]
-     ["Subprogram End" idlwave-end-of-subprogram t]
-     ["Block Start" idlwave-beginning-of-block t]
-     ["Block End" idlwave-end-of-block t]
-     ["Up Block" idlwave-backward-up-block t]
-     ["Down Block" idlwave-down-block t]
-     ["Skip Block Backward" idlwave-backward-block t]
-     ["Skip Block Forward" idlwave-forward-block t])
-    ("Mark"
-     ["Subprogram" idlwave-mark-subprogram t]
-     ["Block" idlwave-mark-block t]
-     ["Header" idlwave-mark-doclib t])
-    ("Format"
-     ["Indent Entire Statement" idlwave-indent-statement
-      :active t :keys "C-u \\[indent-for-tab-command]" ]
-     ["Indent Subprogram" idlwave-indent-subprogram t]
-     ["(Un)Comment Region" idlwave-toggle-comment-region t]
-     ["Continue/Split line" idlwave-split-line t]
-     "--"
-     ["Toggle Auto Fill" auto-fill-mode :style toggle
-      :selected auto-fill-function])
-    ("Templates"
-     ["Procedure" idlwave-procedure t]
-     ["Function" idlwave-function t]
-     ["Doc Header" idlwave-doc-header t]
-     ["Log" idlwave-doc-modification t]
-     "--"
-     ["Case" idlwave-case t]
-     ["For" idlwave-for t]
-     ["Repeat" idlwave-repeat t]
-     ["While" idlwave-while t]
-     "--"
-     ["Close Block" idlwave-close-block t])
-    ("Completion"
-     ["Complete" idlwave-complete t]
-     ("Complete Specific"
-      ["1 Procedure Name" (idlwave-complete 'procedure) t]
-      ["2 Procedure Keyword" (idlwave-complete 'procedure-keyword) t]
-      "--"
-      ["3 Function Name" (idlwave-complete 'function) t]
-      ["4 Function Keyword" (idlwave-complete 'function-keyword) t]
-      "--"
-      ["5 Procedure Method Name" (idlwave-complete 'procedure-method) t]
-      ["6 Procedure Method Keyword" (idlwave-complete 'procedure-method-keyword) t]
-      "--"
-      ["7 Function Method Name" (idlwave-complete 'function-method) t]
-      ["8 Function Method Keyword" (idlwave-complete 'function-method-keyword) t]
-      "--"
-      ["9 Class Name"  idlwave-complete-class t]))
-    ("Routine Info"
-     ["Show Routine Info" idlwave-routine-info t]
-     ["Online Context Help" idlwave-context-help t]
-     "--"
-     ["Find Routine Source" idlwave-find-module t]
-     ["Resolve Routine" idlwave-resolve (featurep 'idlw-shell)]
-     "--"
-     ["Update Routine Info" idlwave-update-routine-info t]
-     ["Rescan XML Help Catalog" idlwave-convert-xml-system-routine-info t]
-     "--"
-     "IDL User Catalog"
-     ["Select Catalog Directories" (idlwave-create-user-catalog-file nil) t]
-     ["Scan Directories" (idlwave-update-routine-info '(16))
-      (and idlwave-path-alist (not idlwave-catalog-process))]
-     ["Scan Directories &" (idlwave-update-routine-info '(64))
-      (and idlwave-path-alist (not idlwave-catalog-process))]
-     "--"
-     "Routine Shadows"
-     ["Check Current Buffer" idlwave-list-buffer-load-path-shadows t]
-     ["Check Compiled Routines" idlwave-list-shell-load-path-shadows t]
-     ["Check Everything" idlwave-list-all-load-path-shadows t])
-    ("Misc"
-     ["Kill auto-created buffers" idlwave-kill-autoloaded-buffers t]
-     "--"
-     ["Insert TAB character" idlwave-hard-tab t])
-    "--"
-    ("External"
-     ["Start IDL shell" idlwave-shell t]
-     ["Edit file in IDLDE" idlwave-edit-in-idlde t]
-     ["Launch IDL Help" idlwave-launch-idlhelp t])
-    "--"
-    ("Customize"
-     ["Browse IDLWAVE Group" idlwave-customize t]
-     "--"
-     ["Build Full Customize Menu" idlwave-create-customize-menu t])
-    ("Documentation"
-     ["Describe Mode" describe-mode t]
-     ["Abbreviation List" idlwave-list-abbrevs t]
-     "--"
-     ["Commentary in idlwave.el" idlwave-show-commentary t]
-     ["Commentary in idlw-shell.el" idlwave-shell-show-commentary t]
-     "--"
-     ["Info" idlwave-info t]
-     "--"
-     ["Help with Topic" idlwave-help-assistant-help-with-topic
-      idlwave-help-use-assistant]
-     ["Launch IDL Help" idlwave-launch-idlhelp t])))
-
-(defvar idlwave-mode-debug-menu-def
-  '("Debug"
-    ["Start IDL shell" idlwave-shell t]
-    ["Save and .RUN buffer" idlwave-shell-save-and-run
-     (and (boundp 'idlwave-shell-automatic-start)
-         idlwave-shell-automatic-start)]))
-
-(easy-menu-define idlwave-mode-menu idlwave-mode-map
-  "IDL and WAVE CL editing menu."
-  idlwave-mode-menu-def)
-(easy-menu-define idlwave-mode-debug-menu idlwave-mode-map
-  "IDL and WAVE CL editing menu."
-  idlwave-mode-debug-menu-def)
-
-(defun idlwave-customize ()
-  "Call the customize function with `idlwave' as argument."
-  (interactive)
-  ;; Try to load the code for the shell, so that we can customize it
-  ;; as well.
-  (or (featurep 'idlw-shell)
-      (load "idlw-shell" t))
-  (customize-browse 'idlwave))
-
-(defun idlwave-create-customize-menu ()
-  "Create a full customization menu for IDLWAVE, insert it into the menu."
-  (interactive)
-  ;; Try to load the code for the shell, so that we can customize it
-  ;; as well.
-  (or (featurep 'idlw-shell)
-      (load "idlw-shell" t))
-  (easy-menu-change
-   '("IDLWAVE") "Customize"
-   `(["Browse IDLWAVE group" idlwave-customize t]
-     "--"
-     ,(customize-menu-create 'idlwave)
-     ["Set" Custom-set t]
-     ["Save" Custom-save t]
-     ["Reset to Current" Custom-reset-current t]
-     ["Reset to Saved" Custom-reset-saved t]
-     ["Reset to Standard Settings" Custom-reset-standard t]))
-  (message "\"IDLWAVE\"-menu now contains full customization menu"))
-
-(defun idlwave-show-commentary ()
-  "Use the finder to view the file documentation from `idlwave.el'."
-  (interactive)
-  (finder-commentary "idlwave.el"))
-
-(defun idlwave-shell-show-commentary ()
-  "Use the finder to view the file documentation from `idlw-shell.el'."
-  (interactive)
-  (finder-commentary "idlw-shell.el"))
-
-(defun idlwave-info ()
-  "Read documentation for IDLWAVE in the info system."
-  (interactive)
-  (info "idlwave"))
-
-(defun idlwave-list-abbrevs (arg)
-  "Show the code abbreviations define in IDLWAVE mode.
-This lists all abbrevs where the replacement text differs from the input text.
-These are the ones the users want to learn to speed up their writing.
-
-The function does *not* list abbrevs which replace a word with itself
-to call a hook.  These hooks are used to change the case of words or
-to blink the matching `begin', and the user does not need to know them.
-
-With arg, list all abbrevs with the corresponding hook.
-
-This function was written since `list-abbrevs' looks terrible for IDLWAVE mode."
-
-  (interactive "P")
-  (let ((table idlwave-mode-abbrev-table)
-       abbrevs
-       str rpl func fmt (len-str 0) (len-rpl 0))
-    (mapatoms
-     (lambda (sym)
-       (if (symbol-value sym)
-          (progn
-            (setq str (symbol-name sym)
-                  rpl (symbol-value sym)
-                  func (symbol-function sym))
-            (if arg
-                (setq func (prin1-to-string func))
-              (if (and (listp func) (stringp (nth 2 func)))
-                  (setq rpl (concat "EVAL: " (nth 2 func))
-                        func "")
-                (setq func "")))
-            (if (or arg (not (string= rpl str)))
-                (progn
-                  (setq len-str (max len-str (length str)))
-                  (setq len-rpl (max len-rpl (length rpl)))
-                  (setq abbrevs (cons (list str rpl func) abbrevs)))))))
-     table)
-    ;; sort the list
-    (setq abbrevs (sort abbrevs (lambda (a b) (string< (car a) (car b)))))
-    ;; Make the format
-    (setq fmt (format "%%-%ds   %%-%ds   %%s\n" len-str len-rpl))
-    (with-output-to-temp-buffer "*Help*"
-      (if arg
-         (progn
-           (princ "Abbreviations and Actions in IDLWAVE-Mode\n")
-           (princ "=========================================\n\n")
-           (princ (format fmt "KEY" "REPLACE" "HOOK"))
-           (princ (format fmt "---" "-------" "----")))
-       (princ "Code Abbreviations and Templates in IDLWAVE-Mode\n")
-       (princ "================================================\n\n")
-       (princ (format fmt "KEY" "ACTION" ""))
-       (princ (format fmt "---" "------" "")))
-      (dolist (list abbrevs)
-       (setq str (car list)
-             rpl (nth 1 list)
-             func (nth 2 list))
-       (princ (format fmt str rpl func)))))
-  ;; Make sure each abbreviation uses only one display line
-  (with-current-buffer "*Help*"
-    (setq truncate-lines t)))
-
-(declare-function speedbar-add-supported-extension "speedbar" (extension))
-
-;; Add .pro files to speedbar for support, if it's loaded
-(eval-after-load "speedbar" '(speedbar-add-supported-extension ".pro"))
-
-;; Set an idle timer to load the routine info.
-;; Will only work on systems which support this.
-(or idlwave-routines (idlwave-start-load-rinfo-timer))
-
-;; Run the hook
-(run-hooks 'idlwave-load-hook)
-
-;; Obsolete.
-(define-obsolete-function-alias 'idlwave-uniquify #'seq-uniq "28.1")
-
-(provide 'idlwave)
-
-;;; idlwave.el ends here