Mercurial > emacs
diff 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 |
line wrap: on
line diff
--- a/lisp/progmodes/idlw-shell.el Thu Jul 18 18:57:28 2002 +0000 +++ b/lisp/progmodes/idlw-shell.el Thu Jul 18 18:58:07 2002 +0000 @@ -1,10 +1,11 @@ -;;; idlw-shell.el --- run IDL or WAVE as an inferior process of Emacs -;; Copyright (c) 1999, 2000 Free Software Foundation - -;; Author: Chris Chase <chase@att.com> -;; Maintainer: John-David Smith <jdsmith@astro.cornell.edu> -;; Version: 4.7 -;; Date: $Date: 2002/07/09 10:47:02 $ +;; idlw-shell.el --- run IDL as an inferior process of Emacs. +;; Copyright (c) 1999, 2000, 2001 Free Software Foundation + +;; Author: Carsten Dominik <dominik@astro.uva.nl> +;; Chris Chase <chase@att.com> +;; Maintainer: J.D. Smith <jdsmith@as.arizona.edu> +;; Version: 4.14 +;; Date: $Date: 2002/06/14 19:05:30 $ ;; Keywords: processes ;; This file is part of GNU Emacs. @@ -25,10 +26,10 @@ ;; Boston, MA 02111-1307, USA. ;;; Commentary: - -;; This mode is for IDL version 4 or later. It should work on Emacs -;; or XEmacs version 19 or later. - +;; +;; This mode is for IDL version 5 or later. It should work on +;; Emacs>20.3 or XEmacs>20.4. +;; ;; Runs IDL as an inferior process of Emacs, much like the emacs ;; `shell' or `telnet' commands. Provides command history and ;; searching. Provides debugging commands available in buffers @@ -37,7 +38,11 @@ ;; visual line pointer for current execution line, etc. ;; ;; Documentation should be available online with `M-x idlwave-info'. - +;; +;; New versions of IDLWAVE, documentation, and more information +;; available from: +;; http://idlwave.org +;; ;; INSTALLATION: ;; ============= ;; @@ -54,7 +59,7 @@ ;; The newest version of this file can be found on the maintainers ;; web site. ;; -;; http://www.strw.leidenuniv.el/~dominik/Tools/idlwave +;; http://idlwave.org ;; ;; DOCUMENTATION ;; ============= @@ -88,7 +93,6 @@ ;; ;;-------------------------------------------------------------------------- ;; -;; ;;; Code: @@ -99,17 +103,17 @@ (defvar idlwave-shell-have-new-custom nil) (eval-and-compile - ;; Kludge to allow `defcustom' for Emacs 19. - (condition-case () (require 'custom) (error nil)) - (if (and (featurep 'custom) - (fboundp 'custom-declare-variable) - (fboundp 'defface)) - ;; We've got what we needed - (setq idlwave-shell-have-new-custom t) - ;; We have the old or no custom-library, hack around it! - (defmacro defgroup (&rest args) nil) - (defmacro defcustom (var value doc &rest args) - `(defvar ,var ,value ,doc)))) + ;; Kludge to allow `defcustom' for Emacs 19. + (condition-case () (require 'custom) (error nil)) + (if (and (featurep 'custom) + (fboundp 'custom-declare-variable) + (fboundp 'defface)) + ;; We've got what we needed + (setq idlwave-shell-have-new-custom t) + ;; We have the old or no custom-library, hack around it! + (defmacro defgroup (&rest args) nil) + (defmacro defcustom (var value doc &rest args) + `(defvar ,var ,value ,doc)))) ;;; Customizations: idlwave-shell group @@ -141,9 +145,25 @@ "Initial commands, separated by newlines, to send to IDL. This string is sent to the IDL process by `idlwave-shell-mode' which is invoked by `idlwave-shell'." - :group 'idlwave-shell-initial-commands + :group 'idlwave-shell-general-setup :type 'string) +(defcustom idlwave-shell-save-command-history t + "Non-nil means preserve command history between sessions. +The file `idlwave-shell-command-history-file' is used to save and restore +the history." + :group 'idlwave-shell-general-setup + :type 'boolean) + +(defcustom idlwave-shell-command-history-file "~/.idlwhist" + "The file in which the command history of the idlwave shell is saved. +In order to change the size of the history, see the variable +`comint-input-ring-size'. +The history is only saved if the variable `idlwave-shell-save-command-history' +is non-nil." + :group 'idlwave-shell-general-setup + :type 'file) + (defcustom idlwave-shell-use-dedicated-frame nil "*Non-nil means, IDLWAVE should use a special frame to display shell buffer." :group 'idlwave-shell-general-setup @@ -158,6 +178,11 @@ :type '(repeat (cons symbol sexp))) +(defcustom idlwave-shell-raise-frame t + "*Non-nil means, `idlwave-shell' raises the frame showing the shell window." + :group 'idlwave-shell-general-setup + :type 'boolean) + (defcustom idlwave-shell-arrows-do-history t "*Non-nil means UP and DOWN arrows move through command history. This variable can have 3 values: @@ -172,6 +197,21 @@ (const :tag "everywhere" t) (const :tag "in command line only" cmdline))) +;; FIXME: add comint-input-ring-size? +(defcustom idlwave-shell-comint-settings + '((comint-scroll-to-bottom-on-input . t) + (comint-scroll-to-bottom-on-output . nil) + (comint-scroll-show-maximum-output . t) + ) + "Alist of special settings for the comint variables in the IDLWAVE Shell. +Each entry is a cons cell with the name of a variable and a value. +The function `idlwave-shell-mode' will make local variables out of each entry. +Changes to this variable will only be active when the shell buffer is +newly created." + :group 'idlwave-shell-general-setup + :type '(repeat + (cons variable sexp))) + (defcustom idlwave-shell-use-toolbar t "*Non-nil means, use the debugging toolbar in all IDL related buffers. Starting the shell will then add the toolbar to all idlwave-mode buffers. @@ -185,7 +225,7 @@ (defcustom idlwave-shell-temp-pro-prefix "/tmp/idltemp" "*The prefix for temporary IDL files used when compiling regions. It should be an absolute pathname. -The full temporary file name is obtained by to using `make-temp-name' +The full temporary file name is obtained by using `make-temp-file' so that the name will be unique among multiple Emacs processes." :group 'idlwave-shell-general-setup :type 'string) @@ -240,15 +280,36 @@ :group 'idlwave-shell-general-setup :type 'hook) -(defcustom idlwave-shell-print-expression-function nil - "When non-nil, a function to handle display of evaluated expressions. -This can be used to arrange for displaying the value of an expression -in (e.g.) a special frame. The function must accept one argument: -the expression which was evaluated. The output from IDL will be -available in the variable `idlwave-shell-command-output'." - :group 'idlwave-shell-highlighting-and-faces - :type 'symbol) - +(defvar idlwave-shell-print-expression-function nil + "*OBSOLETE VARIABLE, is no longer used.") + +(defcustom idlwave-shell-examine-alist + '(("Print" . "print,___") + ("Help" . "help,___") + ("Structure Help" . "help,___,/STRUCTURE") + ("Dimensions" . "print,size(___,/DIMENSIONS)") + ("Type" . "print,size(___,/TNAME)") + ("N_Elements" . "print,n_elements(___)") + ("All Size Info" . "help,(__IWsz__=size(___,/STRUCTURE)),/STRUCTURE & print,__IWsz__.DIMENSIONS") + ("Ptr Valid" . "print,ptr_valid(___)") + ("Widget Valid" . "print,widget_info(___,/VALID)") + ("Widget Geometry" . "help,widget_info(___,/GEOMETRY)")) + "Alist of special examine commands for popup selection. +The keys are used in the selection popup created by +`idlwave-shell-examine-select', and the corresponding value is sent as +a command to the shell, with special sequence `___' replaced by the +expression being examined." + :group 'idlwave-shell-general-setup + :type '(repeat + (cons + (string :tag "Label ") + (string :tag "Command")))) + +(defcustom idlwave-shell-separate-examine-output t + "*Non-nil mean, put output of examine commands in their own buffer." + :group 'idlwave-shell-general-setup + :type 'boolean) + (defcustom idlwave-shell-use-input-mode-magic nil "*Non-nil means, IDLWAVE should check for input mode spells in output. The spells are strings printed by your IDL program and matched @@ -346,7 +407,7 @@ The overlay-arrow has the disadvantage to hide the first chars of a line. Since many people do not have the main block of IDL programs indented, a face highlighting may be better. -On Emacs 21, the overlay arrow is displayed in a special area and never +In Emacs 21, the overlay arrow is displayed in a special area and never hides any code, so setting this to 'arrow on Emacs 21 sounds like a good idea." :group 'idlwave-shell-highlighting-and-faces :type '(choice @@ -413,33 +474,78 @@ :group 'idlwave-shell-highlighting-and-faces :type 'symbol) +(defcustom idlwave-shell-output-face 'secondary-selection + "*The face for `idlwave-shell-output-overlay'. +Allows you to choose the font, color and other properties for +the expression output by IDL." + :group 'idlwave-shell-highlighting-and-faces + :type 'symbol) + ;;; End user customization variables ;;; External variables (defvar comint-last-input-start) (defvar comint-last-input-end) +(defun idlwave-shell-temp-file (type) + "Return a temp file, creating it if necessary. + +TYPE is either 'pro or 'rinfo, and idlwave-shell-temp-pro-file or +idlwave-shell-temp-rinfo-save-file is set (respectively)." + (cond + ((eq type 'rinfo) + (or idlwave-shell-temp-rinfo-save-file + (setq idlwave-shell-temp-rinfo-save-file + (idlwave-shell-make-temp-file idlwave-shell-temp-pro-prefix)))) + ((eq type 'pro) + (or idlwave-shell-temp-pro-file + (setq idlwave-shell-temp-pro-file + (idlwave-shell-make-temp-file idlwave-shell-temp-pro-prefix)))) + (t (error "Wrong argument (idlwave-shell-temp-file): %s" + (symbol-name type))))) + + +(defun idlwave-shell-make-temp-file (prefix) + "Create a temporary file." + ; Hard coded make-temp-file for Emacs<21 + (if (fboundp 'make-temp-file) + (make-temp-file prefix) + (let (file + (temp-file-dir (if (boundp 'temporary-file-directory) + temporary-file-directory + "/tmp"))) + (while (condition-case () + (progn + (setq file + (make-temp-name + (expand-file-name prefix temp-file-dir))) + (if (featurep 'xemacs) + (write-region "" nil file nil 'silent nil) + (write-region "" nil file nil 'silent nil 'excl)) + nil) + (file-already-exists t)) + ;; the file was somehow created by someone else between + ;; `make-temp-name' and `write-region', let's try again. + nil) + file))) + ;; Other variables - -(defvar idlwave-shell-temp-file-base - (make-temp-name idlwave-shell-temp-pro-prefix) - "Base name of the temporary files.") - -(defvar idlwave-shell-temp-pro-file - (concat idlwave-shell-temp-file-base ".pro") +(defvar idlwave-shell-temp-pro-file + nil "Absolute pathname for temporary IDL file for compiling regions") (defvar idlwave-shell-temp-rinfo-save-file - (concat idlwave-shell-temp-file-base ".sav") + nil "Absolute pathname for temporary IDL file save file for routine_info. This is used to speed up the reloading of the routine info procedure before use by the shell.") - (defvar idlwave-shell-dirstack-query "printd" "Command used by `idlwave-shell-resync-dirs' to query IDL for the directory stack.") +(defvar idlwave-shell-wd-is-synched nil) + (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+'>'" "The command which gets !PATH and !DIR infor from the shell.") @@ -463,15 +569,22 @@ (defvar idlwave-shell-is-stopped nil) (defvar idlwave-shell-expression-overlay nil "The overlay for where IDL is currently stopped.") +(defvar idlwave-shell-output-overlay nil + "The overlay for the last IDL output.") + ;; If these were already overlays, delete them. This probably means that we ;; are reloading this file. (if (overlayp idlwave-shell-stop-line-overlay) (delete-overlay idlwave-shell-stop-line-overlay)) (if (overlayp idlwave-shell-expression-overlay) (delete-overlay idlwave-shell-expression-overlay)) +(if (overlayp idlwave-shell-output-overlay) + (delete-overlay idlwave-shell-output-overlay)) + ;; Set to nil initially (setq idlwave-shell-stop-line-overlay nil - idlwave-shell-expression-overlay nil) + idlwave-shell-expression-overlay nil + idlwave-shell-output-overlay nil) ;; Define the shell stop overlay. When left nil, the arrow will be used. (cond @@ -499,10 +612,14 @@ (overlay-put idlwave-shell-stop-line-overlay 'face idlwave-shell-stop-line-face))))) -;; Now the expression overlay +;; Now the expression and output overlays (setq idlwave-shell-expression-overlay (make-overlay 1 1)) (overlay-put idlwave-shell-expression-overlay 'face idlwave-shell-expression-face) +(setq idlwave-shell-output-overlay (make-overlay 1 1)) +(overlay-put idlwave-shell-output-overlay + 'face idlwave-shell-output-face) + (defvar idlwave-shell-bp-query "help,/breakpoints" "Command to obtain list of breakpoints") @@ -514,6 +631,9 @@ The current command is finished when the IDL prompt is displayed. This is evaluated if it is a list or called with funcall.") +(defvar idlwave-shell-sentinel-hook nil + "Hook run when the idl process exits.") + (defvar idlwave-shell-hide-output nil "If non-nil the process output is not inserted into the output buffer.") @@ -665,7 +785,7 @@ Info documentation for this package is available. Use \\[idlwave-info] to display (complain to your sysadmin if that does not work). For Postscript and HTML versions of the documentation, check IDLWAVE's - homepage at `http://www.strw.leidenuniv.nl/~dominik/Tools/idlwave'. + homepage at `http://idlwave.org'. IDLWAVE has customize support - see the group `idlwave'. 7. Keybindings @@ -679,7 +799,7 @@ (setq comint-process-echoes t) ;; Can not use history expansion because "!" is used for system variables. (setq comint-input-autoexpand nil) - (setq comint-input-ring-size 64) +; (setq comint-input-ring-size 64) (make-local-variable 'comint-completion-addsuffix) (set (make-local-variable 'completion-ignore-case) t) (setq comint-completion-addsuffix '("/" . "")) @@ -723,6 +843,9 @@ (setq idlwave-shell-sources-alist nil) (setq idlwave-shell-default-directory default-directory) (setq idlwave-shell-hide-output nil) + + ;; NB: `make-local-hook' needed for older/alternative Emacs compatibility + (make-local-hook 'kill-buffer-hook) (add-hook 'kill-buffer-hook 'idlwave-shell-kill-shell-buffer-confirm nil 'local) (add-hook 'kill-buffer-hook 'idlwave-shell-delete-temp-files nil 'local) @@ -730,16 +853,30 @@ (use-local-map idlwave-shell-mode-map) (easy-menu-add idlwave-shell-mode-menu idlwave-shell-mode-map) - (set (make-local-variable 'comint-scroll-to-bottom-on-input) t) - (set (make-local-variable 'comint-scroll-show-maximum-output) t) + ;; Set the optional comint variables + (when idlwave-shell-comint-settings + (let ((list idlwave-shell-comint-settings) entry) + (while (setq entry (pop list)) + (set (make-local-variable (car entry)) (cdr entry))))) ;; IDLWAVE syntax, and turn on abbreviations (setq local-abbrev-table idlwave-mode-abbrev-table) (set-syntax-table idlwave-mode-syntax-table) (set (make-local-variable 'comment-start) ";") (setq abbrev-mode t) + + ;; NB: `make-local-hook' needed for older/alternative Emacs compatibility + (make-local-hook 'post-command-hook) (add-hook 'post-command-hook 'idlwave-command-hook nil t) + ;; Read the command history? + (when (and idlwave-shell-save-command-history + (stringp idlwave-shell-command-history-file)) + (set (make-local-variable 'comint-input-ring-file-name) + idlwave-shell-command-history-file) + (if (file-regular-p idlwave-shell-command-history-file) + (comint-read-input-ring))) + ;; Run the hooks. (run-hooks 'idlwave-shell-mode-hook) (idlwave-shell-send-command idlwave-shell-initial-commands nil 'hide) @@ -780,10 +917,20 @@ ;; The frame exists, so we use it. idlwave-shell-display-wframe ;; The frame does not exist. We use the current frame. - ;; However, if the current is the shell frame, we make a new frame. + ;; However, if the current is the shell frame, we make a new frame, + ;; or recycle the first existing visible frame (setq idlwave-shell-display-wframe (if (eq (selected-frame) idlwave-shell-idl-wframe) - (make-frame) + (or + (let ((flist (visible-frame-list)) + (frame (selected-frame))) + (catch 'exit + (while flist + (if (not (eq (car flist) + idlwave-shell-idl-wframe)) + (throw 'exit (car flist)) + (setq flist (cdr flist)))))) + (make-frame)) (selected-frame)))))) (defun idlwave-shell-shell-frame () @@ -802,7 +949,7 @@ (make-frame idlwave-shell-frame-parameters))))) ;;;###autoload -(defun idlwave-shell (&optional arg) +(defun idlwave-shell (&optional arg quick) "Run an inferior IDL, with I/O through buffer `(idlwave-shell-buffer)'. If buffer exists but shell process is not running, start new IDL. If buffer exists and shell process is running, just switch to the buffer. @@ -811,7 +958,8 @@ is non-nil, the shell buffer and the source buffers will be in separate frames. -The command to run comes from variable `idlwave-shell-explicit-file-name'. +The command to run comes from variable `idlwave-shell-explicit-file-name', +with options taken from `idlwave-shell-command-line-options'. The buffer is put in `idlwave-shell-mode', providing commands for sending input and controlling the IDL job. See help on `idlwave-shell-mode'. @@ -819,34 +967,47 @@ \(Type \\[describe-mode] in the shell buffer for a list of commands.)" (interactive "P") - - ;; A non-nil arg means, we want a dedicated frame. This will last - ;; for the current editing session. - (if arg (setq idlwave-shell-use-dedicated-frame t)) - (if (equal arg '(16)) (setq idlwave-shell-use-dedicated-frame nil)) - - ;; Check if the process still exists. If not, create it. - (unless (comint-check-proc (idlwave-shell-buffer)) - (let* ((prg (or idlwave-shell-explicit-file-name "idl")) - (buf (apply 'make-comint - idlwave-shell-process-name prg nil - idlwave-shell-command-line-options)) - (process (get-buffer-process buf))) - (setq idlwave-idlwave_routine_info-compiled nil) - (set-process-filter process 'idlwave-shell-filter) - (set-process-sentinel process 'idlwave-shell-sentinel) - (set-buffer buf) - (idlwave-shell-mode))) - (let ((window (idlwave-display-buffer (idlwave-shell-buffer) nil - (idlwave-shell-shell-frame))) - (current-window (selected-window))) - (select-window window) - (goto-char (point-max)) - (select-window current-window) - (raise-frame (window-frame window)) - (if (eq (selected-frame) (window-frame window)) - (select-window window)) - )) + (if (eq arg 'quick) + (progn + (let ((idlwave-shell-use-dedicated-frame nil)) + (idlwave-shell nil) + (delete-other-windows)) + (and idlwave-shell-use-dedicated-frame + (setq idlwave-shell-idl-wframe (selected-frame))) + (add-hook 'idlwave-shell-sentinel-hook + 'save-buffers-kill-emacs t)) + + ;; A non-nil arg means, we want a dedicated frame. This will last + ;; for the current editing session. + (if arg (setq idlwave-shell-use-dedicated-frame t)) + (if (equal arg '(16)) (setq idlwave-shell-use-dedicated-frame nil)) + + ;; Check if the process still exists. If not, create it. + (unless (comint-check-proc (idlwave-shell-buffer)) + (let* ((prg (or idlwave-shell-explicit-file-name "idl")) + (buf (apply 'make-comint + idlwave-shell-process-name prg nil + (if (stringp idlwave-shell-command-line-options) + (idlwave-split-string + idlwave-shell-command-line-options) + idlwave-shell-command-line-options))) + (process (get-buffer-process buf))) + (setq idlwave-idlwave_routine_info-compiled nil) + (set-process-filter process 'idlwave-shell-filter) + (set-process-sentinel process 'idlwave-shell-sentinel) + (set-buffer buf) + (idlwave-shell-mode))) + (let ((window (idlwave-display-buffer (idlwave-shell-buffer) nil + (idlwave-shell-shell-frame))) + (current-window (selected-window))) + (select-window window) + (goto-char (point-max)) + (select-window current-window) + (if idlwave-shell-ready + (raise-frame (window-frame window))) + (if (eq (selected-frame) (window-frame window)) + (select-window window)) + ))) (defun idlwave-shell-recenter-shell-window (&optional arg) "Run `idlwave-shell', but make sure the current window stays selected." @@ -871,6 +1032,7 @@ and if `idlwave-shell-ready' is non-nil." ;(setq hide nil) ; FIXME: turn this on for debugging only +; (message "SENDING %s|||%s" cmd pcmd) ;?????????????????????? (let (buf proc) ;; Get or make the buffer and its process (if (or (not (setq buf (get-buffer (idlwave-shell-buffer)))) @@ -1061,17 +1223,14 @@ ;; We no longer do the cleanup here - this is done by the process sentinel (when (eq (process-status idlwave-shell-process-name) 'run) ;; OK, process is still running, so we can use it. - (let ((data (match-data))) + (setq idlwave-shell-wd-is-synched nil) ;; something might have changed cwd + (let ((data (match-data)) p) (unwind-protect (progn ;; May change the original match data. - (let (p) - (while (setq p (string-match "\C-M" string)) - (aset string p ? ))) -;;; Test/Debug code -;; (save-excursion (set-buffer (get-buffer-create "*test*")) -;; (goto-char (point-max)) -;; (insert "%%%" string)) + (while (setq p (string-match "\C-M" string)) + (aset string p ?\ )) + ;; ;; Keep output @@ -1084,6 +1243,9 @@ ; (concat idlwave-shell-command-output string)) ;; Insert the string. Do this before getting the ;; state. + (while (setq p (string-match "\C-G" string)) + (ding) + (aset string p ?\C-j )) (if idlwave-shell-hide-output (save-excursion (set-buffer @@ -1091,7 +1253,7 @@ (goto-char (point-max)) (insert string)) (idlwave-shell-comint-filter proc string)) - ;; Watch for prompt - need to accumulate the current line + ;; Watch for magic - need to accumulate the current line ;; since it may not be sent all at once. (if (string-match "\n" string) (progn @@ -1106,7 +1268,13 @@ (concat idlwave-shell-accumulation string))) - ;; Check for prompt in current line +;;; Test/Debug code +; (save-excursion (set-buffer +; (get-buffer-create "*idlwave-shell-output*")) +; (goto-char (point-max)) +; (insert "\nSTRING===>\n" string "\n<====\n")) + + ;; Check for prompt in current accumulating line (if (setq idlwave-shell-ready (string-match idlwave-shell-prompt-pattern idlwave-shell-accumulation)) @@ -1114,10 +1282,19 @@ (if idlwave-shell-hide-output (save-excursion (set-buffer idlwave-shell-hidden-output-buffer) - (goto-char (point-min)) - (re-search-forward idlwave-shell-prompt-pattern nil t) +; (goto-char (point-min)) +; (re-search-forward idlwave-shell-prompt-pattern nil t) + (goto-char (point-max)) + (re-search-backward idlwave-shell-prompt-pattern nil t) + (goto-char (match-end 0)) (setq idlwave-shell-command-output (buffer-substring (point-min) (point))) +;; Test/Debug +; (save-excursion (set-buffer +; (get-buffer-create "*idlwave-shell-output*")) +; (goto-char (point-max)) +; (insert "\nOUPUT===>\n" idlwave-shell-command-output "\n<===\n")) + (delete-region (point-min) (point))) (setq idlwave-shell-command-output (save-excursion @@ -1129,11 +1306,6 @@ (beginning-of-line nil) (point)) comint-last-input-end)))) -;;; Test/Debug code -;; (save-excursion (set-buffer -;; (get-buffer-create "*idlwave-shell-output*")) -;; (goto-char (point-max)) -;; (insert "%%%" string)) ;; Scan for state and do post command - bracket them ;; with idlwave-shell-ready=nil since they ;; may call idlwave-shell-send-command. @@ -1163,15 +1335,28 @@ (save-excursion (set-buffer (idlwave-shell-buffer)) (goto-char (point-max)) - (insert (format "\n\n Process %s %s" process event)))) + (insert (format "\n\n Process %s %s" process event)) + (if (and idlwave-shell-save-command-history + (stringp idlwave-shell-command-history-file)) + (condition-case nil + (comint-write-input-ring) + (error nil))))) + (when (and (> (length (frame-list)) 1) (frame-live-p idlwave-shell-idl-wframe)) (delete-frame idlwave-shell-idl-wframe) (setq idlwave-shell-idl-wframe nil idlwave-shell-display-wframe nil)) - (when (window-live-p win) + (when (and (window-live-p win) + (not (one-window-p 'nomini))) (delete-window win)) - (idlwave-shell-cleanup))) + (idlwave-shell-cleanup) + ;; Run the hook, if possible in the shell buffer. + (if (get-buffer buf) + (save-excursion + (set-buffer buf) + (run-hooks 'idlwave-shell-sentinel-hook)) + (run-hooks 'idlwave-shell-sentinel-hook)))) (defun idlwave-shell-scan-for-state () "Scan for state info. @@ -1471,6 +1656,7 @@ (let ((text idlwave-shell-command-output) (start 0) sep sep-re file type spec specs name cs key keys class entry) +; (message "GOT: %s" text) ;?????????????????????? ;; Initialize variables (setq idlwave-compiled-routines nil idlwave-unresolved-routines nil) @@ -1483,10 +1669,12 @@ text (substring text (match-end 0))) ;; Set dummy values and kill the text (setq sep "@" sep-re "@ *" text "") - (message "Routine Info warning: No match for BEGIN line")) + (message "Routine Info warning: No match for BEGIN line in \n>>>>\n%s\n<<<<\n" + idlwave-shell-command-output)) (if (string-match "^>>>END OF IDLWAVE ROUTINE INFO.*" text) (setq text (substring text 0 (match-beginning 0))) - (message "Routine Info warning: No match for END line")) + (message "Routine Info warning: No match for END line in \n>>>>\n%s\n<<<<\n" + idlwave-shell-command-output)) (if (string-match "\\S-" text) ;; Obviously, the pro worked. Make a note that we have it now. (setq idlwave-idlwave_routine_info-compiled t)) @@ -1604,10 +1792,28 @@ We assume that we are after a file name when completing one of the args of an executive .run, .rnew or .compile. Also, in a string constant we complete file names. Otherwise return nil, so that -other completion functions can do thier work." - (let* ((comint-file-name-chars idlwave-shell-file-name-chars) - (completion-ignore-case (default-value 'completion-ignore-case))) - (comint-dynamic-complete-filename))) +other completion functions can do their work." + ;; Comint does something funny with the default directory, + ;; so we set it here from out safe own variable + (setq default-directory + (file-name-as-directory idlwave-shell-default-directory)) + (if (not idlwave-shell-wd-is-synched) + ;; Some IDL stuff has been executed since last update, so we need to + ;; do it again. + (idlwave-shell-send-command + idlwave-shell-dirstack-query + `(progn + (idlwave-shell-filter-directory) + (setq idlwave-shell-wd-is-synched t) + (switch-to-buffer (idlwave-shell-buffer)) + (goto-char ,(point)) ;; This is necesary on Emacs, don't know why + ;; after the update, we immediately redo the completion, so the + ;; user will hardly notice we did the update. + (idlwave-shell-complete-filename)) + 'hide) + (let* ((comint-file-name-chars idlwave-shell-file-name-chars) + (completion-ignore-case (default-value 'completion-ignore-case))) + (comint-dynamic-complete-filename)))) (defun idlwave-shell-executive-command () "Return the name of the current executive command, if any." @@ -2045,36 +2251,91 @@ (interactive "P") (idlwave-shell-print arg 'help)) +(defmacro idlwave-shell-mouse-examine (help &optional ev) + "Create a function for generic examination of expressions." + `(lambda (event) + "Expansion function for expression examination." + (interactive "e") + (let ((transient-mark-mode t) + (zmacs-regions t) + (tracker (if (featurep 'xemacs) 'mouse-track + 'mouse-drag-region))) + (funcall tracker event) + (idlwave-shell-print (if (idlwave-region-active-p) '(16) nil) + ,help ,ev)))) + (defun idlwave-shell-mouse-print (event) - "Call `idlwave-shell-print' at the mouse position." + "Print value of variable at the mouse position, with `help'" (interactive "e") - (mouse-set-point event) - (idlwave-shell-print nil nil 'mouse)) + (funcall (idlwave-shell-mouse-examine nil) event)) (defun idlwave-shell-mouse-help (event) - "Call `idlwave-shell-print' at the mouse position." + "Print value of variable at the mouse position, with `print'." + (interactive "e") + (funcall (idlwave-shell-mouse-examine 'help) event)) + +(defun idlwave-shell-examine-select (event) + "Pop-up a list to select from for examining the expression" (interactive "e") - (mouse-set-point event) - (idlwave-shell-print nil 'help 'mouse)) - -(defun idlwave-shell-print (arg &optional help mouse) - "Print current expression. With HELP, show help on expression. + (funcall (idlwave-shell-mouse-examine nil event) event)) + +(defmacro idlwave-shell-examine (help) + "Create a function for key-driven expression examination." + `(lambda () + (interactive) + (idlwave-shell-print nil ,help))) + +(defun idlwave-shell-define-key-both (key hook) + "Define a key in both the shell and buffer mode maps." + (define-key idlwave-mode-map key hook) + (define-key idlwave-shell-mode-map key hook)) + +(defvar idlwave-shell-examine-label nil + "Label to include with examine text if separate.") + +(defun idlwave-shell-print (arg &optional help ev) + "Print current expression. + +With HELP non-nil, show help on expression. If HELP is a string, +the expression will be put in place of ___, e.g.: + + print,size(___,/DIMENSIONS) + +Otherwise, print is called on the expression. + An expression is an identifier plus 1 pair of matched parentheses -directly following the identifier - an array or function -call. Alternatively, an expression is the contents of any matched -parentheses when the open parentheses is not directly preceded by an +directly following the identifier - an array or function call. +Alternatively, an expression is the contents of any matched +parentheses when the open parenthesis is not directly preceded by an identifier. If point is at the beginning or within an expression return the inner-most containing expression, otherwise, return the preceding expression. -With prefix arg ARG, or when called from the shell buffer, prompt -for an expression." +With prefix arg ARG prompt for an expression. + +With double prefix arg, use the current region. + +If EV is a valid event passed, pop-up a list from +idlw-shell-examine-alist from which to select the help command text." (interactive "P") (save-excursion - (let (expr beg end cmd) - (if (and (not mouse) - (or arg (eq major-mode 'idlwave-shell-mode))) - (setq expr (read-string "Expression: ")) + (let* ((process (get-buffer-process (current-buffer))) + (process-mark (if process (process-mark process))) + (stack-label + (if (and (integerp idlwave-shell-calling-stack-index) + (> idlwave-shell-calling-stack-index 0)) + (format " [-%d:%s]" + idlwave-shell-calling-stack-index + idlwave-shell-calling-stack-routine))) + expr beg end cmd examine-hook) + (cond + ((and (equal arg '(16)) + (< (- (region-end) (region-beginning)) 2000)) + (setq beg (region-beginning) + end (region-end))) + (arg + (setq expr (read-string "Expression: "))) + (t (idlwave-with-special-syntax1 ;; Move to beginning of current or previous expression (if (looking-at "\\<\\|(") @@ -2093,27 +2354,177 @@ (while (looking-at "\\>[[(]\\|\\.") ;; an array (forward-sexp)) - (setq end (point)) - (setq expr (buffer-substring beg end)))) + (setq end (point))))) + + ;; Get expression, but first move the begin mark if a + ;; process-mark is inside the region, to keep the overlay from + ;; wandering in the Shell. + (when (and beg end) + (if (and process-mark (> process-mark beg) (< process-mark end)) + (setq beg (marker-position process-mark))) + (setq expr (buffer-substring beg end))) + + ;; Show the overlay(s) and attach any necessary hooks and filters (when (and beg end idlwave-shell-expression-overlay) (move-overlay idlwave-shell-expression-overlay beg end (current-buffer)) - (add-hook 'pre-command-hook 'idlwave-shell-delete-expression-overlay)) - (if (and (integerp idlwave-shell-calling-stack-index) - (> idlwave-shell-calling-stack-index 0)) + (add-hook 'pre-command-hook + 'idlwave-shell-delete-expression-overlay)) + (setq examine-hook + (if idlwave-shell-separate-examine-output + 'idlwave-shell-examine-display + 'idlwave-shell-examine-highlight)) + (add-hook 'pre-command-hook + 'idlwave-shell-delete-output-overlay) + + ;; Remove empty or comment-only lines + (while (string-match "\n[ \t]*\\(;.*\\)?\r*\n" expr) + (setq expr (replace-match "\n" t t expr))) + ;; Concatenate continuation lines + (while (string-match "[ \t]*\\$.*\\(;.*\\)?\\(\n[ \t]*\\|$\\)" expr) + (setq expr (replace-match "" t t expr))) + ;; Remove final newline + (if (string-match "\n[ \t\r]*\\'" expr) + (setq expr (replace-match "" t t expr))) + ;; Pop-up the examine selection list, if appropriate + (if (and ev idlwave-shell-examine-alist) + (let* ((help-cons + (assoc + (idlwave-popup-select + ev (mapcar 'car idlwave-shell-examine-alist) + "Examine with") + idlwave-shell-examine-alist))) + (setq help (cdr help-cons)) + (if idlwave-shell-separate-examine-output + (setq idlwave-shell-examine-label + (concat + (format "==>%s<==\n%s:" expr (car help-cons)) + stack-label "\n")))) + (setq idlwave-shell-examine-label + (concat + (format "==>%s<==\n%s:" expr + (cond ((null help) "print") + ((stringp help) help) + (t (symbol-name help)))) + stack-label "\n"))) + + ;; Send the command + (if stack-label (setq cmd (idlwave-retrieve-expression-from-level expr idlwave-shell-calling-stack-index idlwave-shell-calling-stack-routine help)) - (setq cmd (concat (if help "help," "print,") expr))) - (if idlwave-shell-print-expression-function - (idlwave-shell-send-command - cmd - (list idlwave-shell-print-expression-function expr) - 'hide) - (idlwave-shell-recenter-shell-window) - (idlwave-shell-send-command cmd))))) + (setq cmd (idlwave-shell-help-statement help expr))) + ;(idlwave-shell-recenter-shell-window) + (idlwave-shell-send-command + cmd + examine-hook + (if idlwave-shell-separate-examine-output 'hide))))) + +(defvar idlwave-shell-examine-window-alist nil + "Variable to hold the win/height pairs for all *Examine* windows.") + +(defun idlwave-shell-examine-display () + "View the examine command output in a separate buffer." + (let (win cur-beg cur-end) + (save-excursion + (set-buffer (get-buffer-create "*Examine*")) + (use-local-map idlwave-shell-examine-map) + (setq buffer-read-only nil) + (goto-char (point-max)) + (save-restriction + (narrow-to-region (point) (point)) + (if (string-match "^% Syntax error." idlwave-shell-command-output) + (insert "% Syntax error.\n") + (insert idlwave-shell-command-output) + ;; Just take the last bit between the prompts (if more than one). + (let* ((end (or + (re-search-backward idlwave-shell-prompt-pattern nil t) + (point-max))) + (beg (progn + (goto-char + (or (progn (if (re-search-backward + idlwave-shell-prompt-pattern nil t) + (match-end 0))) + (point-min))) + (re-search-forward "\n"))) + (str (buffer-substring beg end))) + (delete-region (point-min) (point-max)) + (insert str) + (if idlwave-shell-examine-label + (progn (goto-char (point-min)) + (insert idlwave-shell-examine-label) + (setq idlwave-shell-examine-label nil))))) + (setq cur-beg (point-min) + cur-end (point-max)) + (setq buffer-read-only t) + (move-overlay idlwave-shell-output-overlay cur-beg cur-end + (current-buffer)) + + ;; Look for the examine buffer in all windows. If one is + ;; found in a frame all by itself, use that, otherwise, switch + ;; to or create an examine window in this frame, and resize if + ;; it's a newly created window + (let* ((winlist (get-buffer-window-list "*Examine*" nil 'visible))) + (setq win (idlwave-display-buffer + "*Examine*" + nil + (let ((list winlist) thiswin) + (catch 'exit + (save-selected-window + (while (setq thiswin (pop list)) + (select-window thiswin) + (if (one-window-p) + (throw 'exit (window-frame thiswin))))))))) + (set-window-start win (point-min)) ; Ensure the point is visible. + (save-selected-window + (select-window win) + (let ((elt (assoc win idlwave-shell-examine-window-alist))) + (when (and (not (one-window-p)) + (or (not (memq win winlist)) ;a newly created window + (eq (window-height) (cdr elt)))) + ;; Autosize it. + (enlarge-window (- (/ (frame-height) 2) + (window-height))) + (shrink-window-if-larger-than-buffer) + ;; Clean the window list of dead windows + (setq idlwave-shell-examine-window-alist + (delq nil + (mapcar (lambda (x) (if (window-live-p (car x)) x)) + idlwave-shell-examine-window-alist))) + ;; And add the new value. + (if (setq elt (assoc win idlwave-shell-examine-window-alist)) + (setcdr elt (window-height)) + (add-to-list 'idlwave-shell-examine-window-alist + (cons win (window-height))))))))) + ;; Recenter for maximum output, after widened + (save-selected-window + (select-window win) + (goto-char (point-max)) + (skip-chars-backward "\n") + (recenter -1))))) + +(defvar idlwave-shell-examine-map (make-sparse-keymap)) +(define-key idlwave-shell-examine-map "q" 'idlwave-shell-examine-display-quit) +(define-key idlwave-shell-examine-map "c" 'idlwave-shell-examine-display-clear) + +(defun idlwave-shell-examine-display-quit () + (interactive) + (let ((win (selected-window))) + (if (one-window-p) + (delete-frame (window-frame win)) + (delete-window win)))) + +(defun idlwave-shell-examine-display-clear () + (interactive) + (save-excursion + (let ((buf (get-buffer "*Examine*"))) + (when (bufferp buf) + (set-buffer buf) + (setq buffer-read-only nil) + (erase-buffer) + (setq buffer-read-only t))))) (defun idlwave-retrieve-expression-from-level (expr level routine help) "Return IDL command to print the expression EXPR from stack level LEVEL. @@ -2126,37 +2537,38 @@ level. Since this function depends upon the undocumented IDL routine routine_names, -there is no guarantie that this will work with future versions of IDL." +there is no guarantee that this will work with future versions of IDL." (let ((prefix "___") ;; No real variables should starts with this. (fetch (- 0 level)) (start 0) var tvar fetch-vars pre post) ;; FIXME: In the following we try to find the variables in expression - ;; This is quite empirical - I don't know in what situations this will - ;; break. We will look for identifiers and exclude cases where we - ;; know it is not a variable. To distinguish array references from - ;; function calls, we require that arrays use [] instead of () - - (while (string-match - "\\(\\`\\|[^a-zA-Z0-9$_]\\)\\([a-zA-Z][a-zA-Z0-9$_]*\\)\\([^a-zA-Z0-9$_]\\|\\'\\)" expr start) - (setq var (match-string 2 expr) - tvar (concat prefix var) - start (match-beginning 2) - pre (substring expr 0 (match-beginning 2)) - post (substring expr (match-end 2))) - (cond - ;; Exclude identifiers which are not variables - ((string-match ",[ \t]*/\\'" pre)) ;; a `/' KEYWORD - ((and (string-match "[,(][ \t]*\\'" pre) - (string-match "\\`[ \t]*=" post))) ;; a `=' KEYWORD - ((string-match "\\`(" post)) ;; a function - ((string-match "->[ \t]*\\'" pre)) ;; a method - ((string-match "\\.\\'" pre)) ;; structure member - (t ;; seems to be a variable - arrange to get it and replace - ;; its name in the expression with the temproary name. - (push (cons var tvar) fetch-vars) - (setq expr (concat pre tvar post))))) + ;; This is quite empirical - I don't know in what situations this will + ;; break. We will look for identifiers and exclude cases where we + ;; know it is not a variable. To distinguish array references from + ;; function calls, we require that arrays use [] instead of () + + (while (string-match + "\\(\\`\\|[^a-zA-Z0-9$_]\\)\\([a-zA-Z][a-zA-Z0-9$_]*\\)\\([^a-zA-Z0-9$_]\\|\\'\\)" expr start) + (setq var (match-string 2 expr) + tvar (concat prefix var) + start (match-beginning 2) + pre (substring expr 0 (match-beginning 2)) + post (substring expr (match-end 2))) + (cond + ;; Exclude identifiers which are not variables + ((string-match ",[ \t]*/\\'" pre)) ;; a `/' KEYWORD + ((and (string-match "[,(][ \t]*\\'" pre) + (string-match "\\`[ \t]*=" post))) ;; a `=' KEYWORD + ((string-match "\\`(" post)) ;; a function + ((string-match "->[ \t]*\\'" pre)) ;; a method + ((string-match "\\.\\'" pre)) ;; structure member + (t ;; seems to be a variable - arrange to get it and replace + ;; its name in the expression with the temproary name. + (push (cons var tvar) fetch-vars) + (setq expr (concat pre tvar post)))) + (if (= start 0) (setq start 1))) ;; Make a command line that first copies the relevant variables ;; and then prints the expression. (concat @@ -2165,17 +2577,65 @@ (format "%s = routine_names('%s',fetch=%d)" (cdr x) (car x) fetch)) (nreverse fetch-vars) " & ") - (if idlwave-shell-print-expression-function " & " "\n") - (if help "help, " "print, ") - expr + "\n" + (idlwave-shell-help-statement help expr) (format " ; [-%d:%s]" level routine)))) +(defun idlwave-shell-help-statement (help expr) + "Construct a help statement for printing expression EXPR. + +HELP can be non-nil for `help,', nil for 'print,' or any string into which +to insert expression in place of the marker ___, e.g.: print, +size(___,/DIMENSIONS)" + (cond + ((null help) (concat "print, " expr)) + ((stringp help) + (if (string-match "\\(^\\|[^_]\\)\\(___\\)\\([^_]\\|$\\)" help) + (concat (substring help 0 (match-beginning 2)) + expr + (substring help (match-end 2))))) + (t (concat "help, " expr)))) + + +(defun idlwave-shell-examine-highlight () + "Highlight the most recent IDL output." + (let* ((buffer (get-buffer (idlwave-shell-buffer))) + (process (get-buffer-process buffer)) + (process-mark (if process (process-mark process))) + output-begin output-end) + (save-excursion + (set-buffer buffer) + (goto-char process-mark) + (beginning-of-line) + (setq output-end (point)) + (re-search-backward idlwave-shell-prompt-pattern nil t) + (beginning-of-line 2) + (setq output-begin (point))) + + ;; First make sure the shell window is visible + (idlwave-display-buffer (idlwave-shell-buffer) + nil (idlwave-shell-shell-frame)) + (if (and idlwave-shell-output-overlay process-mark) + (move-overlay idlwave-shell-output-overlay + output-begin output-end buffer)))) + +(defun idlwave-shell-delete-output-overlay () + (if (eq this-command 'idlwave-shell-mouse-nop) + nil + (condition-case nil + (if idlwave-shell-output-overlay + (delete-overlay idlwave-shell-output-overlay)) + (error nil)) + (remove-hook 'pre-command-hook 'idlwave-shell-delete-output-overlay))) + (defun idlwave-shell-delete-expression-overlay () - (condition-case nil - (if idlwave-shell-expression-overlay - (delete-overlay idlwave-shell-expression-overlay)) - (error nil)) - (remove-hook 'pre-command-hook 'idlwave-shell-delete-expression-overlay)) + (if (eq this-command 'idlwave-shell-mouse-nop) + nil + (condition-case nil + (if idlwave-shell-expression-overlay + (delete-overlay idlwave-shell-expression-overlay)) + (error nil)) + (remove-hook 'pre-command-hook 'idlwave-shell-delete-expression-overlay))) (defvar idlwave-shell-bp-alist nil "Alist of breakpoints. @@ -2213,7 +2673,9 @@ (let ((oldbuf (current-buffer))) (save-excursion (set-buffer (idlwave-find-file-noselect - idlwave-shell-temp-pro-file 'tmp)) + (idlwave-shell-temp-file 'pro) 'tmp)) + (set (make-local-variable 'comment-start-skip) ";+[ \t]*") + (set (make-local-variable 'comment-start) ";") (erase-buffer) (insert-buffer-substring oldbuf beg end) (if (not (save-excursion @@ -2253,13 +2715,8 @@ (error nil)))) (defun idlwave-display-buffer (buf not-this-window-p &optional frame) - (if (or (< emacs-major-version 20) - (and (= emacs-major-version 20) - (< emacs-minor-version 3))) - ;; Only two args. - (display-buffer buf not-this-window-p) - ;; Three ares possible. - (display-buffer buf not-this-window-p frame))) + (if (not (frame-live-p frame)) (setq frame nil)) + (display-buffer buf not-this-window-p frame)) (defvar idlwave-shell-bp-buffer " *idlwave-shell-bp*" "Scratch buffer for parsing IDL breakpoint lists and other stuff.") @@ -2302,22 +2759,37 @@ (insert idlwave-shell-command-output) (goto-char (point-min)) (let ((old-bp-alist idlwave-shell-bp-alist) - file line index module) + ;; Searching the breakpoints + ;; In IDL 5.5, the breakpoint reporting format changed. + (bp-re54 "^[ \t]*\\([0-9]+\\)[ \t]+\\(\\S-+\\)?[ \t]+\\([0-9]+\\)[ \t]+\\(\\S-+\\)") + (bp-re55 "^\\s-*\\([0-9]+\\)\\s-+\\([0-9]+\\)\\s-+\\(Uncompiled\\|Func=\\|Pro=\\)\\(\\S-+\\)?\\s-+\\(\\S-+\\)") + file line index module + bp-re indmap) (setq idlwave-shell-bp-alist (list nil)) - (when (re-search-forward "^\\s-*Index.*\n\\s-*-" nil t) + ;; Search for either header type, and set the correct regexp + (when (or + (if (re-search-forward "^\\s-*Index.*\n\\s-*-" nil t) + (setq bp-re bp-re54 ; versions <= 5.4 + indmap '(1 2 3 4))) + (if (re-search-forward + "^\\s-*Index\\s-*Line\\s-*Attributes\\s-*File" nil t) + (setq bp-re bp-re55 ; versions >= 5.5 + indmap '(1 4 2 5)))) ;; There seems to be a breakpoint listing here. ;; Parse breakpoint lines. - ;; Breakpoints have the form: + ;; Breakpoints have the form + ;; for IDL<=v5.4: ;; Index Module Line File - ;; All seperated by whitespace. + ;; All separated by whitespace. ;; Module may be missing if the file is not compiled. - ;; - (while (re-search-forward - "^[ \t]*\\([0-9]+\\)[ \t]+\\(\\S-+\\)?[ \t]+\\([0-9]+\\)[ \t]+\\(\\S-+\\)" nil t) - (setq index (match-string 1) - module (match-string 2) - line (string-to-int (match-string 3)) - file (idlwave-shell-file-name (match-string 4))) + ;; for IDL>=v5.5: + ;; Index Line Attributes File + ;; (attributes replaces module, "Uncompiled" included) + (while (re-search-forward bp-re nil t) + (setq index (match-string (nth 0 indmap)) + module (match-string (nth 1 indmap)) + line (string-to-int (match-string (nth 2 indmap))) + file (idlwave-shell-file-name (match-string (nth 3 indmap)))) ;; Add the breakpoint info to the list (nconc idlwave-shell-bp-alist (list (cons (list file line) @@ -2372,24 +2844,24 @@ The breakpoint will be placed at the beginning of the statement on the line specified by BP or at the next IDL statement if that line is not a statement. -Determines IDL's internal representation for the breakpoint which may -have occurred at a different line then used with the breakpoint +Determines IDL's internal representation for the breakpoint, which may +have occurred at a different line than used with the breakpoint command." ;; Get and save the old breakpoints (idlwave-shell-send-command idlwave-shell-bp-query '(progn - (idlwave-shell-filter-bp) - (setq idlwave-shell-old-bp idlwave-shell-bp-alist)) + (idlwave-shell-filter-bp) + (setq idlwave-shell-old-bp idlwave-shell-bp-alist)) 'hide) ;; Get sources for IDL compiled procedures followed by setting ;; breakpoint. (idlwave-shell-send-command idlwave-shell-sources-query `(progn - (idlwave-shell-sources-filter) - (idlwave-shell-set-bp2 (quote ,bp))) + (idlwave-shell-sources-filter) + (idlwave-shell-set-bp2 (quote ,bp))) 'hide)) (defun idlwave-shell-set-bp2 (bp) @@ -2619,7 +3091,7 @@ idlwave-routines) (idlwave-shell-update-routine-info t))) -(defvar idlwave-shell-sources-query "help,/source" +(defvar idlwave-shell-sources-query "help,/source,/full" "IDL command to obtain source files for compiled procedures.") (defvar idlwave-shell-sources-alist nil @@ -2746,11 +3218,10 @@ (let ((def-dir (if (eq major-mode 'idlwave-shell-mode) default-directory idlwave-shell-default-directory))) - (if idlwave-shell-use-truename - (file-truename name def-dir) + (if idlwave-shell-use-truename + (file-truename name def-dir) (expand-file-name name def-dir)))) - ;; Keybindings -------------------------------------------------------------- (defvar idlwave-shell-mode-map (copy-keymap comint-mode-map) @@ -2777,23 +3248,42 @@ (define-key idlwave-shell-mode-map [(down)] 'idlwave-shell-down-or-history) (define-key idlwave-mode-map "\C-c\C-y" 'idlwave-shell-char-mode-loop) (define-key idlwave-mode-map "\C-c\C-x" 'idlwave-shell-send-char) -(define-key idlwave-mode-map - (if (featurep 'xemacs) [(shift button2)] [(shift mouse-2)]) - 'idlwave-shell-mouse-print) -(define-key idlwave-mode-map - (if (featurep 'xemacs) [(shift control button2)] [(shift control mouse-2)]) + +;; The mouse bindings for PRINT and HELP +(idlwave-shell-define-key-both + (if (featurep 'xemacs) + [(shift button2)] + [(shift down-mouse-2)]) + 'idlwave-shell-mouse-print) +(idlwave-shell-define-key-both + (if (featurep 'xemacs) + [(control meta button2)] + [(control meta down-mouse-2)]) 'idlwave-shell-mouse-help) +(idlwave-shell-define-key-both + (if (featurep 'xemacs) + [(control shift button2)] + [(control shift down-mouse-2)]) + 'idlwave-shell-examine-select) +;; Add this one from the idlwave-mode-map (define-key idlwave-shell-mode-map - (if (featurep 'xemacs) [(shift button2)] [(shift mouse-2)]) - 'idlwave-shell-mouse-print) -(define-key idlwave-shell-mode-map - (if (featurep 'xemacs) [(shift control button2)] [(shift control mouse-2)]) - 'idlwave-shell-mouse-help) -(define-key idlwave-shell-mode-map - (if (featurep 'xemacs) [(shift button3)] [(shift mouse-3)]) + (if (featurep 'xemacs) + [(shift button3)] + [(shift mouse-3)]) 'idlwave-mouse-context-help) - +;; For Emacs, we need to turn off the button release events. +(defun idlwave-shell-mouse-nop (event) + (interactive "e")) +(unless (featurep 'xemacs) + (idlwave-shell-define-key-both + [(shift mouse-2)] 'idlwave-shell-mouse-nop) + (idlwave-shell-define-key-both + [(shift control mouse-2)] 'idlwave-shell-mouse-nop) + (idlwave-shell-define-key-both + [(control meta mouse-2)] 'idlwave-shell-mouse-nop)) + + ;; The following set of bindings is used to bind the debugging keys. ;; If `idlwave-shell-activate-prefix-keybindings' is non-nil, the first key ;; in the list gets bound the C-c C-d prefix map. @@ -2994,7 +3484,7 @@ (let ((image-string "/* XPM */ static char * file[] = { \"14 12 3 1\", -\" c #FFFFFFFFFFFF s backgroundColor\", +\" c None s backgroundColor\", \". c #4B4B4B4B4B4B\", \"R c #FFFF00000000\", \" \", @@ -3017,7 +3507,7 @@ ((and (not (featurep 'xemacs)) (fboundp 'image-type-available-p) (image-type-available-p 'xpm)) - (list 'image :type 'xpm :data image-string)) + (list 'image :type 'xpm :data image-string :ascent 'center)) (t nil)))) (provide 'idlw-shell)