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