idlwave.el 341 KB
Newer Older
1
;; idlwave.el --- IDL editing mode for GNU Emacs
Glenn Morris's avatar
Glenn Morris committed
2

Paul Eggert's avatar
Paul Eggert committed
3
;; Copyright (C) 1999-2019 Free Software Foundation, Inc.
4

Paul Eggert's avatar
Paul Eggert committed
5
;; Authors: JD Smith <jd.smith@utoledo.edu>
Richard M. Stallman's avatar
Richard M. Stallman committed
6
;;          Carsten Dominik <dominik@science.uva.nl>
7
;;          Chris Chase <chase@att.com>
8
;; Version: 6.1.22
9 10
;; Keywords: languages

11
;; This file is part of GNU Emacs.
12

13
;; GNU Emacs is free software: you can redistribute it and/or modify
14
;; it under the terms of the GNU General Public License as published by
15 16
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
17 18 19 20 21 22 23

;; 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
24
;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
25 26 27

;;; Commentary:

28
;; IDLWAVE enables feature-rich development and interaction with IDL,
Stefan Monnier's avatar
Stefan Monnier committed
29
;; the Interactive Data Language.  It provides a compelling,
30 31
;; full-featured alternative to the IDLDE development environment
;; bundled with IDL.
32

33 34
;; In the remotely distant past, based on pascal.el, though bears
;; little resemblance to it now.
35 36 37 38 39 40 41 42 43
;;
;; 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'
;;
44 45
;; New versions of IDLWAVE, documentation, and more information
;; available from:
Glenn Morris's avatar
Glenn Morris committed
46
;;                 http://github.com/jdtsmith/idlwave
47 48 49 50 51 52
;;
;; INSTALLATION
;; ============
;;
;; Follow the instructions in the INSTALL file of the distribution.
;; In short, put this file on your load path and add the following
53
;; lines to your init file:
54 55
;;
;; (autoload 'idlwave-mode "idlwave" "IDLWAVE Mode" t)
56
;; (autoload 'idlwave-shell "idlw-shell" "IDLWAVE Shell" t)
57 58 59 60 61 62
;; (setq auto-mode-alist (cons '("\\.pro\\'" . idlwave-mode) auto-mode-alist))
;;
;;
;; SOURCE
;; ======
;;
63
;; The newest version of this file is available from the maintainer's
64
;; Webpage:
65
;;
Glenn Morris's avatar
Glenn Morris committed
66
;;   http://github.com/jdtsmith/idlwave
67 68 69 70
;;
;; DOCUMENTATION
;; =============
;;
71 72 73
;; IDLWAVE is documented online in info format.  A printable version
;; of the documentation is available from the maintainers webpage (see
;; SOURCE).
74
;;
75
;;
76 77 78 79 80
;; ACKNOWLEDGMENTS
;; ===============
;;
;;  Thanks to the following people for their contributions and comments:
;;
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
;;    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>
97 98 99 100
;;
;; CUSTOMIZATION:
;; =============
;;
101 102 103
;; IDLWAVE has extensive customize support; to learn about the
;; variables which control the mode's behavior, use `M-x
;; idlwave-customize'.
104 105 106
;;
;; 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
107 108
;; the TexInfo documentation or see a complete .emacs available at the
;; website.
109 110 111 112
;;
;; KNOWN PROBLEMS:
;; ==============
;;
113 114 115
;;   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
116
;;   even have "WAVE" in its title, but it's catchy, and was required
117
;;   to avoid conflict with the CORBA idl.el mode.  Caveat WAVEor.
118
;;
119 120 121 122 123 124
;;   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
125
;;   using a temporary function in `post-command-hook' - not pretty,
126
;;   but it works.
127 128 129 130 131 132 133 134
;;
;;   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'.
;;
135 136 137 138
;;   Muti-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.
139
;;
140 141 142
;;   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
143
;;   a pre-selected region.
144 145 146
;;
;;   When forcing completion of method keywords, the initial
;;   query for a method has multiple entries for some methods.  Would
147
;;   be too difficult to fix this hardly used case.
148 149 150 151
;;

;;; Code:

152

153
(eval-when-compile (require 'cl-lib))
154 155 156 157 158 159 160 161 162
(require 'idlw-help)

;; For XEmacs
(unless (fboundp 'line-beginning-position)
  (defalias 'line-beginning-position 'point-at-bol))
(unless (fboundp 'line-end-position)
  (defalias 'line-end-position 'point-at-eol))
(unless (fboundp 'char-valid-p)
  (defalias 'char-valid-p 'characterp))
163 164
(unless (fboundp 'match-string-no-properties)
  (defalias 'match-string-no-properties 'match-string))
165

166 167 168 169 170
(if (not (fboundp 'cancel-timer))
    (condition-case nil
	(require 'timer)
      (error nil)))

171 172 173 174 175 176
(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" ())

177
(defgroup idlwave nil
178
  "Major mode for editing IDL .pro files."
179
  :tag "IDLWAVE"
180
  :link '(url-link :tag "Home Page"
Glenn Morris's avatar
Glenn Morris committed
181
		   "http://github.com/jdtsmith/idlwave")
182 183
  :link '(emacs-commentary-link :tag "Commentary in idlw-shell.el"
				"idlw-shell.el")
184 185 186 187 188
  :link '(emacs-commentary-link :tag "Commentary in idlwave.el" "idlwave.el")
  :link '(custom-manual "(idlwave)Top")
  :prefix "idlwave"
  :group 'languages)

189

190 191 192 193 194 195
;;; Variables for indentation behavior ---------------------------------------

(defgroup idlwave-code-formatting nil
  "Indentation and formatting options for IDLWAVE mode."
  :group 'idlwave)

196
(defcustom idlwave-main-block-indent 2
197
  "Extra indentation for the main block of code.
198 199 200 201 202
That is the block between the FUNCTION/PRO statement and the END
statement for that program unit."
  :group 'idlwave-code-formatting
  :type 'integer)

203
(defcustom idlwave-block-indent 3
204
  "Extra indentation applied to block lines.
205 206 207 208
If you change this, you probably also want to change `idlwave-end-offset'."
  :group 'idlwave-code-formatting
  :type 'integer)

209
(defcustom idlwave-end-offset -3
210
  "Extra indentation applied to block END lines.
211 212 213 214 215
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)

216
(defcustom idlwave-continuation-indent 3
217
  "Extra indentation applied to continuation lines.
218
This extra offset applies to the first of a set of continuation lines.
219 220 221 222
The following lines receive the same indentation as the first."
  :group 'idlwave-code-formatting
  :type 'integer)

223
(defcustom idlwave-max-extra-continuation-indent 40
224
  "Maximum additional indentation for special continuation indent.
225 226
Several special indentations are tried to help line up continuation
lines in routine calls or definitions, other statements with
227
parentheses, or assignment statements.  This variable specifies a
228 229 230 231
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
232
cases.  See also `idlwave-indent-to-open-paren', which can override
233
this variable."
234 235 236
  :group 'idlwave-code-formatting
  :type 'integer)

237
(defcustom idlwave-indent-to-open-paren t
238
  "Non-nil means, indent continuation lines to innermost open parenthesis.
Juanma Barranquero's avatar
Juanma Barranquero committed
239
This indentation occurs even if otherwise disallowed by
240 241 242 243 244 245 246 247 248 249
`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
Juanma Barranquero's avatar
Juanma Barranquero committed
250 251
the value of `idlwave-max-extra-continuation-indent', which, if zero,
would yield:
252 253 254 255 256 257

  x = function_a(function_b(function_c( a, b, [1,2,3, $
     4,5,6 $
     ], $
     c, d $
     )))"
Juanma Barranquero's avatar
Juanma Barranquero committed
258
  :group 'idlwave-code-formatting
259 260
  :type 'boolean)

261
(defcustom idlwave-indent-parens-nested nil
262
  "Non-nil means, indent continuation lines with parens by nesting
263 264 265 266 267
lines at consecutively deeper levels."
 :group 'idlwave-code-formatting
  :type 'boolean)


268
(defcustom idlwave-hanging-indent t
269
  "If set non-nil then comment paragraphs are indented under the
270 271 272 273 274 275
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 "- "
276
  "Regular expression matching the position of the hanging indent
Juanma Barranquero's avatar
Juanma Barranquero committed
277
in the first line of a comment paragraph.  The size of the indent
278 279 280 281 282
extends to the end of the match for the regular expression."
  :group 'idlwave-code-formatting
  :type 'regexp)

(defcustom idlwave-use-last-hang-indent nil
283
  "If non-nil then use last match on line for `idlwave-indent-regexp'."
284 285 286 287
  :group 'idlwave-code-formatting
  :type 'boolean)

(defcustom idlwave-fill-comment-line-only t
288
  "If non-nil then auto fill will only operate on comment lines."
289 290 291 292
  :group 'idlwave-code-formatting
  :type 'boolean)

(defcustom idlwave-auto-fill-split-string t
293
  "If non-nil then auto fill will split strings with the IDL `+' operator.
294
When the line end falls within a string, string concatenation with the
Paul Eggert's avatar
Paul Eggert committed
295
`+' operator will be used to distribute a long string over lines.
296 297 298 299 300 301 302 303
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
304
  "If non-nil then `idlwave-split-line' will split strings with `+'.
305 306 307 308 309 310 311
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 ";;;"
312
  "The indentation of a comment that starts with this regular
Juanma Barranquero's avatar
Juanma Barranquero committed
313
expression will not be changed.  Note that the indentation of a comment
314 315 316 317 318
at the beginning of a line is never changed."
  :group 'idlwave-code-formatting
  :type 'string)

(defcustom idlwave-begin-line-comment nil
319
  "A comment anchored at the beginning of line.
320 321 322 323 324 325 326 327 328
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 ";;[^;]"
329
  "A comment that starts with this regular expression on a line by
330 331 332 333 334 335 336 337 338 339
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 ---------------------------------------

340 341
(defgroup idlwave-routine-info nil
  "Routine Info options for IDLWAVE mode."
342 343
  :group 'idlwave)

344
(defcustom idlwave-use-library-catalogs t
345
  "Non-nil means search the IDL path for library catalog files.
346 347 348

These files, named .idlwave_catalog, document routine information for
individual directories and libraries of IDL .pro files.  Many popular
Juanma Barranquero's avatar
Juanma Barranquero committed
349 350
libraries come with catalog files by default, so leaving this on is
usually a good idea."
351 352
  :group 'idlwave-routine-info
  :type 'boolean)
353 354

(defcustom idlwave-init-rinfo-when-idle-after 10
355
  "Seconds of idle time before routine info is automatically initialized.
Juanma Barranquero's avatar
Juanma Barranquero committed
356 357 358 359 360 361 362 363 364 365 366 367
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."
368 369 370
  :group 'idlwave-routine-info
  :type 'number)

371
(defcustom idlwave-scan-all-buffers-for-routine-info t
372
  "Non-nil means, scan buffers for IDL programs when updating info.
373 374 375 376
The scanning is done by the command `idlwave-update-routine-info'.
The following values are allowed:

nil       Don't scan any buffers.
Juanma Barranquero's avatar
Juanma Barranquero committed
377
t         Scan all `idlwave-mode' buffers in the current editing session.
378
`current' Scan only the current buffer, but no other buffers."
379 380 381 382
  :group 'idlwave-routine-info
  :type '(choice
	  (const :tag "No buffer" nil)
	  (const :tag "All buffers" t)
Glenn Morris's avatar
Glenn Morris committed
383
	  (const :tag "Current buffer only" current)))
384 385

(defcustom idlwave-query-shell-for-routine-info t
386
  "Non-nil means query the shell for info about compiled routines.
387 388 389
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."
390
  :group 'idlwave-routine-info
391 392
  :type 'boolean)

393 394
(defcustom idlwave-auto-routine-info-updates
  '(find-file save-buffer kill-buffer compile-buffer)
395
  "Controls under what circumstances routine info is updated automatically.
396 397 398
Possible values:
nil       Never
t         All available
Juanma Barranquero's avatar
Juanma Barranquero committed
399
\(...)     A list of circumstances.  Allowed members are:
400 401 402 403 404 405 406 407 408 409 410 411 412
           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))))
413

414
(defcustom idlwave-rinfo-max-source-lines 5
415
  "Maximum number of source files displayed in the Routine Info window.
416
When an integer, it is the maximum number of source files displayed.
Juanma Barranquero's avatar
Juanma Barranquero committed
417
A value of t means to show all source files."
418 419 420
  :group 'idlwave-routine-info
  :type 'integer)

421
(defcustom idlwave-library-path nil
422
  "Library path for Windows and Mac OS (OS9).  Not needed under UNIX.
423 424
When selecting the directories to scan for IDL user catalog routine
info, IDLWAVE can, under UNIX, query the shell for the exact search
425 426 427 428 429
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
Glenn Morris's avatar
Glenn Morris committed
430
preceded by a `+' will be searched recursively.  If you set this
431 432
variable on a UNIX system, the shell will not be queried.  See
also `idlwave-system-directory'."
433
  :group 'idlwave-routine-info
434 435
  :type '(repeat (directory)))

436
(defcustom idlwave-system-directory ""
437
  "The IDL system directory for Windows and Mac OS.  Not needed under
438 439 440 441 442 443
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'."
444 445 446
  :group 'idlwave-routine-info
  :type 'directory)

447
;; Configuration files
448
(defcustom idlwave-config-directory
Stefan Monnier's avatar
Stefan Monnier committed
449
  (locate-user-emacs-file "idlwave" ".idlwave")
450
  "Directory for configuration files and user-library catalog."
451
  :version "24.4"			; added locate-user-emacs-file
452
  :group 'idlwave-routine-info
453 454
  :type 'file)

455
(defvar idlwave-user-catalog-file "idlusercat.el")
456
(defvar idlwave-xml-system-rinfo-converted-file "idl_xml_rinfo.el")
457 458
(defvar idlwave-path-file "idlpath.el")

459 460 461
(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
462
the file defining the routine is located.  By default it lists `SystemLib'
463 464 465 466 467 468 469 470 471
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)))

472
(defcustom idlwave-auto-write-paths t
473
  "Write out path (!PATH) and system directory (!DIR) info automatically.
474 475 476 477 478
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
479
  :type 'boolean)
480

481 482 483 484 485
(defgroup idlwave-completion nil
  "Completion options for IDLWAVE mode."
  :prefix "idlwave"
  :group 'idlwave)

486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503
(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
504
methods.
505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531
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."
532
  :group 'idlwave-completion
533 534 535 536 537
  :type `(repeat
	  (cons (symbol :tag "Derive completion case for")
		,idlwave-tmp)))

(defcustom idlwave-completion-force-default-case nil
538
  "Non-nil means, completion will always honor `idlwave-completion-case'.
539 540 541 542
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."
543
  :group 'idlwave-completion
544 545 546
  :type 'boolean)

(defcustom idlwave-complete-empty-string-as-lower-case nil
547
  "Non-nil means, the empty string is considered downcase for completion.
548 549 550 551
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."
552
  :group 'idlwave-completion
553 554 555
  :type 'boolean)

(defcustom idlwave-buffer-case-takes-precedence nil
556
  "Non-nil means, the case of tokens in buffers dominates over system stuff.
557 558 559 560
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."
561 562 563 564
  :group 'idlwave-completion
  :type 'boolean)

(defcustom idlwave-highlight-help-links-in-completion t
565
  "Non-nil means, highlight completions for which system help is available.
566 567 568
Help can then be accessed with mouse-3.
This option is only effective when the online help system is installed."
  :group 'idlwave-completion
569 570
  :type 'boolean)

571 572
(defcustom idlwave-support-inheritance t
  "Non-nil means, treat inheritance with completion, online help etc.
573
When nil, IDLWAVE only knows about the native methods and tags of a class,
574 575 576 577
not about inherited ones."
  :group 'idlwave-routine-info
  :type 'boolean)

578 579 580 581 582 583 584 585 586
(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:")))
587

588

589
(defcustom idlwave-completion-show-classes 1
590
  "Number of classes to show when completing object methods and keywords.
591
When completing methods or keywords for an object with unknown class,
592
the *Completions* buffer will show the valid classes for each completion
593 594 595 596 597 598 599 600
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.

On XEmacs, a full list of classes will also be placed into a `help-echo'
Paul Eggert's avatar
Paul Eggert committed
601
property on the completion items, so that the list of classes for the current
602 603
item is displayed in the echo area.  If the value of this variable is a
negative integer, the `help-echo' property will be suppressed."
604
  :group 'idlwave-completion
605 606 607 608
  :type '(choice (const :tag "Don't show" nil)
		 (integer :tag "Number of classes shown" 1)))

(defcustom idlwave-completion-fontify-classes t
609
  "Non-nil means, fontify the classes in completions buffer.
610 611
This makes it easier to distinguish the completion items from the extra
class info listed.  See `idlwave-completion-show-classes'."
612
  :group 'idlwave-completion
613 614 615 616 617 618
  :type 'boolean)

(defcustom idlwave-query-class '((method-default . nil)
				 (keyword-default . nil))
  "Association list governing specification of object classes for completion.

619 620 621
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
622 623 624 625 626 627 628 629 630 631 632 633
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
634
   `idlwave-completion-show-classes'.
635 636 637 638 639 640 641 642 643 644

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'.

645 646 647
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
J.D. Smith's avatar
J.D. Smith committed
648
\(keyword-default . VALUE), where VALUE is either t or nil.  These
649 650
specify if the class should be found during method and keyword
completion, respectively.
651

652
The alist may have additional entries specifying exceptions from the
653 654 655
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."
656
  :group 'idlwave-completion
657 658 659 660 661 662 663 664 665 666 667
  :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")))))

668
(defcustom idlwave-store-inquired-class t
669
  "Non-nil means, store class of a method call as text property on `->'.
670 671 672 673 674 675
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
676
property on the `->' arrow in the source code, so that during the same
677 678 679 680 681 682 683 684 685 686 687 688 689
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."
690
  :group 'idlwave-completion
691 692 693
  :type 'boolean)

(defcustom idlwave-class-arrow-face 'bold
694
  "Face to highlight object operator arrows `->' which carry a class property.
695
When IDLWAVE stores a class name as text property on an object arrow
J.D. Smith's avatar
J.D. Smith committed
696
\(see variable `idlwave-store-inquired-class', it highlights the arrow
697
with this font in order to remind the user that this arrow is special."
698
  :group 'idlwave-completion
699 700 701
  :type 'symbol)

(defcustom idlwave-resize-routine-help-window t
702
  "Non-nil means, resize the Routine-info *Help* window to fit the content."
703
  :group 'idlwave-completion
704 705 706
  :type 'boolean)

(defcustom idlwave-keyword-completion-adds-equal t
707
  "Non-nil means, completion automatically adds `=' after completed keywords."
708
  :group 'idlwave-completion
709 710 711
  :type 'boolean)

(defcustom idlwave-function-completion-adds-paren t
712
  "Non-nil means, completion automatically adds `(' after completed function.
Pavel Janík's avatar
Pavel Janík committed
713
nil means, don't add anything.
714 715
A value of `2' means, also add the closing parenthesis and position cursor
between the two."
716
  :group 'idlwave-completion
717 718 719 720 721
  :type '(choice (const :tag "Nothing" nil)
		 (const :tag "(" t)
		 (const :tag "()" 2)))

(defcustom idlwave-completion-restore-window-configuration t
722
  "Non-nil means, try to restore the window configuration after completion.
723 724 725
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."
726
  :group 'idlwave-completion
727 728 729 730 731 732 733 734 735 736
  :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
737
  "Non-nil means performs actions when indenting.
738 739 740 741 742
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 "\\"
743
  "A single character string used to start abbreviations in abbrev mode.
744
Possible characters to choose from: ~\\=`%
745
or even `?'.  `.' is not a good choice because it can make structure
746 747 748
field names act like abbrevs in certain circumstances.

Changes to this in `idlwave-mode-hook' will have no effect.  Instead a user
749
must set it directly using `setq' in the init file before idlwave.el
750 751 752 753 754
is loaded."
  :group 'idlwave-abbrev-and-indent-action
  :type 'string)

(defcustom idlwave-surround-by-blank nil
755
  "Non-nil means, enable `idlwave-surround'.
756
If non-nil, `=',`<',`>',`&',`,', `->' are surrounded with spaces by
757 758 759 760 761 762 763 764 765 766 767 768 769
`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
Paul Eggert's avatar
Paul Eggert committed
770 771
  "Non-nil means pad `=' in keywords (routine calls or defs) like assignment.
Whenever `idlwave-surround' is non-nil then this affects how `=' is
772 773 774
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."
775
  :group 'idlwave-abbrev-and-indent-action
776 777 778
  :type '(choice
	  (const :tag "Pad like assignments" t)
	  (const :tag "Remove space near `='" nil)
Glenn Morris's avatar
Glenn Morris committed
779
	  (other :tag "Keep space near `='" keep)))
780 781

(defcustom idlwave-show-block t
782
  "Non-nil means point blinks to block beginning for `idlwave-show-begin'."
783 784 785 786
  :group 'idlwave-abbrev-and-indent-action
  :type 'boolean)

(defcustom idlwave-expand-generic-end nil
787
  "Non-nil means expand generic END to ENDIF/ENDELSE/ENDWHILE etc."
788 789 790
  :group 'idlwave-abbrev-and-indent-action
  :type 'boolean)

791
(defcustom idlwave-reindent-end t
792
  "Non-nil means re-indent line after END was typed."
793 794 795
  :group 'idlwave-abbrev-and-indent-action
  :type 'boolean)

796
(defcustom idlwave-abbrev-move t
797
  "Non-nil means the abbrev hook can move point.
Juanma Barranquero's avatar
Juanma Barranquero committed
798
Set to nil by `idlwave-expand-region-abbrevs'.  To see the abbrev
799
definitions, use the command `list-abbrevs', for abbrevs that move
Juanma Barranquero's avatar
Juanma Barranquero committed
800
point.  Moving point is useful, for example, to place point between
801 802 803 804 805 806 807
parentheses of expanded functions.

See `idlwave-check-abbrev'."
  :group 'idlwave-abbrev-and-indent-action
  :type 'boolean)

(defcustom idlwave-abbrev-change-case nil
808
  "Non-nil means all abbrevs will be forced to either upper or lower case.
809
If the value t, all expanded abbrevs will be upper case.
810
If the value is `down' then abbrevs will be forced to lower case.
811 812 813 814 815 816 817
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
818
  "Non-nil means, reserved words will be made upper case via abbrev expansion.
819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854
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 '(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)
;;  Capitalize label
;;   (idlwave-action-and-binding (concat "^[ \t]*" idlwave-label)
;;                           '(capitalize-word -1) t)

(defvar idlwave-indent-action-table nil
855
  "Associated array containing action lists of search string (car),
Juanma Barranquero's avatar
Juanma Barranquero committed
856
and function as a cdr.  This table is used by `idlwave-indent-line'.
857 858 859 860 861 862 863 864
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
865
  "Associated array containing action lists of search string (car),
Juanma Barranquero's avatar
Juanma Barranquero committed
866 867
and function as a cdr.  The table is used by the
`idlwave-indent-and-action' function.  See documentation for
868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943
`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:
;
;-
")
944
  "A list (PATHNAME STRING) specifying the doc-header template to use for
Juanma Barranquero's avatar
Juanma Barranquero committed
945 946
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.
947 948 949
For example you might set PATHNAME to the path for the
lib_template.pro file included in the IDL distribution.")

950
(defcustom idlwave-header-to-beginning-of-file t
951
  "Non-nil means, the documentation header will always be at start of file.
952 953 954 955 956 957
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)

958
(defcustom idlwave-timestamp-hook 'idlwave-default-insert-timestamp
959
  "The hook function used to update the timestamp of a function."
960 961 962 963
  :group 'idlwave-documentation
  :type 'function)

(defcustom idlwave-doc-modifications-keyword "HISTORY"
964
  "The modifications keyword to use with the log documentation commands.
965
A `:' is added to the keyword end.
966 967 968 969 970 971
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 "^;+\\+"
972
  "Regexp matching the start of a document library header."
973 974 975 976
  :group 'idlwave-documentation
  :type 'regexp)

(defcustom idlwave-doclib-end "^;+-"
977
  "Regexp matching the end of a document library header."
978 979 980 981 982 983
  :group 'idlwave-documentation
  :type 'regexp)

;;; External Programs -------------------------------------------------------

(defgroup idlwave-external-programs nil
984
  "Path locations of external commands used by IDLWAVE."
985 986 987
  :group 'idlwave)

(defcustom idlwave-shell-explicit-file-name "idl"
988
  "If non-nil, this is the command to run IDL.
989
Should be an absolute file path or path relative to the current environment
990
execution search path.  If you want to specify command line switches
Juanma Barranquero's avatar
Juanma Barranquero committed
991
for the IDL program, use `idlwave-shell-command-line-options'.
992 993

I know the name of this variable is badly chosen, but I cannot change
Juanma Barranquero's avatar
Juanma Barranquero committed
994
it without compromising backwards-compatibility."
995 996 997 998
  :group 'idlwave-external-programs
  :type 'string)

(defcustom idlwave-shell-command-line-options nil
999
  "A list of command line options for calling the IDL program.
1000
Since IDL is executed directly without going through a shell like /bin/sh,
1001
this should be a list of strings like (\"-rt=file\" \"-nw\") with a separate
1002 1003 1004 1005 1006 1007
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 "")))
1008 1009 1010
  :group 'idlwave-external-programs)

(defcustom idlwave-help-application "idlhelp"
1011
  "The external application providing reference help for programming.
1012
Obsolete, if the IDL Assistant is being used for help."
1013 1014 1015
  :group 'idlwave-external-programs
  :type 'string)

1016 1017 1018 1019 1020 1021 1022
;;; 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.
1023
If you set this to (control shift), this means setting a breakpoint will
1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035
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
1036
  "If non-nil attempt invoke `idlwave-shell' if not already running.
1037 1038 1039 1040 1041
This is checked when an attempt to send a command to an
IDL process is made."
  :group 'idlwave-shell-general-setup
  :type 'boolean)

1042 1043 1044 1045
;;; Miscellaneous variables -------------------------------------------------

(defgroup idlwave-misc nil
  "Miscellaneous options for IDLWAVE mode."
1046
  :link '(custom-group-link :tag "Font Lock Faces group" font-lock-faces)
1047 1048 1049
  :group 'idlwave)

(defcustom idlwave-startup-message t
1050
  "Non-nil displays a startup message when `idlwave-mode' is first called."
1051 1052 1053
  :group 'idlwave-misc
  :type 'boolean)

1054
(defcustom idlwave-default-font-lock-items
J.D. Smith's avatar
J.D. Smith committed
1055
  '(pros-and-functions batch-files idlwave-idl-keywords label goto
1056 1057 1058 1059
		       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.
Juanma Barranquero's avatar
Juanma Barranquero committed
1060 1061
This variable must be set before IDLWAVE gets loaded.
It is a list of symbols; the following symbols are allowed:
1062 1063 1064

pros-and-functions   Procedure and Function definitions
batch-files          Batch Files
J.D. Smith's avatar
J.D. Smith committed
1065
idlwave-idl-keywords IDL Keywords
1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076
label                Statement Labels
goto                 Goto Statements
common-blocks        Common Blocks
keyword-parameters   Keyword Parameters in routine definitions and calls
system-variables     System Variables
fixme                FIXME: Warning in comments (on XEmacs only v. 21.0 and up)
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)
J.D. Smith's avatar
J.D. Smith committed
1077 1078 1079 1080 1081 1082 1083 1084 1085 1086
	  (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 "FIXME: Warning"                    fixme)
1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098
	  (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)

1099 1100 1101 1102 1103 1104
(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.")

1105 1106 1107 1108 1109 1110 1111
;;;
;;; End customization variables section
;;;

;;; Non customization variables

;;; font-lock mode - Additions by Phil Williams, Ulrik Dickow and
1112
;;; Simon Marshall <simon_at_gnu.ai.mit.edu>
1113 1114
;;; and Carsten Dominik...

1115
;; The following are the reserved words in IDL.  Maybe we should
1116
;; highlight some more stuff as well?
1117 1118
;; Procedure declarations.  Fontify keyword plus procedure name.
(defvar idlwave-idl-keywords
1119
  ;; To update this regexp, update the list of keywords and
1120
  ;; evaluate the form.
1121
  ;;	(insert
1122
  ;;	 (prin1-to-string
1123
  ;;	  (concat
1124
  ;;	   "\\<\\("
1125
  ;;	   (regexp-opt
1126
  ;;	    '("||" "&&" "and" "or" "xor" "not"
1127
  ;;	      "eq" "ge" "gt" "le" "lt" "ne"
1128
  ;;	      "for" "do" "endfor"
1129
  ;;	      "if" "then" "endif" "else" "endelse"
1130 1131 1132 1133
  ;;	      "case" "of" "endcase"
  ;;	      "switch" "break" "continue" "endswitch"
  ;;	      "begin" "end"
  ;;	      "repeat" "until" "endrep"
1134
  ;;	      "while" "endwhile"
1135 1136 1137 1138 1139
  ;;	      "goto" "return"
  ;;	      "inherits" "mod"
  ;;	      "compile_opt" "forward_function"
  ;;	      "on_error" "on_ioerror"))  ; on_error is not officially reserved
  ;;	   "\\)\\>")))
1140 1141
  "\\<\\(&&\\|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\\|||\\)\\>")

1142

J.D. Smith's avatar
J.D. Smith committed
1143
(let* (;; Procedure declarations.  Fontify keyword plus procedure name.
1144 1145 1146 1147 1148 1149 1150 1151 1152 1153
       ;; 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"
1154
	  (2 font-lock-constant-face nil t)      ; block name
1155
	  ("[ \t]*\\(\\sw+\\)[ ,]*"
1156
	   ;; Start with point after block name and comma
1157
	   (goto-char (match-end 0))  ; needed for XEmacs, could be nil
1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171
	   nil
	   (1 font-lock-variable-name-face)       ; variable names
	   )))

       ;; Batch files
       (batch-files
	'("^[ \t]*\\(@[^ \t\n]+\\)" (1 font-lock-string-face)))

       ;; FIXME warning.
       (fixme
	'("\\<FIXME:" (0 font-lock-warning-face t)))

       ;; Labels
       (label
1172
	'("^[ \t]*\\([a-zA-Z]\\sw*:\\)" (1 font-lock-constant-face)))
1173 1174 1175 1176 1177

       ;; The goto statement and its label
       (goto
	'("\\(goto\\)[ \t]*,[ \t]*\\([a-zA-Z]\\sw*\\)"
	  (1 font-lock-keyword-face)
1178
	  (2 font-lock-constant-face)))
1179

1180 1181 1182 1183
       ;; 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.
1184
       (structtag
1185
	'("\\<\\([a-zA-Z][a-zA-Z0-9_]*:\\)[^:]" (1 font-lock-constant-face)))
1186 1187 1188 1189 1190 1191

       ;; Structure names
       (structname
	'("\\({\\|\\<inherits\\s-\\)\\s-*\\([a-zA-Z][a-zA-Z0-9_]*\\)[},\t \n]"
	  (2 font-lock-function-name-face)))

1192
       ;; Keyword parameters, like /xlog or ,xrange=[]
Glenn Morris's avatar
Glenn Morris committed
1193
       ;; This is anchored to the comma preceding the keyword.
1194 1195
       ;; Treats continuation lines, works only during whole buffer
       ;; fontification.  Slow, use it only in fancy fontification.
1196
       (keyword-parameters
1197
	'("\\(,\\|[a-zA-Z0-9_](\\)[ \t]*\\(\\$[ \t]*\\(;.*\\)?\n\\([ \t]*\\(;.*\\)?\n\\)*[ \t]*\\)?\\(/[a-zA-Z_]\\sw*\\|[a-zA-Z_]\\sw*[ \t]*=\\)"
1198
	  (6 font-lock-constant-face)))
1199

1200
       ;; System variables start with a bang.
1201
       (system-variables
1202
	'("\\(![a-zA-Z_0-9]+\\(\\.\\sw+\\)?\\)"
1203 1204 1205
	  (1 font-lock-variable-name-face)))

       ;; Special and unusual operators (not used because too noisy)
Stefan Monnier's avatar
Stefan Monnier committed
1206 1207
       ;; (special-operators
       ;;  '("[<>#]" (0 font-lock-keyword-face)))
1208 1209

       ;; All operators (not used because too noisy)
Stefan Monnier's avatar
Stefan Monnier committed
1210 1211
       ;; (all-operators
       ;;  '("[-*^#+<>/]" (0 font-lock-keyword-face)))
1212

1213 1214
       ;; Arrows with text property `idlwave-class'
       (class-arrows
J.D. Smith's avatar
J.D. Smith committed
1215 1216 1217 1218 1219
	'(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.")
1220

J.D. Smith's avatar
J.D. Smith committed
1221 1222 1223
  (defconst idlwave-font-lock-keywords-2
    (mapcar 'symbol-value idlwave-default-font-lock-items)
    "Medium level highlighting for IDLWAVE mode.")
1224

J.D. Smith's avatar
J.D. Smith committed
1225
  (defconst idlwave-font-lock-keywords-3
1226 1227
	(list pros-and-functions
	      batch-files
1228
	      idlwave-idl-keywords
1229
	      label goto
1230 1231
	      structtag
	      structname
1232 1233 1234
	      common-blocks
	      keyword-parameters
	      system-variables
J.D. Smith's avatar
J.D. Smith committed
1235 1236
	  class-arrows)
    "Gaudy level highlighting for IDLWAVE mode."))
1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248

(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
1249
     idlwave-font-lock-keywords-1
1250 1251
     idlwave-font-lock-keywords-2
     idlwave-font-lock-keywords-3)
1252 1253
    nil t
    ((?$ . "w") (?_ . "w") (?. . "w") (?| . "w") (?& . "w"))
1254 1255
    beginning-of-line))

1256
(put 'idlwave-mode 'font-lock-defaults
1257 1258 1259 1260 1261 1262 1263
     idlwave-font-lock-defaults) ; XEmacs

(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.")

1264
(defconst idlwave-begin-block-reg
1265
  "\\<\\(pro\\|function\\|begin\\|case\\|switch\\)\\>"
Juanma Barranquero's avatar
Juanma Barranquero committed
1266 1267
  "Regular expression to find the beginning of a block.
The case does not matter.  The search skips matches in comments.")
1268

1269
(defconst idlwave-begin-unit-reg "^\\s-*\\(pro\\|function\\)\\>\\|\\`"