254 lines
9.6 KiB
EmacsLisp
254 lines
9.6 KiB
EmacsLisp
|
;;; ess-toolbar.el --- Support for a toolbar in ESS.
|
||
|
|
||
|
;; Copyright (C) 1997--2009 A.J. Rossini, Richard M. Heiberger, Martin
|
||
|
;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen.
|
||
|
|
||
|
;; Author: Stephen Eglen
|
||
|
;; Created: 2004-05-06
|
||
|
;; Revised: 2009-03-16
|
||
|
;; Maintainer: ESS-core <ESS-core@r-project.org>
|
||
|
|
||
|
;; This file is part of ESS
|
||
|
|
||
|
;; This file 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.
|
||
|
|
||
|
;; This file 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.
|
||
|
|
||
|
;; A copy of the GNU General Public License is available at
|
||
|
;; http://www.r-project.org/Licenses/
|
||
|
|
||
|
;;; Commentary:
|
||
|
|
||
|
;; This code adds a toolbar to ESS modes for editing R and S code.
|
||
|
;; Support can be added for other modes (e.g. STATA), just ask!
|
||
|
;;
|
||
|
;; This code is experimental, and runs best on Emacs 21 and XEmacs
|
||
|
;; 21. It has been tested only on Linux machines. All feedback
|
||
|
;; appreciated.
|
||
|
;;
|
||
|
;; If your emacs can support images, the ESS toolbar should be loaded.
|
||
|
;;
|
||
|
;; If you see a toolbar, but no icons, check out the value of
|
||
|
;; ess-icon-directory.
|
||
|
;;
|
||
|
;; The toolbar can be customized in several ways. To see options, do:
|
||
|
;; M-x customize-group RET ess-toolbar RET
|
||
|
;; If you change any of the variables, you _may_ need to restart Emacs
|
||
|
;; to see any effect. See also the documentation for ess-toolbar-items
|
||
|
;; if you wish to change its value.
|
||
|
|
||
|
;;; Technical issues.
|
||
|
|
||
|
;; 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.
|
||
|
|
||
|
;; 2009-03-16: toolbar code in Emacs 23 has changed slightly to 22,
|
||
|
;; and presumably once Emacs 22 is no longer supported, this code can
|
||
|
;; be cleaned up a bit (i.e. no need to set load-path.)
|
||
|
|
||
|
;;; Code:
|
||
|
|
||
|
(defgroup ess-toolbar nil
|
||
|
"ESS: toolbar support."
|
||
|
:group 'ess
|
||
|
:link '(emacs-commentary-link :tag "Commentary" "ess-toolbar.el")
|
||
|
:prefix "ess-")
|
||
|
|
||
|
(defcustom ess-use-toolbar
|
||
|
(if (featurep 'xemacs)
|
||
|
(memq (device-type) '(x gtk mswindows))
|
||
|
(and (fboundp 'display-images-p) (display-images-p)))
|
||
|
"*Non-nil means ESS should support the toolbar.
|
||
|
Currently works only under Emacs 21 and maybe XEmacs 21.4."
|
||
|
:group 'ess-toolbar
|
||
|
:type 'boolean)
|
||
|
|
||
|
|
||
|
(defcustom ess-toolbar-own-icons nil
|
||
|
"*Non-nil means that we only put our toolbar entries in ESS.
|
||
|
Otherwise we get standard toolbar as well as ESS entries.
|
||
|
Under Emacs, the standard toolbar items are copied from the default toolbar.
|
||
|
Under XEmacs, the items stored in `ess-toolbar-xemacs-general' are added."
|
||
|
:group 'ess-toolbar
|
||
|
:type 'boolean)
|
||
|
|
||
|
(defcustom ess-toolbar-global nil
|
||
|
"*Non-nil means that the ESS toolbar is available in all emacs buffers.
|
||
|
Otherwise, the ESS toolbar is present only in R/S mode buffers.
|
||
|
For beginners, this is probably better set to a non-nil value."
|
||
|
:group 'ess-toolbar
|
||
|
:type 'boolean)
|
||
|
|
||
|
(defcustom ess-toolbar-items
|
||
|
'( (R "startr" "Start R process")
|
||
|
;;(S "spluslogo" "Start S process")
|
||
|
(S "splus_letter_small" "Start S process")
|
||
|
(ess-eval-line-and-step "rline" "Eval line & step")
|
||
|
(ess-eval-region "rregion" "Eval region")
|
||
|
(ess-eval-function-or-paragraph-and-step "rregion"
|
||
|
"Eval function or paragraph and step")
|
||
|
(ess-load-file "rbuffer" "Load file")
|
||
|
(ess-eval-function "rfunction" "Eval function")
|
||
|
(ess-switch-to-ESS "switch_ess" "Switch to ESS buffer"))
|
||
|
"Items to be added to the ESS toolbar.
|
||
|
Each list element has three items:
|
||
|
1. the name of the function to run
|
||
|
2. the icon to be used (without .xpm extension)
|
||
|
3. the tooltip doc string (XEmacs only; Emacs gets doc string from menu items.
|
||
|
|
||
|
General toolbar items are also added to the ESS toolbar
|
||
|
iff `ess-toolbar-own-icons' is nil.
|
||
|
|
||
|
Setting this variable with setq doesn't take effect once you have
|
||
|
loaded ess-site, unless you follow it by a call to
|
||
|
`ess-make-toolbar' afterwards. Instead, change its value using
|
||
|
Custom, and then on all new ESS buffers you should see the
|
||
|
toolbar has changed."
|
||
|
:group 'ess-toolbar
|
||
|
:set (lambda (symbol value)
|
||
|
(set-default symbol value)
|
||
|
(if (fboundp 'ess-make-toolbar)
|
||
|
(ess-make-toolbar)))
|
||
|
:type '(repeat (list (function :tag "Function to run")
|
||
|
(string :tag "Icon")
|
||
|
(string :tag "Tooltip"))))
|
||
|
|
||
|
(defvar ess-icon-directory
|
||
|
(expand-file-name (concat (file-name-as-directory ess-etc-directory) "icons"))
|
||
|
"*Location for ESS icons.
|
||
|
This variable should be set automatically by the ESS install process.
|
||
|
Icons should be found in ESS/etc/icons/ directory.
|
||
|
If `ess-icon-directory' is invalid, please report a bug.")
|
||
|
|
||
|
(unless (file-directory-p ess-icon-directory)
|
||
|
(ess-write-to-dribble-buffer
|
||
|
"`ess-icon-directory' does not exist; using `ess-etc-directory'.\n")
|
||
|
(setq ess-icon-directory ess-etc-directory))
|
||
|
|
||
|
(defvar ess-toolbar nil
|
||
|
"Toolbar items to be added to ESS editing buffers.")
|
||
|
|
||
|
(defun ess-make-toolbar ()
|
||
|
"Make the ESS toolbar."
|
||
|
(if (featurep 'xemacs)
|
||
|
(ess-make-toolbar-xemacs)
|
||
|
;; Under Emacs, only worth building the toolbar if tool-bar-map is
|
||
|
;; available. e.g. when running Emacs within a terminal, tool-bar-map
|
||
|
;; is not available, so no need to make the tool-bar.
|
||
|
(if (boundp 'tool-bar-map)
|
||
|
(ess-make-toolbar-emacs))))
|
||
|
|
||
|
(defun ess-make-toolbar-emacs ()
|
||
|
"Make the ESS toolbar under Emacs."
|
||
|
(setq ess-toolbar
|
||
|
(if (or ess-toolbar-own-icons (null tool-bar-map))
|
||
|
(make-sparse-keymap)
|
||
|
(copy-keymap tool-bar-map)))
|
||
|
(let ((tool-bar-map ess-toolbar)
|
||
|
(load-path (list ess-icon-directory)))
|
||
|
;; in Emacs 22, icons are found by examining load-path, bound here
|
||
|
;; whereas Emacs 23 seems to want them in image-load-path, set at the
|
||
|
;; bottom of this file.
|
||
|
(mapc 'ess-add-icon-emacs ess-toolbar-items)))
|
||
|
|
||
|
(defun ess-add-icon-emacs (x)
|
||
|
"Add an ESS item to the Emacs toolbar."
|
||
|
;; By using tool-bar-add-item-from-menu instead of tool-bar-add-item
|
||
|
;; we get the tooltips "for free" from ess-mode-map.
|
||
|
(tool-bar-add-item-from-menu (car x) (cadr x) ess-mode-map))
|
||
|
|
||
|
(defun ess-add-icon-xemacs (x)
|
||
|
"Return a 4-vector containing the spec for an ESS toolbar entry in XEmacs."
|
||
|
(vector
|
||
|
(toolbar-make-button-list
|
||
|
(expand-file-name (concat (cadr x) ".xpm") ess-icon-directory))
|
||
|
(car x) ;function
|
||
|
t
|
||
|
(nth 2 x) ;doc string
|
||
|
))
|
||
|
|
||
|
(defvar ess-toolbar-xemacs-general
|
||
|
(list
|
||
|
[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-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]
|
||
|
)
|
||
|
"General Xemacs icons to be added iff `ess-toolbar-own-icons' is non-nil.
|
||
|
These toolbar items were taken from the list that John Fox's code provided.
|
||
|
Each vector is of length four specifying: 1 - icon; 2 - function to call;
|
||
|
3 - whether to activate; 4 - doc string.")
|
||
|
|
||
|
(defun ess-make-toolbar-xemacs ()
|
||
|
"Set up the ESS toolbar for XEmacs."
|
||
|
(setq ess-toolbar
|
||
|
(append (if ess-toolbar-own-icons nil ess-toolbar-xemacs-general)
|
||
|
(mapcar 'ess-add-icon-xemacs ess-toolbar-items)))
|
||
|
)
|
||
|
|
||
|
(defun ess-add-toolbar ()
|
||
|
"Add the ESS toolbar to a particular mode.
|
||
|
The toolbar is added iff `ess-toolbar-global' is nil, else the toolbar
|
||
|
is added globally when ess-toolbar.el is loaded."
|
||
|
(if (and ess-toolbar (not ess-toolbar-global))
|
||
|
(if (featurep 'xemacs)
|
||
|
(set-specifier default-toolbar ess-toolbar (current-buffer))
|
||
|
;; Support for Emacs
|
||
|
(set (make-local-variable 'tool-bar-map) ess-toolbar))))
|
||
|
|
||
|
;; 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)
|
||
|
;; After making the toolbar, if ESS toolbar is needed globally,
|
||
|
;; add it here.
|
||
|
(if ess-toolbar-global
|
||
|
(if (featurep 'xemacs)
|
||
|
;; Xemacs
|
||
|
(progn
|
||
|
(set-specifier default-toolbar ess-toolbar)
|
||
|
(ess-write-to-dribble-buffer "Creating global XEmacs toolbar"))
|
||
|
;; Emacs
|
||
|
(setq tool-bar-map ess-toolbar)
|
||
|
(ess-write-to-dribble-buffer "Creating global Emacs toolbar"))
|
||
|
)
|
||
|
|
||
|
;; Check for toolbar support - needed iff ess-use-toolbar is non-nil.
|
||
|
(or
|
||
|
;; XEmacs test for image support, adapted from vm-version.el:
|
||
|
(and (featurep 'xemacs) (memq (device-type) '(x gtk mswindows)))
|
||
|
;;
|
||
|
;; Emacs support for images:
|
||
|
(and (fboundp 'display-images-p) (display-images-p))
|
||
|
;; if above tests failed, give a warning.
|
||
|
(progn
|
||
|
(message "Toolbar support for ESS not available in this emacs.")
|
||
|
;; Not sure if we want to delay startup of ESS.
|
||
|
;;(sit-for 2)
|
||
|
))
|
||
|
))
|
||
|
|
||
|
;; Following needed for Emacs 23, not Emacs 22 (nor XEmacs).
|
||
|
(when (boundp 'image-load-path)
|
||
|
(add-to-list 'image-load-path ess-icon-directory))
|
||
|
|
||
|
(provide 'ess-toolbar)
|
||
|
|
||
|
;;; ess-toolbar.el ends here
|