(require 'mouseme)
(defun ess-mouse-me ()
"Popup a menu of functions to run on selected string or region."
(interactive)
(ess-mouse-me-helper
(lambda ()
(or (x-popup-menu (list '(0 0)
(get-buffer-window (get-buffer (buffer-name))))
(funcall mouse-me-build-menu-function name))
(error "No command to run")))))
(defun ess-mouse-me-helper (func)
"Determine the string to use to process EVENT and call FUNC to get cmd."
(let (name sp sm mouse beg end cmd mmtype)
(save-match-data
(save-excursion
(setq sp (point))
(setq sm (mark t))
(setq mouse (point))
(if (and sm
(or (and transient-mark-mode mark-active)
(eq last-command 'mouse-drag-region))
(>= mouse (setq beg (min sp sm)))
(<= mouse (setq end (max sp sm))))
(setq name (buffer-substring beg end))
(setq name (funcall mouse-me-get-string-function))
(if (listp name)
(setq beg (nth 1 name)
end (nth 2 name)
name (car name))
(goto-char mouse)
(while (not (looking-at (regexp-quote name)))
(backward-char 1))
(setq beg (point))
(setq end (search-forward name))))))
(if (or (null name)
(and (stringp name) (string= name "" )))
(error "No string to pass to function"))
(setq cmd (funcall func))
(if (listp cmd)
(setq cmd (eval cmd)))
(setq mmtype (get cmd 'mouse-me-type))
(cond ((eq mmtype 'region)
(funcall cmd beg end))
((eq mmtype 'string)
(funcall cmd name))
(t
(funcall cmd name)))))
(defcustom ess-S-mouse-me-menu-commands-alist
'("S-Plus 4 and 6 GUI under Windows"
("Edit.data" . ess-mouse-me-Edit.data)
"----"
("print" . ess-mouse-me-print)
("summary" . ess-mouse-me-summary)
("plot" . ess-mouse-me-plot)
("show" . ess-mouse-me-show)
("help" . ess-display-help-on-object)
("args" . ess-mouse-me-args)
"----"
("Browser on" . ess-mouse-me-browser-on)
("Browser off" . ess-mouse-me-browser-off))
"*Command menu used by `mouse-me-build-menu'.
A alist of elements where each element is either a cons cell or a string.
If a cons cell the car is a string to be displayed in the menu and the
cdr is either a function to call passing a string to, or a list which evals
to a function to call passing a string to. If the element is a string
it makes a non-selectable element in the menu. To make a separator line
use a string consisting solely of hyphens.
The function returned from this menu will be called with one string
argument. Or if the function has the symbol property `mouse-me-type'
and if its value is the symbol `region' it will be called with the
beginning and ending points of the selected string. If the value is
the symbol `string' it will be called with one string argument."
:type '(repeat sexp)
:group 'mouseme)
(defun ess-mouse-me-Edit.data (string)
(ess-mouse-me-eval-expanded string "Edit.data(" ")" nil nil nil))
(defun ess-mouse-me-print (string)
(ess-mouse-me-eval-expanded string "" "" nil (ess-ddeclient-p) t))
(defun ess-mouse-me-summary (string)
(ess-mouse-me-eval-expanded string "summary(" ")" nil (ess-ddeclient-p) t))
(defun ess-mouse-me-plot (string)
(ess-mouse-me-eval-expanded string "plot(" ")") nil nil nil)
(defun ess-mouse-me-show (string)
(ess-mouse-me-eval-expanded string "show(" ")") nil nil nil)
(defun ess-mouse-me-args (string)
(ess-mouse-me-eval-expanded string "args(" ")" nil (ess-ddeclient-p) t))
(defun ess-mouse-me-browser-on (string)
(if (equal (substring ess-dialect 0 1) "R")
(ess-eval-linewise (concat "debug(" string ")"))
(ess-mouse-me-eval-expanded string "trace(" ", exit=browser)") nil nil nil))
(defun ess-mouse-me-browser-off (string)
(if (equal (substring ess-dialect 0 1) "R")
(ess-eval-linewise (concat "undebug(" string ")"))
(ess-mouse-me-eval-expanded string "untrace(" ")") nil nil nil))
(defun ess-mouse-me-eval-expanded (string &optional head tail commands-buffer
page value-returned)
"Send the expanded STRING to the inferior-ess process using `ess-command'
after first concating the HEAD and TAIL. Put answer in COMMANDS-BUFFER if
specified and not using ddeclient, otherwise in \"tmp-buffer\". In either
case the buffer containing the answer is renamed to the value of the
constructed command. If PAGE is non-nil and using ddeclient, expand
the string one more time by embedding it in a \"page()\" command."
(interactive)
(let* (scommand
page-scommand
(lproc-name ess-local-process-name)
(ess-mouse-customize-alist ess-local-customize-alist))
(if (not head) (setq head "summary("))
(if (not tail) (setq tail ")"))
(if (not commands-buffer) (setq commands-buffer
(get-buffer-create "tmp-buffer")))
(setq scommand (concat head string tail))
(if (ess-ddeclient-p)
(progn
(setq page-scommand (if page
(concat "page(" scommand ")")
scommand))
(set-buffer-file-coding-system 'undecided-dos)
(ess-command page-scommand commands-buffer)
(if (not value-returned)
nil
(sleep-for 2)
(switch-to-buffer (car (buffer-list)))))
(ess-make-buffer-current)
(switch-to-buffer commands-buffer)
(ess-setq-vars-local (eval ess-mouse-customize-alist) (current-buffer))
(setq ess-local-process-name lproc-name)
(ess-command (concat scommand "\n") commands-buffer)
(if (not value-returned) (switch-to-buffer (nth 1 (buffer-list)))))
(if (not value-returned)
nil
(if ess-microsoft-p
(while (search-forward "\r" nil t)
(replace-match "" nil t)))
(ess-transcript-mode (eval ess-mouse-customize-alist))
(setq ess-local-process-name lproc-name)
(rename-buffer scommand))))
(provide 'ess-mouse)
(make-variable-buffer-local 'mouse-me-menu-commands)
(defun ess-S-mouse-me-menu-commands ()
(if (equal ess-language "S")
(setq mouse-me-menu-commands ess-S-mouse-me-menu-commands-alist)))
(add-hook 'ess-mode-hook 'ess-S-mouse-me-menu-commands)
(add-hook 'inferior-ess-mode-hook 'ess-S-mouse-me-menu-commands)
(add-hook 'ess-transcript-mode-hook 'ess-S-mouse-me-menu-commands)