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)
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.
30 ;;; This file defines all the S-PLUS 4.x customizations for ess-mode
33 ;;; Requires and Autoloads:
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.")
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
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
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")
75 "Variables to customize for S+4")
77 (defvar Sqpe
+4-customize-alist
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
90 "STERM='" ess-STERM
"'"
92 (concat ", editor='" ess-editor
"'"))
94 (concat ", pager='" ess-pager
"'"))
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."
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
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"))
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))
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."
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.
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))
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
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."
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
255 (setq ess-customize-alist
; change inferior-ess-primary-prompt
256 (append ess-customize-alist
'((inferior-ess-primary-prompt .
"^"))))
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)
263 inferior-ess-primary-prompt
265 inferior-ess-secondary-prompt
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."
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."
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."
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
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
)
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))
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
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."
388 (let* ((inferior-S+4-multipleinstances
""))
389 (S+4-msdos proc-name
))
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))
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
407 \f ; Local variables section
409 ;;; This file is automatically placed in Outline minor mode.
410 ;;; The file is structured as follows:
413 ;;; Subsections: ;;;*;;;
414 ;;; Components: defuns, defvars, defconsts
415 ;;; Random code beginning with a ;;;;* comment
419 ;;; outline-minor-mode: nil
420 ;;; mode: outline-minor
421 ;;; outline-regexp: "\^L\\|\\`;\\|;;\\*\\|;;;\\*\\|(def[cvu]\\|(setq\\|;;;;\\*"
424 ;;; essd-s+4.el ends here