idlw-shell.el 172 KB
Newer Older
1
;; idlw-shell.el --- run IDL as an inferior process of Emacs.  -*- lexical-binding:t -*-
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>
6 7
;;          Carsten Dominik <dominik@astro.uva.nl>
;;          Chris Chase <chase@att.com>
8
;; Maintainer: emacs-devel@gnu.org
9
;; Keywords: processes
10
;; Package: idlwave
11 12 13

;; This file is part of GNU Emacs.

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

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

;;; Commentary:
28 29 30 31
;;
;; This mode is for IDL version 5 or later.  It should work on
;; Emacs>20.3 or XEmacs>20.4.
;;
32
;; Runs IDL as an inferior process of Emacs, much like the Emacs
33 34 35 36 37 38 39
;; `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'.
40 41 42
;;
;; New versions of IDLWAVE, documentation, and more information
;; available from:
Glenn Morris's avatar
Glenn Morris committed
43
;;                 http://github.com/jdtsmith/idlwave
44
;;
45 46
;; INSTALLATION:
;; =============
Glenn Morris's avatar
Glenn Morris committed
47
;;
48 49
;; Follow the instructions in the INSTALL file of the distribution.
;; In short, put this file on your load path and add the following
50
;; lines to your init file:
51 52 53 54 55 56 57 58 59
;;
;; (autoload 'idlwave-shell "idlw-shell" "IDLWAVE Shell" t)
;;
;;
;; SOURCE
;; ======
;;
;;   The newest version of this file can be found on the maintainers
;;   web site.
Glenn Morris's avatar
Glenn Morris committed
60
;;
Glenn Morris's avatar
Glenn Morris committed
61
;;     http://github.com/jdtsmith/idlwave
Glenn Morris's avatar
Glenn Morris committed
62
;;
63 64 65 66 67 68 69 70 71 72 73 74 75 76
;; DOCUMENTATION
;; =============
;;
;; IDLWAVE is documented online in info format.
;; A printable version of the documentation is available from the
;; maintainers webpage (see under SOURCE)
;;
;;
;; KNOWN PROBLEMS
;; ==============
;;
;; Under XEmacs the Debug menu in the shell does not display the
;; keybindings in the prefix map.  There bindings are available anyway - so
;; it is a bug in XEmacs.
77
;; The Debug menu in source buffers *does* display the bindings correctly.
78
;;
Glenn Morris's avatar
Glenn Morris committed
79
;;
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
;; 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'.
;;
;;--------------------------------------------------------------------------
;;

;;; Code:

(require 'comint)
(require 'idlwave)

95
(eval-when-compile (require 'cl-lib))
96 97 98 99 100

(defvar idlwave-shell-have-new-custom nil)

;;; Customizations: idlwave-shell group

101
;; General/Misc. customizations
102
(defgroup idlwave-shell-general-setup nil
103 104
  "General setup of the Shell interaction for IDLWAVE/Shell."
  :prefix "idlwave-shell"
105 106
  :group 'idlwave)

107
(defcustom idlwave-shell-prompt-pattern "^\r? ?IDL> "
108
  "Regexp to match IDL prompt at beginning of a line.
Glenn Morris's avatar
Glenn Morris committed
109
For example, \"^\r?IDL> \" or \"^\r?WAVE> \".
110 111
The \"^\r?\" is needed, to indicate the beginning of the line, with
optional return character (which IDL seems to output randomly).
Glenn Morris's avatar
Glenn Morris committed
112
This variable is used to initialize `comint-prompt-regexp' in the
113
process buffer."
114 115 116 117
  :group 'idlwave-shell-general-setup
  :type 'regexp)

(defcustom idlwave-shell-process-name "idl"
118
  "Name to be associated with the IDL process.  The buffer for the
119 120 121 122
process output is made by surrounding this name with `*'s."
  :group 'idlwave-shell-general-setup
  :type 'string)

123
;; (defcustom idlwave-shell-automatic-start...)  See idlwave.el
124

125
(defcustom idlwave-shell-use-dedicated-window nil
126
  "Non-nil means, never replace the shell frame with another buffer."
127
  :group 'idlwave-shell-general-setup
Glenn Morris's avatar
Glenn Morris committed
128
  :type 'boolean)
129

130
(defcustom idlwave-shell-use-dedicated-frame nil
131
  "Non-nil means, IDLWAVE should use a special frame to display shell buffer."
132 133 134 135 136 137 138 139 140 141 142 143
  :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)))

144
(defcustom idlwave-shell-raise-frame t
145
  "Non-nil means, `idlwave-shell' raises the frame showing the shell window."
146 147 148
  :group 'idlwave-shell-general-setup
  :type 'boolean)

149
(defcustom idlwave-shell-arrows-do-history t
150
  "Non-nil means UP and DOWN arrows move through command history.
151 152 153 154
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
155
`cmdline'  When the cursor is in the current command line, arrows walk the
156 157 158 159 160 161 162
           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)))

163 164
;; FIXME: add comint-input-ring-size?

165
(defcustom idlwave-shell-use-toolbar t
166
  "Non-nil means, use the debugging toolbar in all IDL related buffers.
167 168
Starting the shell will then add the toolbar to all idlwave-mode buffers.
Exiting the shell will removed everywhere.
169
Available on XEmacs and on Emacs 21.x or later.
170 171
At any time you can toggle the display of the toolbar with
`C-c C-d C-t' (`idlwave-shell-toggle-toolbar')."
172 173 174 175
  :group 'idlwave-shell-general-setup
  :type 'boolean)

(defcustom idlwave-shell-temp-pro-prefix "/tmp/idltemp"
176
  "The prefix for temporary IDL files used when compiling regions.
177
It should be an absolute pathname.
178
The full temporary file name is obtained by using `make-temp-file'
179 180 181 182 183
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"
184
  "The prefix key for the debugging map `idlwave-shell-mode-prefix-map'.
185
This variable must already be set when idlwave-shell.el is loaded.
186
Setting it in the mode-hook is too late."
187 188 189 190 191 192 193 194 195 196
  :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)

197
(defcustom idlwave-shell-automatic-electric-debug 'breakpoint
Glenn Morris's avatar
Glenn Morris committed
198
  "Enter the electric-debug minor mode automatically.
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
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)

215 216
;; (defcustom idlwave-shell-debug-modifiers... See idlwave.el

217
(defcustom idlwave-shell-use-truename nil
218
  "Non-nil means, use `file-truename' when looking for buffers.
219 220 221
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.
222
However, when a file is already visited under a different name, IDLWAVE will
223 224 225 226 227 228 229
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)

230
(defcustom idlwave-shell-file-name-chars "~/A-Za-z0-9+:_.$#%={}\\- "
231
  "The characters allowed in file names, as a string.
232
Used for file name completion.  Must not contain `\\='', `,' and `\"'
233 234 235 236 237
because these are used as separators by IDL."
  :group 'idlwave-shell-general-setup
  :type 'string)

(defcustom idlwave-shell-mode-hook '()
238
  "Hook for customizing `idlwave-shell-mode'."
239 240 241
  :group 'idlwave-shell-general-setup
  :type 'hook)

242 243 244 245 246 247 248 249 250
(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")))

251

252 253 254 255 256 257
;; 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)

258
(defcustom idlwave-shell-initial-commands "!more=0 & defsysv,'!ERROR_STATE',EXISTS=__e & if __e then begin & !ERROR_STATE.MSG_PREFIX=\"% \" & delvar,__e & endif"
259 260 261 262 263 264 265 266 267 268 269 270 271
  "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)

272
(defcustom idlwave-shell-command-history-file "idlwhist"
273 274 275 276 277 278 279
  "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)
Glenn Morris's avatar
Glenn Morris committed
280

281 282
(defcustom idlwave-shell-show-commands
  '(run misc breakpoint)
283
  "A list of command types to show output from in the shell.
284 285 286
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."
287 288 289 290
  :group 'idlwave-shell-command-setup
  :type '(choice
	  (const everything)
	  (set :tag "Checklist" :greedy t
Glenn Morris's avatar
Glenn Morris committed
291
	       (const :tag "All .run and .compile commands"  	   run)
292 293 294
	       (const :tag "All breakpoint commands"         	   breakpoint)
	       (const :tag "All debug and stepping commands" 	   debug)
	       (const :tag "Close, window, retall, etc. commands"  misc))))
295

296 297 298 299 300
(defcustom idlwave-shell-max-print-length 200
  "Maximum number of array elements to print when examining."
  :group 'idlwave-shell-command-setup
  :type 'integer)

Glenn Morris's avatar
Glenn Morris committed
301 302 303
(defcustom idlwave-shell-examine-alist
  `(("Print"          	. ,(concat "idlwave_print_safe,___,"
				   (number-to-string
304
				    idlwave-shell-max-print-length)))
305 306 307 308 309 310 311
    ("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(___)")
312
    ("Arg Present"      . "print,arg_present(___)")
313 314
    ("Widget Valid"     . "print,widget_info(___,/VALID)")
    ("Widget Geometry"  . "help,widget_info(___,/GEOMETRY)"))
Glenn Morris's avatar
Glenn Morris committed
315
  "Alist of special examine commands for popup selection.
316 317 318 319
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."
320
  :group 'idlwave-shell-command-setup
321
  :type '(repeat
Glenn Morris's avatar
Glenn Morris committed
322
	  (cons
323 324
	   (string :tag "Label  ")
	   (string :tag "Command"))))
325

326
(defcustom idlwave-shell-separate-examine-output t
327
  "Non-nil means, put output of examine commands in their own buffer."
328
  :group 'idlwave-shell-command-setup
329
  :type 'boolean)
Glenn Morris's avatar
Glenn Morris committed
330

331 332 333
(defcustom idlwave-shell-comint-settings
  '((comint-scroll-to-bottom-on-input . t)
    (comint-scroll-to-bottom-on-output . t)
334 335
    (comint-scroll-show-maximum-output . nil)
    (comint-prompt-read-only . t))
336 337 338 339 340 341 342 343 344 345 346

  "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
347
  "Non-nil means query the shell for object class on object completions."
348 349 350
  :group 'idlwave-shell-command-setup
  :type 'boolean)

351
(defcustom idlwave-shell-use-input-mode-magic nil
352
  "Non-nil means, IDLWAVE should check for input mode spells in output.
353 354 355 356
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."
357
  :group 'idlwave-shell-command-setup
358 359 360 361 362 363
  :type 'boolean)

(defcustom idlwave-shell-input-mode-spells
  '("^<onechar>$" "^<chars>$" "^</chars>$")
  "The three regular expressions which match the magic spells for input modes.

364
When the first regexp matches in the output stream of IDL, IDLWAVE
365 366 367 368 369 370 371 372 373 374 375 376 377 378 379
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
380
strings.  Here is some example code which makes use of the default spells.
381

382
  print,\\='<chars>\\='               ; Make IDLWAVE switch to character mode
383 384 385
  REPEAT BEGIN
      A = GET_KBRD(1)
      PRINT, BYTE(A)
386 387
  ENDREP UNTIL A EQ \\='q\\='
  print,\\='</chars>\\='              ; Make IDLWAVE switch back to line mode
388

389 390
  print,\\='Quit the program, y or n?\\='
  print,\\='<onechar>\\='             ; Ask IDLWAVE to send one character
391 392 393
  answer = GET_KBRD(1)

Since the IDLWAVE shell defines the system variable `!IDLWAVE_VERSION',
Glenn Morris's avatar
Glenn Morris committed
394
you could actually check if you are running under Emacs before printing
395 396 397 398 399 400
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
401
idlwave_char_input,/off          ; End the loop to send characters
402 403 404 405


pro idlwave_char_input,on=on,off=off
  ;; Test if we are running under Emacs
406
  defsysv,\\='!idlwave_version\\=',exists=running_emacs
407
  if running_emacs then begin
408 409 410
      if keyword_set(on) then         print,\\='<chars>\\=' $
        else if keyword_set(off) then print,\\='</chars>\\=' $
        else                          print,\\='<onechar>\\='
Glenn Morris's avatar
Glenn Morris committed
411
  endif
412
end"
413
  :group 'idlwave-shell-command-setup
414 415 416 417 418
  :type '(list
	  (regexp :tag "One-char  regexp")
	  (regexp :tag "Char-mode regexp")
	  (regexp :tag "Line-mode regexp")))

419
(defcustom idlwave-shell-breakpoint-popup-menu t
420
  "If non-nil, provide a menu on mouse-3 on breakpoint lines, and
421 422 423
popup help text on the line."
  :group 'idlwave-shell-command-setup
  :type 'boolean)
424

425 426 427 428 429
(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)

430
;; Breakpoint Overlays etc
431
(defgroup idlwave-shell-highlighting-and-faces nil
Juanma Barranquero's avatar
Juanma Barranquero committed
432
  "Highlighting and faces used by the IDLWAVE Shell mode."
433
  :prefix "idlwave-shell"
434 435 436
  :group 'idlwave)

(defcustom idlwave-shell-mark-stop-line t
437
  "Non-nil means, mark the source code line where IDL is currently stopped.
438
Value decides about the method which is used to mark the line.  Valid values
439 440 441
are:

nil       Do not mark the line
442 443
`arrow'   Use the overlay arrow
`face'    Use `idlwave-shell-stop-line-face' to highlight the line.
444
t         Use what IDLWAVE thinks is best.  Will be a face where possible,
445 446 447
          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,
448
a face highlighting may be better."
449 450 451 452 453 454 455 456
  :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 ">"
457
  "The overlay arrow to display at source lines where execution halts.
458 459 460 461 462 463 464 465
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-use-overlay-arrow'."
  :group 'idlwave-shell-highlighting-and-faces
  :type 'string)

(defcustom idlwave-shell-stop-line-face 'highlight
466
  "The face for `idlwave-shell-stop-line-overlay'.
467 468 469 470 471
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)

472
(defcustom idlwave-shell-electric-stop-color "Violet"
473
  "The color for the default face or overlay arrow when stopped."
474 475 476
  :group 'idlwave-shell-highlighting-and-faces
  :type 'string)

Glenn Morris's avatar
Glenn Morris committed
477
(defcustom idlwave-shell-electric-stop-line-face
478
  (prog1
479
      (copy-face 'mode-line 'idlwave-shell-electric-stop-line)
Glenn Morris's avatar
Glenn Morris committed
480
    (set-face-background 'idlwave-shell-electric-stop-line
481 482
			 idlwave-shell-electric-stop-color)
    (condition-case nil
483
	(set-face-foreground 'idlwave-shell-electric-stop-line nil)
484
      (error nil)))
485
  "The face for `idlwave-shell-stop-line-overlay' when in electric debug mode.
486 487 488 489 490
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)

491
(defcustom idlwave-shell-mark-breakpoints t
492
  "Non-nil means, mark breakpoints in the source files.
493
Valid values are:
494
nil        Do not mark breakpoints.
495 496 497 498
`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')."
499 500 501 502 503 504 505
  :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)))

506
(defcustom idlwave-shell-breakpoint-face 'idlwave-shell-bp
507
  "The face for breakpoint lines in the source code.
508 509 510 511 512
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)

513 514 515 516 517 518 519 520
(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."
521
    :group 'idlwave-shell-highlighting-and-faces))
522

Glenn Morris's avatar
Glenn Morris committed
523
(defcustom idlwave-shell-disabled-breakpoint-face
524
  'idlwave-shell-disabled-bp
525
  "The face for disabled breakpoint lines in the source code.
526 527 528 529 530
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)

531 532 533 534 535 536 537 538
(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."
539
    :group 'idlwave-shell-highlighting-and-faces))
540

541

542
(defcustom idlwave-shell-expression-face 'secondary-selection
543
  "The face for `idlwave-shell-expression-overlay'.
544 545 546 547 548
Allows you to choose the font, color and other properties for
the expression printed by IDL."
  :group 'idlwave-shell-highlighting-and-faces
  :type 'symbol)

549
(defcustom idlwave-shell-output-face 'secondary-selection
550
  "The face for `idlwave-shell-output-overlay'.
551 552 553 554 555
Allows you to choose the font, color and other properties for
the expression output by IDL."
  :group 'idlwave-shell-highlighting-and-faces
  :type 'symbol)

556 557 558 559 560 561
;;; End user customization variables

;;; External variables
(defvar comint-last-input-start)
(defvar comint-last-input-end)

562 563 564 565 566 567 568 569 570
;; 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.")

571 572 573
(defun idlwave-shell-temp-file (type)
  "Return a temp file, creating it if necessary.

574 575
TYPE is either 'pro' or 'rinfo', and `idlwave-shell-temp-pro-file' or
`idlwave-shell-temp-rinfo-save-file' is set (respectively)."
Glenn Morris's avatar
Glenn Morris committed
576
  (cond
577
   ((eq type 'rinfo)
Glenn Morris's avatar
Glenn Morris committed
578 579
    (or idlwave-shell-temp-rinfo-save-file
	(setq idlwave-shell-temp-rinfo-save-file
580 581 582
	      (idlwave-shell-make-temp-file idlwave-shell-temp-pro-prefix))))
   ((eq type 'pro)
    (or idlwave-shell-temp-pro-file
Glenn Morris's avatar
Glenn Morris committed
583
	(setq idlwave-shell-temp-pro-file
584
	      (idlwave-shell-make-temp-file idlwave-shell-temp-pro-prefix))))
Glenn Morris's avatar
Glenn Morris committed
585
   (t (error "Wrong argument (idlwave-shell-temp-file): %s"
586
	     (symbol-name type)))))
Glenn Morris's avatar
Glenn Morris committed
587

588

589 590
(defun idlwave-shell-make-temp-file (prefix)
  "Create a temporary file."
591
  (if (featurep 'emacs)
592
      (make-temp-file prefix)
593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612
    (if (fboundp 'make-temp-file)
	(make-temp-file prefix)
      (let (file
	    (temp-file-dir (if (boundp 'temporary-file-directory)
			       temporary-file-directory
			     "/tmp")))
	(while (condition-case ()
		   (progn
		     (setq file
			   (make-temp-name
			    (expand-file-name prefix temp-file-dir)))
		     (if (featurep 'xemacs)
			 (write-region "" nil file nil 'silent nil)
		       (write-region "" nil file nil 'silent nil 'excl))
		     nil)
		 (file-already-exists t))
	  ;; the file was somehow created by someone else between
	  ;; `make-temp-name' and `write-region', let's try again.
	  nil)
	file))))
613

614

615
(defvar idlwave-shell-dirstack-query "cd,current=___cur & print,___cur"
Glenn Morris's avatar
Glenn Morris committed
616
  "Command used by `idlwave-shell-resync-dirs' to query IDL for
617 618
the directory stack.")

619 620 621
(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.")
622

623
(defvar idlwave-shell-mode-line-info nil
Juanma Barranquero's avatar
Juanma Barranquero committed
624
  "Additional info displayed in the mode line.")
625

626 627 628 629 630 631 632 633 634 635 636 637 638 639
(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-...'.")

;; Highlighting uses overlays.  When necessary, require the emulation.
(if (not (fboundp 'make-overlay))
    (condition-case nil
	(require 'overlay)
      (error nil)))

(defvar idlwave-shell-stop-line-overlay nil
  "The overlay for where IDL is currently stopped.")
640
(defvar idlwave-shell-is-stopped nil)
641
(defvar idlwave-shell-expression-overlay nil
642
  "The overlay for the examined expression.")
643 644 645
(defvar idlwave-shell-output-overlay nil
  "The overlay for the last IDL output.")

646 647 648 649 650 651
;; 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))
652 653 654
(if (overlayp idlwave-shell-output-overlay)
    (delete-overlay idlwave-shell-output-overlay))

655 656
;; Set to nil initially
(setq idlwave-shell-stop-line-overlay nil
657 658
      idlwave-shell-expression-overlay nil
      idlwave-shell-output-overlay nil)
659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674

;; 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 (or (featurep 'xemacs)            ; XEmacs can do also ttys
	    (fboundp 'tty-defined-colors) ; Emacs 21 as well
	    window-system)                ; Window systems always
    (progn
      (setq idlwave-shell-stop-line-overlay (make-overlay 1 1))
Glenn Morris's avatar
Glenn Morris committed
675
      (overlay-put idlwave-shell-stop-line-overlay
676 677 678 679 680 681 682
		   '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))
Glenn Morris's avatar
Glenn Morris committed
683
	(overlay-put idlwave-shell-stop-line-overlay
684 685
		     'face idlwave-shell-stop-line-face)))))

686
;; Now the expression and output overlays
687 688 689
(setq idlwave-shell-expression-overlay (make-overlay 1 1))
(overlay-put idlwave-shell-expression-overlay
	     'face idlwave-shell-expression-face)
690 691
(overlay-put idlwave-shell-expression-overlay
	     'priority 1)
692 693 694 695
(setq idlwave-shell-output-overlay (make-overlay 1 1))
(overlay-put idlwave-shell-output-overlay
	     'face idlwave-shell-output-face)

Glenn Morris's avatar
Glenn Morris committed
696
(copy-face idlwave-shell-stop-line-face
697
	   'idlwave-shell-pending-stop)
Glenn Morris's avatar
Glenn Morris committed
698
(copy-face idlwave-shell-electric-stop-line-face
699 700 701 702 703 704
	   'idlwave-shell-pending-electric-stop)
(set-face-background 'idlwave-shell-pending-stop "gray70")
(set-face-background 'idlwave-shell-pending-electric-stop "gray70")



705
(defvar idlwave-shell-bp-query "help,/breakpoints"
Juanma Barranquero's avatar
Juanma Barranquero committed
706
  "Command to obtain list of breakpoints.")
707 708 709 710 711 712 713 714 715

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

716
(defvar idlwave-shell-sentinel-hook nil
Juanma Barranquero's avatar
Juanma Barranquero committed
717
  "Hook run when the IDL process exits.")
718

719
(defvar idlwave-shell-hide-output nil
Juanma Barranquero's avatar
Juanma Barranquero committed
720
  "If non-nil the process output is not inserted into the output buffer.")
721 722 723 724

(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.")
725 726 727 728 729 730 731 732 733 734

(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.
735
Each element of the list is list of \(CMD PCMD HIDE), where CMD is a
736
string to be sent to IDL and PCMD is a post-command to be placed on
Juanma Barranquero's avatar
Juanma Barranquero committed
737 738
`idlwave-shell-post-command-hook'.  If HIDE is non-nil, hide the output
from command CMD.  PCMD and HIDE are optional.")
739 740 741

(defun idlwave-shell-buffer ()
  "Name of buffer associated with IDL process.
Juanma Barranquero's avatar
Juanma Barranquero committed
742
The name of the buffer is made by surrounding `idlwave-shell-process-name'
743 744 745 746 747 748 749 750
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.
Glenn Morris's avatar
Glenn Morris committed
751
;;;
752 753 754 755 756 757 758 759 760 761 762

(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
763
  '("^% Interrupted at:"
764
    "^% Stepped to:"
765
    "^% Skipped to:"
766 767
    "^% Stop encountered:"
    )
768
  "A list of regular expressions matching IDL messages.
769 770 771
These are the messages containing file and line information where
IDL is currently stopped.")

772

773 774
(defconst idlwave-shell-halt-messages-re
  (mapconcat 'identity idlwave-shell-halt-messages "\\|")
Juanma Barranquero's avatar
Juanma Barranquero committed
775
  "The regular expression computed from `idlwave-shell-halt-messages'.")
776

777 778
(defconst idlwave-shell-trace-message-re
  "^% At "    ;; First line of a trace message
779
  "A regular expression matching IDL trace messages.  These are the
780 781
messages containing file and line information of a current
traceback.")
782 783 784 785

(defconst idlwave-shell-step-messages
  '("^% Stepped to:"
    )
786
  "A list of regular expressions matching stepped execution messages.
787 788 789 790
These are IDL messages containing file and line information where
IDL has currently stepped.")

(defvar idlwave-shell-break-message "^% Breakpoint at:"
791
  "Regular expression matching an IDL breakpoint message line.")
792

793 794
(defconst idlwave-shell-electric-debug-help
  "   ==> IDLWAVE Electric Debug Mode Help <==
Glenn Morris's avatar
Glenn Morris committed
795

796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820
 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 ?]).
Glenn Morris's avatar
Glenn Morris committed
821
  x          Examine expression near point or in region ([C-u x]) with
822
             letter completion of the examine type.
823
  e          Prompt for an expression to print.
824 825 826 827 828 829 830

 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.")
831 832 833 834 835 836 837 838 839 840 841 842 843 844

(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)
845
(defvar idlwave-shell-calling-stack-index)
846 847
(defvar idlwave-shell-only-prompt-pattern nil)
(defvar tool-bar-map)
848

849
(define-derived-mode idlwave-shell-mode comint-mode "IDL-Shell"
850 851 852 853 854 855
  "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
Juanma Barranquero's avatar
Juanma Barranquero committed
856 857
   process output copies the current line (except for the prompt) to
   the end of the buffer.
858 859 860

   Command history, searching of previous commands, command line
   editing are available via the comint-mode key bindings, by default
861 862
   mostly on the key `C-c'.  Command history is also available with
   the arrow keys UP and DOWN.
863 864 865

2. Completion
   ----------
866 867 868 869
   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'.
870 871 872 873 874 875

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.
Glenn Morris's avatar
Glenn Morris committed
876
   To update IDLWAVE's knowledge about compiled or edited modules, use
877 878 879
   \\[idlwave-update-routine-info].
   \\[idlwave-find-module] find the source of a module.
   \\[idlwave-resolve] tells IDL to compile an unresolved module.
880 881
   \\[idlwave-context-help] shows the online help on the item at
   point, if online help has been installed.
Glenn Morris's avatar
Glenn Morris committed
882

883 884 885 886

4. Debugging
   ---------
   A complete set of commands for compiling and debugging IDL programs
Glenn Morris's avatar
Glenn Morris committed
887
   is available from the menu.  Also keybindings starting with a
888 889 890 891 892 893 894 895 896 897 898 899 900 901
   `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.

902 903 904 905 906 907 908
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
Paul Eggert's avatar
Paul Eggert committed
909
   configurable set of custom examine commands using
910 911 912 913 914
   \\[idlwave-shell-examine-select].  The mouse examine commands can
   also work by click and drag, to select an expression for
   examination.

6. Hooks
915 916 917 918
   -----
   Turning on `idlwave-shell-mode' runs `comint-mode-hook' and
   `idlwave-shell-mode-hook' (in that order).

919
7. Documentation and Customization
920 921 922
   -------------------------------
   Info documentation for this package is available.  Use \\[idlwave-info]
   to display (complain to your sysadmin if that does not work).
Juanma Barranquero's avatar
Juanma Barranquero committed
923
   For PostScript and HTML versions of the documentation, check IDLWAVE's
Glenn Morris's avatar
Glenn Morris committed
924
   homepage at URL `http://github.com/jdtsmith/idlwave'.
925 926
   IDLWAVE has customize support - see the group `idlwave'.

927
8. Keybindings
928 929
   -----------
\\{idlwave-shell-mode-map}"
930
  :abbrev-table idlwave-mode-abbrev-table
931 932 933 934 935 936
  (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)))

937 938
  (setq comint-prompt-regexp idlwave-shell-prompt-pattern)
  (setq comint-process-echoes t)
939

940 941
  ;; Can not use history expansion because "!" is used for system variables.
  (setq comint-input-autoexpand nil)
942
  ;; (setq comint-input-ring-size 64)
Juanma Barranquero's avatar
Juanma Barranquero committed
943

944
  (set (make-local-variable 'completion-ignore-case) t)
945
  (set (make-local-variable 'comint-completion-addsuffix) '("/" . ""))
946
  (setq comint-input-ignoredups t)
947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965
  (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")
	  "-%-"))
966 967 968 969 970 971
  ;; (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)
972
  (setq idlwave-shell-calling-stack-index 0)
973
  (setq idlwave-shell-only-prompt-pattern
Glenn Morris's avatar
Glenn Morris committed
974 975
	(concat "\\`[ \t\n]*"
		(substring idlwave-shell-prompt-pattern 1)
976
		"[ \t\n]*\\'"))
977

978 979 980 981 982
  (when idlwave-shell-query-for-class
      (add-to-list (make-local-variable 'idlwave-determine-class-special)
		   'idlwave-shell-get-object-class)
      (setq idlwave-store-inquired-class t))

983 984 985
  ;; 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))
986
  (setq idlwave-idlwave_routine_info-compiled nil)
987 988 989
  (setq idlwave-shell-ready nil)
  (setq idlwave-shell-bp-alist nil)
  (idlwave-shell-update-bp-overlays) ; Throw away old overlays
990 991
  (setq idlwave-shell-post-command-hook nil ;clean up any old stuff
	idlwave-shell-sources-alist nil)
992
  (setq idlwave-shell-default-directory default-directory)
993
  (setq idlwave-shell-hide-output nil)
994

995 996
  ;; NB: `make-local-hook' needed for older/alternative Emacs compatibility
  ;; (make-local-hook 'kill-buffer-hook)
997 998
  (add-hook 'kill-buffer-hook 'idlwave-shell-kill-shell-buffer-confirm
	    nil 'local)
999 1000
  (add-hook 'kill-buffer-hook 'idlwave-shell-delete-temp-files nil 'local)
  (add-hook 'kill-emacs-hook 'idlwave-shell-delete-temp-files)
1001
  (easy-menu-add idlwave-shell-mode-menu idlwave-shell-mode-map)
1002

1003 1004 1005 1006 1007
  ;; 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)))))
1008

Glenn Morris's avatar
Glenn Morris committed
1009 1010

  (unless (memq 'comint-carriage-motion
1011 1012 1013 1014 1015
		(default-value 'comint-output-filter-functions))
    ;; Strip those pesky ctrl-m's.
    (add-hook 'comint-output-filter-functions
	      (lambda (string)
		(when (string-match "\r" string)
Glenn Morris's avatar
Glenn Morris committed
1016
		  (let ((pmark (process-mark (get-buffer-process
1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030
					      (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.
  (remove-hook 'comint-output-filter-functions 'py-pdbtrack-track-stack-file)

1031
  ;; IDLWAVE syntax, and turn on abbreviations
1032
  (set (make-local-variable 'comment-start) ";")
1033
  (setq abbrev-mode t)
1034

1035 1036
  ;; NB: `make-local-hook' needed for older/alternative Emacs compatibility
  ;; make-local-hook 'post-command-hook)
1037 1038
  (add-hook 'post-command-hook 'idlwave-command-hook nil t)

1039 1040 1041 1042 1043 1044 1045 1046
  ;; 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)))

1047 1048 1049
  ;; Turn off the non-debug toolbar buttons (open,save,etc.)
  (set (make-local-variable 'tool-bar-map) nil)

1050
  (idlwave-shell-send-command idlwave-shell-initial-commands nil 'hide)
1051 1052
  ;; Turn off IDL's ^d interpreting, and define a system
  ;; variable which knows the version of IDLWAVE
Glenn Morris's avatar
Glenn Morris committed
1053
  (idlwave-shell-send-command
1054
   (format "defsysv,'!idlwave_version','%s',1" idlwave-mode-version)
1055
   nil 'hide)
1056 1057 1058 1059
  ;; Read the paths, and save if they changed
  (idlwave-shell-send-command idlwave-shell-path-query
			      'idlwave-shell-get-path-info
			      'hide))
1060

1061
(defvar idlwave-system-directory)
1062 1063
(defun idlwave-shell-get-path-info (&optional no-write)
  "Get the path lists, writing to file unless NO-WRITE is set."
1064 1065
  (let* ((rpl (idlwave-shell-path-filter))
	 (sysdir (car rpl))
1066
	 (dirs (cdr rpl))
1067 1068 1069
	 (old-path-alist idlwave-path-alist)
	 (old-sys-dir idlwave-system-directory)
	 path-changed sysdir-changed)
1070 1071
    (when sysdir
      (setq idlwave-system-directory sysdir)
Glenn Morris's avatar
Glenn Morris committed
1072
      (if (setq sysdir-changed
J.D. Smith's avatar