Commits

Anonymous committed 3ed0038

IDLWAVE 3.15

  • Participants
  • Parent commits a50885c

Comments (0)

Files changed (8)

-This is the CHANGES file of the IDLWAVE distribution, version 3.13 
+This is the CHANGES file of the IDLWAVE distribution, version 3.15 
 
 The file covers only the changes for Revision 3.0 and later.  Earlier
 changes are documented in the (obsolete) files idl.el and
 http://www.strw.leidenuniv.nl/~dominik/Tools/idlwave.
 
 
+Revision 3.15
+=============
+   - Printing expressions while execution is halted can now also
+     access all levels on the calling stack.
+   - Padding of long operators (like `->') is now possible.  The
+     object arrow `->' has been added to the defaults - when
+     `idlwave-do-actions' is non-nil, `->' will have at least one
+     space before and after it.
+   - Code templates now respect settings of `idlwave-abbrev-change-case'
+     and `idlwave-reserved-word-upcase'.
+   - Fixed bug with `idlwave-pad-keywords' in procedure method calls.
+   - Fontification of keyword parameters works with embedded comments.
+
 Revision 3.13
 =============
    - Minor cleanup.
 ============
    - Library scan implemented for Windows and MacOS.  On these systems 
      the search path need to be given in `idlwave-library-path'.
-   - *Completions* window dissapears after successful completion.
+   - *Completions* window disappears after successful completion.
    - Fixed library scan bug with keywords in continuations line.
 
 Revision 3.7
    - Font-lock enhancements.  Multi-level fontification based on the
      value of `font-lock-maximum-decoration'.  Reunified the different
      expressions for Emacs and XEmacs.
-   - `idlwave-show-begin' check the correctness of the endstatement.
+   - `idlwave-show-begin' check the correctness of the END statement.
    - `idlwave-surround' exception for `->'.
    - Better listing of abbreviations with `idlwave-list-abbrevs'.
    - Some general cleanup of the code.  Menu reorganized.
+2000-02-04  Carsten Dominik  <dominik@astro.uva.nl>
+
+	* idlwave 3.15.
+
 2000-01-12  Andreas Jaeger  <aj@suse.de>
 
 	* idlwave 3.13 from Carsten Dominik imported.
 # Boston, MA 02111-1307, USA.
 
 VERSION = 1.0
-AUTHOR_VERSION = 3.13
+AUTHOR_VERSION = 3.15
 MAINTAINER = Carsten Dominik <dominik@astro.uva.nl>
 PACKAGE = idlwave
 PKG_TYPE = regular

File idlw-rinfo.el

 ;;; idlw-rinfo.el --- Routine Information for IDLWAVE
 ;; Copyright (c) 1999 Carsten Dominik
-;; Copyright (c) 1999 Free Software Foundation
+;; Copyright (c) 1999, 2000 Free Software Foundation
 
 ;; Author: Carsten Dominik <dominik@strw.leidenuniv.nl>
-;; Version: 3.13
+;; Version: 3.15
 ;; Keywords: languages
 
 ;; This file is part of GNU Emacs.
 ;; and procedures.  This information is extracted automatically from
 ;; the IDL documentation.
 ;;
-;; Created by get_rinfo on Wed Jan  5 13:17:23 2000
+;; Created by get_rinfo on Mon Jan 17 14:28:10 2000
 ;; IDL version: 5.3
 ;; Number of files scanned:  5
 ;;       903 syntax entries in file refguide.txt.bz2

File idlw-shell.el

 
 ;; Author: Chris Chase <chase@att.com>
 ;; Maintainer: Carsten Dominik <dominik@strw.leidenuniv.nl>
-;; Version: 3.13
+;; Version: 3.15
 ;; Date: $Date$
 ;; Keywords: processes
 
 ;; KNOWN PROBLEMS
 ;; ==============
 ;;
-;; The idlwave-shell buffer seems to occasionally lose output from the IDL
-;; process.  I have not been able to consistently observe this.  I
-;; do not know if it is a problem with idlwave-shell, comint, or Emacs
-;; handling of subprocesses.
-;; 
 ;; I don't plan on implementing directory tracking by watching the IDL
 ;; commands entered at the prompt, since too often an IDL procedure
 ;; will change the current directory. If you want the the idl process
 ;; buffer to match the IDL current working just execute `M-x
 ;; idlwave-shell-resync-dirs' (bound to "\C-c\C-d\C-w" by default.)
 ;;
-;; The stack motion commands `idlwave-shell-stack-up' and
-;; `idlwave-shell-stack-down' only display the calling frame but
-;; cannot show the values of variables in higher frames correctly.  I
-;; just don't know how to get these values from IDL.  Anyone knows the 
-;; magic word to do this?
-;; Also, the stack pointer stays at the level where is was and is not
-;; reset correctly when you type executive commands in the shell buffer
-;; yourself.  However, using the executive commands bound to key sequences
-;; does the reset correctly.  As a workaround, just jump down when needed.
-;; 
 ;; Under XEmacs the Debug menu in the shell does not display the
 ;; keybindings in the prefix map.  There bindings are available anyway - so
 ;; it is a bug in XEmacs.
-;; The Debug menu in source buffers does display the bindings correctly.
+;; The Debug menu in source buffers *does* display the bindings correctly.
 ;;
 ;; 
 ;; CUSTOMIZATION VARIABLES
 
 (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.
+Exiting the shell will removed everywhere.
 Available on XEmacs and on Emacs 21.x or later.
-Needs to be set at load-time, so don't try to do this in the hook."
+At any time you can toggle the display of the toolbar with
+`C-c C-d C-t' (`idlwave-shell-toggle-toolbar')."
   :group 'idlwave-shell-general-setup
   :type 'boolean)
 
   :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)
+
 ;;; Breakpoint Overlays etc
 
 (defgroup idlwave-shell-highlighting-and-faces nil
   :group 'idlwave-shell-highlighting-and-faces
   :type 'symbol)
 
-(defcustom idlwave-shell-expression-face 'secondary-selection
-  "*The face for `idlwave-shell-expression-overlay'.
-Allows you to choose the font, color and other properties for
-the expression printed by IDL."
-  :group 'idlwave-shell-highlighting-and-faces
-  :type 'symbol)
-
 (defcustom idlwave-shell-mark-breakpoints t
   "*Non-nil means, mark breakpoints in the source files.
 Legal values are:
   ;; Just copy the underline face to be on the safe side.
   (copy-face 'underline 'idlwave-shell-bp-face))
 
+(defcustom idlwave-shell-expression-face 'secondary-selection
+  "*The face for `idlwave-shell-expression-overlay'.
+Allows you to choose the font, color and other properties for
+the expression printed by IDL."
+  :group 'idlwave-shell-highlighting-and-faces
+  :type 'symbol)
+
 ;;; End user customization variables
 
 ;;; External variables
   "Command used by `idlwave-shell-resync-dirs' to query IDL for 
 the directory stack.")
 
+(defvar idlwave-shell-mode-line-info nil
+  "Additional info displayed in the mode line")  
+
 (defvar idlwave-shell-default-directory nil
   "The default directory in the idlwave-shell buffer, of outside use.")
 
 (setq idlwave-shell-expression-overlay (make-overlay 1 1))
 (overlay-put idlwave-shell-expression-overlay
 	     'face idlwave-shell-expression-face)
-
 (defvar idlwave-shell-bp-query "help,/breakpoints"
   "Command to obtain list of breakpoints")
 
 (defvar idlwave-shell-bp-buffer)
 (defvar idlwave-shell-sources-query)
 (defvar idlwave-shell-mode-map)
+(defvar idlwave-shell-calling-stack-index)
 
 (defun idlwave-shell-mode ()
   "Major mode for interacting with an inferior IDL process.
   (setq comint-input-ignoredups t)
   (setq major-mode 'idlwave-shell-mode)
   (setq mode-name "IDL-Shell")
+  (setq idlwave-shell-mode-line-info nil)
+  (setq mode-line-format
+	'(""
+	  mode-line-modified
+	  mode-line-buffer-identification
+	  "   "
+	  global-mode-string
+	  "   %[("
+	  mode-name
+	  mode-line-process
+	  minor-mode-alist
+	  "%n"
+	  ")%]-"
+	  idlwave-shell-mode-line-info
+	  "---"
+	  (line-number-mode "L%l--")
+	  (column-number-mode "C%c--")
+	  (-3 . "%p")
+	  "-%-"))
   ;; (make-local-variable 'idlwave-shell-bp-alist)
   (setq idlwave-shell-halt-frame nil
         idlwave-shell-trace-frame nil
         idlwave-shell-command-output nil
         idlwave-shell-step-frame nil)
   (idlwave-shell-display-line nil)
+  (setq idlwave-shell-calling-stack-index 0)
   ;; Make sure comint-last-input-end does not go to beginning of
   ;; buffer (in case there were other processes already in this buffer).
   (set-marker comint-last-input-end (point))
 (defvar idlwave-shell-display-wframe nil
   "Frame for displaying the idl source files.")
 
-(defvar idlwave-shell-last-calling-stack nil
-  "Caches the last calling stack, so that we can compare.")
 (defvar idlwave-shell-calling-stack-index 0)
+(defvar idlwave-shell-calling-stack-routine nil)
 
 (defun idlwave-shell-source-frame ()
   "Return the frame to be used for source display."
      ((string-match idlwave-shell-halt-messages-re
 		    idlwave-shell-command-output)
       ;; Grab the file and line state info.
+      (setq idlwave-shell-calling-stack-index 0)
       (setq idlwave-shell-halt-frame
             (idlwave-shell-parse-line 
              (substring idlwave-shell-command-output (match-end 0)))
      ;; Handle breakpoints separately
      ((string-match idlwave-shell-break-message
                     idlwave-shell-command-output)
+      (setq idlwave-shell-calling-stack-index 0)
       (setq idlwave-shell-halt-frame 
             (idlwave-shell-parse-line 
              (substring idlwave-shell-command-output (match-end 0)))
 	    (idlwave-shell-send-command "exit")
 	  (error nil)))))
 
-(defun idlwave-shell-reset (&optional visible)
+(defun idlwave-shell-reset (&optional hidden)
   "Reset IDL.  Return to main level and destroy the leaftover variables.
 This issues the following commands:  
 RETALL
   ;; OBJ_DESTROY, OBJ_VALID()  FIXME: should this be added?
   (interactive "P")
   (message "Resetting IDL")
-  (idlwave-shell-send-command "retall" nil (not visible))
-  (idlwave-shell-send-command "widget_control,/reset" nil (not visible))
-  (idlwave-shell-send-command "close,/all" nil (not visible))
-  ;; (idlwave-shell-send-command "obj_destroy, obj_valid()" nil (not visible))
-  (idlwave-shell-send-command "heap_gc,/verbose" nil (not visible))
-  (setq idlwave-shell-calling-stack-index 0))
+  (setq idlwave-shell-calling-stack-index 0)
+  (idlwave-shell-send-command "retall" nil hidden)
+  (idlwave-shell-send-command "widget_control,/reset" nil hidden)
+  (idlwave-shell-send-command "close,/all" nil hidden)
+  ;; (idlwave-shell-send-command "obj_destroy, obj_valid()" nil hidden)
+  (idlwave-shell-send-command "heap_gc,/verbose" nil hidden)
+  (idlwave-shell-display-line nil))
 
 (defun idlwave-shell-filter-directory ()
   "Get the current directory from `idlwave-shell-command-output'.
 `idlwave-shell-display-line'.  Also updates the breakpoint
 overlays."
   (interactive)
+  (setq idlwave-shell-calling-stack-index 0)
   (idlwave-shell-send-command
    "help,/trace"
    '(idlwave-shell-display-line
 (defun idlwave-shell-display-level-in-calling-stack (&optional hide)
   (idlwave-shell-send-command 
    "help,/trace"
-   'idlwave-shell-parse-stack-and-display
+   `(progn
+      ;; scanning for the state will reset the stack level - restore it
+      (setq idlwave-shell-calling-stack-index
+	    ,idlwave-shell-calling-stack-index)
+      ;; parse the stack and visit the selected frame
+      (idlwave-shell-parse-stack-and-display))
    hide))
 
 (defun idlwave-shell-parse-stack-and-display ()
 	 (stack (delq nil (mapcar 'idlwave-shell-parse-line lines)))
 	 (nmax (1- (length stack)))
 	 (nmin 0) message)
-;    ;; Reset the stack to zero if it is a new stack.
-;    (if (not (equal stack idlwave-shell-last-calling-stack))
-;	(setq idlwave-shell-calling-stack-index 0))
-;    (setq idlwave-shell-last-calling-stack stack)
     (cond
      ((< nmax nmin)
       (setq idlwave-shell-calling-stack-index 0)      
       (error "Problem with calling stack"))
      ((> idlwave-shell-calling-stack-index nmax)
+      (ding)
       (setq idlwave-shell-calling-stack-index nmax
-	    message (format "%d is the highest level on the calling stack"
-			    nmax)))
+	    message (format "%d is the highest calling stack level - can't go further up"
+			    (- nmax))))
      ((< idlwave-shell-calling-stack-index nmin)
+      (ding)
       (setq idlwave-shell-calling-stack-index nmin
-	    message (format "%d is the lowest level on the calling stack"
-			    nmin))))    
+	    message (format "%d is the current calling stack level - can't go further down"
+			    (- nmin)))))
+    (setq idlwave-shell-calling-stack-routine 
+	  (nth 2 (nth idlwave-shell-calling-stack-index stack)))
     (idlwave-shell-display-line 
      (nth idlwave-shell-calling-stack-index stack))
     (message (or message 
-		 (format "On stack level %d"
-			 idlwave-shell-calling-stack-index)))))
+		 (format "In routine %s (stack level %d)"
+			 idlwave-shell-calling-stack-routine
+			 (- idlwave-shell-calling-stack-index))))))
 
 (defun idlwave-shell-stack-up ()
   "Display the source code one step up the calling stack."
   "Returns the frame for IDL execution."
   (and idlwave-shell-halt-frame
        (list (nth 0 idlwave-shell-halt-frame) 
-	     (nth 1 idlwave-shell-halt-frame))))
+	     (nth 1 idlwave-shell-halt-frame)
+	     (nth 2 idlwave-shell-halt-frame))))
 
 (defun idlwave-shell-valid-frame (frame)
   "Check that frame is for an existing file."
       ;; Remove stop-line overlay from old position
       (progn 
         (setq overlay-arrow-string nil)
+	(setq idlwave-shell-mode-line-info nil)
         (if idlwave-shell-stop-line-overlay
             (delete-overlay idlwave-shell-stop-line-overlay)))
     (if (not (idlwave-shell-valid-frame frame))
 ;;; buffer : the buffer to display a line in.
 ;;; select-shell: current buffer is the shell.
 ;;; 
+      (setq idlwave-shell-mode-line-info
+	    (if (nth 2 frame)
+		(format "[%d:%s]" 
+			(- idlwave-shell-calling-stack-index)
+			(nth 2 frame))))
       (let* ((buffer (idlwave-find-file-noselect (car frame)))
              (select-shell (equal (buffer-name) (idlwave-shell-buffer)))
              window pos)
   (mouse-set-point event)
   (idlwave-shell-help-expression))
 
-(defun idlwave-shell-print (&optional help special)
-  "Print current expression.  With are HELP, show help on expression.
+(defun idlwave-shell-print (&optional help)
+  "Print current expression.  With HELP, show help on 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
 identifier. If point is at the beginning or within an expression
 return the inner-most containing expression, otherwise, return the
 preceding expression."
-  (interactive "P")
+  (interactive)
   (save-excursion
-    (let (beg end)
-      ;; Move to beginning of current or previous expression
-      (if (looking-at "\\<\\|(")
-          ;; At beginning of expression, don't move backwards unless
-          ;; this is at the end of an indentifier.
-          (if (looking-at "\\>")
-              (backward-sexp))
-        (backward-sexp))
-      (if (looking-at "\\>")
-          ;; Move to beginning of identifier - must be an array or
-          ;; function expression.
-          (backward-sexp))
-      ;; Move to end of expression
-      (setq beg (point))
-      (forward-sexp)
-      (while (looking-at "\\>(\\|\\.")
-        ;; an array
-        (forward-sexp))
-      (setq end (point))
-      (when idlwave-shell-expression-overlay
-	(move-overlay idlwave-shell-expression-overlay beg end)
+    (let (expr beg end cmd)
+      (if current-prefix-arg
+	  (setq expr (read-string "Expression: "))
+	;; Move to beginning of current or previous expression
+	(if (looking-at "\\<\\|(")
+	    ;; At beginning of expression, don't move backwards unless
+	    ;; this is at the end of an indentifier.
+	    (if (looking-at "\\>")
+		(backward-sexp))
+	  (backward-sexp))
+	(if (looking-at "\\>")
+	    ;; Move to beginning of identifier - must be an array or
+	    ;; function expression.
+	    (backward-sexp))
+	;; Move to end of expression
+	(setq beg (point))
+	(forward-sexp)
+	(while (looking-at "\\>[[(]\\|\\.")
+	  ;; an array
+	  (forward-sexp))
+	(setq end (point))
+	(setq expr (buffer-substring beg end)))
+      (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 special
+      (if (and (integerp idlwave-shell-calling-stack-index)
+	       (> idlwave-shell-calling-stack-index 0))
+	  (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 
-	   (concat (if help "help," "print,") (buffer-substring beg end))
-	   `(idlwave-shell-process-print-output ,(buffer-substring beg end) 
-						idlwave-shell-command-output
-						,special)
+	   cmd
+	   (list idlwave-shell-print-expression-function expr)
 	   'hide)
 	(idlwave-shell-recenter-shell-window)
-	(idlwave-shell-send-command 
-	 (concat (if help "help," "print,") (buffer-substring beg end)))))))
+	(idlwave-shell-send-command cmd)))))
+
+(defun idlwave-retrieve-expression-from-level (expr level routine help)
+  "Return IDL command to print the expression EXPR from stack level LEVEL.
+
+It does not seem possible to evaluate an expression on a differnt
+level than the current.  Therefore, this function retrieves *copies* of
+the variables involved in the expression from the desired level in the
+calling stack.  The copies are given some unlikely names on the
+*current* level, and the expression is then evaluated on the *current*
+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."
+  (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)))))
+    ;; Make a command line that first copies the relevant variables
+    ;; and then prints the expression.
+    (concat
+     (mapconcat
+      (lambda (x)
+	(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
+     (format " ; [-%d:%s]" level routine))))
 
 (defun idlwave-shell-delete-expression-overlay ()
   (condition-case nil
 	    ;; use a glyph
 	    (let ((string "@"))
 	      (put-text-property 0 1
-				 'display (cons nil idlwave-shell-bp-glyph)
+				 'display idlwave-shell-bp-glyph
 				 string)
 	      (overlay-put ov 'before-string string))
 	  (overlay-put ov 'face 'idlwave-shell-bp-face)))
 	  arg)
       (setq idlwave-shell-command-line-to-execute 
 	    (read-string "IDL> " idlwave-shell-command-line-to-execute)))
-  (idlwave-shell-reset nil)
+  (idlwave-shell-reset 'hidden)
   (idlwave-shell-send-command idlwave-shell-command-line-to-execute
 			      '(idlwave-shell-redisplay 'hide)))
 
 
 ;;; Load the toolbar when wanted by the user.
 
+(autoload 'idlwave-toolbar-toggle "idlw-toolbar" 
+  "Toggle the IDLWAVE toolbar")
+(autoload 'idlwave-toolbar-add-everywhere "idlw-toolbar"
+  "Add IDLWAVE toolbar")
 (defun idlwave-shell-toggle-toolbar ()
   "Toggle the display of the debugging toolbar."
   (interactive)
-  (if (featurep 'idlw-toolbar)
-      (idlwave-toolbar-toggle)
-    (require 'idlw-toolbar)
-    (idlwave-toolbar-toggle)))
+  (idlwave-toolbar-toggle))
 
-
-(when idlwave-shell-use-toolbar
-  (or (load "idlw-toolbar" t)
-      (message
-       "Tried to load file `idlw-toolbar.el', but file does not exist")))
+(if idlwave-shell-use-toolbar
+    (add-hook 'idlwave-shell-mode-hook 'idlwave-toolbar-add-everywhere))
 
 ;;; idlw-shell.el ends here
 
-

File idlw-toolbar.el

 ;; Copyright (c) 1999 Free Software Foundation
 
 ;; Author: Carsten Dominik <dominik@strw.leidenuniv.nl>
-;; Version: 3.13
+;; Version: 3.15
 ;; Date: $Date$
 ;; Keywords: processes
 
 		  (featurep 'xpm)                   ; need xpm
 		  (featurep 'toolbar))              ; ... and the toolbar
 	     (and (not (featurep 'xemacs))          ; This is Emacs
-		  (boundp 'toolbar-button-margin)   ; need toolbar
+		  (boundp 'tool-bar-button-margin)   ; need toolbar
 		  (fboundp 'image-type-available-p) ; need image stuff
 		  (image-type-available-p 'xpm))    ; need xpm
 	     ))
     (message "Sorry, IDLWAVE xpm toolbar cannot be used on this version of Emacs")
 ;; OK, we can define a toolbar
 
+(defconst idlwave-toolbar-is-possible t
+  "When defined, indicates that a toolbar is possible with this Emacs.")
 (defvar idlwave-toolbar-compile-icon
   (idlwave-toolbar-make-button
    "/* XPM */
      "Reset IDL (RETALL & CLOSE,/ALL and more)"]
     ))
 
-
-;; Add the toolbar to all open idlwave buffers when the shell starts.
-(add-hook 'idlwave-shell-mode-hook 'idlwave-toolbar-add-everywhere)
-;; Make sure the toolbar will be added to any future idlwave-mode buffers
-(add-hook 'idlwave-mode-hook 'idlwave-toolbar-add)
-;; When the shell exits, remove the special toolbar everywhere.
+;; When the shell exits, arrange to remove the special toolbar everywhere.
 (add-hook 'idlwave-shell-cleanup-hook
 	  'idlwave-toolbar-remove-everywhere)
 );; End can define toolbar
 (defun idlwave-toolbar-add ()
   "Add the IDLWAVE toolbar if appropriate."
   (if (and (featurep 'xemacs)    ; This is a noop on Emacs
+	   (boundp 'idlwave-toolbar-is-possible)
 	   (or (eq major-mode 'idlwave-mode)
 	       (eq major-mode 'idlwave-shell-mode)))
       (set-specifier default-toolbar (cons (current-buffer)
 (defun idlwave-toolbar-remove ()
   "Add the IDLWAVE toolbar if appropriate."
   (if (and (featurep 'xemacs)    ; This is a noop on Emacs
+	   (boundp 'idlwave-toolbar-is-possible)
 	   (or (eq major-mode 'idlwave-mode)
 	       (eq major-mode 'idlwave-shell-mode)))
       (remove-specifier default-toolbar (current-buffer))))
 (defvar idlwave-toolbar-visible nil)
 (defun idlwave-toolbar-add-everywhere ()
   "Add the toolbar in all appropriate buffers."
-  (if (featurep 'xemacs)
-      ;; For XEmacs, map over all buffers to add toolbar
-      (save-excursion
-	(mapcar (lambda (buf)
-		  (set-buffer buf)
-		  (idlwave-toolbar-add))
-		(buffer-list)))
-    ;; For Emacs, add the key definitions to the mode maps
-    (mapcar (lambda (x)
-	      (let* ((icon (aref x 0))
-		     (func (aref x 1))
-		     ;;(show (aref x 2))
-		     (help (aref x 3))
-		     (key (vector 'toolbar func))
-		     (def (list 'menu-item
-				"a"
-				func
-				:image (symbol-value icon)
-				:help help)))
-		(define-key idlwave-mode-map key def)
-		(define-key idlwave-shell-mode-map key def)))
-	    (reverse idlwave-toolbar)))
-  (setq idlwave-toolbar-visible t))
+  (when (boundp 'idlwave-toolbar-is-possible)
+
+    ;; First make sure new buffers will get the toolbar
+    (add-hook 'idlwave-mode-hook 'idlwave-toolbar-add)
+    ;; Then add it to all existing buffers
+    (if (featurep 'xemacs)
+	;; For XEmacs, map over all buffers to add toolbar
+	(save-excursion
+	  (mapcar (lambda (buf)
+		    (set-buffer buf)
+		    (idlwave-toolbar-add))
+		  (buffer-list)))
+      ;; For Emacs, add the key definitions to the mode maps
+      (mapcar (lambda (x)
+		(let* ((icon (aref x 0))
+		       (func (aref x 1))
+		       ;;(show (aref x 2))
+		       (help (aref x 3))
+		       (key (vector 'tool-bar func))
+		       (def (list 'menu-item
+				  "a"
+				  func
+				  :image (symbol-value icon)
+				  :help help)))
+		  (define-key idlwave-mode-map key def)
+		  (define-key idlwave-shell-mode-map key def)))
+	      (reverse idlwave-toolbar)))
+    (setq idlwave-toolbar-visible t)))
 
 (defun idlwave-toolbar-remove-everywhere ()
   "Remove the toolbar in all appropriate buffers."
   ;; First make sure new buffers won't get the toolbar
-  (remove-hook 'idlwave-mode-hook 'idlwave-toolbar-add)
-  ;; Then remove it in all existing buffers.
-  (if (featurep 'xemacs)
-      ;; For XEmacs, map over all buffers to remove toolbar
-      (save-excursion
-	(mapcar (lambda (buf)
-		  (set-buffer buf)
-		  (idlwave-toolbar-remove))
-		(buffer-list)))
-    ;; For Emacs, remove the key definitions from the mode maps
-    (mapcar (lambda (x)
-	      (let* (;;(icon (aref x 0))
-		     (func (aref x 1))
-		     ;;(show (aref x 2))
-		     ;;(help (aref x 3))
-		     (key (vector 'toolbar func)))
-		(define-key idlwave-mode-map key nil)
-		(define-key idlwave-shell-mode-map key nil)))
-	    idlwave-toolbar))
-  (setq idlwave-toolbar-visible nil))
+  (when idlwave-toolbar-is-possible
+    (remove-hook 'idlwave-mode-hook 'idlwave-toolbar-add)
+    ;; Then remove it in all existing buffers.
+    (if (featurep 'xemacs)
+	;; For XEmacs, map over all buffers to remove toolbar
+	(save-excursion
+	  (mapcar (lambda (buf)
+		    (set-buffer buf)
+		    (idlwave-toolbar-remove))
+		  (buffer-list)))
+      ;; For Emacs, remove the key definitions from the mode maps
+      (mapcar (lambda (x)
+		(let* (;;(icon (aref x 0))
+		       (func (aref x 1))
+		       ;;(show (aref x 2))
+		       ;;(help (aref x 3))
+		       (key (vector 'tool-bar func)))
+		  (define-key idlwave-mode-map key nil)
+		  (define-key idlwave-shell-mode-map key nil)))
+	      idlwave-toolbar))
+    (setq idlwave-toolbar-visible nil)))
 
-(defun idlwave-toolbar-toggle ()
+(defun idlwave-toolbar-toggle (&optional force-on)
   (interactive)
   (if idlwave-toolbar-visible
-      (idlwave-toolbar-remove-everywhere)
+      (or force-on (idlwave-toolbar-remove-everywhere))
     (idlwave-toolbar-add-everywhere)))
 
 (provide 'idlw-toolbar)
 
 ;; Author: Chris Chase <chase@att.com>
 ;; Maintainer: Carsten Dominik <dominik@strw.leidenuniv.nl>
-;; Version: 3.13
+;; Version: 3.15
 ;; Date: $Date$
 ;; Keywords: languages
 
 ;;   point backward, e.g., "\cl" expanded with a space becomes
 ;;   "LONG( )" with point before the close paren.  This is solved by
 ;;   using a temporary function in `post-command-hook' - not pretty, 
-;;   but it works.<
+;;   but it works.
 ;;
 ;;   Tabs and spaces are treated equally as whitespace when filling a
 ;;   comment paragraph.  To accomplish this, tabs are permanently
 ;;   problems with pointer dereferencing statements.  I don't use
 ;;   pointers often enough to find out - please report any problems.
 ;;
-;;   Completion of keywords for SETPROPERTY and GETPROPERTY assumes that
-;;   all INIT keywords are allowed in these methods as well.  In some
-;;   cases, there are exceptions to this rule and IDLWAVE will offer
-;;   a few illegal keyword parameters.
-;;
 ;;   Completion and Routine Info do not know about inheritance.  Thus,
 ;;   Keywords inherited from superclasses are not displayed and cannot
 ;;   completed.
 ;;
 ;;   When forcing completion of method keywords, the initial
 ;;   query for a method has multiple entries for some methods.  Would
-;;   be too difficult to fix this hardly used problem.
+;;   be too difficult to fix this hardly used case.
 ;;
 
 ;;; Code:
 case, this variable specifies the path where IDLWAVE can find library files.
 The shell will only be asked when this variable is nil.
 The value is a list of directories.  A directory preceeded by a `+' will
-be search recursively."
+be searched recursively.  If you set this variable on a UNIX system, the shell
+will not be asked."
   :group 'idlwave-routine-info-and-completion
   :type '(repeat (directory)))
 
 
 (defcustom idlwave-surround-by-blank nil
   "*Non-nil means, enable `idlwave-surround'.
-If non-nil, `=',`<',`>',`&',`,' are surrounded with spaces by
+If non-nil, `=',`<',`>',`&',`,', `->' are surrounded with spaces by
 `idlwave-surround'.
 See help for `idlwave-indent-action-table' for symbols using `idlwave-surround'.
 
        ;; The following are the reserved words in IDL.  Maybe we should
        ;; highlight some more stuff as well?       
        (idl-keywords
-;	'("and" "or" "xor" "not"
-;	  "eq" "ge" "gt" "le" "lt" "ne" 
-;	  "for" "do" "endfor"
-;	  "if" "then" "endif" "else" "endelse" 
-;	  "case" "of" "endcase"
-;	  "begin" "end"
-;	  "repeat" "until" "endrep"
-;	  "while" "endwhile" 
-;	  "goto" "return"
-;         "inherits" "mod" "on_error" "on_ioerror")  ;; on_error is not reserved
+	;; To update this regexp, update the list of keywords and 
+	;; evaluate the form.
+;	(insert 
+;	 (concat 
+;	  "\"\\\\<"
+;	  (regexp-opt 
+;	   '("and" "or" "xor" "not"
+;	     "eq" "ge" "gt" "le" "lt" "ne" 
+;	     "for" "do" "endfor"
+;	     "if" "then" "endif" "else" "endelse" 
+;	     "case" "of" "endcase"
+;	     "begin" "end"
+;	     "repeat" "until" "endrep"
+;	     "while" "endwhile" 
+;	     "goto" "return"
+;	     "inherits" "mod"
+;	     "on_error" "on_ioerror"))  ; on_error is not officially reserved
+;	  "\\\\>\""))
 	(concat	"\\<\\("
 		"and\\|begin\\|case\\|do\\|e\\(lse\\|nd\\(case\\|else\\|"
 		"for\\|if\\|rep\\|while\\)?\\|q\\)\\|for\\|g\\(oto\\|[et]\\)"
 
        ;; Named parameters, like /xlog or ,xrange=[]
        ;; This is anchored to the comma preceeding the keyword.
-       ;; With continuation lines, works only during whole buffer fontification.
+       ;; Treats continuation lines, works only during whole buffer
+       ;; fontification.  Slow, use it only in fancy fontification.
        (keyword-parameters
-	'("[(,][ \t]*\\(\\$[ \t]*\n[ \t]*\\)?\\(/[a-zA-Z_]\\sw*\\|[a-zA-Z_]\\sw*[ \t]*=\\)"
-	  (2 font-lock-reference-face)))
-
-       ;; System variables stars with a bang.
+	'("[(,][ \t]*\\(\\$[ \t]*\\(;.*\\)?\\(\n[ \t]*;.*\\)*\n[ \t]*\\)?\\(/[a-zA-Z_]\\sw*\\|[a-zA-Z_]\\sw*[ \t]*=\\)"
+	  (4 font-lock-reference-face)))
+
+       ;; System variables start with a bang.
        (system-variables
 	'("\\(![a-zA-Z_]+\\(\\.\\sw+\\)?\\)"
 	  (1 font-lock-variable-name-face)))
    '(goto . ("goto\\>" nil))
    '(case . ("case\\>" nil))
    (cons 'call (list (concat idlwave-identifier "\\(\\s *$\\|\\s *,\\)") nil))
-   '(assign . ("[^=\n]*=" nil)))
+   '(assign . ("[^=>\n]*=" nil)))
   
   "Associated list of statement matching regular expressions.
 Each regular expression matches the start of an IDL statement.  The
   "Character which is inserted as a last character on previous line by
    \\[idlwave-split-line] to begin a continuation line.  Normally $.")
 
-(defconst idlwave-mode-version " 3.13")
+(defconst idlwave-mode-version " 3.15")
 
 (defmacro idlwave-keyword-abbrev (&rest args)
   "Creates a function for abbrev hooks to call `idlwave-check-abbrev' with args."
 
 (fset 'idlwave-debug-map (make-sparse-keymap))
 
+(define-key idlwave-mode-map "\C-c "    'idlwave-hard-tab)
+;(define-key idlwave-mode-map "\C-c\C- " 'idlwave-hard-tab)
 (define-key idlwave-mode-map "'"        'idlwave-show-matching-quote)
 (define-key idlwave-mode-map "\""       'idlwave-show-matching-quote)
 (define-key idlwave-mode-map "\C-c;"    'idlwave-toggle-comment-region)
 (idlwave-action-and-binding "&"  '(idlwave-surround -1 -1))
 (idlwave-action-and-binding "<"  '(idlwave-surround -1 -1))
 (idlwave-action-and-binding ">"  '(idlwave-surround -1 -1 '(?-)))
+(idlwave-action-and-binding "->" '(idlwave-surround -1 -1 nil 2))
 (idlwave-action-and-binding ","  '(idlwave-surround 0 -1))
 ;; Automatically add spaces to equal sign if not keyword
 (idlwave-action-and-binding "="  '(idlwave-expand-equal -1 -1))
     (insert end)
     (idlwave-newline)))
 
-(defun idlwave-surround (&optional before after escape-chars)
-  "Surround the character before point with blanks.
+(defun idlwave-surround (&optional before after escape-chars length)
+  "Surround the LENGTH characters before point with blanks.
+LENGTH defaults to 1.
 Optional arguments BEFORE and AFTER affect the behavior before and
-after the previous character. See description of `idlwave-make-space'.
+after the characters (see also description of `idlwave-make-space'):
+
+nil            do nothing
+0              force no spaces
+integer > 0    force exactly n spaces
+integer < 0    at least |n| spaces
 
 The function does nothing if any of the following conditions is true:
 - `idlwave-surround-by-blank' is nil
 - the character before point is inside a string or comment
-
-When the character 2 positions before point is a member of
-ESCAPE-CHARS, BEFORE is forced to nil."
-
-  (if (and idlwave-surround-by-blank
-	   (not (idlwave-quoted)))
-      (progn
-	(if (memq (char-after (- (point) 2)) escape-chars)
-	    (setq before nil))
-        (backward-char 1)
-        (save-restriction
-          (let ((here (point)))
-            (skip-chars-backward " \t")
-            (if (bolp)
-                ;; avoid clobbering indent
-                (progn
-                  (move-to-column (idlwave-calculate-indent))
-                  (if (<= (point) here)
-                      (narrow-to-region (point) here))
-                  (goto-char here)))
-            (idlwave-make-space before))
-          (skip-chars-forward " \t"))
-        (forward-char 1)
-        (idlwave-make-space after)
-        ;; Check to see if the line should auto wrap
-        (if (and (equal (char-after (1- (point))) ? )
-                 (> (current-column) fill-column))
-            (funcall auto-fill-function)))))
+- the char preceeding the string to be surrounded is a member of ESCAPE-CHARS.
+  This hack is used to avoid padding of `>' when it is part of
+  the '->' operator.  In this case, ESCAPE-CHARS would be '(?-)."
+
+  (setq length (or length 1))   ; establish a default for LENGTH
+
+  (when (and idlwave-surround-by-blank
+	     (not (idlwave-quoted))
+	     (not (memq (char-after (- (point) (1+ length))) escape-chars)))
+    (backward-char length)
+    (save-restriction
+      (let ((here (point)))
+	(skip-chars-backward " \t")
+	(if (bolp)
+	    ;; avoid clobbering indent
+	    (progn
+	      (move-to-column (idlwave-calculate-indent))
+	      (if (<= (point) here)
+		  (narrow-to-region (point) here))
+	      (goto-char here)))
+	(idlwave-make-space before))
+      (skip-chars-forward " \t"))
+    (forward-char length)
+    (idlwave-make-space after)
+    ;; Check to see if the line should auto wrap
+    (if (and (equal (char-after (1- (point))) ? )
+	     (> (current-column) fill-column))
+	(funcall auto-fill-function))))
 
 (defun idlwave-make-space (n)
   "Make space at point.
 The amount of space at point is determined by N.
 If the value of N is:
 nil   - do nothing.
-c > 0 - exactly c spaces.
-c < 0 - a minimum of -c spaces, i.e., do not change if there are
-        already -c spaces.
-0     - no spaces."
+> 0   - exactly N spaces.
+< 0   - a minimum of -N spaces, i.e., do not change if there are
+        already -N spaces.
+0     - no spaces (i.e. remove any existing space)."
   (if (integerp n)
       (let
           ((start-col (progn (skip-chars-backward " \t") (current-column)))
 
 Opens a line if point is not followed by a newline modulo intervening
 whitespace.  S1 and S2 are strings.  S1 is inserted at point followed
-by S2.  Point is inserted between S1 and S2.  If optional argument
+by S2.  Point is inserted between S1 and S2.  The case of S1 and S2 is
+adjusted according to `idlwave-abbrev-change-case'.  If optional argument
 PROMPT is a string then it is displayed as a message in the
 minibuffer.  The PROMPT serves as a reminder to the user of an
 expression to enter.
 
 The lines containing S1 and S2 are reindented using `indent-region'
 unless the optional second argument NOINDENT is non-nil."
+  (cond ((eq idlwave-abbrev-change-case 'down)
+	 (setq s1 (downcase s1) s2 (downcase s2)))
+	(idlwave-abbrev-change-case
+	 (setq s1 (upcase s1) s2 (upcase s2))))
   (let ((beg (save-excursion (beginning-of-line) (point)))
         end)
     (if (not (looking-at "\\s-*\n"))
     (if (stringp prompt)
         (message prompt))))
 
+(defun idlwave-rw-case (string)
+  "Make STRING have the case required by `idlwave-reserved-word-upcase'."
+  (if idlwave-reserved-word-upcase
+      (upcase string)
+    string))
+
 (defun idlwave-elif ()
   "Build skeleton IDL if-else block."
   (interactive)
-  (idlwave-template "if" 
-		    " then begin\n\nendif else begin\n\nendelse"
-		    "Condition expression"))
+  (idlwave-template
+   (idlwave-rw-case "if")
+   (idlwave-rw-case " then begin\n\nendif else begin\n\nendelse")
+   "Condition expression"))
 
 (defun idlwave-case ()
   "Build skeleton IDL case statement."
   (interactive)
-  (idlwave-template "case" " of\n\nendcase" "Selector expression"))
+  (idlwave-template 
+   (idlwave-rw-case "case")
+   (idlwave-rw-case " of\n\nendcase")
+   "Selector expression"))
 
 (defun idlwave-for ()
   "Build skeleton for loop statment."
   (interactive)
-  (idlwave-template "for" " do begin\n\nendfor" "Loop expression"))
+  (idlwave-template 
+   (idlwave-rw-case "for")
+   (idlwave-rw-case " do begin\n\nendfor")
+   "Loop expression"))
 
 (defun idlwave-if ()
   "Build skeleton for loop statment."
   (interactive)
-  (idlwave-template "if" " then begin\n\nendif" "Scalar logical expression"))
+  (idlwave-template
+   (idlwave-rw-case "if")
+   (idlwave-rw-case " then begin\n\nendif")
+   "Scalar logical expression"))
 
 (defun idlwave-procedure ()
   (interactive)
-  (idlwave-template "pro" "\n\nreturn\nend" "Procedure name"))
+  (idlwave-template 
+   (idlwave-rw-case "pro")
+   (idlwave-rw-case "\n\nreturn\nend")
+   "Procedure name"))
 
 (defun idlwave-function ()
   (interactive)
-  (idlwave-template "function" "\n\nreturn\nend" "Function name"))
+  (idlwave-template 
+   (idlwave-rw-case "function")
+   (idlwave-rw-case "\n\nreturn\nend")
+   "Function name"))
 
 (defun idlwave-repeat ()
   (interactive)
-  (idlwave-template "repeat begin\n\nendrep until" "" "Exit condition"))
+  (idlwave-template
+   (idlwave-rw-case "repeat begin\n\nendrep until")
+   (idlwave-rw-case "")
+   "Exit condition"))
 
 (defun idlwave-while ()
   (interactive)
-  (idlwave-template "while" " do begin\n\nendwhile" "Entry condition"))
+  (idlwave-template 
+   (idlwave-rw-case "while")
+   (idlwave-rw-case " do begin\n\nendwhile")
+   "Entry condition"))
 
 (defun idlwave-split-string (string &optional pattern)
   "Return a list of substrings of STRING which are separated by PATTERN.
 	      (idlwave-make-force-complete-where-list arg module class)
 	    (idlwave-where)))
 	 (what (nth 2 where-list))
-	 (idlwave-force-class-query (equal arg '(4)))
-	 cwin)
+	 (idlwave-force-class-query (equal arg '(4))))
 
     (if (and module (string-match "::" module))
 	(setq class (substring module 0 (match-beginning 0))
 
      ((and (null arg)
 	   (eq (car-safe last-command) 'idlwave-display-completion-list)
-	   (setq cwin (get-buffer-window "*Completions*")))
+	   (get-buffer-window "*Completions*"))
       (setq this-command last-command)
       (idlwave-scroll-completions))
 
 
 ;;; idlwave.el ends here
 
+
+

File idlwave.texi

 @synindex ky cp
 @syncodeindex vr cp
 @syncodeindex fn cp
-@set VERSION 3.13
-@set EDITION 1.8
+@set VERSION 3.15
+@set EDITION 1.10
 @set IDLVERSION 5.3
 @set NSYSROUTINES 1226
-@set NSYSKEYWORDS 5230
-@set DATE December 1999
+@set NSYSKEYWORDS 5229
+@set DATE February 2000
 @set AUTHOR Carsten Dominik
 @set AUTHOR-EMAIL dominik@@astro.uva.nl
 @set MAINTAINER Carsten Dominik
 This is edition @value{EDITION} of the IDLWAVE User Manual for
 IDLWAVE @value{VERSION}@refill
 
-Copyright (c) 1999 Free Software Foundation, Inc.
+Copyright (c) 1999, 2000 Free Software Foundation, Inc.
 
 Permission is granted to make and distribute verbatim
 copies of this manual provided the copyright notice and
 
 @author by Carsten Dominik
 @page
-Copyright @copyright{} 1999 Free Software Foundation, Inc.
+Copyright @copyright{} 1999, 2000 Free Software Foundation, Inc.
 
 @sp 2
 This is edition @value{EDITION} of the @cite{IDLWAVE User Manual} for
 @cindex IDLWAVE in a Nutshell
 @cindex Nutshell, IDLWAVE in a
 
-If you are in a hurry, here is some quick-start information.
-
 @subheading Editing IDL Programs
 
 @multitable @columnfractions .15 .85
 (setq idlwave-main-block-indent 2         ; default  0
       idlwave-block-indent 2              ; default  4
       idlwave-end-offset -2)              ; default -4
-
+;; Pad some operators with spaces
+(setq idlwave-do-actions t
+      idlwave-surround-by-blank t)
+;; Automatically expand END to ENDIF, ENDELSE, ...
+(setq idlwave-expand-generic-end t)
 ;; Syntax Highlighting
 (add-hook 'idlwave-mode-hook 'turn-on-font-lock)
-;; Automatically expand END to ENDIF, ENDELSE, ...
-(setq idlwave-expand-generic-end t)
 
-;; Automatically start the shell when needed
-(setq idlwave-shell-automatic-start t)
-;; Always use a separate frame for the shell buffer
-(setq idlwave-shell-use-dedicated-frame t)
+;; Automatically start the shell when needed, in dedicated frame
+(setq idlwave-shell-automatic-start t
+      idlwave-shell-use-dedicated-frame t)
 
 ;; Specify a file where library info can be stored.
 (setq idlwave-libinfo-file "~/idlinfo.el")
 default - the variable @code{idlwave-store-inquired-class} can be used
 to turn it on.@refill
 
-@defopt idlwave-completion-show-classes (@code{t})
+@defopt idlwave-completion-show-classes (@code{1})
 Non-@code{nil} means, show classes in @file{*Completions*} buffer when
 completing object methods and keywords.@refill
 @end defopt
 expanded by typing text into the buffer and pressing @key{SPC} or
 @key{RET}.  The special abbreviations used to insert code templates all
 start with a @samp{\} (the backslash).  Here are a few examples of
-predefined abbreviations.  For a full list, use @kbd{M-x
+predefined abbreviations.   For a full list, use @kbd{M-x
 idlwave-list-abbrevs}.
 
 @multitable @columnfractions .15 .85
 @item @code{\b}
 @tab @code{BEGIN}
 @end multitable
- 
+
+The templates are expanded in upper or lower case, depending upon the
+variables @code{idlwave-abbrev-change-case} and
+@code{idlwave-reserved-word-upcase}.@refill
+
 @defopt idlwave-abbrev-start-char
 A single character string used to start abbreviations in abbrev
 mode.@refill
 Some operators can be automatically surrounded by spaces.  This can
 happen when the operator is typed, or also later when the line is
 indented.  IDLWAVE contains this setting for the operators @samp{&},
-@samp{<}, @samp{>}, @samp{,}, @samp{=}, but the feature is turned off by
-default.  If you want to turn it on, customize the variable
-@code{idlwave-surround-by-blank}.  You can also define similar actions
-for other operators by using the function
-@code{idlwave-action-and-binding} in the mode hook.  For example, to
-enforce space padding of the @samp{+} and @samp{*} operators, try this
-in @file{.emacs}
+@samp{<}, @samp{>}, @samp{,}, @samp{=}, and @samp{->}@footnote{operators
+longer than one character can only be padded during line indentation.},
+but the feature is turned off by default.  If you want to turn it on,
+customize the variables @code{idlwave-surround-by-blank} and
+@code{idlwave-do-actions}.  You can also define similar actions for
+other operators by using the function @code{idlwave-action-and-binding}
+in the mode hook.  For example, to enforce space padding of the @samp{+}
+and @samp{*} operators, try this in @file{.emacs}@refill
 
 @lisp
 (add-hook 'idlwave-mode-hook
 
 @defopt idlwave-surround-by-blank (@code{nil})
 Non-@code{nil} means, enable @code{idlwave-surround}.  If non-nil,
-@samp{=}, @samp{<}, @samp{>}, @samp{&}, @samp{,} are surrounded with
-spaces by @code{idlwave-surround}.
+@samp{=}, @samp{<}, @samp{>}, @samp{&}, @samp{,}, @samp{->} are
+surrounded with spaces by @code{idlwave-surround}.@refill
 @end defopt
 
 @defopt idlwave-pad-keyword (@code{t})
 @cindex Mouse binding to print expressions
 
 When execution is stopped you can examine the values of variables.  The
-command @kbd{C-c C-d C-p} prints the expression at point in the shell
-buffer, while @kbd{C-c C-d ?} shows help on this expression.  The
-expression at point is an array expression or a function call, or the
-contents of a pair of parenthesis.  The selected expression becomes
-highlighted in the source code for a short time.
+command @kbd{C-c C-d C-p} prints the expression at point, while @kbd{C-c
+C-d ?} shows help on this expression.  The expression at point is an
+array expression or a function call, or the contents of a pair of
+parenthesis.  The selected expression becomes highlighted in the source
+code for a short time.  Calling the above commands with a prefix
+argument will prompt for an expression instead of using the one at
+point.
 
 I find it very convenient to bind these functions to a mouse event, so
-that simply clicking on an expression prints its value.  Here is a way
-to do this with XEmacs:
+that simply clicking on an expression prints its value.  The following
+code binds printing an expression to a click with mouse button 2 while
+holding down the @key{SHIFT} key:
 
 @lisp
 (add-hook 'idlwave-shell-mode-hook
 	  (lambda() 
-	    (define-key idlwave-mode-map [(shift button1)]
-	      'idlwave-shell-mouse-print)
-	    (define-key idlwave-mode-map [(shift button2)]
-	      'idlwave-shell-mouse-help)))
+	    (define-key idlwave-mode-map [(shift mouse-2)]
+	      'idlwave-shell-mouse-print)))
 @end lisp
 
+Printing of expressions also works on higher levels of the calling
+stack.  This means that you can examine the values of variables and
+expressions inside the routine which called the current routine etc.
+Use the commands @kbd{C-c C-d C-@key{UP}}
+(@code{idlwave-shell-stack-up}) and @kbd{C-c C-d C-@key{DOWN}}
+(@code{idlwave-shell-stack-down}) or the corresponding toolbar buttons
+to move through the calling stack.  The mode line will indicate the
+routine and the calling stack level which define the context for
+printing expressions.  The following restrictions apply for all levels
+except the current:@refill
+
+@itemize @bullet
+@item
+Array expressions must use the @samp{[ ]} index delimiters.  Identifiers
+with a @samp{( )} will be interpreted as function calls.
+@item
+Variable names in the expression may not start with an underscore
+@samp{_}.
+@item
+@cindex ROUTINE_NAMES, IDL procedure
+Printing values of expressions on higher levels of the calling stack
+uses the @emph{unsupported} IDL routine @code{ROUTINE_NAMES}, which may
+or may not be available in future versions of IDL.
+@end itemize
+
 @defopt idlwave-shell-expression-face
 The face for @code{idlwave-shell-expression-overlay}.
 Allows you to choose the font, color and other properties for
 the expression printed by IDL.
 @end defopt
 
+@defopt idlwave-shell-print-expression-function (@code{nil})
+A function to handle special display of evaluated expressions.
+@end defopt
 
 @node Installation, Acknowledgement, The IDLWAVE Shell, Top
 @chapter Installation
 @node Installing IDLWAVE, Upgrading from idl.el, Installation, Installation
 @section Installing IDLWAVE
 
-IDLWAVE is part of Emacs 21.1 and later.  It is also@footnote{or will be
-soon} an XEmacs packages and can be installed from
+IDLWAVE is part of Emacs 21.1 and later.  It is also an XEmacs packages
+and can be installed from
 @uref{ftp://ftp.xemacs.org/pub/xemacs/packages/,the XEmacs ftp site}
 with the normal package management system on XEmacs 21.@refill
 
 @lisp
 (setq idlwave-shell-use-dedicated-frame t)
 @end lisp
+@item 
+The key sequence @kbd{M-@key{TAB}} no longer inserts a TAB character,
+but (as in many other Emacs modes) does completion.  Inserting a TAB is
+now bound to @kbd{C-c @key{SPC}}.@refill
 @end enumerate
 
 @node Acknowledgement, Sources of Routine Info, Installation, Top
 usually not a serious problem.  However, if you have scanned the part of
 the library relevant for you, and if you are not compiling files which
 are not on the library search path, the information about compiled
-routines is in fact unnecessary.  In this case, you can turn of the
+routines is in fact unnecessary.  In this case, you can turn off the
 shell query for compiled routines with the variable
 @code{idlwave-query-shell-for-routine-info}.@refill
 
 actually set in your own configuration?
 
 @noindent
-@b{Answer:} Hardly any.  As the maintainer, I set the default of all
-options to what I think is best.  However, I do not turn on features by
-default which
+@b{Answer:} Hardly any.  As the maintainer, I set the default of most
+options to what I think is best.  However, the default settings do not
+turn on features which
 @itemize @minus
 @item
 are not self-evident (i.e. too magic) when used by an unsuspecting user
 break with what I think are widely used standards.
 @end itemize
 
-@noindent To see what I mean, here is the entire configuration I have in
-my @file{.emacs}:
+@noindent To see what I mean, here is the @emph{entire} configuration I
+have in my @file{.emacs}:
 
 @lisp
 (setq idlwave-shell-activate-alt-keybindings t
     ;;
     ;; Only pad after comma and with exactly 1 space
     (idlwave-action-and-binding "," '(idlwave-surround nil 1))
+    (idlwave-action-and-binding "&" '(idlwave-surround 1 1))
     ;;
+    ;; Pad only after `->', remove any space before the arrow
+    (idlwave-action-and-binding "->"  '(idlwave-surround 0 -1 nil 2))
+    ;;;
     ;; Set some personal bindings
     ;; (In this case, makes `,' have the normal self-insert behavior.)
     (local-set-key "," 'self-insert-command)
 (setq idlwave-shell-prompt-pattern "^WAVE> ")  ; default is "^IDL> "
 (setq idlwave-shell-explicit-file-name "wave")
 (setq idlwave-shell-process-name "wave")
-(setq idlwave-shell-use-dedicated-frame t)     ; Shell on separate frame
 (setq idlwave-shell-use-toolbar nil)           ; No toolbar
 @end example