(ess-r-args-get): Do not use zap-to-char within defun,
[ess.git] / lisp / essd-sp4.el
blob5f74ddb5ff04b9591ccc72f0c97b85a2090b3814
1 ;;; essd-sp4.el --- S-PLUS 4.x customization
3 ;; Copyright (C) 1998--2002 Richard M. Heiberger <rmh@temple.edu>
4 ;; Copyright (C) 2003--2004 A.J. Rossini, Rich M. Heiberger, Martin
5 ;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen.
7 ;; Original Author: Richard M. Heiberger <rmh@temple.edu>
8 ;; Created: December 1998
9 ;; Maintainers: ESS-core <ESS-core@stat.math.ethz.ch>
11 ;; Keywords: start up, configuration.
13 ;; This file is part of ESS.
15 ;; This file is free software; you can redistribute it and/or modify
16 ;; it under the terms of the GNU General Public License as published by
17 ;; the Free Software Foundation; either version 2, or (at your option)
18 ;; any later version.
20 ;; This file is distributed in the hope that it will be useful,
21 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
22 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 ;; GNU General Public License for more details.
25 ;; You should have received a copy of the GNU General Public License
26 ;; along with GNU Emacs; see the file COPYING. If not, write to
27 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
29 ;;; Commentary:
30 ;;; This file defines all the S-PLUS 4.x customizations for ess-mode
31 ;;; with ddeclient.
33 ;;; Requires and Autoloads:
35 (require 'essl-s)
36 ;;NO: this is autoloaded from other places (require 'ess-dde)
38 (autoload 'inferior-ess "ess-inf" "Run an ESS process.")
39 (autoload 'ess-mode "ess-mode" "Edit an ESS process.")
41 ;;; Code:
43 (defvar S+4-dialect-name "S+4"
44 "Name of 'dialect' for S-PLUS 4.x.");easily changeable in a user's .emacs
46 (defvar inferior-S+4-multipleinstances "/MULTIPLEINSTANCES"
47 "Default \"/MULTIPLEINSTANCES\" opens up a new instance of S+4 in a
48 GUI window and connects it to the '(ddeESS [S+4])' window. The
49 alternative nil uses an existing S+4 GUI (if there is one) and
50 connects it to the '(ddeESS [S+4])' window.")
52 (defvar S+4-customize-alist
53 (append
54 '((ess-local-customize-alist . 'S+4-customize-alist)
55 (ess-dialect . S+4-dialect-name)
56 (ess-loop-timeout . ess-S-loop-timeout);fixme: dialect spec.
57 (ess-object-name-db-file . "ess-sp4-namedb.el" )
58 (inferior-ess-program . inferior-S+4-program-name)
59 (inferior-ess-help-command . "help(\"%s\")\n")
60 (inferior-ess-help-filetype . "chm")
62 (inferior-ess-start-file . nil) ;"~/.ess-S+4")
63 (inferior-ess-start-args . (concat
64 inferior-S+4-multipleinstances " "
65 inferior-S+4-print-command
66 " S_PROJ="
67 (directory-file-name default-directory)))
68 ;; (inferior-ess-ddeclient . "ddeclient")
69 ;; (inferior-ess-client-name . "S-PLUS")
70 ;; (inferior-ess-client-command . "SCommand")
71 (ess-STERM . "ddeESS")
73 S+common-cust-alist)
75 "Variables to customize for S+4")
77 (defvar Sqpe+4-customize-alist
78 (append
79 '((ess-local-customize-alist . 'Sqpe+4-customize-alist)
80 (ess-dialect . S+4-dialect-name)
81 (ess-loop-timeout . 500000 );fixme: dialect specific custom.v
82 (ess-object-name-db-file . "ess-sp4-namedb.el" )
83 (inferior-ess-program . inferior-Sqpe+4-program-name)
84 (inferior-ess-help-command . "help(\"%s\")\n")
85 (inferior-ess-help-filetype . "chm")
86 (inferior-ess-search-list-command . "searchPaths()\n")
87 (inferior-ess-start-file . nil) ;"~/.ess-S+4")
88 (inferior-ess-language-start . (concat
89 "options("
90 "STERM='" ess-STERM "'"
91 (if ess-editor
92 (concat ", editor='" ess-editor "'"))
93 (if ess-pager
94 (concat ", pager='" ess-pager "'"))
95 ")"))
96 (ess-STERM . "iESS")
98 S+common-cust-alist)
100 "Variables to customize for Sqpe+4.")
103 ;;; There are extra complications in S+4 (compared to S+3) because
105 ;;; (1) The StatSci supplied Splus.exe doesn't work in an emacs
106 ;;; buffer. It works as as a GUI window and we must send commands
107 ;;; to it through ddeclient. Nonetheless, we need to give it a
108 ;;; process name and be sure that that there is a valid running
109 ;;; process in the '(ddeESS [S+4])' buffer. Therefore we create an
110 ;;; ESS process in the buffer as a placeholder and start a shell
111 ;;; in the ESS buffer. From the shell we start Splus. Once Splus
112 ;;; finishes initializing and kills the original shell, we start
113 ;;; another shell. We have a buffer-local variable
114 ;;; inferior-ess-ddeclient, initialized to nil. When there is a
115 ;;; non-nil value of inferior-ess-ddeclient we send lines to
116 ;;; inferior-ess-ddeclient rather than to the Splus process.
117 ;;; (2) There is no Splus process running in the '(ddeESS [S+4])'
118 ;;; buffer. Therefore inferior-ess will never see a prompt,
119 ;;; unless we first change it to the null prompt "^". Then once
120 ;;; the process has started, we change it back.
121 ;;; (3) When M-x S+4 starts Splus by a shell command, then Splus is an
122 ;;; independent process and will be survive if the '(ddeESS [S+4])'
123 ;;; buffer is killed (or emacs is quit). The '(ddeESS [S+4])' is
124 ;;; made read-only and a warning is placed in it saying that "You
125 ;;; can't type anything here." Actually, if the standalone Splus
126 ;;; is killed and the '(ddeESS [S+4])' is made writable (C-x C-q),
127 ;;; then '(ddeESS [S+4])' becomes a shell buffer.
129 (defun S+4 (&optional proc-name)
130 "Call 'S-PLUS 4.x', the 'GUI Thing' from StatSci. Put S-Plus in an
131 independent MS-Window (Splus persists even if the '(ddeESS [S+4])'
132 window is killed in emacs). Do this by creating a comint process that
133 calls sh. Send a shell command in that sh buffer to call Splus. When
134 it completes set up a shell as a placeholder in the '(ddeESS [S+4])'
135 buffer. The S-Plus options are correctly set. In particular, the
136 S-Plus Commands window is opened if the Options/General
137 Settings/Startup menu says it should be. There is a 30 second delay
138 during startup in which the screen will not be refreshed. This delay
139 is here to allow slow disks to start the Splus program."
140 (interactive)
141 (save-excursion
142 (setq ess-customize-alist S+4-customize-alist)
143 (ess-write-to-dribble-buffer
144 (format "\n(S+4): ess-dialect=%s, buf=%s\n" ess-dialect
145 (current-buffer)))
146 (setq ess-customize-alist ; change inferior-ess-program
147 (append ess-customize-alist '((inferior-ess-program . "sh"))))
148 (setq ess-customize-alist ; change inferior-ess-primary-prompt
149 (append ess-customize-alist '((inferior-ess-primary-prompt . "^"))))
150 (setq ess-customize-alist ; change inferior-ess-start-args
151 (append ess-customize-alist '((inferior-ess-start-args . "-i"))))
152 (let ((s-proj (getenv "S_PROJ"))
153 (manpath (getenv "MANPATH")))
154 (cd (w32-short-file-name (directory-file-name default-directory)))
155 (setenv "S_PROJ" default-directory)
156 ;; I don't know why this PATH/MANPATH game is needed,
157 ;; except that it doesn't work without it.
158 (setenv "MANPATH" (getenv "PATH"))
159 (inferior-ess)
160 (sleep-for 2) ; need to wait, else working too fast! The Splus
161 ; command in '(ddeESS [S+4])' should follow the "$"
162 ; prompt. If not, then increase the sleep-for time!
163 (setenv "MANPATH" manpath)
164 (setenv "S_PROJ" s-proj))
165 (setq ess-customize-alist S+4-customize-alist)
166 (ess-setq-vars-local ess-customize-alist)
167 ;;; the next three lines belong in customize-alist, but can't be there
168 ;;; because of the broken ess-setq-vars-default usage in ess-inf.el
169 (setq inferior-ess-ddeclient "ddeclient")
170 (setq inferior-ess-client-name "S-PLUS")
171 (setq inferior-ess-client-command "SCommand")
172 ;;; end of what belongs in customize-alist
173 (setq comint-process-echoes nil)
174 (setq comint-input-sender 'comint-simple-send)
175 (goto-char (point-max))
176 (insert (concat inferior-S+4-program-name " "
177 inferior-ess-start-args)) ; Note: there is no final "&".
178 ;; Without the "&", the results of !system.command come to '(ddeESS [S+4])'
179 ;; With the "&", the results of !system.command in S get lost.
180 (inferior-ess-send-input)
181 (sleep-for 30) ; Need to wait, else working too fast!
182 ; If the ess-current-process-name doesn't appear in the
183 ; Splus Commands window increase the sleep-for time!
184 (setq ess-local-process-name ess-current-process-name)
185 (ess-eval-linewise (concat "#" ess-current-process-name))
186 (goto-char (point-min))
187 (insert
188 "This is a placeholder buffer. You can't type anything here.
189 Use `C-x b RET' to return to your file.\n
190 Anything sent to this process from an S-mode buffer goes
191 directly to the associated Splus Commands window.\n
192 The S-Plus Commands window must be visible.
193 You may need to open the S-Plus Commands window manually (by clicking on
194 Splus/Window/Commands Window).\n
195 Any results of the !system.command typed at the S prompt in the
196 Splus Commands window appear in this buffer.\n\n")
197 (goto-char (point-max)) ; comint-mode-map makes '(ddeESS [S+4])'
198 ;; (use-local-map comint-mode-map) ;a shell buffer after Splus is finished.
199 (set-buffer-process-coding-system 'raw-text-dos 'raw-text-unix)
200 (toggle-read-only t) ; force buffer to be read-only
201 (setq mode-name "ddeESS")
202 ;; (ess-eval-linewise inferior-S+4-editor-pager-command)
203 (if inferior-ess-language-start
204 (ess-eval-linewise inferior-ess-language-start))
210 (defun S+4-existing (&optional proc-name)
211 "Call 'S-PLUS 4.x', the 'GUI Thing' from StatSci. Do so by finding
212 an existing S-Plus in an independent MS-Window (if there is one) and
213 set up a '(ddeESS [S+4])' buffer in emacs. If there is no existing
214 S-Plus, then a new one will be opened in the default directory,
215 usually something like c:/Program Files/spls45se/users/yourname.
216 If you have a HOME environment variable, it will open it there."
217 (interactive)
218 (let* ((inferior-S+4-multipleinstances " & # ")) ; Note: there is a final "&".
219 ;; Without the "&", there is a core dump.
220 ;; With the "&", the results of !system.command in S get lost.
221 ;; We are picking up an existing S-Plus process for sending to.
222 ;; It doesn't know about us, so nothing comes back.
223 (S+4 proc-name))
224 (save-excursion
225 (set-buffer (car (buffer-list))) ; get the ESS buffer just created
226 (toggle-read-only nil) ; permit writing in ESS buffer
227 (goto-char (point-max))
228 (beginning-of-line)
229 (forward-line -1)
230 (insert
231 "This is S+4-existing.
232 Results of the !system.command typed at the S prompt in the
233 Splus Commands window blink a DOS window and you won't see them.\n\n")
234 (toggle-read-only t) ; restore ESS buffer to be read-only
238 ;;; There are extra complications in Sqpe+4 (compared to S+3) because
239 ;;; (1) The StatSci supplied Sqpe.exe won't work without SHOME as an
240 ;;; environment variable and Sqpe does not take command line
241 ;;; arguments and
242 ;;; (2) Sqpe.exe comes up with options(interactive=F), which means it
243 ;;; doesn't provide prompts by default, and we must change it to T so
244 ;;; it will provide prompts.
246 (defun Sqpe+4 (&optional proc-name)
247 "Call 'Sqpe' from 'S-PLUS 4.x', the 'Real Thing' from StatSci."
248 (interactive)
249 (setq ess-customize-alist Sqpe+4-customize-alist)
250 (let* ((shome-nil-p (equal (getenv "SHOME") nil)))
251 (if shome-nil-p (setenv "SHOME" inferior-Sqpe+4-SHOME-name))
252 (ess-write-to-dribble-buffer
253 (format "\n(Sqpe+4): ess-dialect=%s, buf=%s\n" ess-dialect
254 (current-buffer)))
255 (setq ess-customize-alist ; change inferior-ess-primary-prompt
256 (append ess-customize-alist '((inferior-ess-primary-prompt . "^"))))
257 (inferior-ess)
258 (setq ess-customize-alist Sqpe+4-customize-alist) ; restore i-e-p-p in alist
259 (ess-setq-vars-local ess-customize-alist) ; restore i-e-p-p in buffer
260 (setq inferior-ess-prompt ; define with correct i-e-p-p
261 ;; Do not anchor to bol with `^' ; (copied from ess-inf.el)
262 (concat "\\("
263 inferior-ess-primary-prompt
264 "\\|"
265 inferior-ess-secondary-prompt
266 "\\)"))
267 (setq comint-prompt-regexp (concat "^" inferior-ess-prompt))
268 ; define with correct i-e-p-p
269 (setq comint-input-sender 'inferior-ess-input-sender)
270 (add-hook 'comint-output-filter-functions 'shell-strip-ctrl-m nil t)
271 (goto-char (point-max))
272 (insert "options(interactive=T)")
273 (inferior-ess-send-input)
274 (setq mode-name "iESS(Sqpe)")
275 ;; (ess-eval-linewise inferior-S+4-editor-pager-command)
276 (if inferior-ess-language-start
277 (ess-eval-linewise inferior-ess-language-start))
278 (if shome-nil-p (setenv "SHOME" nil))))
282 (defun S+4-mode (&optional proc-name)
283 "Major mode for editing S+4 source. See `ess-mode' for more help."
284 (interactive)
285 (setq ess-customize-alist S+4-customize-alist)
286 (ess-mode S+4-customize-alist proc-name)
287 (if ess-imenu-use-S (ess-imenu-R)))
289 (defun S+4-transcript-mode ()
290 "S-PLUS 4.x transcript mode."
291 (interactive)
292 (ess-transcript-mode S+4-customize-alist))
295 (defun S+4-msdos (&optional proc-name)
296 "Call 'S-PLUS 4.x', the 'GUI Thing' from StatSci. Put S-Plus in an
297 independent MS-Window (Splus persists even if the '(ddeESS [S+4])'
298 window is killed in emacs). Do this by creating a comint process that
299 calls sh. Send a shell command in that sh buffer to call Splus. When
300 it completes set up a shell as a placeholder in the '(ddeESS [S+4])'
301 buffer. The S-Plus options are correctly set. In particular, the
302 S-Plus Commands window is opened if the Options/General
303 Settings/Startup menu says it should be. There is a 30 second delay
304 during startup in which the screen will not be refreshed. This delay
305 is here to allow slow disks to start the Splus program."
306 (interactive)
307 (save-excursion
308 (setq ess-customize-alist S+4-customize-alist)
309 (ess-write-to-dribble-buffer
310 (format "\n(S+4): ess-dialect=%s, buf=%s\n" ess-dialect
311 (current-buffer)))
312 (setq ess-customize-alist ; change inferior-ess-program
313 (append ess-customize-alist '((inferior-ess-program
314 . (getenv "COMSPEC")))))
315 (setq ess-customize-alist ; change inferior-ess-primary-prompt
316 (append ess-customize-alist '((inferior-ess-primary-prompt . "^"))))
317 (setq ess-customize-alist ; change inferior-ess-start-args
318 (append ess-customize-alist '((inferior-ess-start-args . ""))))
319 (let ((s-proj (getenv "S_PROJ")))
320 (cd (w32-short-file-name (directory-file-name default-directory)))
321 (setenv "S_PROJ" default-directory)
322 (inferior-ess)
323 (sleep-for 2) ; need to wait, else working too fast! The Splus
324 ; command in '(ddeESS [S+4])' should follow the "$"
325 ; prompt. If not, then increase the sleep-for time!
326 (setenv "S_PROJ" s-proj))
327 (setq ess-customize-alist S+4-customize-alist)
328 (ess-setq-vars-local ess-customize-alist)
329 ;;; the next three lines belong in customize-alist, but can't be there
330 ;;; because of the broken ess-setq-vars-default usage in ess-inf.el
331 (setq inferior-ess-ddeclient "ddeclient")
332 (setq inferior-ess-client-name "S-PLUS")
333 (setq inferior-ess-client-command "SCommand")
334 ;;; end of what belongs in customize-alist
335 (setq comint-input-sender 'comint-simple-send)
336 (setq comint-process-echoes nil)
337 (set-buffer-process-coding-system 'raw-text-dos 'raw-text-dos)
338 (goto-char (point-max))
339 (insert (concat inferior-S+4-program-name " "
340 inferior-ess-start-args)) ; Note: there is no final "&".
341 ; Without the "&", the results of !system.command come to '(ddeESS [S+4])'
342 ; With the "&", the results of !system.command in S get lost.
343 (inferior-ess-send-input)
344 (sleep-for 30) ; Need to wait, else working too fast!
345 ; If the ess-current-process-name doesn't appear in the
346 ; Splus Commands window increase the sleep-for time!
347 ;;; from msdos-minor-mode
348 (setq comint-process-echoes t)
349 (add-hook 'comint-output-filter-functions 'shell-strip-ctrl-m nil t)
350 ;;; end from msdos-minor-mode
351 (setq ess-local-process-name ess-current-process-name)
352 (ess-eval-linewise (concat "#" ess-current-process-name))
353 (goto-char (point-min))
354 (insert
355 "This is a placeholder buffer. You can't type anything here.
356 Use 'C-x b RET' to return to your file.\n
357 Anything sent to this process from an S-mode buffer goes
358 directly to the associated Splus Commands window.\n
359 The S-Plus Commands window must be visible.
360 You may need to open the S-Plus Commands window manually
361 (by clicking on Splus/Window/Commands Window).\n
362 There is a 30 second delay when this program starts during which the
363 emacs screen will be partially blank.\n
364 Remember to
365 `q()' from S-Plus and
366 then C-x C-q exit from the `'(ddeESS [S+4])'' buffer,
367 or take the risk of not being able to shut down your computer
368 and suffering through scandisk.\n
369 Any results of the !system.command typed at the S prompt in the
370 Splus Commands window (are supposed to) appear in this buffer.\n\n")
371 (goto-char (point-max)) ; comint-mode-map makes '(ddeESS [S+4])'
372 (use-local-map comint-mode-map) ; a shell buffer after Splus is finished.
373 (toggle-read-only t) ; force buffer to be read-only
374 (setq mode-name "ddeESS")
375 ;; (ess-eval-linewise inferior-S+4-editor-pager-command)
376 (if inferior-ess-language-start
377 (ess-eval-linewise inferior-ess-language-start))
380 (defun S+4-msdos-existing (&optional proc-name)
381 "Call 'S-PLUS 4.x', the 'GUI Thing' from StatSci. Do so by finding
382 an existing S-Plus in an independent MS-Window (if there is one) and
383 set up a '(ddeESS [S+4])' buffer in emacs. If there is no existing
384 S-Plus, then a new one will be opened in the default directory,
385 usually something like c:/Program Files/spls45se/users/yourname.
386 If you have a HOME environment variable, it will open it there."
387 (interactive)
388 (let* ((inferior-S+4-multipleinstances ""))
389 (S+4-msdos proc-name))
390 (save-excursion
391 (set-buffer (car (buffer-list))) ; get the ESS buffer just created
392 (toggle-read-only nil) ; permit writing in ESS buffer
393 (goto-char (point-max))
394 (beginning-of-line)
395 (forward-line -1)
396 (insert
397 "This is S+4-msdos-existing.
398 Results of the !system.command typed at the S prompt in the
399 Splus Commands window blink a DOS window and you won't see them.\n\n")
400 (toggle-read-only t) ; restore ESS buffer to be read-only
403 \f ; Provide package
405 (provide 'essd-sp4)
407 \f ; Local variables section
409 ;;; This file is automatically placed in Outline minor mode.
410 ;;; The file is structured as follows:
411 ;;; Chapters: ^L ;
412 ;;; Sections: ;;*;;
413 ;;; Subsections: ;;;*;;;
414 ;;; Components: defuns, defvars, defconsts
415 ;;; Random code beginning with a ;;;;* comment
417 ;;; Local variables:
418 ;;; mode: emacs-lisp
419 ;;; outline-minor-mode: nil
420 ;;; mode: outline-minor
421 ;;; outline-regexp: "\^L\\|\\`;\\|;;\\*\\|;;;\\*\\|(def[cvu]\\|(setq\\|;;;;\\*"
422 ;;; End:
424 ;;; essd-s+4.el ends here