Mercurial > emacs
comparison lisp/progmodes/idlw-shell.el @ 46529:148f4d9a8905
Updated to IDLWAVE version 4.14. See idlwave.org.
author | J.D. Smith <jdsmith@as.arizona.edu> |
---|---|
date | Thu, 18 Jul 2002 18:58:07 +0000 |
parents | 0b9af9ab98d2 |
children | 1c1d47728dc8 |
comparison
equal
deleted
inserted
replaced
46528:0fc136f66777 | 46529:148f4d9a8905 |
---|---|
1 ;;; idlw-shell.el --- run IDL or WAVE as an inferior process of Emacs | 1 ;; idlw-shell.el --- run IDL as an inferior process of Emacs. |
2 ;; Copyright (c) 1999, 2000 Free Software Foundation | 2 ;; Copyright (c) 1999, 2000, 2001 Free Software Foundation |
3 | 3 |
4 ;; Author: Chris Chase <chase@att.com> | 4 ;; Author: Carsten Dominik <dominik@astro.uva.nl> |
5 ;; Maintainer: John-David Smith <jdsmith@astro.cornell.edu> | 5 ;; Chris Chase <chase@att.com> |
6 ;; Version: 4.7 | 6 ;; Maintainer: J.D. Smith <jdsmith@as.arizona.edu> |
7 ;; Date: $Date: 2002/07/09 10:47:02 $ | 7 ;; Version: 4.14 |
8 ;; Date: $Date: 2002/06/14 19:05:30 $ | |
8 ;; Keywords: processes | 9 ;; Keywords: processes |
9 | 10 |
10 ;; This file is part of GNU Emacs. | 11 ;; This file is part of GNU Emacs. |
11 | 12 |
12 ;; GNU Emacs is free software; you can redistribute it and/or modify | 13 ;; GNU Emacs is free software; you can redistribute it and/or modify |
23 ;; along with GNU Emacs; see the file COPYING. If not, write to the | 24 ;; along with GNU Emacs; see the file COPYING. If not, write to the |
24 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 25 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
25 ;; Boston, MA 02111-1307, USA. | 26 ;; Boston, MA 02111-1307, USA. |
26 | 27 |
27 ;;; Commentary: | 28 ;;; Commentary: |
28 | 29 ;; |
29 ;; This mode is for IDL version 4 or later. It should work on Emacs | 30 ;; This mode is for IDL version 5 or later. It should work on |
30 ;; or XEmacs version 19 or later. | 31 ;; Emacs>20.3 or XEmacs>20.4. |
31 | 32 ;; |
32 ;; Runs IDL as an inferior process of Emacs, much like the emacs | 33 ;; Runs IDL as an inferior process of Emacs, much like the emacs |
33 ;; `shell' or `telnet' commands. Provides command history and | 34 ;; `shell' or `telnet' commands. Provides command history and |
34 ;; searching. Provides debugging commands available in buffers | 35 ;; searching. Provides debugging commands available in buffers |
35 ;; visiting IDL procedure files, e.g., breakpoint setting, stepping, | 36 ;; visiting IDL procedure files, e.g., breakpoint setting, stepping, |
36 ;; execution until a certain line, printing expressions under point, | 37 ;; execution until a certain line, printing expressions under point, |
37 ;; visual line pointer for current execution line, etc. | 38 ;; visual line pointer for current execution line, etc. |
38 ;; | 39 ;; |
39 ;; Documentation should be available online with `M-x idlwave-info'. | 40 ;; Documentation should be available online with `M-x idlwave-info'. |
40 | 41 ;; |
42 ;; New versions of IDLWAVE, documentation, and more information | |
43 ;; available from: | |
44 ;; http://idlwave.org | |
45 ;; | |
41 ;; INSTALLATION: | 46 ;; INSTALLATION: |
42 ;; ============= | 47 ;; ============= |
43 ;; | 48 ;; |
44 ;; Follow the instructions in the INSTALL file of the distribution. | 49 ;; Follow the instructions in the INSTALL file of the distribution. |
45 ;; In short, put this file on your load path and add the following | 50 ;; In short, put this file on your load path and add the following |
52 ;; ====== | 57 ;; ====== |
53 ;; | 58 ;; |
54 ;; The newest version of this file can be found on the maintainers | 59 ;; The newest version of this file can be found on the maintainers |
55 ;; web site. | 60 ;; web site. |
56 ;; | 61 ;; |
57 ;; http://www.strw.leidenuniv.el/~dominik/Tools/idlwave | 62 ;; http://idlwave.org |
58 ;; | 63 ;; |
59 ;; DOCUMENTATION | 64 ;; DOCUMENTATION |
60 ;; ============= | 65 ;; ============= |
61 ;; | 66 ;; |
62 ;; IDLWAVE is documented online in info format. | 67 ;; IDLWAVE is documented online in info format. |
86 ;; the variables which control the behavior of the mode, use | 91 ;; the variables which control the behavior of the mode, use |
87 ;; `M-x idlwave-customize'. | 92 ;; `M-x idlwave-customize'. |
88 ;; | 93 ;; |
89 ;;-------------------------------------------------------------------------- | 94 ;;-------------------------------------------------------------------------- |
90 ;; | 95 ;; |
91 ;; | |
92 | 96 |
93 ;;; Code: | 97 ;;; Code: |
94 | 98 |
95 (require 'comint) | 99 (require 'comint) |
96 (require 'idlwave) | 100 (require 'idlwave) |
97 | 101 |
98 (eval-when-compile (require 'cl)) | 102 (eval-when-compile (require 'cl)) |
99 | 103 |
100 (defvar idlwave-shell-have-new-custom nil) | 104 (defvar idlwave-shell-have-new-custom nil) |
101 (eval-and-compile | 105 (eval-and-compile |
102 ;; Kludge to allow `defcustom' for Emacs 19. | 106 ;; Kludge to allow `defcustom' for Emacs 19. |
103 (condition-case () (require 'custom) (error nil)) | 107 (condition-case () (require 'custom) (error nil)) |
104 (if (and (featurep 'custom) | 108 (if (and (featurep 'custom) |
105 (fboundp 'custom-declare-variable) | 109 (fboundp 'custom-declare-variable) |
106 (fboundp 'defface)) | 110 (fboundp 'defface)) |
107 ;; We've got what we needed | 111 ;; We've got what we needed |
108 (setq idlwave-shell-have-new-custom t) | 112 (setq idlwave-shell-have-new-custom t) |
109 ;; We have the old or no custom-library, hack around it! | 113 ;; We have the old or no custom-library, hack around it! |
110 (defmacro defgroup (&rest args) nil) | 114 (defmacro defgroup (&rest args) nil) |
111 (defmacro defcustom (var value doc &rest args) | 115 (defmacro defcustom (var value doc &rest args) |
112 `(defvar ,var ,value ,doc)))) | 116 `(defvar ,var ,value ,doc)))) |
113 | 117 |
114 ;;; Customizations: idlwave-shell group | 118 ;;; Customizations: idlwave-shell group |
115 | 119 |
116 (defgroup idlwave-shell-general-setup nil | 120 (defgroup idlwave-shell-general-setup nil |
117 "General setup of the Shell interaction for IDLWAVE/Shell." | 121 "General setup of the Shell interaction for IDLWAVE/Shell." |
139 | 143 |
140 (defcustom idlwave-shell-initial-commands "!more=0" | 144 (defcustom idlwave-shell-initial-commands "!more=0" |
141 "Initial commands, separated by newlines, to send to IDL. | 145 "Initial commands, separated by newlines, to send to IDL. |
142 This string is sent to the IDL process by `idlwave-shell-mode' which is | 146 This string is sent to the IDL process by `idlwave-shell-mode' which is |
143 invoked by `idlwave-shell'." | 147 invoked by `idlwave-shell'." |
144 :group 'idlwave-shell-initial-commands | 148 :group 'idlwave-shell-general-setup |
145 :type 'string) | 149 :type 'string) |
146 | 150 |
151 (defcustom idlwave-shell-save-command-history t | |
152 "Non-nil means preserve command history between sessions. | |
153 The file `idlwave-shell-command-history-file' is used to save and restore | |
154 the history." | |
155 :group 'idlwave-shell-general-setup | |
156 :type 'boolean) | |
157 | |
158 (defcustom idlwave-shell-command-history-file "~/.idlwhist" | |
159 "The file in which the command history of the idlwave shell is saved. | |
160 In order to change the size of the history, see the variable | |
161 `comint-input-ring-size'. | |
162 The history is only saved if the variable `idlwave-shell-save-command-history' | |
163 is non-nil." | |
164 :group 'idlwave-shell-general-setup | |
165 :type 'file) | |
166 | |
147 (defcustom idlwave-shell-use-dedicated-frame nil | 167 (defcustom idlwave-shell-use-dedicated-frame nil |
148 "*Non-nil means, IDLWAVE should use a special frame to display shell buffer." | 168 "*Non-nil means, IDLWAVE should use a special frame to display shell buffer." |
149 :group 'idlwave-shell-general-setup | 169 :group 'idlwave-shell-general-setup |
150 :type 'boolean) | 170 :type 'boolean) |
151 | 171 |
155 See also `idlwave-shell-use-dedicated-frame'. | 175 See also `idlwave-shell-use-dedicated-frame'. |
156 The default makes the frame splittable, so that completion works correctly." | 176 The default makes the frame splittable, so that completion works correctly." |
157 :group 'idlwave-shell-general-setup | 177 :group 'idlwave-shell-general-setup |
158 :type '(repeat | 178 :type '(repeat |
159 (cons symbol sexp))) | 179 (cons symbol sexp))) |
180 | |
181 (defcustom idlwave-shell-raise-frame t | |
182 "*Non-nil means, `idlwave-shell' raises the frame showing the shell window." | |
183 :group 'idlwave-shell-general-setup | |
184 :type 'boolean) | |
160 | 185 |
161 (defcustom idlwave-shell-arrows-do-history t | 186 (defcustom idlwave-shell-arrows-do-history t |
162 "*Non-nil means UP and DOWN arrows move through command history. | 187 "*Non-nil means UP and DOWN arrows move through command history. |
163 This variable can have 3 values: | 188 This variable can have 3 values: |
164 nil Arrows just move the cursor | 189 nil Arrows just move the cursor |
170 :type '(choice | 195 :type '(choice |
171 (const :tag "never" nil) | 196 (const :tag "never" nil) |
172 (const :tag "everywhere" t) | 197 (const :tag "everywhere" t) |
173 (const :tag "in command line only" cmdline))) | 198 (const :tag "in command line only" cmdline))) |
174 | 199 |
200 ;; FIXME: add comint-input-ring-size? | |
201 (defcustom idlwave-shell-comint-settings | |
202 '((comint-scroll-to-bottom-on-input . t) | |
203 (comint-scroll-to-bottom-on-output . nil) | |
204 (comint-scroll-show-maximum-output . t) | |
205 ) | |
206 "Alist of special settings for the comint variables in the IDLWAVE Shell. | |
207 Each entry is a cons cell with the name of a variable and a value. | |
208 The function `idlwave-shell-mode' will make local variables out of each entry. | |
209 Changes to this variable will only be active when the shell buffer is | |
210 newly created." | |
211 :group 'idlwave-shell-general-setup | |
212 :type '(repeat | |
213 (cons variable sexp))) | |
214 | |
175 (defcustom idlwave-shell-use-toolbar t | 215 (defcustom idlwave-shell-use-toolbar t |
176 "*Non-nil means, use the debugging toolbar in all IDL related buffers. | 216 "*Non-nil means, use the debugging toolbar in all IDL related buffers. |
177 Starting the shell will then add the toolbar to all idlwave-mode buffers. | 217 Starting the shell will then add the toolbar to all idlwave-mode buffers. |
178 Exiting the shell will removed everywhere. | 218 Exiting the shell will removed everywhere. |
179 Available on XEmacs and on Emacs 21.x or later. | 219 Available on XEmacs and on Emacs 21.x or later. |
183 :type 'boolean) | 223 :type 'boolean) |
184 | 224 |
185 (defcustom idlwave-shell-temp-pro-prefix "/tmp/idltemp" | 225 (defcustom idlwave-shell-temp-pro-prefix "/tmp/idltemp" |
186 "*The prefix for temporary IDL files used when compiling regions. | 226 "*The prefix for temporary IDL files used when compiling regions. |
187 It should be an absolute pathname. | 227 It should be an absolute pathname. |
188 The full temporary file name is obtained by to using `make-temp-name' | 228 The full temporary file name is obtained by using `make-temp-file' |
189 so that the name will be unique among multiple Emacs processes." | 229 so that the name will be unique among multiple Emacs processes." |
190 :group 'idlwave-shell-general-setup | 230 :group 'idlwave-shell-general-setup |
191 :type 'string) | 231 :type 'string) |
192 | 232 |
193 (defvar idlwave-shell-fix-inserted-breaks nil | 233 (defvar idlwave-shell-fix-inserted-breaks nil |
238 (defcustom idlwave-shell-mode-hook '() | 278 (defcustom idlwave-shell-mode-hook '() |
239 "*Hook for customising `idlwave-shell-mode'." | 279 "*Hook for customising `idlwave-shell-mode'." |
240 :group 'idlwave-shell-general-setup | 280 :group 'idlwave-shell-general-setup |
241 :type 'hook) | 281 :type 'hook) |
242 | 282 |
243 (defcustom idlwave-shell-print-expression-function nil | 283 (defvar idlwave-shell-print-expression-function nil |
244 "When non-nil, a function to handle display of evaluated expressions. | 284 "*OBSOLETE VARIABLE, is no longer used.") |
245 This can be used to arrange for displaying the value of an expression | 285 |
246 in (e.g.) a special frame. The function must accept one argument: | 286 (defcustom idlwave-shell-examine-alist |
247 the expression which was evaluated. The output from IDL will be | 287 '(("Print" . "print,___") |
248 available in the variable `idlwave-shell-command-output'." | 288 ("Help" . "help,___") |
249 :group 'idlwave-shell-highlighting-and-faces | 289 ("Structure Help" . "help,___,/STRUCTURE") |
250 :type 'symbol) | 290 ("Dimensions" . "print,size(___,/DIMENSIONS)") |
251 | 291 ("Type" . "print,size(___,/TNAME)") |
292 ("N_Elements" . "print,n_elements(___)") | |
293 ("All Size Info" . "help,(__IWsz__=size(___,/STRUCTURE)),/STRUCTURE & print,__IWsz__.DIMENSIONS") | |
294 ("Ptr Valid" . "print,ptr_valid(___)") | |
295 ("Widget Valid" . "print,widget_info(___,/VALID)") | |
296 ("Widget Geometry" . "help,widget_info(___,/GEOMETRY)")) | |
297 "Alist of special examine commands for popup selection. | |
298 The keys are used in the selection popup created by | |
299 `idlwave-shell-examine-select', and the corresponding value is sent as | |
300 a command to the shell, with special sequence `___' replaced by the | |
301 expression being examined." | |
302 :group 'idlwave-shell-general-setup | |
303 :type '(repeat | |
304 (cons | |
305 (string :tag "Label ") | |
306 (string :tag "Command")))) | |
307 | |
308 (defcustom idlwave-shell-separate-examine-output t | |
309 "*Non-nil mean, put output of examine commands in their own buffer." | |
310 :group 'idlwave-shell-general-setup | |
311 :type 'boolean) | |
312 | |
252 (defcustom idlwave-shell-use-input-mode-magic nil | 313 (defcustom idlwave-shell-use-input-mode-magic nil |
253 "*Non-nil means, IDLWAVE should check for input mode spells in output. | 314 "*Non-nil means, IDLWAVE should check for input mode spells in output. |
254 The spells are strings printed by your IDL program and matched | 315 The spells are strings printed by your IDL program and matched |
255 by the regular expressions in `idlwave-shell-input-mode-spells'. | 316 by the regular expressions in `idlwave-shell-input-mode-spells'. |
256 When these expressions match, IDLWAVE switches to character input mode and | 317 When these expressions match, IDLWAVE switches to character input mode and |
344 t Use what IDLWAVE thinks is best. Will be a face where possible, | 405 t Use what IDLWAVE thinks is best. Will be a face where possible, |
345 otherwise the overlay arrow. | 406 otherwise the overlay arrow. |
346 The overlay-arrow has the disadvantage to hide the first chars of a line. | 407 The overlay-arrow has the disadvantage to hide the first chars of a line. |
347 Since many people do not have the main block of IDL programs indented, | 408 Since many people do not have the main block of IDL programs indented, |
348 a face highlighting may be better. | 409 a face highlighting may be better. |
349 On Emacs 21, the overlay arrow is displayed in a special area and never | 410 In Emacs 21, the overlay arrow is displayed in a special area and never |
350 hides any code, so setting this to 'arrow on Emacs 21 sounds like a good idea." | 411 hides any code, so setting this to 'arrow on Emacs 21 sounds like a good idea." |
351 :group 'idlwave-shell-highlighting-and-faces | 412 :group 'idlwave-shell-highlighting-and-faces |
352 :type '(choice | 413 :type '(choice |
353 (const :tag "No marking" nil) | 414 (const :tag "No marking" nil) |
354 (const :tag "Use overlay arrow" arrow) | 415 (const :tag "Use overlay arrow" arrow) |
411 Allows you to choose the font, color and other properties for | 472 Allows you to choose the font, color and other properties for |
412 the expression printed by IDL." | 473 the expression printed by IDL." |
413 :group 'idlwave-shell-highlighting-and-faces | 474 :group 'idlwave-shell-highlighting-and-faces |
414 :type 'symbol) | 475 :type 'symbol) |
415 | 476 |
477 (defcustom idlwave-shell-output-face 'secondary-selection | |
478 "*The face for `idlwave-shell-output-overlay'. | |
479 Allows you to choose the font, color and other properties for | |
480 the expression output by IDL." | |
481 :group 'idlwave-shell-highlighting-and-faces | |
482 :type 'symbol) | |
483 | |
416 ;;; End user customization variables | 484 ;;; End user customization variables |
417 | 485 |
418 ;;; External variables | 486 ;;; External variables |
419 (defvar comint-last-input-start) | 487 (defvar comint-last-input-start) |
420 (defvar comint-last-input-end) | 488 (defvar comint-last-input-end) |
421 | 489 |
490 (defun idlwave-shell-temp-file (type) | |
491 "Return a temp file, creating it if necessary. | |
492 | |
493 TYPE is either 'pro or 'rinfo, and idlwave-shell-temp-pro-file or | |
494 idlwave-shell-temp-rinfo-save-file is set (respectively)." | |
495 (cond | |
496 ((eq type 'rinfo) | |
497 (or idlwave-shell-temp-rinfo-save-file | |
498 (setq idlwave-shell-temp-rinfo-save-file | |
499 (idlwave-shell-make-temp-file idlwave-shell-temp-pro-prefix)))) | |
500 ((eq type 'pro) | |
501 (or idlwave-shell-temp-pro-file | |
502 (setq idlwave-shell-temp-pro-file | |
503 (idlwave-shell-make-temp-file idlwave-shell-temp-pro-prefix)))) | |
504 (t (error "Wrong argument (idlwave-shell-temp-file): %s" | |
505 (symbol-name type))))) | |
506 | |
507 | |
508 (defun idlwave-shell-make-temp-file (prefix) | |
509 "Create a temporary file." | |
510 ; Hard coded make-temp-file for Emacs<21 | |
511 (if (fboundp 'make-temp-file) | |
512 (make-temp-file prefix) | |
513 (let (file | |
514 (temp-file-dir (if (boundp 'temporary-file-directory) | |
515 temporary-file-directory | |
516 "/tmp"))) | |
517 (while (condition-case () | |
518 (progn | |
519 (setq file | |
520 (make-temp-name | |
521 (expand-file-name prefix temp-file-dir))) | |
522 (if (featurep 'xemacs) | |
523 (write-region "" nil file nil 'silent nil) | |
524 (write-region "" nil file nil 'silent nil 'excl)) | |
525 nil) | |
526 (file-already-exists t)) | |
527 ;; the file was somehow created by someone else between | |
528 ;; `make-temp-name' and `write-region', let's try again. | |
529 nil) | |
530 file))) | |
531 | |
422 ;; Other variables | 532 ;; Other variables |
423 | 533 (defvar idlwave-shell-temp-pro-file |
424 (defvar idlwave-shell-temp-file-base | 534 nil |
425 (make-temp-name idlwave-shell-temp-pro-prefix) | |
426 "Base name of the temporary files.") | |
427 | |
428 (defvar idlwave-shell-temp-pro-file | |
429 (concat idlwave-shell-temp-file-base ".pro") | |
430 "Absolute pathname for temporary IDL file for compiling regions") | 535 "Absolute pathname for temporary IDL file for compiling regions") |
431 | 536 |
432 (defvar idlwave-shell-temp-rinfo-save-file | 537 (defvar idlwave-shell-temp-rinfo-save-file |
433 (concat idlwave-shell-temp-file-base ".sav") | 538 nil |
434 "Absolute pathname for temporary IDL file save file for routine_info. | 539 "Absolute pathname for temporary IDL file save file for routine_info. |
435 This is used to speed up the reloading of the routine info procedure | 540 This is used to speed up the reloading of the routine info procedure |
436 before use by the shell.") | 541 before use by the shell.") |
437 | 542 |
438 | |
439 (defvar idlwave-shell-dirstack-query "printd" | 543 (defvar idlwave-shell-dirstack-query "printd" |
440 "Command used by `idlwave-shell-resync-dirs' to query IDL for | 544 "Command used by `idlwave-shell-resync-dirs' to query IDL for |
441 the directory stack.") | 545 the directory stack.") |
546 | |
547 (defvar idlwave-shell-wd-is-synched nil) | |
442 | 548 |
443 (defvar idlwave-shell-path-query "__pa=expand_path(!path,/array)&for i=0,n_elements(__pa)-1 do print,'PATH:<'+__pa[i]+'>'&print,'SYSDIR:<'+!dir+'>'" | 549 (defvar idlwave-shell-path-query "__pa=expand_path(!path,/array)&for i=0,n_elements(__pa)-1 do print,'PATH:<'+__pa[i]+'>'&print,'SYSDIR:<'+!dir+'>'" |
444 "The command which gets !PATH and !DIR infor from the shell.") | 550 "The command which gets !PATH and !DIR infor from the shell.") |
445 | 551 |
446 (defvar idlwave-shell-mode-line-info nil | 552 (defvar idlwave-shell-mode-line-info nil |
461 (defvar idlwave-shell-stop-line-overlay nil | 567 (defvar idlwave-shell-stop-line-overlay nil |
462 "The overlay for where IDL is currently stopped.") | 568 "The overlay for where IDL is currently stopped.") |
463 (defvar idlwave-shell-is-stopped nil) | 569 (defvar idlwave-shell-is-stopped nil) |
464 (defvar idlwave-shell-expression-overlay nil | 570 (defvar idlwave-shell-expression-overlay nil |
465 "The overlay for where IDL is currently stopped.") | 571 "The overlay for where IDL is currently stopped.") |
572 (defvar idlwave-shell-output-overlay nil | |
573 "The overlay for the last IDL output.") | |
574 | |
466 ;; If these were already overlays, delete them. This probably means that we | 575 ;; If these were already overlays, delete them. This probably means that we |
467 ;; are reloading this file. | 576 ;; are reloading this file. |
468 (if (overlayp idlwave-shell-stop-line-overlay) | 577 (if (overlayp idlwave-shell-stop-line-overlay) |
469 (delete-overlay idlwave-shell-stop-line-overlay)) | 578 (delete-overlay idlwave-shell-stop-line-overlay)) |
470 (if (overlayp idlwave-shell-expression-overlay) | 579 (if (overlayp idlwave-shell-expression-overlay) |
471 (delete-overlay idlwave-shell-expression-overlay)) | 580 (delete-overlay idlwave-shell-expression-overlay)) |
581 (if (overlayp idlwave-shell-output-overlay) | |
582 (delete-overlay idlwave-shell-output-overlay)) | |
583 | |
472 ;; Set to nil initially | 584 ;; Set to nil initially |
473 (setq idlwave-shell-stop-line-overlay nil | 585 (setq idlwave-shell-stop-line-overlay nil |
474 idlwave-shell-expression-overlay nil) | 586 idlwave-shell-expression-overlay nil |
587 idlwave-shell-output-overlay nil) | |
475 | 588 |
476 ;; Define the shell stop overlay. When left nil, the arrow will be used. | 589 ;; Define the shell stop overlay. When left nil, the arrow will be used. |
477 (cond | 590 (cond |
478 ((or (null idlwave-shell-mark-stop-line) | 591 ((or (null idlwave-shell-mark-stop-line) |
479 (eq idlwave-shell-mark-stop-line 'arrow)) | 592 (eq idlwave-shell-mark-stop-line 'arrow)) |
497 (progn | 610 (progn |
498 (setq idlwave-shell-stop-line-overlay (make-overlay 1 1)) | 611 (setq idlwave-shell-stop-line-overlay (make-overlay 1 1)) |
499 (overlay-put idlwave-shell-stop-line-overlay | 612 (overlay-put idlwave-shell-stop-line-overlay |
500 'face idlwave-shell-stop-line-face))))) | 613 'face idlwave-shell-stop-line-face))))) |
501 | 614 |
502 ;; Now the expression overlay | 615 ;; Now the expression and output overlays |
503 (setq idlwave-shell-expression-overlay (make-overlay 1 1)) | 616 (setq idlwave-shell-expression-overlay (make-overlay 1 1)) |
504 (overlay-put idlwave-shell-expression-overlay | 617 (overlay-put idlwave-shell-expression-overlay |
505 'face idlwave-shell-expression-face) | 618 'face idlwave-shell-expression-face) |
619 (setq idlwave-shell-output-overlay (make-overlay 1 1)) | |
620 (overlay-put idlwave-shell-output-overlay | |
621 'face idlwave-shell-output-face) | |
622 | |
506 (defvar idlwave-shell-bp-query "help,/breakpoints" | 623 (defvar idlwave-shell-bp-query "help,/breakpoints" |
507 "Command to obtain list of breakpoints") | 624 "Command to obtain list of breakpoints") |
508 | 625 |
509 (defvar idlwave-shell-command-output nil | 626 (defvar idlwave-shell-command-output nil |
510 "String for accumulating current command output.") | 627 "String for accumulating current command output.") |
511 | 628 |
512 (defvar idlwave-shell-post-command-hook nil | 629 (defvar idlwave-shell-post-command-hook nil |
513 "Lisp list expression or function to run when an IDL command is finished. | 630 "Lisp list expression or function to run when an IDL command is finished. |
514 The current command is finished when the IDL prompt is displayed. | 631 The current command is finished when the IDL prompt is displayed. |
515 This is evaluated if it is a list or called with funcall.") | 632 This is evaluated if it is a list or called with funcall.") |
633 | |
634 (defvar idlwave-shell-sentinel-hook nil | |
635 "Hook run when the idl process exits.") | |
516 | 636 |
517 (defvar idlwave-shell-hide-output nil | 637 (defvar idlwave-shell-hide-output nil |
518 "If non-nil the process output is not inserted into the output | 638 "If non-nil the process output is not inserted into the output |
519 buffer.") | 639 buffer.") |
520 | 640 |
663 6. Documentation and Customization | 783 6. Documentation and Customization |
664 ------------------------------- | 784 ------------------------------- |
665 Info documentation for this package is available. Use \\[idlwave-info] | 785 Info documentation for this package is available. Use \\[idlwave-info] |
666 to display (complain to your sysadmin if that does not work). | 786 to display (complain to your sysadmin if that does not work). |
667 For Postscript and HTML versions of the documentation, check IDLWAVE's | 787 For Postscript and HTML versions of the documentation, check IDLWAVE's |
668 homepage at `http://www.strw.leidenuniv.nl/~dominik/Tools/idlwave'. | 788 homepage at `http://idlwave.org'. |
669 IDLWAVE has customize support - see the group `idlwave'. | 789 IDLWAVE has customize support - see the group `idlwave'. |
670 | 790 |
671 7. Keybindings | 791 7. Keybindings |
672 ----------- | 792 ----------- |
673 \\{idlwave-shell-mode-map}" | 793 \\{idlwave-shell-mode-map}" |
677 ;; comint - idlwave-shell-mode only add on top of that. | 797 ;; comint - idlwave-shell-mode only add on top of that. |
678 (setq comint-prompt-regexp idlwave-shell-prompt-pattern) | 798 (setq comint-prompt-regexp idlwave-shell-prompt-pattern) |
679 (setq comint-process-echoes t) | 799 (setq comint-process-echoes t) |
680 ;; Can not use history expansion because "!" is used for system variables. | 800 ;; Can not use history expansion because "!" is used for system variables. |
681 (setq comint-input-autoexpand nil) | 801 (setq comint-input-autoexpand nil) |
682 (setq comint-input-ring-size 64) | 802 ; (setq comint-input-ring-size 64) |
683 (make-local-variable 'comint-completion-addsuffix) | 803 (make-local-variable 'comint-completion-addsuffix) |
684 (set (make-local-variable 'completion-ignore-case) t) | 804 (set (make-local-variable 'completion-ignore-case) t) |
685 (setq comint-completion-addsuffix '("/" . "")) | 805 (setq comint-completion-addsuffix '("/" . "")) |
686 (setq comint-input-ignoredups t) | 806 (setq comint-input-ignoredups t) |
687 (setq major-mode 'idlwave-shell-mode) | 807 (setq major-mode 'idlwave-shell-mode) |
721 (setq idlwave-shell-bp-alist nil) | 841 (setq idlwave-shell-bp-alist nil) |
722 (idlwave-shell-update-bp-overlays) ; Throw away old overlays | 842 (idlwave-shell-update-bp-overlays) ; Throw away old overlays |
723 (setq idlwave-shell-sources-alist nil) | 843 (setq idlwave-shell-sources-alist nil) |
724 (setq idlwave-shell-default-directory default-directory) | 844 (setq idlwave-shell-default-directory default-directory) |
725 (setq idlwave-shell-hide-output nil) | 845 (setq idlwave-shell-hide-output nil) |
846 | |
847 ;; NB: `make-local-hook' needed for older/alternative Emacs compatibility | |
848 (make-local-hook 'kill-buffer-hook) | |
726 (add-hook 'kill-buffer-hook 'idlwave-shell-kill-shell-buffer-confirm | 849 (add-hook 'kill-buffer-hook 'idlwave-shell-kill-shell-buffer-confirm |
727 nil 'local) | 850 nil 'local) |
728 (add-hook 'kill-buffer-hook 'idlwave-shell-delete-temp-files nil 'local) | 851 (add-hook 'kill-buffer-hook 'idlwave-shell-delete-temp-files nil 'local) |
729 (add-hook 'kill-emacs-hook 'idlwave-shell-delete-temp-files) | 852 (add-hook 'kill-emacs-hook 'idlwave-shell-delete-temp-files) |
730 (use-local-map idlwave-shell-mode-map) | 853 (use-local-map idlwave-shell-mode-map) |
731 (easy-menu-add idlwave-shell-mode-menu idlwave-shell-mode-map) | 854 (easy-menu-add idlwave-shell-mode-menu idlwave-shell-mode-map) |
732 | 855 |
733 (set (make-local-variable 'comint-scroll-to-bottom-on-input) t) | 856 ;; Set the optional comint variables |
734 (set (make-local-variable 'comint-scroll-show-maximum-output) t) | 857 (when idlwave-shell-comint-settings |
858 (let ((list idlwave-shell-comint-settings) entry) | |
859 (while (setq entry (pop list)) | |
860 (set (make-local-variable (car entry)) (cdr entry))))) | |
735 | 861 |
736 ;; IDLWAVE syntax, and turn on abbreviations | 862 ;; IDLWAVE syntax, and turn on abbreviations |
737 (setq local-abbrev-table idlwave-mode-abbrev-table) | 863 (setq local-abbrev-table idlwave-mode-abbrev-table) |
738 (set-syntax-table idlwave-mode-syntax-table) | 864 (set-syntax-table idlwave-mode-syntax-table) |
739 (set (make-local-variable 'comment-start) ";") | 865 (set (make-local-variable 'comment-start) ";") |
740 (setq abbrev-mode t) | 866 (setq abbrev-mode t) |
867 | |
868 ;; NB: `make-local-hook' needed for older/alternative Emacs compatibility | |
869 (make-local-hook 'post-command-hook) | |
741 (add-hook 'post-command-hook 'idlwave-command-hook nil t) | 870 (add-hook 'post-command-hook 'idlwave-command-hook nil t) |
871 | |
872 ;; Read the command history? | |
873 (when (and idlwave-shell-save-command-history | |
874 (stringp idlwave-shell-command-history-file)) | |
875 (set (make-local-variable 'comint-input-ring-file-name) | |
876 idlwave-shell-command-history-file) | |
877 (if (file-regular-p idlwave-shell-command-history-file) | |
878 (comint-read-input-ring))) | |
742 | 879 |
743 ;; Run the hooks. | 880 ;; Run the hooks. |
744 (run-hooks 'idlwave-shell-mode-hook) | 881 (run-hooks 'idlwave-shell-mode-hook) |
745 (idlwave-shell-send-command idlwave-shell-initial-commands nil 'hide) | 882 (idlwave-shell-send-command idlwave-shell-initial-commands nil 'hide) |
746 ;; Define a system variable which knows the version of IDLWAVE | 883 ;; Define a system variable which knows the version of IDLWAVE |
778 ;; We want separate frames for source and shell | 915 ;; We want separate frames for source and shell |
779 (if (frame-live-p idlwave-shell-display-wframe) | 916 (if (frame-live-p idlwave-shell-display-wframe) |
780 ;; The frame exists, so we use it. | 917 ;; The frame exists, so we use it. |
781 idlwave-shell-display-wframe | 918 idlwave-shell-display-wframe |
782 ;; The frame does not exist. We use the current frame. | 919 ;; The frame does not exist. We use the current frame. |
783 ;; However, if the current is the shell frame, we make a new frame. | 920 ;; However, if the current is the shell frame, we make a new frame, |
921 ;; or recycle the first existing visible frame | |
784 (setq idlwave-shell-display-wframe | 922 (setq idlwave-shell-display-wframe |
785 (if (eq (selected-frame) idlwave-shell-idl-wframe) | 923 (if (eq (selected-frame) idlwave-shell-idl-wframe) |
786 (make-frame) | 924 (or |
925 (let ((flist (visible-frame-list)) | |
926 (frame (selected-frame))) | |
927 (catch 'exit | |
928 (while flist | |
929 (if (not (eq (car flist) | |
930 idlwave-shell-idl-wframe)) | |
931 (throw 'exit (car flist)) | |
932 (setq flist (cdr flist)))))) | |
933 (make-frame)) | |
787 (selected-frame)))))) | 934 (selected-frame)))))) |
788 | 935 |
789 (defun idlwave-shell-shell-frame () | 936 (defun idlwave-shell-shell-frame () |
790 "Return the frame to be used for the shell buffer." | 937 "Return the frame to be used for the shell buffer." |
791 (if idlwave-shell-use-dedicated-frame | 938 (if idlwave-shell-use-dedicated-frame |
800 ;; Return a new frame | 947 ;; Return a new frame |
801 (setq idlwave-shell-idl-wframe | 948 (setq idlwave-shell-idl-wframe |
802 (make-frame idlwave-shell-frame-parameters))))) | 949 (make-frame idlwave-shell-frame-parameters))))) |
803 | 950 |
804 ;;;###autoload | 951 ;;;###autoload |
805 (defun idlwave-shell (&optional arg) | 952 (defun idlwave-shell (&optional arg quick) |
806 "Run an inferior IDL, with I/O through buffer `(idlwave-shell-buffer)'. | 953 "Run an inferior IDL, with I/O through buffer `(idlwave-shell-buffer)'. |
807 If buffer exists but shell process is not running, start new IDL. | 954 If buffer exists but shell process is not running, start new IDL. |
808 If buffer exists and shell process is running, just switch to the buffer. | 955 If buffer exists and shell process is running, just switch to the buffer. |
809 | 956 |
810 When called with a prefix ARG, or when `idlwave-shell-use-dedicated-frame' | 957 When called with a prefix ARG, or when `idlwave-shell-use-dedicated-frame' |
811 is non-nil, the shell buffer and the source buffers will be in | 958 is non-nil, the shell buffer and the source buffers will be in |
812 separate frames. | 959 separate frames. |
813 | 960 |
814 The command to run comes from variable `idlwave-shell-explicit-file-name'. | 961 The command to run comes from variable `idlwave-shell-explicit-file-name', |
962 with options taken from `idlwave-shell-command-line-options'. | |
815 | 963 |
816 The buffer is put in `idlwave-shell-mode', providing commands for sending | 964 The buffer is put in `idlwave-shell-mode', providing commands for sending |
817 input and controlling the IDL job. See help on `idlwave-shell-mode'. | 965 input and controlling the IDL job. See help on `idlwave-shell-mode'. |
818 See also the variable `idlwave-shell-prompt-pattern'. | 966 See also the variable `idlwave-shell-prompt-pattern'. |
819 | 967 |
820 \(Type \\[describe-mode] in the shell buffer for a list of commands.)" | 968 \(Type \\[describe-mode] in the shell buffer for a list of commands.)" |
821 (interactive "P") | 969 (interactive "P") |
822 | 970 (if (eq arg 'quick) |
823 ;; A non-nil arg means, we want a dedicated frame. This will last | 971 (progn |
824 ;; for the current editing session. | 972 (let ((idlwave-shell-use-dedicated-frame nil)) |
825 (if arg (setq idlwave-shell-use-dedicated-frame t)) | 973 (idlwave-shell nil) |
826 (if (equal arg '(16)) (setq idlwave-shell-use-dedicated-frame nil)) | 974 (delete-other-windows)) |
827 | 975 (and idlwave-shell-use-dedicated-frame |
828 ;; Check if the process still exists. If not, create it. | 976 (setq idlwave-shell-idl-wframe (selected-frame))) |
829 (unless (comint-check-proc (idlwave-shell-buffer)) | 977 (add-hook 'idlwave-shell-sentinel-hook |
830 (let* ((prg (or idlwave-shell-explicit-file-name "idl")) | 978 'save-buffers-kill-emacs t)) |
831 (buf (apply 'make-comint | 979 |
832 idlwave-shell-process-name prg nil | 980 ;; A non-nil arg means, we want a dedicated frame. This will last |
833 idlwave-shell-command-line-options)) | 981 ;; for the current editing session. |
834 (process (get-buffer-process buf))) | 982 (if arg (setq idlwave-shell-use-dedicated-frame t)) |
835 (setq idlwave-idlwave_routine_info-compiled nil) | 983 (if (equal arg '(16)) (setq idlwave-shell-use-dedicated-frame nil)) |
836 (set-process-filter process 'idlwave-shell-filter) | 984 |
837 (set-process-sentinel process 'idlwave-shell-sentinel) | 985 ;; Check if the process still exists. If not, create it. |
838 (set-buffer buf) | 986 (unless (comint-check-proc (idlwave-shell-buffer)) |
839 (idlwave-shell-mode))) | 987 (let* ((prg (or idlwave-shell-explicit-file-name "idl")) |
840 (let ((window (idlwave-display-buffer (idlwave-shell-buffer) nil | 988 (buf (apply 'make-comint |
841 (idlwave-shell-shell-frame))) | 989 idlwave-shell-process-name prg nil |
842 (current-window (selected-window))) | 990 (if (stringp idlwave-shell-command-line-options) |
843 (select-window window) | 991 (idlwave-split-string |
844 (goto-char (point-max)) | 992 idlwave-shell-command-line-options) |
845 (select-window current-window) | 993 idlwave-shell-command-line-options))) |
846 (raise-frame (window-frame window)) | 994 (process (get-buffer-process buf))) |
847 (if (eq (selected-frame) (window-frame window)) | 995 (setq idlwave-idlwave_routine_info-compiled nil) |
848 (select-window window)) | 996 (set-process-filter process 'idlwave-shell-filter) |
849 )) | 997 (set-process-sentinel process 'idlwave-shell-sentinel) |
998 (set-buffer buf) | |
999 (idlwave-shell-mode))) | |
1000 (let ((window (idlwave-display-buffer (idlwave-shell-buffer) nil | |
1001 (idlwave-shell-shell-frame))) | |
1002 (current-window (selected-window))) | |
1003 (select-window window) | |
1004 (goto-char (point-max)) | |
1005 (select-window current-window) | |
1006 (if idlwave-shell-ready | |
1007 (raise-frame (window-frame window))) | |
1008 (if (eq (selected-frame) (window-frame window)) | |
1009 (select-window window)) | |
1010 ))) | |
850 | 1011 |
851 (defun idlwave-shell-recenter-shell-window (&optional arg) | 1012 (defun idlwave-shell-recenter-shell-window (&optional arg) |
852 "Run `idlwave-shell', but make sure the current window stays selected." | 1013 "Run `idlwave-shell', but make sure the current window stays selected." |
853 (interactive "P") | 1014 (interactive "P") |
854 (let ((window (selected-window))) | 1015 (let ((window (selected-window))) |
869 | 1030 |
870 IDL is considered ready if the prompt is present | 1031 IDL is considered ready if the prompt is present |
871 and if `idlwave-shell-ready' is non-nil." | 1032 and if `idlwave-shell-ready' is non-nil." |
872 | 1033 |
873 ;(setq hide nil) ; FIXME: turn this on for debugging only | 1034 ;(setq hide nil) ; FIXME: turn this on for debugging only |
1035 ; (message "SENDING %s|||%s" cmd pcmd) ;?????????????????????? | |
874 (let (buf proc) | 1036 (let (buf proc) |
875 ;; Get or make the buffer and its process | 1037 ;; Get or make the buffer and its process |
876 (if (or (not (setq buf (get-buffer (idlwave-shell-buffer)))) | 1038 (if (or (not (setq buf (get-buffer (idlwave-shell-buffer)))) |
877 (not (setq proc (get-buffer-process buf)))) | 1039 (not (setq proc (get-buffer-process buf)))) |
878 (if (not idlwave-shell-automatic-start) | 1040 (if (not idlwave-shell-automatic-start) |
1059 When the IDL prompt is received executes `idlwave-shell-post-command-hook' | 1221 When the IDL prompt is received executes `idlwave-shell-post-command-hook' |
1060 and then calls `idlwave-shell-send-command' for any pending commands." | 1222 and then calls `idlwave-shell-send-command' for any pending commands." |
1061 ;; We no longer do the cleanup here - this is done by the process sentinel | 1223 ;; We no longer do the cleanup here - this is done by the process sentinel |
1062 (when (eq (process-status idlwave-shell-process-name) 'run) | 1224 (when (eq (process-status idlwave-shell-process-name) 'run) |
1063 ;; OK, process is still running, so we can use it. | 1225 ;; OK, process is still running, so we can use it. |
1064 (let ((data (match-data))) | 1226 (setq idlwave-shell-wd-is-synched nil) ;; something might have changed cwd |
1227 (let ((data (match-data)) p) | |
1065 (unwind-protect | 1228 (unwind-protect |
1066 (progn | 1229 (progn |
1067 ;; May change the original match data. | 1230 ;; May change the original match data. |
1068 (let (p) | 1231 (while (setq p (string-match "\C-M" string)) |
1069 (while (setq p (string-match "\C-M" string)) | 1232 (aset string p ?\ )) |
1070 (aset string p ? ))) | 1233 |
1071 ;;; Test/Debug code | |
1072 ;; (save-excursion (set-buffer (get-buffer-create "*test*")) | |
1073 ;; (goto-char (point-max)) | |
1074 ;; (insert "%%%" string)) | |
1075 ;; | 1234 ;; |
1076 ;; Keep output | 1235 ;; Keep output |
1077 | 1236 |
1078 ; Should not keep output because the concat is costly. If hidden put | 1237 ; Should not keep output because the concat is costly. If hidden put |
1079 ; the output in a hide-buffer. Then when the output is needed in post | 1238 ; the output in a hide-buffer. Then when the output is needed in post |
1082 ; is hidden and there is no post command, could throw away output. | 1241 ; is hidden and there is no post command, could throw away output. |
1083 ; (setq idlwave-shell-command-output | 1242 ; (setq idlwave-shell-command-output |
1084 ; (concat idlwave-shell-command-output string)) | 1243 ; (concat idlwave-shell-command-output string)) |
1085 ;; Insert the string. Do this before getting the | 1244 ;; Insert the string. Do this before getting the |
1086 ;; state. | 1245 ;; state. |
1246 (while (setq p (string-match "\C-G" string)) | |
1247 (ding) | |
1248 (aset string p ?\C-j )) | |
1087 (if idlwave-shell-hide-output | 1249 (if idlwave-shell-hide-output |
1088 (save-excursion | 1250 (save-excursion |
1089 (set-buffer | 1251 (set-buffer |
1090 (get-buffer-create idlwave-shell-hidden-output-buffer)) | 1252 (get-buffer-create idlwave-shell-hidden-output-buffer)) |
1091 (goto-char (point-max)) | 1253 (goto-char (point-max)) |
1092 (insert string)) | 1254 (insert string)) |
1093 (idlwave-shell-comint-filter proc string)) | 1255 (idlwave-shell-comint-filter proc string)) |
1094 ;; Watch for prompt - need to accumulate the current line | 1256 ;; Watch for magic - need to accumulate the current line |
1095 ;; since it may not be sent all at once. | 1257 ;; since it may not be sent all at once. |
1096 (if (string-match "\n" string) | 1258 (if (string-match "\n" string) |
1097 (progn | 1259 (progn |
1098 (if idlwave-shell-use-input-mode-magic | 1260 (if idlwave-shell-use-input-mode-magic |
1099 (idlwave-shell-input-mode-magic | 1261 (idlwave-shell-input-mode-magic |
1104 (match-end 0))))) | 1266 (match-end 0))))) |
1105 (setq idlwave-shell-accumulation | 1267 (setq idlwave-shell-accumulation |
1106 (concat idlwave-shell-accumulation string))) | 1268 (concat idlwave-shell-accumulation string))) |
1107 | 1269 |
1108 | 1270 |
1109 ;; Check for prompt in current line | 1271 ;;; Test/Debug code |
1272 ; (save-excursion (set-buffer | |
1273 ; (get-buffer-create "*idlwave-shell-output*")) | |
1274 ; (goto-char (point-max)) | |
1275 ; (insert "\nSTRING===>\n" string "\n<====\n")) | |
1276 | |
1277 ;; Check for prompt in current accumulating line | |
1110 (if (setq idlwave-shell-ready | 1278 (if (setq idlwave-shell-ready |
1111 (string-match idlwave-shell-prompt-pattern | 1279 (string-match idlwave-shell-prompt-pattern |
1112 idlwave-shell-accumulation)) | 1280 idlwave-shell-accumulation)) |
1113 (progn | 1281 (progn |
1114 (if idlwave-shell-hide-output | 1282 (if idlwave-shell-hide-output |
1115 (save-excursion | 1283 (save-excursion |
1116 (set-buffer idlwave-shell-hidden-output-buffer) | 1284 (set-buffer idlwave-shell-hidden-output-buffer) |
1117 (goto-char (point-min)) | 1285 ; (goto-char (point-min)) |
1118 (re-search-forward idlwave-shell-prompt-pattern nil t) | 1286 ; (re-search-forward idlwave-shell-prompt-pattern nil t) |
1287 (goto-char (point-max)) | |
1288 (re-search-backward idlwave-shell-prompt-pattern nil t) | |
1289 (goto-char (match-end 0)) | |
1119 (setq idlwave-shell-command-output | 1290 (setq idlwave-shell-command-output |
1120 (buffer-substring (point-min) (point))) | 1291 (buffer-substring (point-min) (point))) |
1292 ;; Test/Debug | |
1293 ; (save-excursion (set-buffer | |
1294 ; (get-buffer-create "*idlwave-shell-output*")) | |
1295 ; (goto-char (point-max)) | |
1296 ; (insert "\nOUPUT===>\n" idlwave-shell-command-output "\n<===\n")) | |
1297 | |
1121 (delete-region (point-min) (point))) | 1298 (delete-region (point-min) (point))) |
1122 (setq idlwave-shell-command-output | 1299 (setq idlwave-shell-command-output |
1123 (save-excursion | 1300 (save-excursion |
1124 (set-buffer | 1301 (set-buffer |
1125 (process-buffer proc)) | 1302 (process-buffer proc)) |
1127 (progn | 1304 (progn |
1128 (goto-char (process-mark proc)) | 1305 (goto-char (process-mark proc)) |
1129 (beginning-of-line nil) | 1306 (beginning-of-line nil) |
1130 (point)) | 1307 (point)) |
1131 comint-last-input-end)))) | 1308 comint-last-input-end)))) |
1132 ;;; Test/Debug code | |
1133 ;; (save-excursion (set-buffer | |
1134 ;; (get-buffer-create "*idlwave-shell-output*")) | |
1135 ;; (goto-char (point-max)) | |
1136 ;; (insert "%%%" string)) | |
1137 ;; Scan for state and do post command - bracket them | 1309 ;; Scan for state and do post command - bracket them |
1138 ;; with idlwave-shell-ready=nil since they | 1310 ;; with idlwave-shell-ready=nil since they |
1139 ;; may call idlwave-shell-send-command. | 1311 ;; may call idlwave-shell-send-command. |
1140 (let ((idlwave-shell-ready nil)) | 1312 (let ((idlwave-shell-ready nil)) |
1141 (idlwave-shell-scan-for-state) | 1313 (idlwave-shell-scan-for-state) |
1161 (win (get-buffer-window buf))) | 1333 (win (get-buffer-window buf))) |
1162 (when (get-buffer buf) | 1334 (when (get-buffer buf) |
1163 (save-excursion | 1335 (save-excursion |
1164 (set-buffer (idlwave-shell-buffer)) | 1336 (set-buffer (idlwave-shell-buffer)) |
1165 (goto-char (point-max)) | 1337 (goto-char (point-max)) |
1166 (insert (format "\n\n Process %s %s" process event)))) | 1338 (insert (format "\n\n Process %s %s" process event)) |
1339 (if (and idlwave-shell-save-command-history | |
1340 (stringp idlwave-shell-command-history-file)) | |
1341 (condition-case nil | |
1342 (comint-write-input-ring) | |
1343 (error nil))))) | |
1344 | |
1167 (when (and (> (length (frame-list)) 1) | 1345 (when (and (> (length (frame-list)) 1) |
1168 (frame-live-p idlwave-shell-idl-wframe)) | 1346 (frame-live-p idlwave-shell-idl-wframe)) |
1169 (delete-frame idlwave-shell-idl-wframe) | 1347 (delete-frame idlwave-shell-idl-wframe) |
1170 (setq idlwave-shell-idl-wframe nil | 1348 (setq idlwave-shell-idl-wframe nil |
1171 idlwave-shell-display-wframe nil)) | 1349 idlwave-shell-display-wframe nil)) |
1172 (when (window-live-p win) | 1350 (when (and (window-live-p win) |
1351 (not (one-window-p 'nomini))) | |
1173 (delete-window win)) | 1352 (delete-window win)) |
1174 (idlwave-shell-cleanup))) | 1353 (idlwave-shell-cleanup) |
1354 ;; Run the hook, if possible in the shell buffer. | |
1355 (if (get-buffer buf) | |
1356 (save-excursion | |
1357 (set-buffer buf) | |
1358 (run-hooks 'idlwave-shell-sentinel-hook)) | |
1359 (run-hooks 'idlwave-shell-sentinel-hook)))) | |
1175 | 1360 |
1176 (defun idlwave-shell-scan-for-state () | 1361 (defun idlwave-shell-scan-for-state () |
1177 "Scan for state info. | 1362 "Scan for state info. |
1178 Looks for messages in output from last IDL command indicating where | 1363 Looks for messages in output from last IDL command indicating where |
1179 IDL has stopped. The types of messages we are interested in are | 1364 IDL has stopped. The types of messages we are interested in are |
1469 (defun idlwave-shell-routine-info-filter () | 1654 (defun idlwave-shell-routine-info-filter () |
1470 "Function which parses the special output from idlwave_routine_info.pro." | 1655 "Function which parses the special output from idlwave_routine_info.pro." |
1471 (let ((text idlwave-shell-command-output) | 1656 (let ((text idlwave-shell-command-output) |
1472 (start 0) | 1657 (start 0) |
1473 sep sep-re file type spec specs name cs key keys class entry) | 1658 sep sep-re file type spec specs name cs key keys class entry) |
1659 ; (message "GOT: %s" text) ;?????????????????????? | |
1474 ;; Initialize variables | 1660 ;; Initialize variables |
1475 (setq idlwave-compiled-routines nil | 1661 (setq idlwave-compiled-routines nil |
1476 idlwave-unresolved-routines nil) | 1662 idlwave-unresolved-routines nil) |
1477 ;; Cut out the correct part of the output. | 1663 ;; Cut out the correct part of the output. |
1478 (if (string-match | 1664 (if (string-match |
1481 (setq sep (match-string 1 text) | 1667 (setq sep (match-string 1 text) |
1482 sep-re (concat (regexp-quote sep) " *") | 1668 sep-re (concat (regexp-quote sep) " *") |
1483 text (substring text (match-end 0))) | 1669 text (substring text (match-end 0))) |
1484 ;; Set dummy values and kill the text | 1670 ;; Set dummy values and kill the text |
1485 (setq sep "@" sep-re "@ *" text "") | 1671 (setq sep "@" sep-re "@ *" text "") |
1486 (message "Routine Info warning: No match for BEGIN line")) | 1672 (message "Routine Info warning: No match for BEGIN line in \n>>>>\n%s\n<<<<\n" |
1673 idlwave-shell-command-output)) | |
1487 (if (string-match "^>>>END OF IDLWAVE ROUTINE INFO.*" text) | 1674 (if (string-match "^>>>END OF IDLWAVE ROUTINE INFO.*" text) |
1488 (setq text (substring text 0 (match-beginning 0))) | 1675 (setq text (substring text 0 (match-beginning 0))) |
1489 (message "Routine Info warning: No match for END line")) | 1676 (message "Routine Info warning: No match for END line in \n>>>>\n%s\n<<<<\n" |
1677 idlwave-shell-command-output)) | |
1490 (if (string-match "\\S-" text) | 1678 (if (string-match "\\S-" text) |
1491 ;; Obviously, the pro worked. Make a note that we have it now. | 1679 ;; Obviously, the pro worked. Make a note that we have it now. |
1492 (setq idlwave-idlwave_routine_info-compiled t)) | 1680 (setq idlwave-idlwave_routine_info-compiled t)) |
1493 ;; Match the output lines | 1681 ;; Match the output lines |
1494 (while (string-match "^IDLWAVE-\\(PRO\\|FUN\\): \\(.*\\)" text start) | 1682 (while (string-match "^IDLWAVE-\\(PRO\\|FUN\\): \\(.*\\)" text start) |
1602 (defun idlwave-shell-complete-filename (&optional arg) | 1790 (defun idlwave-shell-complete-filename (&optional arg) |
1603 "Complete a file name at point if after a file name. | 1791 "Complete a file name at point if after a file name. |
1604 We assume that we are after a file name when completing one of the | 1792 We assume that we are after a file name when completing one of the |
1605 args of an executive .run, .rnew or .compile. Also, in a string | 1793 args of an executive .run, .rnew or .compile. Also, in a string |
1606 constant we complete file names. Otherwise return nil, so that | 1794 constant we complete file names. Otherwise return nil, so that |
1607 other completion functions can do thier work." | 1795 other completion functions can do their work." |
1608 (let* ((comint-file-name-chars idlwave-shell-file-name-chars) | 1796 ;; Comint does something funny with the default directory, |
1609 (completion-ignore-case (default-value 'completion-ignore-case))) | 1797 ;; so we set it here from out safe own variable |
1610 (comint-dynamic-complete-filename))) | 1798 (setq default-directory |
1799 (file-name-as-directory idlwave-shell-default-directory)) | |
1800 (if (not idlwave-shell-wd-is-synched) | |
1801 ;; Some IDL stuff has been executed since last update, so we need to | |
1802 ;; do it again. | |
1803 (idlwave-shell-send-command | |
1804 idlwave-shell-dirstack-query | |
1805 `(progn | |
1806 (idlwave-shell-filter-directory) | |
1807 (setq idlwave-shell-wd-is-synched t) | |
1808 (switch-to-buffer (idlwave-shell-buffer)) | |
1809 (goto-char ,(point)) ;; This is necesary on Emacs, don't know why | |
1810 ;; after the update, we immediately redo the completion, so the | |
1811 ;; user will hardly notice we did the update. | |
1812 (idlwave-shell-complete-filename)) | |
1813 'hide) | |
1814 (let* ((comint-file-name-chars idlwave-shell-file-name-chars) | |
1815 (completion-ignore-case (default-value 'completion-ignore-case))) | |
1816 (comint-dynamic-complete-filename)))) | |
1611 | 1817 |
1612 (defun idlwave-shell-executive-command () | 1818 (defun idlwave-shell-executive-command () |
1613 "Return the name of the current executive command, if any." | 1819 "Return the name of the current executive command, if any." |
1614 (save-excursion | 1820 (save-excursion |
1615 (idlwave-beginning-of-statement) | 1821 (idlwave-beginning-of-statement) |
2043 (defun idlwave-shell-help-expression (arg) | 2249 (defun idlwave-shell-help-expression (arg) |
2044 "Print help on current expression. See `idlwave-shell-print'." | 2250 "Print help on current expression. See `idlwave-shell-print'." |
2045 (interactive "P") | 2251 (interactive "P") |
2046 (idlwave-shell-print arg 'help)) | 2252 (idlwave-shell-print arg 'help)) |
2047 | 2253 |
2254 (defmacro idlwave-shell-mouse-examine (help &optional ev) | |
2255 "Create a function for generic examination of expressions." | |
2256 `(lambda (event) | |
2257 "Expansion function for expression examination." | |
2258 (interactive "e") | |
2259 (let ((transient-mark-mode t) | |
2260 (zmacs-regions t) | |
2261 (tracker (if (featurep 'xemacs) 'mouse-track | |
2262 'mouse-drag-region))) | |
2263 (funcall tracker event) | |
2264 (idlwave-shell-print (if (idlwave-region-active-p) '(16) nil) | |
2265 ,help ,ev)))) | |
2266 | |
2048 (defun idlwave-shell-mouse-print (event) | 2267 (defun idlwave-shell-mouse-print (event) |
2049 "Call `idlwave-shell-print' at the mouse position." | 2268 "Print value of variable at the mouse position, with `help'" |
2050 (interactive "e") | 2269 (interactive "e") |
2051 (mouse-set-point event) | 2270 (funcall (idlwave-shell-mouse-examine nil) event)) |
2052 (idlwave-shell-print nil nil 'mouse)) | |
2053 | 2271 |
2054 (defun idlwave-shell-mouse-help (event) | 2272 (defun idlwave-shell-mouse-help (event) |
2055 "Call `idlwave-shell-print' at the mouse position." | 2273 "Print value of variable at the mouse position, with `print'." |
2056 (interactive "e") | 2274 (interactive "e") |
2057 (mouse-set-point event) | 2275 (funcall (idlwave-shell-mouse-examine 'help) event)) |
2058 (idlwave-shell-print nil 'help 'mouse)) | 2276 |
2059 | 2277 (defun idlwave-shell-examine-select (event) |
2060 (defun idlwave-shell-print (arg &optional help mouse) | 2278 "Pop-up a list to select from for examining the expression" |
2061 "Print current expression. With HELP, show help on expression. | 2279 (interactive "e") |
2280 (funcall (idlwave-shell-mouse-examine nil event) event)) | |
2281 | |
2282 (defmacro idlwave-shell-examine (help) | |
2283 "Create a function for key-driven expression examination." | |
2284 `(lambda () | |
2285 (interactive) | |
2286 (idlwave-shell-print nil ,help))) | |
2287 | |
2288 (defun idlwave-shell-define-key-both (key hook) | |
2289 "Define a key in both the shell and buffer mode maps." | |
2290 (define-key idlwave-mode-map key hook) | |
2291 (define-key idlwave-shell-mode-map key hook)) | |
2292 | |
2293 (defvar idlwave-shell-examine-label nil | |
2294 "Label to include with examine text if separate.") | |
2295 | |
2296 (defun idlwave-shell-print (arg &optional help ev) | |
2297 "Print current expression. | |
2298 | |
2299 With HELP non-nil, show help on expression. If HELP is a string, | |
2300 the expression will be put in place of ___, e.g.: | |
2301 | |
2302 print,size(___,/DIMENSIONS) | |
2303 | |
2304 Otherwise, print is called on the expression. | |
2305 | |
2062 An expression is an identifier plus 1 pair of matched parentheses | 2306 An expression is an identifier plus 1 pair of matched parentheses |
2063 directly following the identifier - an array or function | 2307 directly following the identifier - an array or function call. |
2064 call. Alternatively, an expression is the contents of any matched | 2308 Alternatively, an expression is the contents of any matched |
2065 parentheses when the open parentheses is not directly preceded by an | 2309 parentheses when the open parenthesis is not directly preceded by an |
2066 identifier. If point is at the beginning or within an expression | 2310 identifier. If point is at the beginning or within an expression |
2067 return the inner-most containing expression, otherwise, return the | 2311 return the inner-most containing expression, otherwise, return the |
2068 preceding expression. | 2312 preceding expression. |
2069 | 2313 |
2070 With prefix arg ARG, or when called from the shell buffer, prompt | 2314 With prefix arg ARG prompt for an expression. |
2071 for an expression." | 2315 |
2316 With double prefix arg, use the current region. | |
2317 | |
2318 If EV is a valid event passed, pop-up a list from | |
2319 idlw-shell-examine-alist from which to select the help command text." | |
2072 (interactive "P") | 2320 (interactive "P") |
2073 (save-excursion | 2321 (save-excursion |
2074 (let (expr beg end cmd) | 2322 (let* ((process (get-buffer-process (current-buffer))) |
2075 (if (and (not mouse) | 2323 (process-mark (if process (process-mark process))) |
2076 (or arg (eq major-mode 'idlwave-shell-mode))) | 2324 (stack-label |
2077 (setq expr (read-string "Expression: ")) | 2325 (if (and (integerp idlwave-shell-calling-stack-index) |
2326 (> idlwave-shell-calling-stack-index 0)) | |
2327 (format " [-%d:%s]" | |
2328 idlwave-shell-calling-stack-index | |
2329 idlwave-shell-calling-stack-routine))) | |
2330 expr beg end cmd examine-hook) | |
2331 (cond | |
2332 ((and (equal arg '(16)) | |
2333 (< (- (region-end) (region-beginning)) 2000)) | |
2334 (setq beg (region-beginning) | |
2335 end (region-end))) | |
2336 (arg | |
2337 (setq expr (read-string "Expression: "))) | |
2338 (t | |
2078 (idlwave-with-special-syntax1 | 2339 (idlwave-with-special-syntax1 |
2079 ;; Move to beginning of current or previous expression | 2340 ;; Move to beginning of current or previous expression |
2080 (if (looking-at "\\<\\|(") | 2341 (if (looking-at "\\<\\|(") |
2081 ;; At beginning of expression, don't move backwards unless | 2342 ;; At beginning of expression, don't move backwards unless |
2082 ;; this is at the end of an indentifier. | 2343 ;; this is at the end of an indentifier. |
2091 (setq beg (point)) | 2352 (setq beg (point)) |
2092 (forward-sexp) | 2353 (forward-sexp) |
2093 (while (looking-at "\\>[[(]\\|\\.") | 2354 (while (looking-at "\\>[[(]\\|\\.") |
2094 ;; an array | 2355 ;; an array |
2095 (forward-sexp)) | 2356 (forward-sexp)) |
2096 (setq end (point)) | 2357 (setq end (point))))) |
2097 (setq expr (buffer-substring beg end)))) | 2358 |
2359 ;; Get expression, but first move the begin mark if a | |
2360 ;; process-mark is inside the region, to keep the overlay from | |
2361 ;; wandering in the Shell. | |
2362 (when (and beg end) | |
2363 (if (and process-mark (> process-mark beg) (< process-mark end)) | |
2364 (setq beg (marker-position process-mark))) | |
2365 (setq expr (buffer-substring beg end))) | |
2366 | |
2367 ;; Show the overlay(s) and attach any necessary hooks and filters | |
2098 (when (and beg end idlwave-shell-expression-overlay) | 2368 (when (and beg end idlwave-shell-expression-overlay) |
2099 (move-overlay idlwave-shell-expression-overlay beg end | 2369 (move-overlay idlwave-shell-expression-overlay beg end |
2100 (current-buffer)) | 2370 (current-buffer)) |
2101 (add-hook 'pre-command-hook 'idlwave-shell-delete-expression-overlay)) | 2371 (add-hook 'pre-command-hook |
2102 (if (and (integerp idlwave-shell-calling-stack-index) | 2372 'idlwave-shell-delete-expression-overlay)) |
2103 (> idlwave-shell-calling-stack-index 0)) | 2373 (setq examine-hook |
2374 (if idlwave-shell-separate-examine-output | |
2375 'idlwave-shell-examine-display | |
2376 'idlwave-shell-examine-highlight)) | |
2377 (add-hook 'pre-command-hook | |
2378 'idlwave-shell-delete-output-overlay) | |
2379 | |
2380 ;; Remove empty or comment-only lines | |
2381 (while (string-match "\n[ \t]*\\(;.*\\)?\r*\n" expr) | |
2382 (setq expr (replace-match "\n" t t expr))) | |
2383 ;; Concatenate continuation lines | |
2384 (while (string-match "[ \t]*\\$.*\\(;.*\\)?\\(\n[ \t]*\\|$\\)" expr) | |
2385 (setq expr (replace-match "" t t expr))) | |
2386 ;; Remove final newline | |
2387 (if (string-match "\n[ \t\r]*\\'" expr) | |
2388 (setq expr (replace-match "" t t expr))) | |
2389 ;; Pop-up the examine selection list, if appropriate | |
2390 (if (and ev idlwave-shell-examine-alist) | |
2391 (let* ((help-cons | |
2392 (assoc | |
2393 (idlwave-popup-select | |
2394 ev (mapcar 'car idlwave-shell-examine-alist) | |
2395 "Examine with") | |
2396 idlwave-shell-examine-alist))) | |
2397 (setq help (cdr help-cons)) | |
2398 (if idlwave-shell-separate-examine-output | |
2399 (setq idlwave-shell-examine-label | |
2400 (concat | |
2401 (format "==>%s<==\n%s:" expr (car help-cons)) | |
2402 stack-label "\n")))) | |
2403 (setq idlwave-shell-examine-label | |
2404 (concat | |
2405 (format "==>%s<==\n%s:" expr | |
2406 (cond ((null help) "print") | |
2407 ((stringp help) help) | |
2408 (t (symbol-name help)))) | |
2409 stack-label "\n"))) | |
2410 | |
2411 ;; Send the command | |
2412 (if stack-label | |
2104 (setq cmd (idlwave-retrieve-expression-from-level | 2413 (setq cmd (idlwave-retrieve-expression-from-level |
2105 expr | 2414 expr |
2106 idlwave-shell-calling-stack-index | 2415 idlwave-shell-calling-stack-index |
2107 idlwave-shell-calling-stack-routine | 2416 idlwave-shell-calling-stack-routine |
2108 help)) | 2417 help)) |
2109 (setq cmd (concat (if help "help," "print,") expr))) | 2418 (setq cmd (idlwave-shell-help-statement help expr))) |
2110 (if idlwave-shell-print-expression-function | 2419 ;(idlwave-shell-recenter-shell-window) |
2111 (idlwave-shell-send-command | 2420 (idlwave-shell-send-command |
2112 cmd | 2421 cmd |
2113 (list idlwave-shell-print-expression-function expr) | 2422 examine-hook |
2114 'hide) | 2423 (if idlwave-shell-separate-examine-output 'hide))))) |
2115 (idlwave-shell-recenter-shell-window) | 2424 |
2116 (idlwave-shell-send-command cmd))))) | 2425 (defvar idlwave-shell-examine-window-alist nil |
2426 "Variable to hold the win/height pairs for all *Examine* windows.") | |
2427 | |
2428 (defun idlwave-shell-examine-display () | |
2429 "View the examine command output in a separate buffer." | |
2430 (let (win cur-beg cur-end) | |
2431 (save-excursion | |
2432 (set-buffer (get-buffer-create "*Examine*")) | |
2433 (use-local-map idlwave-shell-examine-map) | |
2434 (setq buffer-read-only nil) | |
2435 (goto-char (point-max)) | |
2436 (save-restriction | |
2437 (narrow-to-region (point) (point)) | |
2438 (if (string-match "^% Syntax error." idlwave-shell-command-output) | |
2439 (insert "% Syntax error.\n") | |
2440 (insert idlwave-shell-command-output) | |
2441 ;; Just take the last bit between the prompts (if more than one). | |
2442 (let* ((end (or | |
2443 (re-search-backward idlwave-shell-prompt-pattern nil t) | |
2444 (point-max))) | |
2445 (beg (progn | |
2446 (goto-char | |
2447 (or (progn (if (re-search-backward | |
2448 idlwave-shell-prompt-pattern nil t) | |
2449 (match-end 0))) | |
2450 (point-min))) | |
2451 (re-search-forward "\n"))) | |
2452 (str (buffer-substring beg end))) | |
2453 (delete-region (point-min) (point-max)) | |
2454 (insert str) | |
2455 (if idlwave-shell-examine-label | |
2456 (progn (goto-char (point-min)) | |
2457 (insert idlwave-shell-examine-label) | |
2458 (setq idlwave-shell-examine-label nil))))) | |
2459 (setq cur-beg (point-min) | |
2460 cur-end (point-max)) | |
2461 (setq buffer-read-only t) | |
2462 (move-overlay idlwave-shell-output-overlay cur-beg cur-end | |
2463 (current-buffer)) | |
2464 | |
2465 ;; Look for the examine buffer in all windows. If one is | |
2466 ;; found in a frame all by itself, use that, otherwise, switch | |
2467 ;; to or create an examine window in this frame, and resize if | |
2468 ;; it's a newly created window | |
2469 (let* ((winlist (get-buffer-window-list "*Examine*" nil 'visible))) | |
2470 (setq win (idlwave-display-buffer | |
2471 "*Examine*" | |
2472 nil | |
2473 (let ((list winlist) thiswin) | |
2474 (catch 'exit | |
2475 (save-selected-window | |
2476 (while (setq thiswin (pop list)) | |
2477 (select-window thiswin) | |
2478 (if (one-window-p) | |
2479 (throw 'exit (window-frame thiswin))))))))) | |
2480 (set-window-start win (point-min)) ; Ensure the point is visible. | |
2481 (save-selected-window | |
2482 (select-window win) | |
2483 (let ((elt (assoc win idlwave-shell-examine-window-alist))) | |
2484 (when (and (not (one-window-p)) | |
2485 (or (not (memq win winlist)) ;a newly created window | |
2486 (eq (window-height) (cdr elt)))) | |
2487 ;; Autosize it. | |
2488 (enlarge-window (- (/ (frame-height) 2) | |
2489 (window-height))) | |
2490 (shrink-window-if-larger-than-buffer) | |
2491 ;; Clean the window list of dead windows | |
2492 (setq idlwave-shell-examine-window-alist | |
2493 (delq nil | |
2494 (mapcar (lambda (x) (if (window-live-p (car x)) x)) | |
2495 idlwave-shell-examine-window-alist))) | |
2496 ;; And add the new value. | |
2497 (if (setq elt (assoc win idlwave-shell-examine-window-alist)) | |
2498 (setcdr elt (window-height)) | |
2499 (add-to-list 'idlwave-shell-examine-window-alist | |
2500 (cons win (window-height))))))))) | |
2501 ;; Recenter for maximum output, after widened | |
2502 (save-selected-window | |
2503 (select-window win) | |
2504 (goto-char (point-max)) | |
2505 (skip-chars-backward "\n") | |
2506 (recenter -1))))) | |
2507 | |
2508 (defvar idlwave-shell-examine-map (make-sparse-keymap)) | |
2509 (define-key idlwave-shell-examine-map "q" 'idlwave-shell-examine-display-quit) | |
2510 (define-key idlwave-shell-examine-map "c" 'idlwave-shell-examine-display-clear) | |
2511 | |
2512 (defun idlwave-shell-examine-display-quit () | |
2513 (interactive) | |
2514 (let ((win (selected-window))) | |
2515 (if (one-window-p) | |
2516 (delete-frame (window-frame win)) | |
2517 (delete-window win)))) | |
2518 | |
2519 (defun idlwave-shell-examine-display-clear () | |
2520 (interactive) | |
2521 (save-excursion | |
2522 (let ((buf (get-buffer "*Examine*"))) | |
2523 (when (bufferp buf) | |
2524 (set-buffer buf) | |
2525 (setq buffer-read-only nil) | |
2526 (erase-buffer) | |
2527 (setq buffer-read-only t))))) | |
2117 | 2528 |
2118 (defun idlwave-retrieve-expression-from-level (expr level routine help) | 2529 (defun idlwave-retrieve-expression-from-level (expr level routine help) |
2119 "Return IDL command to print the expression EXPR from stack level LEVEL. | 2530 "Return IDL command to print the expression EXPR from stack level LEVEL. |
2120 | 2531 |
2121 It does not seem possible to evaluate an expression on a differnt | 2532 It does not seem possible to evaluate an expression on a differnt |
2124 calling stack. The copies are given some unlikely names on the | 2535 calling stack. The copies are given some unlikely names on the |
2125 *current* level, and the expression is then evaluated on the *current* | 2536 *current* level, and the expression is then evaluated on the *current* |
2126 level. | 2537 level. |
2127 | 2538 |
2128 Since this function depends upon the undocumented IDL routine routine_names, | 2539 Since this function depends upon the undocumented IDL routine routine_names, |
2129 there is no guarantie that this will work with future versions of IDL." | 2540 there is no guarantee that this will work with future versions of IDL." |
2130 (let ((prefix "___") ;; No real variables should starts with this. | 2541 (let ((prefix "___") ;; No real variables should starts with this. |
2131 (fetch (- 0 level)) | 2542 (fetch (- 0 level)) |
2132 (start 0) | 2543 (start 0) |
2133 var tvar fetch-vars pre post) | 2544 var tvar fetch-vars pre post) |
2134 | 2545 |
2135 ;; FIXME: In the following we try to find the variables in expression | 2546 ;; FIXME: In the following we try to find the variables in expression |
2136 ;; This is quite empirical - I don't know in what situations this will | 2547 ;; This is quite empirical - I don't know in what situations this will |
2137 ;; break. We will look for identifiers and exclude cases where we | 2548 ;; break. We will look for identifiers and exclude cases where we |
2138 ;; know it is not a variable. To distinguish array references from | 2549 ;; know it is not a variable. To distinguish array references from |
2139 ;; function calls, we require that arrays use [] instead of () | 2550 ;; function calls, we require that arrays use [] instead of () |
2140 | 2551 |
2141 (while (string-match | 2552 (while (string-match |
2142 "\\(\\`\\|[^a-zA-Z0-9$_]\\)\\([a-zA-Z][a-zA-Z0-9$_]*\\)\\([^a-zA-Z0-9$_]\\|\\'\\)" expr start) | 2553 "\\(\\`\\|[^a-zA-Z0-9$_]\\)\\([a-zA-Z][a-zA-Z0-9$_]*\\)\\([^a-zA-Z0-9$_]\\|\\'\\)" expr start) |
2143 (setq var (match-string 2 expr) | 2554 (setq var (match-string 2 expr) |
2144 tvar (concat prefix var) | 2555 tvar (concat prefix var) |
2145 start (match-beginning 2) | 2556 start (match-beginning 2) |
2146 pre (substring expr 0 (match-beginning 2)) | 2557 pre (substring expr 0 (match-beginning 2)) |
2147 post (substring expr (match-end 2))) | 2558 post (substring expr (match-end 2))) |
2148 (cond | 2559 (cond |
2149 ;; Exclude identifiers which are not variables | 2560 ;; Exclude identifiers which are not variables |
2150 ((string-match ",[ \t]*/\\'" pre)) ;; a `/' KEYWORD | 2561 ((string-match ",[ \t]*/\\'" pre)) ;; a `/' KEYWORD |
2151 ((and (string-match "[,(][ \t]*\\'" pre) | 2562 ((and (string-match "[,(][ \t]*\\'" pre) |
2152 (string-match "\\`[ \t]*=" post))) ;; a `=' KEYWORD | 2563 (string-match "\\`[ \t]*=" post))) ;; a `=' KEYWORD |
2153 ((string-match "\\`(" post)) ;; a function | 2564 ((string-match "\\`(" post)) ;; a function |
2154 ((string-match "->[ \t]*\\'" pre)) ;; a method | 2565 ((string-match "->[ \t]*\\'" pre)) ;; a method |
2155 ((string-match "\\.\\'" pre)) ;; structure member | 2566 ((string-match "\\.\\'" pre)) ;; structure member |
2156 (t ;; seems to be a variable - arrange to get it and replace | 2567 (t ;; seems to be a variable - arrange to get it and replace |
2157 ;; its name in the expression with the temproary name. | 2568 ;; its name in the expression with the temproary name. |
2158 (push (cons var tvar) fetch-vars) | 2569 (push (cons var tvar) fetch-vars) |
2159 (setq expr (concat pre tvar post))))) | 2570 (setq expr (concat pre tvar post)))) |
2571 (if (= start 0) (setq start 1))) | |
2160 ;; Make a command line that first copies the relevant variables | 2572 ;; Make a command line that first copies the relevant variables |
2161 ;; and then prints the expression. | 2573 ;; and then prints the expression. |
2162 (concat | 2574 (concat |
2163 (mapconcat | 2575 (mapconcat |
2164 (lambda (x) | 2576 (lambda (x) |
2165 (format "%s = routine_names('%s',fetch=%d)" (cdr x) (car x) fetch)) | 2577 (format "%s = routine_names('%s',fetch=%d)" (cdr x) (car x) fetch)) |
2166 (nreverse fetch-vars) | 2578 (nreverse fetch-vars) |
2167 " & ") | 2579 " & ") |
2168 (if idlwave-shell-print-expression-function " & " "\n") | 2580 "\n" |
2169 (if help "help, " "print, ") | 2581 (idlwave-shell-help-statement help expr) |
2170 expr | |
2171 (format " ; [-%d:%s]" level routine)))) | 2582 (format " ; [-%d:%s]" level routine)))) |
2172 | 2583 |
2584 (defun idlwave-shell-help-statement (help expr) | |
2585 "Construct a help statement for printing expression EXPR. | |
2586 | |
2587 HELP can be non-nil for `help,', nil for 'print,' or any string into which | |
2588 to insert expression in place of the marker ___, e.g.: print, | |
2589 size(___,/DIMENSIONS)" | |
2590 (cond | |
2591 ((null help) (concat "print, " expr)) | |
2592 ((stringp help) | |
2593 (if (string-match "\\(^\\|[^_]\\)\\(___\\)\\([^_]\\|$\\)" help) | |
2594 (concat (substring help 0 (match-beginning 2)) | |
2595 expr | |
2596 (substring help (match-end 2))))) | |
2597 (t (concat "help, " expr)))) | |
2598 | |
2599 | |
2600 (defun idlwave-shell-examine-highlight () | |
2601 "Highlight the most recent IDL output." | |
2602 (let* ((buffer (get-buffer (idlwave-shell-buffer))) | |
2603 (process (get-buffer-process buffer)) | |
2604 (process-mark (if process (process-mark process))) | |
2605 output-begin output-end) | |
2606 (save-excursion | |
2607 (set-buffer buffer) | |
2608 (goto-char process-mark) | |
2609 (beginning-of-line) | |
2610 (setq output-end (point)) | |
2611 (re-search-backward idlwave-shell-prompt-pattern nil t) | |
2612 (beginning-of-line 2) | |
2613 (setq output-begin (point))) | |
2614 | |
2615 ;; First make sure the shell window is visible | |
2616 (idlwave-display-buffer (idlwave-shell-buffer) | |
2617 nil (idlwave-shell-shell-frame)) | |
2618 (if (and idlwave-shell-output-overlay process-mark) | |
2619 (move-overlay idlwave-shell-output-overlay | |
2620 output-begin output-end buffer)))) | |
2621 | |
2622 (defun idlwave-shell-delete-output-overlay () | |
2623 (if (eq this-command 'idlwave-shell-mouse-nop) | |
2624 nil | |
2625 (condition-case nil | |
2626 (if idlwave-shell-output-overlay | |
2627 (delete-overlay idlwave-shell-output-overlay)) | |
2628 (error nil)) | |
2629 (remove-hook 'pre-command-hook 'idlwave-shell-delete-output-overlay))) | |
2630 | |
2173 (defun idlwave-shell-delete-expression-overlay () | 2631 (defun idlwave-shell-delete-expression-overlay () |
2174 (condition-case nil | 2632 (if (eq this-command 'idlwave-shell-mouse-nop) |
2175 (if idlwave-shell-expression-overlay | 2633 nil |
2176 (delete-overlay idlwave-shell-expression-overlay)) | 2634 (condition-case nil |
2177 (error nil)) | 2635 (if idlwave-shell-expression-overlay |
2178 (remove-hook 'pre-command-hook 'idlwave-shell-delete-expression-overlay)) | 2636 (delete-overlay idlwave-shell-expression-overlay)) |
2637 (error nil)) | |
2638 (remove-hook 'pre-command-hook 'idlwave-shell-delete-expression-overlay))) | |
2179 | 2639 |
2180 (defvar idlwave-shell-bp-alist nil | 2640 (defvar idlwave-shell-bp-alist nil |
2181 "Alist of breakpoints. | 2641 "Alist of breakpoints. |
2182 A breakpoint is a cons cell \(\(file line\) . \(\(index module\) data\)\) | 2642 A breakpoint is a cons cell \(\(file line\) . \(\(index module\) data\)\) |
2183 | 2643 |
2211 If there is a prefix argument, display IDL process." | 2671 If there is a prefix argument, display IDL process." |
2212 (interactive "r\nP") | 2672 (interactive "r\nP") |
2213 (let ((oldbuf (current-buffer))) | 2673 (let ((oldbuf (current-buffer))) |
2214 (save-excursion | 2674 (save-excursion |
2215 (set-buffer (idlwave-find-file-noselect | 2675 (set-buffer (idlwave-find-file-noselect |
2216 idlwave-shell-temp-pro-file 'tmp)) | 2676 (idlwave-shell-temp-file 'pro) 'tmp)) |
2677 (set (make-local-variable 'comment-start-skip) ";+[ \t]*") | |
2678 (set (make-local-variable 'comment-start) ";") | |
2217 (erase-buffer) | 2679 (erase-buffer) |
2218 (insert-buffer-substring oldbuf beg end) | 2680 (insert-buffer-substring oldbuf beg end) |
2219 (if (not (save-excursion | 2681 (if (not (save-excursion |
2220 (idlwave-previous-statement) | 2682 (idlwave-previous-statement) |
2221 (idlwave-look-at "\\<end\\>"))) | 2683 (idlwave-look-at "\\<end\\>"))) |
2251 (condition-case nil | 2713 (condition-case nil |
2252 (delete-file idlwave-shell-temp-rinfo-save-file) | 2714 (delete-file idlwave-shell-temp-rinfo-save-file) |
2253 (error nil)))) | 2715 (error nil)))) |
2254 | 2716 |
2255 (defun idlwave-display-buffer (buf not-this-window-p &optional frame) | 2717 (defun idlwave-display-buffer (buf not-this-window-p &optional frame) |
2256 (if (or (< emacs-major-version 20) | 2718 (if (not (frame-live-p frame)) (setq frame nil)) |
2257 (and (= emacs-major-version 20) | 2719 (display-buffer buf not-this-window-p frame)) |
2258 (< emacs-minor-version 3))) | |
2259 ;; Only two args. | |
2260 (display-buffer buf not-this-window-p) | |
2261 ;; Three ares possible. | |
2262 (display-buffer buf not-this-window-p frame))) | |
2263 | 2720 |
2264 (defvar idlwave-shell-bp-buffer " *idlwave-shell-bp*" | 2721 (defvar idlwave-shell-bp-buffer " *idlwave-shell-bp*" |
2265 "Scratch buffer for parsing IDL breakpoint lists and other stuff.") | 2722 "Scratch buffer for parsing IDL breakpoint lists and other stuff.") |
2266 | 2723 |
2267 (defun idlwave-shell-bp-query () | 2724 (defun idlwave-shell-bp-query () |
2300 (set-buffer (get-buffer-create idlwave-shell-bp-buffer)) | 2757 (set-buffer (get-buffer-create idlwave-shell-bp-buffer)) |
2301 (erase-buffer) | 2758 (erase-buffer) |
2302 (insert idlwave-shell-command-output) | 2759 (insert idlwave-shell-command-output) |
2303 (goto-char (point-min)) | 2760 (goto-char (point-min)) |
2304 (let ((old-bp-alist idlwave-shell-bp-alist) | 2761 (let ((old-bp-alist idlwave-shell-bp-alist) |
2305 file line index module) | 2762 ;; Searching the breakpoints |
2763 ;; In IDL 5.5, the breakpoint reporting format changed. | |
2764 (bp-re54 "^[ \t]*\\([0-9]+\\)[ \t]+\\(\\S-+\\)?[ \t]+\\([0-9]+\\)[ \t]+\\(\\S-+\\)") | |
2765 (bp-re55 "^\\s-*\\([0-9]+\\)\\s-+\\([0-9]+\\)\\s-+\\(Uncompiled\\|Func=\\|Pro=\\)\\(\\S-+\\)?\\s-+\\(\\S-+\\)") | |
2766 file line index module | |
2767 bp-re indmap) | |
2306 (setq idlwave-shell-bp-alist (list nil)) | 2768 (setq idlwave-shell-bp-alist (list nil)) |
2307 (when (re-search-forward "^\\s-*Index.*\n\\s-*-" nil t) | 2769 ;; Search for either header type, and set the correct regexp |
2770 (when (or | |
2771 (if (re-search-forward "^\\s-*Index.*\n\\s-*-" nil t) | |
2772 (setq bp-re bp-re54 ; versions <= 5.4 | |
2773 indmap '(1 2 3 4))) | |
2774 (if (re-search-forward | |
2775 "^\\s-*Index\\s-*Line\\s-*Attributes\\s-*File" nil t) | |
2776 (setq bp-re bp-re55 ; versions >= 5.5 | |
2777 indmap '(1 4 2 5)))) | |
2308 ;; There seems to be a breakpoint listing here. | 2778 ;; There seems to be a breakpoint listing here. |
2309 ;; Parse breakpoint lines. | 2779 ;; Parse breakpoint lines. |
2310 ;; Breakpoints have the form: | 2780 ;; Breakpoints have the form |
2781 ;; for IDL<=v5.4: | |
2311 ;; Index Module Line File | 2782 ;; Index Module Line File |
2312 ;; All seperated by whitespace. | 2783 ;; All separated by whitespace. |
2313 ;; Module may be missing if the file is not compiled. | 2784 ;; Module may be missing if the file is not compiled. |
2314 ;; | 2785 ;; for IDL>=v5.5: |
2315 (while (re-search-forward | 2786 ;; Index Line Attributes File |
2316 "^[ \t]*\\([0-9]+\\)[ \t]+\\(\\S-+\\)?[ \t]+\\([0-9]+\\)[ \t]+\\(\\S-+\\)" nil t) | 2787 ;; (attributes replaces module, "Uncompiled" included) |
2317 (setq index (match-string 1) | 2788 (while (re-search-forward bp-re nil t) |
2318 module (match-string 2) | 2789 (setq index (match-string (nth 0 indmap)) |
2319 line (string-to-int (match-string 3)) | 2790 module (match-string (nth 1 indmap)) |
2320 file (idlwave-shell-file-name (match-string 4))) | 2791 line (string-to-int (match-string (nth 2 indmap))) |
2792 file (idlwave-shell-file-name (match-string (nth 3 indmap)))) | |
2321 ;; Add the breakpoint info to the list | 2793 ;; Add the breakpoint info to the list |
2322 (nconc idlwave-shell-bp-alist | 2794 (nconc idlwave-shell-bp-alist |
2323 (list (cons (list file line) | 2795 (list (cons (list file line) |
2324 (list | 2796 (list |
2325 (list index module) | 2797 (list index module) |
2370 "Try to set a breakpoint BP. | 2842 "Try to set a breakpoint BP. |
2371 | 2843 |
2372 The breakpoint will be placed at the beginning of the statement on the | 2844 The breakpoint will be placed at the beginning of the statement on the |
2373 line specified by BP or at the next IDL statement if that line is not | 2845 line specified by BP or at the next IDL statement if that line is not |
2374 a statement. | 2846 a statement. |
2375 Determines IDL's internal representation for the breakpoint which may | 2847 Determines IDL's internal representation for the breakpoint, which may |
2376 have occurred at a different line then used with the breakpoint | 2848 have occurred at a different line than used with the breakpoint |
2377 command." | 2849 command." |
2378 | 2850 |
2379 ;; Get and save the old breakpoints | 2851 ;; Get and save the old breakpoints |
2380 (idlwave-shell-send-command | 2852 (idlwave-shell-send-command |
2381 idlwave-shell-bp-query | 2853 idlwave-shell-bp-query |
2382 '(progn | 2854 '(progn |
2383 (idlwave-shell-filter-bp) | 2855 (idlwave-shell-filter-bp) |
2384 (setq idlwave-shell-old-bp idlwave-shell-bp-alist)) | 2856 (setq idlwave-shell-old-bp idlwave-shell-bp-alist)) |
2385 'hide) | 2857 'hide) |
2386 ;; Get sources for IDL compiled procedures followed by setting | 2858 ;; Get sources for IDL compiled procedures followed by setting |
2387 ;; breakpoint. | 2859 ;; breakpoint. |
2388 (idlwave-shell-send-command | 2860 (idlwave-shell-send-command |
2389 idlwave-shell-sources-query | 2861 idlwave-shell-sources-query |
2390 `(progn | 2862 `(progn |
2391 (idlwave-shell-sources-filter) | 2863 (idlwave-shell-sources-filter) |
2392 (idlwave-shell-set-bp2 (quote ,bp))) | 2864 (idlwave-shell-set-bp2 (quote ,bp))) |
2393 'hide)) | 2865 'hide)) |
2394 | 2866 |
2395 (defun idlwave-shell-set-bp2 (bp) | 2867 (defun idlwave-shell-set-bp2 (bp) |
2396 "Use results of breakpoint and sources query to set bp. | 2868 "Use results of breakpoint and sources query to set bp. |
2397 Use the count argument with IDLs breakpoint command. | 2869 Use the count argument with IDLs breakpoint command. |
2617 (memq 'compile-buffer idlwave-auto-routine-info-updates)) | 3089 (memq 'compile-buffer idlwave-auto-routine-info-updates)) |
2618 idlwave-query-shell-for-routine-info | 3090 idlwave-query-shell-for-routine-info |
2619 idlwave-routines) | 3091 idlwave-routines) |
2620 (idlwave-shell-update-routine-info t))) | 3092 (idlwave-shell-update-routine-info t))) |
2621 | 3093 |
2622 (defvar idlwave-shell-sources-query "help,/source" | 3094 (defvar idlwave-shell-sources-query "help,/source,/full" |
2623 "IDL command to obtain source files for compiled procedures.") | 3095 "IDL command to obtain source files for compiled procedures.") |
2624 | 3096 |
2625 (defvar idlwave-shell-sources-alist nil | 3097 (defvar idlwave-shell-sources-alist nil |
2626 "Alist of IDL procedure names and compiled source files. | 3098 "Alist of IDL procedure names and compiled source files. |
2627 Elements of the alist have the form: | 3099 Elements of the alist have the form: |
2744 "If `idlwave-shell-use-truename' is non-nil, convert file name to true name. | 3216 "If `idlwave-shell-use-truename' is non-nil, convert file name to true name. |
2745 Otherwise, just expand the file name." | 3217 Otherwise, just expand the file name." |
2746 (let ((def-dir (if (eq major-mode 'idlwave-shell-mode) | 3218 (let ((def-dir (if (eq major-mode 'idlwave-shell-mode) |
2747 default-directory | 3219 default-directory |
2748 idlwave-shell-default-directory))) | 3220 idlwave-shell-default-directory))) |
2749 (if idlwave-shell-use-truename | 3221 (if idlwave-shell-use-truename |
2750 (file-truename name def-dir) | 3222 (file-truename name def-dir) |
2751 (expand-file-name name def-dir)))) | 3223 (expand-file-name name def-dir)))) |
2752 | |
2753 | 3224 |
2754 ;; Keybindings -------------------------------------------------------------- | 3225 ;; Keybindings -------------------------------------------------------------- |
2755 | 3226 |
2756 (defvar idlwave-shell-mode-map (copy-keymap comint-mode-map) | 3227 (defvar idlwave-shell-mode-map (copy-keymap comint-mode-map) |
2757 "Keymap for idlwave-mode.") | 3228 "Keymap for idlwave-mode.") |
2775 'idlwave-shell-debug-map) | 3246 'idlwave-shell-debug-map) |
2776 (define-key idlwave-shell-mode-map [(up)] 'idlwave-shell-up-or-history) | 3247 (define-key idlwave-shell-mode-map [(up)] 'idlwave-shell-up-or-history) |
2777 (define-key idlwave-shell-mode-map [(down)] 'idlwave-shell-down-or-history) | 3248 (define-key idlwave-shell-mode-map [(down)] 'idlwave-shell-down-or-history) |
2778 (define-key idlwave-mode-map "\C-c\C-y" 'idlwave-shell-char-mode-loop) | 3249 (define-key idlwave-mode-map "\C-c\C-y" 'idlwave-shell-char-mode-loop) |
2779 (define-key idlwave-mode-map "\C-c\C-x" 'idlwave-shell-send-char) | 3250 (define-key idlwave-mode-map "\C-c\C-x" 'idlwave-shell-send-char) |
2780 (define-key idlwave-mode-map | 3251 |
2781 (if (featurep 'xemacs) [(shift button2)] [(shift mouse-2)]) | 3252 ;; The mouse bindings for PRINT and HELP |
2782 'idlwave-shell-mouse-print) | 3253 (idlwave-shell-define-key-both |
2783 (define-key idlwave-mode-map | 3254 (if (featurep 'xemacs) |
2784 (if (featurep 'xemacs) [(shift control button2)] [(shift control mouse-2)]) | 3255 [(shift button2)] |
3256 [(shift down-mouse-2)]) | |
3257 'idlwave-shell-mouse-print) | |
3258 (idlwave-shell-define-key-both | |
3259 (if (featurep 'xemacs) | |
3260 [(control meta button2)] | |
3261 [(control meta down-mouse-2)]) | |
2785 'idlwave-shell-mouse-help) | 3262 'idlwave-shell-mouse-help) |
3263 (idlwave-shell-define-key-both | |
3264 (if (featurep 'xemacs) | |
3265 [(control shift button2)] | |
3266 [(control shift down-mouse-2)]) | |
3267 'idlwave-shell-examine-select) | |
3268 ;; Add this one from the idlwave-mode-map | |
2786 (define-key idlwave-shell-mode-map | 3269 (define-key idlwave-shell-mode-map |
2787 (if (featurep 'xemacs) [(shift button2)] [(shift mouse-2)]) | 3270 (if (featurep 'xemacs) |
2788 'idlwave-shell-mouse-print) | 3271 [(shift button3)] |
2789 (define-key idlwave-shell-mode-map | 3272 [(shift mouse-3)]) |
2790 (if (featurep 'xemacs) [(shift control button2)] [(shift control mouse-2)]) | |
2791 'idlwave-shell-mouse-help) | |
2792 (define-key idlwave-shell-mode-map | |
2793 (if (featurep 'xemacs) [(shift button3)] [(shift mouse-3)]) | |
2794 'idlwave-mouse-context-help) | 3273 'idlwave-mouse-context-help) |
2795 | 3274 |
2796 | 3275 ;; For Emacs, we need to turn off the button release events. |
3276 (defun idlwave-shell-mouse-nop (event) | |
3277 (interactive "e")) | |
3278 (unless (featurep 'xemacs) | |
3279 (idlwave-shell-define-key-both | |
3280 [(shift mouse-2)] 'idlwave-shell-mouse-nop) | |
3281 (idlwave-shell-define-key-both | |
3282 [(shift control mouse-2)] 'idlwave-shell-mouse-nop) | |
3283 (idlwave-shell-define-key-both | |
3284 [(control meta mouse-2)] 'idlwave-shell-mouse-nop)) | |
3285 | |
3286 | |
2797 ;; The following set of bindings is used to bind the debugging keys. | 3287 ;; The following set of bindings is used to bind the debugging keys. |
2798 ;; If `idlwave-shell-activate-prefix-keybindings' is non-nil, the first key | 3288 ;; If `idlwave-shell-activate-prefix-keybindings' is non-nil, the first key |
2799 ;; in the list gets bound the C-c C-d prefix map. | 3289 ;; in the list gets bound the C-c C-d prefix map. |
2800 ;; If `idlwave-shell-debug-modifiers' is non-nil, the second key | 3290 ;; If `idlwave-shell-debug-modifiers' is non-nil, the second key |
2801 ;; in the list gets bound with the specified modifiers in both | 3291 ;; in the list gets bound with the specified modifiers in both |
2992 "The glyph to mark breakpoint lines in the source code.") | 3482 "The glyph to mark breakpoint lines in the source code.") |
2993 | 3483 |
2994 (let ((image-string "/* XPM */ | 3484 (let ((image-string "/* XPM */ |
2995 static char * file[] = { | 3485 static char * file[] = { |
2996 \"14 12 3 1\", | 3486 \"14 12 3 1\", |
2997 \" c #FFFFFFFFFFFF s backgroundColor\", | 3487 \" c None s backgroundColor\", |
2998 \". c #4B4B4B4B4B4B\", | 3488 \". c #4B4B4B4B4B4B\", |
2999 \"R c #FFFF00000000\", | 3489 \"R c #FFFF00000000\", |
3000 \" \", | 3490 \" \", |
3001 \" \", | 3491 \" \", |
3002 \" RRRR \", | 3492 \" RRRR \", |
3015 (featurep 'xpm)) | 3505 (featurep 'xpm)) |
3016 (make-glyph image-string)) | 3506 (make-glyph image-string)) |
3017 ((and (not (featurep 'xemacs)) | 3507 ((and (not (featurep 'xemacs)) |
3018 (fboundp 'image-type-available-p) | 3508 (fboundp 'image-type-available-p) |
3019 (image-type-available-p 'xpm)) | 3509 (image-type-available-p 'xpm)) |
3020 (list 'image :type 'xpm :data image-string)) | 3510 (list 'image :type 'xpm :data image-string :ascent 'center)) |
3021 (t nil)))) | 3511 (t nil)))) |
3022 | 3512 |
3023 (provide 'idlw-shell) | 3513 (provide 'idlw-shell) |
3024 (provide 'idlwave-shell) | 3514 (provide 'idlwave-shell) |
3025 | 3515 |