Commits

rsparapa  committed 13c8735

ESS: adding new files

  • Participants
  • Parent commits a175105

Comments (0)

Files changed (2)

File lisp/ess-rdired.el

+;;; ess-rdired.el --- prototype object browser for R, looks like dired mode.
+;; Author: Stephen Eglen <stephen@anc.ed.ac.uk>
+;; Maintainer: Stephen Eglen <stephen@anc.ed.ac.uk>
+;; Created: Thu 24 Oct 2002
+;; $Id$
+
+;; This file is not part of GNU Emacs.
+
+;; ess-rdired.el is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; ess-rdired.el is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;; This provides a dired-like buffer for R objects.  Instead of
+;; operating on files, we operate on R objects in the current
+;; environment.  Objects can be viewed, edited, deleted, plotted and
+;; so on.
+
+;; Installation and usage.
+;;
+;; Load in this library, e.g. with the command:
+;; (autoload 'ess-rdired "ess-rdired" "View *R* objects in a dired-like buffer." t)
+;;
+;; After loading this file, do "M-x R" to start an R session, then
+;; create a few variables:
+;; s <- sin(seq(from=0, to=8*pi, length=100))
+;; x <- c(1, 4, 9)
+;; y <- rnorm(20)
+;; z <- TRUE
+
+;; Then in Emacs, do "M-x ess-rdired" and you should see the following in
+;; the buffer *R dired*:
+;;        mode length
+;;   s numeric    100
+;;   x numeric      3
+;;   y numeric     20
+;;   z logical      1
+
+;; Type "?" in the buffer to see the documentation.  e.g. when the
+;; cursor is on the line for `s', type 'p' to plot it, or `v' to view
+;; its contents in a buffer.  Then type 'd' to mark it for deletion.
+
+;; How it works.
+
+;; Most of the hardwork is done by the R routine .rdired.objects(),
+;; which, when called, produces the list of objects in a tidy format.
+;; This function is stored within the lisp variable `ess-rdired-objects',
+;; and can be altered to provide other information if you so need it.
+;; (Martin Maechler suggested providing output from str() here.)
+
+;; Tested on Emacs 21.2, 21.3 pretest and XEmacs 21.1.14, using R 1.6.
+
+;; Todo - compare functionality with ess-mouse-me (ess-mous.el).
+
+;; Todo - How to select alternative environments?  Currently only
+;; shows objects in the .GlobalEnv?  See BrowseEnv() in 1.6.x for way
+;; of browsing other environments.
+
+;; Todo - problem with fix -- have to wait for fix() command to return
+;; before *R* buffer can be used again.  This can get stuck, umm. not
+;; sure what is going wrong here.  Maybe add a hook to the temp buffer
+;; so that when buffer is killed, we send an instruction to R to
+;; update the value of the variable to the contents of the buffer.
+;; This way *R* doesn't have to wait.
+
+;; Todo - small bug in .rdired.objects -- if we have a variable called
+;; `my.x', its value is replaced by the value of my.x used in the
+;; sapply() calls within .rdired.objects().
+
+
+(defvar ess-rdired-objects ".rdired.objects <- function(objs) {
+  if (length(objs)==0)
+    \"No objects to view!\"
+  else {
+  mode <- sapply(objs, function(my.x) {
+    eval(parse(text=(paste('data.class(',my.x,')',sep=''))))})
+  length <- sapply(objs, function(my.x) {
+    eval(parse(text=(paste('length(',my.x,')',sep=''))))
+  })
+  d <- data.frame(mode, length)
+  row.names(d) <- paste('  ', row.names(d), sep='')
+  d
+  }
+}; .rdired.objects(ls())"
+  "Function to call within R to print information on objects.  The last
+line of this string should be the instruction to call the
+function which prints the output for rdired.")
+
+(defvar ess-rdired-buffer "*R dired*"
+  "Name of buffer for displaying R objects.")
+
+(defvar ess-rdired-mode-map nil
+  "Keymap for the *R dired* buffer.")
+
+(if ess-rdired-mode-map
+    ()
+  (setq ess-rdired-mode-map (make-sparse-keymap))
+
+  (define-key ess-rdired-mode-map "?" 'ess-rdired-help)
+  (define-key ess-rdired-mode-map "d" 'ess-rdired-delete)
+  (define-key ess-rdired-mode-map "u" 'ess-rdired-undelete)
+  (define-key ess-rdired-mode-map "x" 'ess-rdired-expunge)
+  ;; editing requires a little more work.
+  ;;(define-key ess-rdired-mode-map "e" 'ess-rdired-edit)
+  (define-key ess-rdired-mode-map "v" 'ess-rdired-view)
+  (define-key ess-rdired-mode-map "V" 'ess-rdired-View)
+  (define-key ess-rdired-mode-map "p" 'ess-rdired-plot)
+  (define-key ess-rdired-mode-map "s" 'ess-rdired-sort)
+  (define-key ess-rdired-mode-map "q" 'ess-rdired-quit)
+  (define-key ess-rdired-mode-map "y" 'ess-rdired-type)	;what type?
+  (define-key ess-rdired-mode-map " "  'ess-rdired-next-line)
+  (define-key ess-rdired-mode-map [backspace] 'ess-rdired-previous-line)
+  (define-key ess-rdired-mode-map "\C-n" 'ess-rdired-next-line)
+  (define-key ess-rdired-mode-map "\C-p" 'ess-rdired-previous-line)
+
+  ;; R mode keybindings.
+  (define-key ess-rdired-mode-map "\C-c\C-s" 'ess-rdired-switch-process)
+  (define-key ess-rdired-mode-map "\C-c\C-y" 'ess-switch-to-ESS)
+  (define-key ess-rdired-mode-map "\C-c\C-z" 'ess-switch-to-end-of-ESS)
+
+  (define-key ess-rdired-mode-map [down] 'ess-rdired-next-line)
+  (define-key ess-rdired-mode-map [up] 'ess-rdired-previous-line)
+  (define-key ess-rdired-mode-map "g" 'revert-buffer)
+  (if (featurep 'xemacs)
+      (define-key ess-rdired-mode-map [button2] 'ess-rdired-mouse-view)
+    (define-key ess-rdired-mode-map [mouse-2] 'ess-rdired-mouse-view)
+    ))
+
+(defun ess-rdired-mode ()
+  "Major mode for output from `ess-rdired'.
+`ess-rdired' provides a dired-like mode for R objects.  It shows the
+list of current objects in the current environment, one-per-line.  You
+can then examine these objects, plot them, and so on.
+\\{ess-rdired-mode-map}"
+  (kill-all-local-variables)
+  (make-local-variable 'revert-buffer-function)
+  (setq revert-buffer-function 'ess-rdired-revert-buffer)
+  (use-local-map ess-rdired-mode-map)
+  (setq major-mode 'ess-rdired-mode)
+  (setq mode-name (concat "RDired " ess-local-process-name)))
+
+(defun ess-rdired ()
+  "Run dired-like mode on R objects.
+This is the main function.  See documentation for `ess-rdired-mode' though
+for more information!"
+  (interactive)
+  (if (get-buffer ess-rdired-buffer)
+      (progn
+	(set-buffer ess-rdired-buffer)
+	(setq buffer-read-only nil)))
+
+   (ess-execute ess-rdired-objects
+		nil
+		(substring ess-rdired-buffer 1 (- (length ess-rdired-buffer) 1))
+		)
+
+  (pop-to-buffer ess-rdired-buffer)
+  ;; When definiting the function .rdired.objects(), a "+ " is printed
+  ;; for every line of the function definition; these are deleted
+  ;; here.
+  (delete-char (* (1- (length (split-string ess-rdired-objects "\n"))) 2))
+
+  ;; todo: not sure how to make ess-rdired-sort-num buffer local?
+  ;;(set (make-local-variable 'ess-rdired-sort-num) 2)
+  ;;(make-variable-buffer-local 'ess-rdired-sort-num)
+  (setq ess-rdired-sort-num 1)
+  (ess-rdired-insert-set-properties (save-excursion
+				  (goto-char (point-min))
+				  (forward-line 1)
+				  (point))
+				(point-max))
+  (setq buffer-read-only t)
+  (ess-rdired-mode)
+  )
+
+(defun ess-rdired-object ()
+  "Return name of object on current line."
+  (save-excursion
+    (beginning-of-line)
+    (forward-char 2)
+    (if (looking-at " ")
+	nil				;on first line
+      ;;
+      (let (beg end)
+	(setq beg (point))
+	(search-forward " ")		;assume space follows object name.
+	(buffer-substring-no-properties beg (1- (point)))))))
+
+(defun ess-rdired-edit ()
+  "Edit (fix) the object at point."
+  (interactive)
+  (let ((objname (ess-rdired-object)))
+    (ess-command (concat "edit(" objname ")\n"))))
+
+(defun ess-rdired-view ()
+  "View the object at point."
+  (interactive)
+  (let ((objname (ess-rdired-object)))
+    (ess-execute objname nil "R view" )))
+
+(defun ess-rdired-View ()
+  "View the object at point in its own buffer.
+Like `ess-rdired-view', but the object gets its own buffer name."
+  (interactive)
+  (let ((objname (ess-rdired-object)))
+    (ess-execute ;;(concat "edit(" objname ")\n")
+     objname
+     nil (concat "R view " objname ))))
+
+(defun ess-rdired-plot ()
+  "Plot the object on current line."
+  (interactive)
+  (let ((objname (ess-rdired-object)))
+    (ess-command (concat "plot(" objname ")\n"))))
+
+(defun ess-rdired-type ()
+  "Run the mode() on command at point.
+Named type because of similarity
+with the dired command bound to y key."
+  (interactive)
+  (let ((objname (ess-rdired-object))
+	;; create a temp buffer, and then show output in echo area
+	(tmpbuf (get-buffer-create "**ess-rdired-mode**")))
+    (if objname
+	(progn
+	  (ess-command (concat "mode(" objname ")\n")  tmpbuf )
+	  (set-buffer tmpbuf)
+	  (message (concat
+		    objname ": "
+		    (buffer-substring (+ 4 (point-min)) (1- (point-max)))))
+	  (kill-buffer tmpbuf)))))
+
+(defun ess-rdired-delete (arg)
+  "Mark the current (or next ARG) objects for deletion.
+If point is on first line, all objects are marked for deletion."
+  (interactive "p")
+  (ess-rdired-mark "D" arg))
+
+(defun ess-rdired-undelete (arg)
+  "Unmark the current (or next ARG) objects.
+If point is on first line, all objects will be unmarked."
+  (interactive "p")
+  (ess-rdired-mark " " arg))
+
+(defun ess-rdired-mark (mark-char arg)
+  "Mark the object, using MARK-CHAR,  on current line (or next ARG lines)."
+  ;; If we are on first line, mark all lines.
+  (let ((buffer-read-only nil)
+	move)
+    (if (eq (point-min)
+	    (save-excursion (beginning-of-line) (point)))
+	(progn
+	  ;; we are on first line, so make a note of point, and count
+	  ;; how many objects we want to delete.  Then at end of defun,
+	  ;; restore point.
+	  (setq move (point))
+	  (forward-line 1)
+	  (setq arg (count-lines (point) (point-max)))))
+    (while (and (> arg 0) (not (eobp)))
+      (setq arg (1- arg))
+      (beginning-of-line)
+      (progn
+	(insert mark-char)
+	(delete-char 1)
+	(forward-line 1)))
+    (if move
+	(goto-char move))))
+
+
+(defun ess-rdired-expunge ()
+  "Delete the marked objects.
+User is queried first to check that objects should really be deleted."
+  (interactive)
+  (let ((objs "rm(") 
+	(count 0))
+    (save-excursion
+      (goto-line 2)
+      (while (< (count-lines (point-min) (point))
+		(count-lines (point-min) (point-max)))
+	(beginning-of-line)
+	(if (looking-at "^D ")
+	    (setq count (1+ count)
+		  objs (concat objs (ess-rdired-object) ", " )))
+	(forward-line 1)
+	))
+    (if (> count 0)
+	;; found objects to delete
+	(progn
+	  (setq objs (concat
+		      (substring objs 0 (- (length objs) 2))
+		      ")\n"))
+	  (if (yes-or-no-p (format "Delete %d %s " count
+				   (if (> count 1) "objects" "object")))
+	      (progn
+		(ess-command objs)
+		(ess-rdired)
+		)))
+      ;; else nothing to delete
+      (message "no objects set to delete")
+      )))
+
+;; Fancy delete method, based on dired.  Bit too much for our needs?
+;; (defun ess-rdired-expunge ()
+;;   "Delete the marked objects.
+;; User is queried first to check that objects should really be deleted."
+;;   (interactive)
+;;   (let ((objs)
+;;	(cmd "rm("))
+;;     (save-excursion
+;;       (goto-line 2)
+;;       (while (< (count-lines (point-min) (point))
+;;		(count-lines (point-min) (point-max)))
+;;	(beginning-of-line)
+;;	(if (looking-at "^D ")
+;;	    (progn
+;;	      (setq objs (cons (ess-rdired-object) objs ))
+;;	      (setq cmd (concat cmd (ess-rdired-object) ", "))
+;;	      ))
+;;	(forward-line 1)
+;;	))
+;;     (if (> (length objs) 0)
+;;	;; found objects to delete
+;;	(if
+;;	    (dired-mark-pop-up "*RDired deletions*" 'delete
+;;			       objs dired-deletion-confirmer
+;;			       (format "delete %s "
+;;				       (dired-mark-prompt nil objs)))
+;;	    ;; should delete the objects.
+;;	    (progn
+;;	      (setq cmd (concat (substring cmd 0 (- (length cmd) 2))
+;;				")\n"))
+;;	      (ess-command cmd)
+;;	      (ess-rdired)))
+;;       ;; else nothing to delete
+;;       (message "no objects set to delete")
+;;       )))
+
+(defun ess-rdired-quit ()
+  "Quit the R dired buffer."
+  (interactive)
+  (kill-buffer ess-rdired-buffer))
+
+(defun ess-rdired-revert-buffer (ignore noconfirm)
+  "Update the buffer list (in case object list has changed).
+Arguments IGNORE and NOCONFIRM currently not used."
+  (ess-rdired))
+
+(defun ess-rdired-help ()
+  "Show help for `ess-rdired-mode'."
+  (interactive)
+  (describe-function 'ess-rdired-mode))
+
+(defun ess-rdired-sort ()
+  "Sort the rdired output according to one of the columns.
+Rotate between the alternative sorting methods."
+  (interactive)
+  (setq ess-rdired-sort-num (1+ ess-rdired-sort-num))
+  (let ((buffer-read-only nil)
+	(beg (save-excursion
+	       (goto-char (point-min))
+	       (forward-line 1)
+	       (point)))
+	(end (point-max)))
+  (if (> ess-rdired-sort-num 3)
+      (setq ess-rdired-sort-num 1))
+  (cond ((eq ess-rdired-sort-num 1)
+	 (sort-fields 1 beg end))
+	((eq ess-rdired-sort-num 2)
+	 (sort-fields 2 beg end))
+	((eq ess-rdired-sort-num 3)
+	 (sort-numeric-fields 3 beg end)))))
+
+(defun ess-rdired-next-line (arg)
+  "Move down lines then position at object.
+Optional prefix ARG says how many lines to move; default is one line."
+  (interactive "p")
+  (next-line arg)
+  (ess-rdired-move-to-object))
+
+(defun ess-rdired-previous-line (arg)
+  "Move up lines then position at object.
+Optional prefix ARG says how many lines to move; default is one line."
+  (interactive "p")
+  (previous-line arg)
+  (ess-rdired-move-to-object))
+
+(defun ess-rdired-move-to-object ()
+  "Put point at start of object."
+  (beginning-of-line)
+  (forward-char 2)
+  )
+
+(defun ess-rdired-mouse-view (event)
+  "In rdired, visit the object on the line you click on."
+  (interactive "e")
+  (let (window pos)
+    (save-excursion
+      (if (featurep 'xemacs)
+	  ;; XEmacs
+	  (setq window (event-window event)
+		pos (event-point event))
+	;; Emacs
+	(setq window (posn-window (event-end event))
+	      pos (posn-point (event-end event))))
+      (if (not (windowp window))
+	  (error "No file chosen"))
+      (set-buffer (window-buffer window))
+      (goto-char pos)
+      (ess-rdired-view))))
+
+(defun ess-rdired-insert-set-properties (beg end)
+  "Add mouse highlighting to each object name in the R dired buffer."
+  (save-excursion
+    (goto-char beg)
+    (while (< (point) end)
+      (ess-rdired-move-to-object)
+      (add-text-properties
+       (point)
+       (save-excursion
+	 (search-forward " ")
+	 (1- (point)))
+       '(mouse-face highlight
+		    help-echo "mouse-2: view object in other window"))
+      (forward-line 1))))
+
+(defun ess-rdired-switch-process ()
+  "Switch to examine different *R* process.
+If you have multiple R processes running, e.g. *R*, *R:2*, *R:3*, you can
+use this command to choose which R process you would like to examine.
+After switching to a new process, the buffer is updated."
+  (interactive)
+  (ess-switch-process)
+  (ess-rdired))
+
+;;; ess-rdired.el ends here.

File lisp/ess-toolbar.el

+;;; ess-toolbar.el --- initial support for an ESS toolbar.
+;;; Thu 06 May 2004
+;;; Stephen Eglen
+;;; GPL.
+;; Modified: $Date$
+;; Version: $Revision$
+;; RCS: $Id$
+
+;;; Notes.
+
+;;; This code is experimental, and runs best on Emacs 21 and XEmacs
+;;; 21.  It has been tested only on Linux machines.  All feedback
+;;; appreciated.
+;;; To use this code, place the following in .emacs after you have
+;;; loaded ess-site:
+;;;
+;;; (setq ess-use-toolbar t)
+;;; (if (fboundp 'tool-bar-mode) (tool-bar-mode t))	;Emacs 21.
+;;; (require 'ess-toolbar)
+
+;;; If you see a toolbar, but no icons, check out the value of
+;;; ess-icon-directory.
+ 
+;;; Emacs vs XEmacs.
+
+;; Of course, Emacs and XEmacs have different interfaces and handle
+;; the toolbars in different ways.  The code here is rough, but
+;; hopefully soon a compatibility toolbar library will be released
+;; that will make the toolbar code more portable.  So, for now the
+;; code should be regarded as proof of concept.
+
+;; Also, I think the Mac OS X version of GNU Emacs does not yet have
+;; tool-bar support.  This may be present in very new versions of CVS
+;; Emacs.  Will check...
+
+
+
+;;; Creating pixmaps:
+;; Need to add backgrounToolBarColor for XEmacs to show okay.
+;;/usr/share/xemacs-21.4.12/etc/toolbar/folder-cap-up.xpm
+;; has header:
+;;"X	c Gray75 s backgroundToolBarColor",
+;; whereas I have set "c None" to indicate the background pixel; this line 
+;; seems to work for both toolbars.
+;;;". c None s backgroundToolBarColor",
+
+
+(defvar ess-use-toolbar (fboundp 'tool-bar-add-item)
+  "*Non-nil means we should support the toolbar.
+Currently works only under Emacs 21 and maybe XEmacs 21.4.")
+
+(defvar ess-own-toolbar nil
+  "*Non-nil means that we only put our toolbar entries in ESS.
+Otherwise we get standard toolbar as well as ESS entries.
+It might be better for the user if we have standard toolbar entries too,
+e.g. for saving/loading files.")
+
+(defvar ess-icon-directory 
+  (expand-file-name (concat ess-etc-directory "/icons"))
+  "*Location for ESS icons.
+Icons should be found in ESS/etc/icons/ directory.")
+
+(if (not (file-exists-p ess-icon-directory))
+    (message "Check that you have set `ess-icon-directory'."))
+
+;; Emacs has the ability to clear the cache.
+;; (clear-image-cache)
+
+
+(defvar ess-toolbar-R nil
+  "Emacs toolbar for R mode in ESS.")
+
+(defvar ess-toolbar-S nil
+  "Emacs toolbar for S mode in ESS.")
+
+(defun ess-make-toolbar-R ()
+  "Make the toolbar for R."
+  (if (featurep 'xemacs)
+      (ess-make-toolbar-R-xemacs)
+    (ess-make-toolbar-R-emacs)))
+
+(defun ess-make-toolbar-S ()
+  "Make the toolbar for S."
+  (if (featurep 'xemacs)
+      (ess-make-toolbar-S-xemacs)
+    (ess-make-toolbar-S-emacs)))
+
+(defun ess-make-toolbar-R-emacs ()
+  "Make the toolbar for R under Emacs."
+  (setq ess-toolbar-R 
+	(if (or ess-own-toolbar (null tool-bar-map))
+	    (make-sparse-keymap)
+	  (copy-keymap tool-bar-map)))
+  (let ((tool-bar-map ess-toolbar-R)
+	(load-path (list ess-icon-directory)))
+
+    ;; icons are found by examining load-path; hence by temporarily setting
+    ;; load-path to our icons directory, they will be found.
+    (tool-bar-add-item-from-menu 'R "startr" ess-mode-map)
+    (tool-bar-add-item-from-menu 'ess-eval-line-and-step "rline" ess-mode-map)
+    (tool-bar-add-item-from-menu 'ess-eval-region "rregion" ess-mode-map)
+    (tool-bar-add-item-from-menu 'ess-load-file "rbuffer" ess-mode-map)
+    (tool-bar-add-item-from-menu 'ess-eval-function "rfunction" ess-mode-map)
+    (tool-bar-add-item-from-menu 'ess-switch-to-ESS "switchr" ess-mode-map)
+    ))
+
+(defun ess-make-toolbar-S-emacs ()
+  "Make the toolbar for S under Emacs."
+  (setq ess-toolbar-S
+	(if (or ess-own-toolbar (null tool-bar-map))
+	    (make-sparse-keymap)
+	  (copy-keymap tool-bar-map)))
+  (let ((tool-bar-map ess-toolbar-S)
+	(load-path (list ess-icon-directory)))
+    
+    ;; icons are found by examining load-path; hence by temporarily setting
+    ;; load-path to our icons directory, they will be found.
+    (tool-bar-add-item-from-menu 'S "spluslogo" ess-mode-map)
+    (tool-bar-add-item-from-menu 'ess-eval-line-and-step "rline" ess-mode-map)
+    (tool-bar-add-item-from-menu 'ess-eval-region "rregion" ess-mode-map)
+    (tool-bar-add-item-from-menu 'ess-load-file "rbuffer" ess-mode-map)
+    (tool-bar-add-item-from-menu 'ess-eval-function "rfunction" ess-mode-map)
+    (tool-bar-add-item-from-menu 'ess-switch-to-ESS "switchs" ess-mode-map)
+    ))
+
+(defun ess-make-toolbar-S-xemacs ()
+  "Set up the R toolbar for XEmacs."
+  (message "Sorry, S toolbar under XEmacs not ready yet."))
+
+(defun ess-make-toolbar-R-xemacs ()
+  "Set up the R toolbar for XEmacs."
+
+  (defvar toolbar-send-line-icon
+    (toolbar-make-button-list
+     (expand-file-name "rline.xpm" ess-icon-directory))
+    "Send line to R")
+
+  (defvar toolbar-r-icon
+    (toolbar-make-button-list
+     (expand-file-name "startr.xpm" ess-icon-directory))
+    "Start R")
+  
+  (defvar toolbar-switch-ess-icon
+    (toolbar-make-button-list
+     (expand-file-name "switchr.xpm" ess-icon-directory))
+    "Switch to ESS")
+  
+  (defvar toolbar-send-para-icon
+    (toolbar-make-button-list
+     (expand-file-name "para.xpm" ess-icon-directory))
+    "Send paragraph to R")
+  
+  (defvar toolbar-send-function-icon
+    (toolbar-make-button-list
+     (expand-file-name "rfunction.xpm" ess-icon-directory))
+    "Send function to R")
+  
+  (defvar toolbar-send-reg-icon
+    (toolbar-make-button-list
+     (expand-file-name "rregion.xpm" ess-icon-directory))
+    "Send region to R")
+  
+  (defvar toolbar-source-icon
+    (toolbar-make-button-list
+     (expand-file-name "rbuffer.xpm" ess-icon-directory)))
+  
+  ;; the following is a modified version of ess-eval-line-and-go
+  
+  ;; make the toolbar
+  
+  (if (or t ess-use-toolbar)
+      (set-specifier 
+       default-toolbar 
+       '(
+	 [toolbar-file-icon toolbar-open t "Open a file"] 
+	 [toolbar-disk-icon toolbar-save t "Save buffer"] 
+	 [toolbar-printer-icon generic-print-buffer t "Print buffer"] ; toolbar-print doesn't work properly    
+	 [toolbar-cut-icon toolbar-cut t "Kill region"] 
+	 [toolbar-copy-icon toolbar-copy t "Copy region"] 
+	 [toolbar-paste-icon toolbar-paste t "Paste from clipboard"] 
+	 [toolbar-undo-icon toolbar-undo t "Undo edit"] 
+	 [toolbar-replace-icon toolbar-replace t "Search & Replace"] 
+	 [:style 3d]
+	 [toolbar-r-icon R t "Start R"]
+	 [toolbar-send-line-icon ess-eval-line-and-step t "Send line to R"]
+	 [toolbar-send-reg-icon ess-eval-region t "Send region to R"]
+	 [toolbar-source-icon ess-load-file t "Send file to R"]
+	 [toolbar-send-function-icon ess-eval-function t "Send function to R"]
+	 [toolbar-switch-ess-icon ess-switch-to-ESS t "Switch to ESS"]
+		       
+	 [toolbar-info-icon toolbar-info t "Info documentation"])))
+
+  )
+
+;; Make the toolbars.  Each toolbar is hopefully made only when this file
+;; is loaded; we don't need it to be remade every time.
+(if ess-use-toolbar
+    (progn
+      (ess-make-toolbar-R)
+      (ess-make-toolbar-S)
+      ))
+
+;; Temporary hack to hook the toolbar creation into R mode.  This should
+;; eventually be deleted/merged into the main source.
+;; Ditto for the S+6-mode defun here.
+(defun R-mode  (&optional proc-name)
+  "Major mode for editing R source.  See `ess-mode' for more help."
+  (interactive)
+  (setq ess-customize-alist R-customize-alist)
+  ;;(setq imenu-generic-expression R-imenu-generic-expression)
+  (ess-mode R-customize-alist proc-name)
+  ;; SJE: hook on Emacs for setting up tool-bar.
+  (if (and ess-toolbar-R (not (featurep 'xemacs)))
+      (set (make-local-variable 'tool-bar-map) ess-toolbar-R))
+  ;; ECB needs seminatic stuff.
+  ;;  (if (featurep 'semantic)
+  ;;      (setq semantic-toplevel-bovine-table r-toplevel-bovine-table))
+  ;; AJR: Need to condition on this...!
+  ;; MM: and you probably should really use ess-imenu-mode-function from the
+  ;;     alist above!
+  (if ess-imenu-use-S (ess-imenu-R)))
+
+(defun S+6-mode (&optional proc-name)
+  "Major mode for editing S+6 source.  See `ess-mode' for more help."
+  (interactive)
+  (setq ess-customize-alist S+6-customize-alist)
+  (ess-mode S+6-customize-alist proc-name)
+  ;; SJE: hook on Emacs for setting up tool-bar.
+  (if (and ess-toolbar-S (not (featurep 'xemacs)))
+      (set (make-local-variable 'tool-bar-map) ess-toolbar-S))
+  (if ess-imenu-use-S (ess-imenu-S)))
+
+(provide 'ess-toolbar)