1 ;;; essd-iw32.el --- ESS customization for ddeclients under Windows 9x/NT
3 ;; Copyright (C) 1998--1999 Richard M. Heiberger <rmh@fisher.stat.temple.edu>
4 ;; Copyright (C) 2000--2004 A.J. Rossini, Rich M. Heiberger, Martin
5 ;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen.
7 ;; Original Author: Richard M. Heiberger <rmh@fisher.stat.temple.edu>
9 ;; Maintainers: ESS-core <ESS-core@stat.math.ethz.ch>
11 ;; This file is part of ESS
13 ;; This file is free software; you can redistribute it and/or modify
14 ;; it under the terms of the GNU General Public License as published by
15 ;; the Free Software Foundation; either version 2, or (at your option)
18 ;; This file is distributed in the hope that it will be useful,
19 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
20 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 ;; GNU General Public License for more details.
23 ;; You should have received a copy of the GNU General Public License
24 ;; along with GNU Emacs; see the file COPYING. If not, write to
25 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
29 ;; Code for dealing with running external processes on Windows 9x/NT
35 \f ; Requires and autoloads
43 (defun ess-eval-region-ddeclient (start end toggle &optional message even-empty)
44 "Loop through lines in region and send them to ESS via ddeclient.
45 The prefix argument is ignored when ddeclient is used"
46 (setq inferior-ess-ddeclient
47 (ess-get-process-variable
48 ess-current-process-name 'inferior-ess-ddeclient))
49 (setq inferior-ess-client-name
50 (ess-get-process-variable
51 ess-current-process-name 'inferior-ess-client-name))
52 (setq inferior-ess-client-command
53 (ess-get-process-variable
54 ess-current-process-name 'inferior-ess-client-command))
55 (narrow-to-region start end)
58 (while (or (< (point) (point-max))
59 (and (= 1 (point-max)) even-empty))
62 ;; call-process-region won't send over a 0-character line.
63 ;; We go outside the loop to create a 1-character line " " in the
64 ;; *ESS-temporary* buffer
65 (if (= beg (point)) ;; do empty line outside loop
66 (ess-eval-linewise-ddeclient " " nil 'eob t)
67 ;;(call-process-region start end
68 ;; "ddeclient" nil nil nil "S-PLUS" "SCommand")
71 inferior-ess-ddeclient nil nil nil
72 inferior-ess-client-name inferior-ess-client-command))
76 (fset 'ess-eval-region-original (symbol-function 'ess-eval-region))
78 (defun ess-eval-region (start end toggle &optional message)
79 "Send the current region to the inferior ESS process. This is the
80 MS-Windows version of `ess-eval-region'. When used with S-Plus 4.x or
81 S-Plus 2000 the prefix argument is ignored; see the documentation for
82 `ess-eval-region-ddeclient'. When used with other ESS programs the
83 prefix argument will toggle meaning of `ess-eval-visibly-p'; see the
84 documentation for `ess-eval-region-original'."
86 (if (equal (ess-get-process-variable
87 ess-current-process-name 'inferior-ess-ddeclient)
88 (default-value 'inferior-ess-ddeclient))
89 (ess-eval-region-original start end toggle message)
90 (ess-force-buffer-current "Process to load into: ")
91 (ess-eval-region-ddeclient start end toggle message t))
96 ;;; switch between Splus by ddeclient and Splus running in an emacs buffer
97 (defun ess-eval-linewise-ddeclient
98 (text-withtabs &optional invisibly eob even-empty)
100 (set-buffer (get-buffer-create "*ESS-temporary*"))
101 (ess-setq-vars-local ess-customize-alist (current-buffer))
103 (insert text-withtabs)
104 (ess-eval-region-ddeclient (point-min) (point-max) t t even-empty)))
106 (fset 'ess-eval-linewise-original (symbol-function 'ess-eval-linewise))
108 (defun ess-eval-linewise (text-withtabs &optional invisibly eob even-empty)
109 (if (equal (ess-get-process-variable
110 ess-current-process-name 'inferior-ess-ddeclient)
111 (default-value 'inferior-ess-ddeclient))
112 (ess-eval-linewise-original text-withtabs invisibly eob even-empty)
113 (ess-eval-linewise-ddeclient text-withtabs invisibly eob even-empty)))
117 ;;; this works for Sqpe+4 and S+4
118 (defun ess-display-help-on-object-ddeclient (object)
119 "Display the ESS documentation for OBJECT in another window.
120 If prefix arg is given, forces a query of the ESS process for the help
121 file. Otherwise just pops to an existing buffer if it exists."
122 (ess-force-buffer-current "Process to load into: ")
123 (ess-eval-linewise (concat "help(" object ")")))
126 (fset 'ess-display-help-on-object-original
127 (symbol-function 'ess-display-help-on-object))
129 (defun ess-display-help-on-object (object)
130 (interactive "sHelp on: ")
131 (if (equal (ess-get-process-variable
132 ess-current-process-name 'inferior-ess-ddeclient)
133 (default-value 'inferior-ess-ddeclient))
134 (ess-display-help-on-object-original object)
135 (ess-display-help-on-object-ddeclient object))
140 ;;; Alternate version of ess-load-file, required with S+4.
141 ;;; This version sends the S-Plus command
142 ;;; source("filename")
143 ;;; to S. This version does not guarantee to save .Last.value
144 ;;; This version does not offer alternate buffers or editing capability.
147 ;;; this works for Sqpe+4 and S+4
148 (defun ess-load-file-ddeclient (filename)
149 "Load an S source file into an inferior ESS process."
150 ;; (require 'ess-inf) ; (rmh) not needed in function. require is on the file.
151 (ess-make-buffer-current)
152 (let ((source-buffer (get-file-buffer filename)))
153 (if (ess-check-source filename)
154 (error "Buffer %s has not been saved" (buffer-name source-buffer))
155 ;; Find the process to load into
158 (set-buffer source-buffer)
159 (ess-force-buffer-current "Process to load into: ")
160 ;; (ess-check-modifications) ;;; not possible with ddeclient
161 ;; it calls ess-command which requires two-way communication
162 ;; with the S-Plus process
164 (ess-eval-linewise (format inferior-ess-load-command filename))))
166 (fset 'ess-load-file-original
167 (symbol-function 'ess-load-file))
169 (defun ess-load-file (filename)
170 "Alternate version of `ess-load-file', required with S+4.
171 This version sends the S-Plus command
173 to S. This version does not guarantee to save .Last.value
174 This version does not offer alternate buffers or editing capability."
177 (and (eq major-mode 'ess-mode)
180 (read-file-name "Load S file: " nil nil t)))))
181 (if (equal (ess-get-process-variable
182 ess-current-process-name 'inferior-ess-ddeclient)
183 (default-value 'inferior-ess-ddeclient))
184 (ess-load-file-original filename)
185 (ess-load-file-ddeclient filename))
189 (defun ess-dump-object-ddeclient (object filename)
190 "Dump the ESS object OBJECT into file FILENAME."
191 (ess-force-buffer-current "Process to load into: ")
192 (ess-eval-linewise (concat "dump('" object "','" filename "')"))
194 (find-file filename))
197 (fset 'ess-dump-object-original
198 (symbol-function 'ess-dump-object))
200 (defun ess-dump-object (object filename)
201 "Dump the ESS object OBJECT into file FILENAME."
202 (if (equal (ess-get-process-variable
203 ess-current-process-name 'inferior-ess-ddeclient)
204 (default-value 'inferior-ess-ddeclient))
205 (ess-dump-object-original object filename)
206 (ess-dump-object-ddeclient object filename))
212 (fset 'ess-dump-object-into-edit-buffer-original
213 (symbol-function 'ess-dump-object-into-edit-buffer))
215 (defun ess-dump-object-into-edit-buffer (object)
216 "Dump the ESS object OBJECT into file FILENAME."
219 (ess-force-buffer-current "Process to dump from: ")
220 (list (read-string "Object to edit: "))))
221 (if (equal (ess-get-process-variable
222 ess-current-process-name 'inferior-ess-ddeclient)
223 (default-value 'inferior-ess-ddeclient))
224 (ess-dump-object-into-edit-buffer-original object)
225 (ess-dump-object-into-edit-buffer-ddeclient object))
231 (defun ess-dump-object-into-edit-buffer-ddeclient (object)
232 "Edit an ESS object in its own buffer.
234 Without a prefix argument, this simply finds the file pointed to by
235 `ess-source-directory'. If this file does not exist, or if a
236 prefix argument is given, a dump() command is sent to the ESS process to
237 generate the source buffer."
240 (ess-force-buffer-current "Process to dump from: ")
241 (ess-read-object-name "Object to edit: ")))
242 (let* ((dirname (file-name-as-directory
243 (if (stringp ess-source-directory)
247 (process-buffer (get-ess-process
248 ess-local-process-name)))
249 (ess-setq-vars-local ess-customize-alist)
250 (apply ess-source-directory nil)))))
251 (filename (concat dirname (format ess-dump-filename-template object)))
252 (old-buff (get-file-buffer filename)))
254 ;; If the directory doesn't exist, offer to create it
255 (if (file-exists-p (directory-file-name dirname)) nil
256 (if (y-or-n-p ; Approved
257 (format "Directory %s does not exist. Create it? " dirname))
258 (make-directory (directory-file-name dirname))
259 (error "Directory %s does not exist." dirname)))
262 ;; (1) Pop to an existing buffer containing the file in question
263 ;; (2) Find an existing file
264 ;; (3) Create a new file by issuing a dump() command to S
265 ;; Force option (3) if there is a prefix arg
267 (if current-prefix-arg
268 (ess-dump-object object filename)
271 (pop-to-buffer old-buff)
272 (message "Popped to edit buffer."))
273 ;; No current buffer containing desired file
274 (if (file-exists-p filename)
276 (ess-find-dump-file-other-window filename)
277 (message "Read %s" filename))
278 ;; No buffer and no file
279 (ess-dump-object object filename))))))
281 (defun ess-command-ddeclient (com &optional buf)
282 "ddeclient bypass of real ess-command"
283 (ess-eval-linewise com))
285 (fset 'ess-command-original (symbol-function 'ess-command))
287 (defun ess-command (com &optional buf sleep)
288 "This is the 'w32' version. Either calls the original `ess-command-original'
289 (see its doc) or `ess-command-ddeclient'."
291 (if buf ;;Mar 01 2002 rmh
294 (setq ess-local-process-name ess-current-process-name)))
295 (if (not (ess-ddeclient-p))
296 (ess-command-original com buf sleep)
297 (ess-force-buffer-current "Process to load into: ")
298 (ess-command-ddeclient com buf)))
302 \f ; Local variables section
304 ;;; This file is automatically placed in Outline minor mode.
305 ;;; The file is structured as follows:
308 ;;; Subsections: ;;;*;;;
309 ;;; Components: defuns, defvars, defconsts
310 ;;; Random code beginning with a ;;;;* comment
314 ;;; mode: outline-minor
315 ;;; outline-regexp: "\^L\\|\\`;\\|;;\\*\\|;;;\\*\\|(def[cvu]\\|(setq\\|;;;;\\*"
318 ;;; ess-iw32.el ends here