Initial Commit
[packages] / xemacs-packages / ess / lisp / essd-sp6w.el
1 ;;; essd-sp6w.el --- S-PLUS 6.x  for Windows customization
2
3 ;;; copied and edited from essd-sp4.el - Richard M. Heiberger, April 2001
4
5 ;; Copyright (C) 2001 Richard M. Heiberger <rmh@sbm.temple.edu>
6 ;; Copyright (C) 2002--2005 A.J. Rossini, Rich M. Heiberger, Martin
7 ;;      Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen.
8
9 ;; Original Author: Richard M. Heiberger <rmh@sbm.temple.edu>
10 ;; Created: April 2001
11 ;; Maintainers: ESS-core <ESS-core@stat.math.ethz.ch>
12
13 ;; Keywords: start up, configuration.
14
15 ;; This file is part of ESS.
16
17 ;; This file is free software; you can redistribute it and/or modify
18 ;; it under the terms of the GNU General Public License as published by
19 ;; the Free Software Foundation; either version 2, or (at your option)
20 ;; any later version.
21
22 ;; This file is distributed in the hope that it will be useful,
23 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
24 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25 ;; GNU General Public License for more details.
26
27 ;; You should have received a copy of the GNU General Public License
28 ;; along with GNU Emacs; see the file COPYING.  If not, write to
29 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
30
31 ;;; Commentary:
32 ;;;
33 ;;; This file defines all the S-PLUS 6.x for Windows customizations
34 ;;; for ess-mode with ddeclient.
35
36 ;;; Requires and Autoloads:
37
38 (require 'essl-s)
39 (require 'ess-iw32)
40
41 (autoload 'inferior-ess "ess-inf" "Run an ESS process.")
42 (autoload 'ess-mode     "ess-mode" "Edit an ESS process.")
43
44 ;;; Code:
45
46 (defvar S+6-dialect-name "S+6"
47   "Name of 'dialect' for S-PLUS 6.x.
48 Easily changeable in a user's `.emacs'.")
49
50 (defvar inferior-S+6-start-args " "
51   "Default is empty.  Can be used for license manager information, for example
52 `(setq inferior-S+6-start-args \" S_ELMHOST=\\\\\\\\@123.456.789.012  ELMTIMEOUT=60 \")'."
53 ;; (setq inferior-S+6-start-args " S_ELMHOST=\\\\@123.456.789.012  ELMTIMEOUT=60 ")  ;; use this line as the model for your site-start.el
54 )
55
56 (defvar inferior-Sqpe-start-args " "
57   "Default is empty.  Can be used for license manager information, for example
58 `(setq inferior-Sqpe-start-args \" S_ELMHOST=@123.456.789.012  ELMTIMEOUT=60 \")'."
59 ;; (setq inferior-Sqpe-start-args " S_ELMHOST=@123.456.789.012  ELMTIMEOUT=60 ")  ;; use this line as the model for your site-start.el
60 )
61
62 (defvar inferior-S+6-multipleinstances "/MULTIPLEINSTANCES"
63   "Default \"/MULTIPLEINSTANCES\" opens up a new instance of S+[67] in a
64 GUI window and connects it to the '(ddeESS [S+6])' window.  The
65 alternative nil uses an existing S+6 GUI (if there is one) and
66 connects it to the '(ddeESS [S+6])' window.")
67
68 (defvar S+6-customize-alist
69   (append
70   '((ess-local-customize-alist  . 'S+6-customize-alist)
71     (ess-dialect                . S+6-dialect-name)
72     (ess-loop-timeout           . ess-S-loop-timeout);fixme: dialect spec.
73     (ess-object-name-db-file    . "ess-sp6-namedb.el" )
74     (inferior-ess-program       . inferior-S+6-program-name)
75     (inferior-ess-help-command  . "help(\"%s\")\n")
76     (inferior-ess-search-list-command . "searchPaths()\n")
77     (inferior-ess-start-file    . nil) ;"~/.ess-S+6")
78     (inferior-ess-start-args    . (concat
79                                    inferior-S+6-multipleinstances
80                                    " "
81                                    inferior-S+6-start-args
82                                    " "
83                                    inferior-S+6-print-command
84                                    " S_PROJ="
85                                    (directory-file-name default-directory)))
86 ;;    (inferior-ess-ddeclient      . "ddeclient")
87 ;;    (inferior-ess-client-name    . "S-PLUS")
88 ;;    (inferior-ess-client-command . "SCommand")
89     (ess-STERM  . "ddeESS")
90     )
91   S+common-cust-alist)
92   "Variables to customize for S+6")
93
94 (defvar Sqpe+6-customize-alist
95   (append
96   '((ess-local-customize-alist  . 'Sqpe+6-customize-alist)
97     (ess-dialect                . S+6-dialect-name)
98     (ess-loop-timeout           . 500000 );fixme: dialect specific custom.var
99     (ess-object-name-db-file    . "ess-sp6-namedb.el" )
100     (inferior-ess-program       . inferior-Sqpe+6-program-name)
101     (inferior-ess-help-command  . "help(\"%s\")\n")
102     (inferior-ess-search-list-command . "searchPaths()\n")
103     (inferior-ess-start-file    . nil) ;"~/.ess-S+6")
104     (inferior-ess-start-args    . (concat
105                                    ;; workaround for bug in S-Plus 6 for Windows:
106                                    "ALWAYS_PROMPT=X"
107                                    " "
108                                    inferior-Sqpe-start-args ;; e.g. license manager
109                                    ))
110     (ess-STERM  . "iESS")
111     )
112   S+common-cust-alist)
113  "Variables to customize for Sqpe+6.")
114
115
116
117 ;;; There are extra complications in S+6 and S+7 (compared to S+3) because
118 ;;;
119 ;;; (1) The StatSci supplied Splus.exe doesn't work in an emacs
120 ;;;     buffer.  It works as as a GUI window and we must send commands
121 ;;;     to it through ddeclient.  Nonetheless, we need to give it a
122 ;;;     process name and be sure that that there is a valid running
123 ;;;     process in the '(ddeESS [S+6])' buffer.  Therefore we create an
124 ;;;     ESS process in the buffer as a placeholder and start a shell
125 ;;;     in the ESS buffer.  From the shell we start Splus.  Once Splus
126 ;;;     finishes initializing and kills the original shell, we start
127 ;;;     another shell.  We have a buffer-local variable
128 ;;;     inferior-ess-ddeclient, initialized to nil.  When there is a
129 ;;;     non-nil value of inferior-ess-ddeclient we send lines to
130 ;;;     inferior-ess-ddeclient rather than to the Splus process.
131 ;;; (2) There is no Splus process running in the '(ddeESS [S+6])'
132 ;;;     buffer.  Therefore inferior-ess will never see a prompt,
133 ;;;     unless we first change it to the null prompt "^".  Then once
134 ;;;     the process has started, we change it back.
135 ;;; (3) When M-x S+6 starts Splus by a shell command, then Splus is an
136 ;;;     independent process and will be survive if the '(ddeESS [S+6])'
137 ;;;     buffer is killed (or emacs is quit).  The '(ddeESS [S+6])' is
138 ;;;     made read-only and a warning is placed in it saying that "You
139 ;;;     can't type anything here."  Actually, if thestandalone Splus
140 ;;;     is killed and the '(ddeESS [S+6])' is made writable (C-x C-q),
141 ;;;     then '(ddeESS [S+6])' becomes a shell buffer.
142 ;;;
143 (defun S+6 (&optional proc-name)
144   "Verify that `inferior-S+6-program-name' points to S-Plus 6 or S-Plus 7.
145 Start normally for S-Plus 6.1 and later.  Inform the user to start S-Plus 6.0
146 from the icon and then connect to it with `S+6-existing'.  Give an error
147 message if `inferior-S+6-program-name' doesn't point to S-Plus 6 or S-Plus 7."
148   (interactive)
149   (save-excursion
150     (set-buffer (find-file-noselect
151                  (concat (executable-find inferior-S+6-program-name)
152                          "/../../versions") t))
153     (toggle-read-only 1)
154     (forward-line)
155     (if (not (search-backward-regexp "[67].[0-9]" (point-min) t))
156         (error "The emacs variable `inferior-S+6-program-name' does
157 not point to S-Plus 6 or 7.  Please add `splus[67]?/cmd' (expand the
158 `[67]?' to match your setup) to your `exec-path' or specify the complete
159 path to `Splus.exe' in the variable `inferior-S+6-program-name' in your
160 `.emacs' file.")
161       (forward-line)
162       (if (search-backward "6.0" (point-min) t)
163           (error "S-Plus 6.0 for Microsoft Windows has a bug that
164 prevents it from being started by emacs.  Instead, you must start it
165 by double-clicking an icon.  Then you can connect to it with
166 `S+6-existing'.  You should consider upgrading to S-Plus 6.1 or higher."))))
167   (S+6-initiate proc-name)) ;; normal start ;
168
169
170 (defun S+6-initiate (&optional proc-name)
171   "Call 'S-PLUS [67].x for Windows', the 'GUI Thing' from StatSci.  Put
172 S-Plus in an independent MS-Window (Splus persists even if the
173 '(ddeESS [S+6])' window is killed in emacs).  Do this by creating a
174 comint process that calls sh.  Send a shell command in that sh buffer
175 to call Splus.  When it completes set up a shell as a placeholder in
176 the '(ddeESS [S+6])' buffer.  The S-Plus options are correctly set.
177 In particular, the S-Plus Commands window is opened if the
178 Options/General Settings/Startup menu says it should be.  There is a
179 startup delay of `ess-S+6-startup-delay' seconds during which the
180 screen will not be refreshed.  This delay is here to allow slow disks
181 to start the Splus program."
182   (interactive)
183   (save-excursion
184     (setq ess-customize-alist S+6-customize-alist)
185     (ess-write-to-dribble-buffer
186      (format "\n(S+6): ess-dialect=%s, buf=%s\n" ess-dialect
187              (current-buffer)))
188     (setq ess-customize-alist           ; change inferior-ess-program
189           (append ess-customize-alist '((inferior-ess-program   . "sh"))))
190     (setq ess-customize-alist           ; change inferior-ess-primary-prompt
191           (append ess-customize-alist '((inferior-ess-primary-prompt   . "^"))))
192     (setq ess-customize-alist           ; change inferior-ess-start-args
193           (append ess-customize-alist '((inferior-ess-start-args   . "-i"))))
194     (let ((s-proj (getenv "S_PROJ")))
195       (cd (w32-short-file-name (directory-file-name default-directory)))
196       (setenv "S_PROJ" default-directory)
197       (inferior-ess)
198       (sleep-for 2) ; need to wait, else working too fast!  The Splus
199                     ; command in '(ddeESS [S+6])' should follow the "$"
200                     ; prompt.  If not, then increase the sleep-for time!
201       (setenv "S_PROJ" s-proj))
202     (setq ess-customize-alist S+6-customize-alist)
203     (ess-setq-vars-local ess-customize-alist)
204 ;;; the next three lines belong in customize-alist, but can't be there
205 ;;; because of the broken ess-setq-vars-default usage in ess-inf.el
206     (setq inferior-ess-ddeclient         "ddeclient")
207     (setq inferior-ess-client-name       "S-PLUS")
208     (setq inferior-ess-client-command    "SCommand")
209 ;;; end of what belongs in customize-alist
210     (setq comint-process-echoes nil)
211     (setq comint-input-sender 'comint-simple-send)
212     (goto-char (point-max))
213     (insert (concat inferior-S+6-program-name " "
214                     inferior-ess-start-args)) ; Note: there is no final "&".
215     ;; Without the "&", the results of  !system.command  come to '(ddeESS [S+6])'
216     ;; With the "&", the results of  !system.command  in S get lost.
217     (inferior-ess-send-input)
218     (sleep-for ess-S+6-startup-delay) ; Need to wait, else working too fast!
219                    ; If the ess-current-process-name doesn't appear in the
220                    ; Splus Commands window increase the sleep-for time!
221     (setq ess-local-process-name ess-current-process-name)
222     (ess-eval-linewise (concat "#" ess-current-process-name))
223     (beginning-of-buffer)
224     (insert
225      "This is a placeholder buffer.  You can't type anything here.
226 Use `C-x b RET' to return to your file.\n
227 Anything sent to this process from an S-mode buffer goes
228 directly to the associated Splus Commands window.\n
229 The S-Plus Commands window must be visible.
230 You may need to open the S-Plus Commands window manually (by clicking on
231 Splus/Window/Commands Window).\n
232 Any results of the   !system.command   typed at the S prompt in the
233 Splus Commands window appear in this buffer.\n\n")
234     (goto-char (point-max))             ; comint-mode-map makes '(ddeESS [S+6])'
235 ;;  (use-local-map comint-mode-map)     ;a shell buffer after Splus is finished.
236     (set-buffer-process-coding-system 'raw-text-dos 'raw-text-unix)
237     (toggle-read-only t)                ; force buffer to be read-only
238     (setq mode-name "ddeESS")
239 ;;  (ess-eval-linewise inferior-S+6-editor-pager-command)
240     (if inferior-ess-language-start
241         (ess-eval-linewise inferior-ess-language-start))
242     ))
243
244
245
246
247 (defun S+6-existing (&optional proc-name)
248   "Call 'S-PLUS [67].x for Windows', the 'GUI Thing' from StatSci.  Do so by
249 finding an existing S-Plus in an independent MS-Window (if there is one) and
250 set up a '(ddeESS [S+6])' buffer in emacs.  If there is no existing
251 S-Plus, then a new one will be opened in the default directory,
252 usually something like c:/Program Files/Insightful/splus70/users/yourname.
253 If you have a HOME environment variable, it will open it there."
254   (interactive)
255   (let* ((inferior-S+6-multipleinstances " & # ") ; Note: there is a final "&".
256          (ess-S+6-startup-delay 0)) ;; No delay for existing S-Plus
257     ;; Without the "&", there is a core dump.
258     ;; With the "&", the results of  !system.command  in S get lost.
259     ;; We are picking up an existing S-Plus process for sending to.
260     ;; It doesn't know about us, so nothing comes back.
261     (S+6-initiate proc-name))
262   (save-excursion
263     (set-buffer (car (buffer-list)))    ; get the ESS buffer just created
264     (toggle-read-only nil)              ; permit writing in ESS buffer
265     (goto-char (point-max))
266     (beginning-of-line)
267     (forward-line -1)
268     (insert
269      "This is S+6-existing.
270 Results of the   !system.command   typed at the S prompt in the
271 Splus Commands window blink a DOS window and you won't see them.\n\n")
272     (toggle-read-only t)                ; restore ESS buffer to be read-only
273     ))
274
275
276 ;;; There are extra complications in Sqpe+6 (compared to S+3) because
277 ;;; (1) The StatSci supplied Sqpe.exe won't work without SHOME as an
278 ;;;     environment variable and Sqpe does not take command line
279 ;;;     arguments and
280 ;;; (2) Sqpe.exe comes up with options(interactive=F), which means it
281 ;;;     doesn't provide prompts by default, and we must change it to T so
282 ;;;     it will provide prompts.
283 ;;;
284 (defun Sqpe+6 (&optional proc-name)
285   "Call 'Sqpe' from 'S-PLUS [67].x for Windows', the 'Real Thing'  from StatSci."
286   (interactive)
287   (setq ess-customize-alist Sqpe+6-customize-alist)
288   (let* ((shome-nil-p (equal (getenv "SHOME") nil)))
289     (if shome-nil-p (setenv "SHOME" inferior-Sqpe+6-SHOME-name))
290     (ess-write-to-dribble-buffer
291      (format "\n(Sqpe+6): ess-dialect=%s, buf=%s\n" ess-dialect
292              (current-buffer)))
293     (setq ess-customize-alist           ; change inferior-ess-primary-prompt
294           (append ess-customize-alist '((inferior-ess-primary-prompt   . "^"))))
295     (inferior-ess)
296     (setq ess-customize-alist Sqpe+6-customize-alist) ; restore i-e-p-p in alist
297     (ess-setq-vars-local ess-customize-alist)    ; restore i-e-p-p in buffer
298     (setq inferior-ess-prompt                    ; define with correct i-e-p-p
299           ;; Do not anchor to bol with `^'       ; (copied from ess-inf.el)
300           (concat "\\("
301                   inferior-ess-primary-prompt
302                   "\\|"
303                   inferior-ess-secondary-prompt
304                   "\\)"))
305     (setq comint-prompt-regexp (concat "^" inferior-ess-prompt))
306                                                 ; define with correct i-e-p-p
307     (setq comint-input-sender 'inferior-ess-input-sender)
308     (add-hook 'comint-output-filter-functions 'shell-strip-ctrl-m nil t)
309     (goto-char (point-max))
310     (insert "options(interactive=T)")
311     (inferior-ess-send-input)
312     (setq mode-name "iESS(Sqpe)")
313 ;;  (ess-eval-linewise inferior-S+6-editor-pager-command)
314     (if inferior-ess-language-start
315         (ess-eval-linewise inferior-ess-language-start))
316     (if shome-nil-p (setenv "SHOME" nil))))
317
318
319
320 (defun S+6-mode (&optional proc-name)
321   "Major mode for editing S+[67] source.  See `ess-mode' for more help."
322   (interactive)
323   (setq ess-customize-alist S+6-customize-alist)
324   (ess-mode S+6-customize-alist proc-name)
325   (if ess-imenu-use-S (ess-imenu-R)))
326
327
328 (defun S+6-transcript-mode ()
329   "S-PLUS 6.x transcript mode."
330   (interactive)
331   (ess-transcript-mode S+6-customize-alist))
332
333
334 (defun S+6-msdos (&optional proc-name)
335   "Verify that `inferior-S+6-program-name' points to S-Plus 6 or S-Plus 7.
336 Start normally for S-Plus 6.1 and later.  Inform the user to start S-Plus 6.0
337 from the icon and then connect to it with `S+6-msdos-existing'.  Give an error
338 message if `inferior-S+6-program-name' doesn't point to S-Plus 6 or S-Plus 7."
339   (interactive)
340   (save-excursion
341     (set-buffer (find-file-noselect
342                  (concat (executable-find inferior-S+6-program-name)
343                          "/../../versions") t))
344     (toggle-read-only 1)
345     (forward-line)
346     (if (not (search-backward-regexp "[67].[0-9]" (point-min) t))
347         (error "The emacs variable `inferior-S+6-program-name' does
348 not point to S-Plus 6 or 7.  Please add `splus[67]?/cmd'
349 (expand the `[67]?' to match your setup) to your `exec-path' or
350 specify the complete path to `Splus.exe' in the variable
351 `inferior-S+6-program-name' in your `.emacs' file.")
352       (progn
353     (forward-line)
354       (if (search-backward "6.0" (point-min) t)
355             (error "S-Plus 6.0 for Microsoft Windows has a bug that
356 prevents it from being started by emacs.  Instead, you must start it
357 by double-clicking an icon.  Then you can connect to it with
358 `S+6-msdos-existing'.  You should consider upgrading to S-Plus 6.1 or higher.")
359   (S+6-msdos-initiate proc-name))) ;; normal start ;
360       )))
361
362
363 (defun S+6-msdos-initiate (&optional proc-name)
364   "Call 'S-PLUS [67].x for Windows', the 'GUI Thing' from StatSci.  Put
365 S-Plus in an independent MS-Window (Splus persists even if the
366 '(ddeESS [S+6])' window is killed in emacs).  Do this by creating a
367 comint process that calls sh.  Send a shell command in that sh buffer
368 to call Splus.  When it completes set up a shell as a placeholder in
369 the '(ddeESS [S+6])' buffer.  The S-Plus options are correctly set.
370 In particular, the S-Plus Commands window is opened if the
371 Options/General Settings/Startup menu says it should be.  There is a
372 startup delay of `ess-S+6-startup-delay' seconds during which the
373 screen will not be refreshed.  This delay is here to allow slow disks
374 to start the Splus program."
375   (interactive)
376   (save-excursion
377     (setq ess-customize-alist S+6-customize-alist)
378     (ess-write-to-dribble-buffer
379      (format "\n(S+6): ess-dialect=%s, buf=%s\n" ess-dialect
380              (current-buffer)))
381     (setq ess-customize-alist           ; change inferior-ess-program
382           (append ess-customize-alist '((inferior-ess-program
383                                          . (getenv "COMSPEC")))))
384     (setq ess-customize-alist           ; change inferior-ess-primary-prompt
385           (append ess-customize-alist '((inferior-ess-primary-prompt   . "^"))))
386     (setq ess-customize-alist           ; change inferior-ess-start-args
387           (append ess-customize-alist '((inferior-ess-start-args   . ""))))
388     (let ((s-proj (getenv "S_PROJ")))
389       (cd (w32-short-file-name (directory-file-name default-directory)))
390       (setenv "S_PROJ" default-directory)
391       (inferior-ess)
392       (sleep-for 2) ; need to wait, else working too fast!  The Splus
393                     ; command in '(ddeESS [S+6])' should follow the "$"
394                     ; prompt.  If not, then increase the sleep-for time!
395       (setenv "S_PROJ" s-proj))
396     (setq ess-customize-alist S+6-customize-alist)
397     (ess-setq-vars-local ess-customize-alist)
398 ;;; the next three lines belong in customize-alist, but can't be there
399 ;;; because of the broken ess-setq-vars-default usage in ess-inf.el
400     (setq inferior-ess-ddeclient         "ddeclient")
401     (setq inferior-ess-client-name       "S-PLUS")
402     (setq inferior-ess-client-command    "SCommand")
403 ;;; end of what belongs in customize-alist
404     (setq comint-input-sender 'comint-simple-send)
405     (setq comint-process-echoes nil)
406     (set-buffer-process-coding-system 'raw-text-dos 'raw-text-dos)
407     (goto-char (point-max))
408     (insert (concat inferior-S+6-program-name " "
409                     inferior-ess-start-args)) ; Note: there is no final "&".
410     ;; Without the "&", the results of  !system.command  come to '(ddeESS [S+6])'
411     ;; With the "&", the results of  !system.command  in S get lost.
412     (inferior-ess-send-input)
413     (sleep-for ess-S+6-startup-delay) ; Need to wait, else working too fast!
414                    ; If the ess-current-process-name doesn't appear in the
415                    ; Splus Commands window increase the sleep-for time!
416 ;;; from msdos-minor-mode
417   (setq comint-process-echoes t)
418   (add-hook 'comint-output-filter-functions 'shell-strip-ctrl-m nil t)
419 ;;; end from msdos-minor-mode
420     (setq ess-local-process-name ess-current-process-name)
421     (ess-eval-linewise (concat "#" ess-current-process-name))
422     (beginning-of-buffer)
423     (insert
424      "This is a placeholder buffer.  You can't type anything here.
425 Use `C-x b RET' to return to your file.\n
426 Anything sent to this process from an S-mode buffer goes
427 directly to the associated Splus Commands window.\n
428 The S-Plus Commands window must be visible.
429 You may need to open the S-Plus Commands window manually
430 (by clicking on Splus/Window/Commands Window).\n
431 There is a `ess-S+6-startup-delay' second delay when this program starts
432 during which the emacs screen will be partially blank.\n
433 Remember to 'q()' from S-Plus and
434 then C-x C-q exit from the '(ddeESS [S+6])' buffer,
435 or take the risk of not being able to shut down your computer
436 and suffering through scandisk.\n
437 Any results of the   !system.command   typed at the S prompt in the
438 Splus Commands window (are supposed to) appear in this buffer.\n\n")
439     (goto-char (point-max))            ; comint-mode-map makes '(ddeESS [S+6])'
440     (use-local-map comint-mode-map)    ; a shell buffer after Splus is finished.
441     (toggle-read-only t)               ; force buffer to be read-only
442     (setq mode-name "ddeESS")
443 ;;  (ess-eval-linewise inferior-S+6-editor-pager-command)
444     (if inferior-ess-language-start
445       (ess-eval-linewise inferior-ess-language-start))
446     ))
447
448 (defun S+6-msdos-existing (&optional proc-name)
449   "Call 'S-PLUS [67].x for Windows', the 'GUI Thing' from StatSci.  Do so by
450 finding an existing S-Plus in an independent MS-Window (if there is one) and
451 set up a '(ddeESS [S+6])' buffer in emacs.  If there is no existing
452 S-Plus, then a new one will be opened in the default directory,
453 usually something like c:/Program Files/Insightful/splus70/users/yourname.
454 If you have a HOME environment variable, it will open it there."
455   (interactive)
456   (let* ((inferior-S+6-multipleinstances "")
457          (ess-S+6-startup-delay 0)) ;; No delay for existing S-Plus
458     (S+6-msdos-initiate proc-name))
459   (save-excursion
460     (set-buffer (car (buffer-list)))    ; get the ESS buffer just created
461     (toggle-read-only nil)              ; permit writing in ESS buffer
462     (goto-char (point-max))
463     (beginning-of-line)
464     (forward-line -1)
465     (insert
466      "This is S+6-msdos-existing.
467 Results of the   !system.command   typed at the S prompt in the
468 Splus Commands window blink a DOS window and you won't see them.\n\n")
469     (toggle-read-only t)                ; restore ESS buffer to be read-only
470     ))
471
472 (defun ess-sqpe-versions-create ()
473   "Generate the `M-x splusxy' functions for starting other versions of
474 Sqpe.  See `ess-sqpe-versions' for strings that determine which
475 functions are created.  This works by creating a temp buffer where the
476 template function `Sqpe+template' is edited by replacing the string
477 'Sqpe+template' by the version name.  The list of functions actually
478 created appears in the *ESS* buffer.
479
480 The result `ess-sqpe-versions-created' will store a list of the new
481 Sqpe defuns, if any, that were created.  The defuns will normally be
482 placed on the menubar upon ESS initialisation."
483   (let ((beg)
484         (versions)
485         (version)
486         (eval-buf (get-buffer-create "*ess-temp-sqpe-evals*"))
487         (ess-sqpe-versions-created)
488         )
489     ;;
490     (save-excursion
491       (set-buffer eval-buf)
492       ;; clear the buffer.
493       (delete-region (point-min) (point-max))
494
495       ;; Find which versions of Sqpe we want.
496       (setq versions (ess-uniq-list ess-SHOME-versions))
497       ;; Iterate over each string in VERSIONS, creating a new defun each time.
498       (while versions
499         (setq version (car versions)
500               versions (cdr versions))
501         (if (file-executable-p version)
502             (progn
503               (setq beg (point))
504               (prin1 (symbol-function 'Sqpe+template) eval-buf)
505               (insert "\n\n")
506               (goto-char beg)
507               (while (search-forward "lambda" nil t 1)
508                 (replace-match
509                  (concat "defun " (file-name-nondirectory version))
510                  t t))
511               (while (search-forward "ess-SHOME" nil t)
512                 (replace-match version t t))
513               (goto-char (point-max))
514               (setq ess-sqpe-versions-created
515                     (cons (file-name-nondirectory version)
516                           ess-sqpe-versions-created))
517               (ess-write-to-dribble-buffer
518                (format
519                 "(Sqpe): ess-sqpe-versions-create making M-x defun %s for %s \n"
520                 (file-name-nondirectory version) version))
521               )))
522       ;; buffer has now been created with defuns, so eval them!
523       (eval-buffer)
524       (kill-buffer eval-buf))
525     ess-sqpe-versions-created))
526
527 ;; template function used by ess-sqpe-versions-create
528 (defun Sqpe+template (&optional proc-name)
529   "Call 'Sqpe' from 'S-PLUS for Windows ess-SHOME',
530 the 'Real Thing'  from StatSci.
531 This function was generated by `ess-sqpe-versions-create'."
532   (interactive)
533   (setq ess-customize-alist Sqpe+6-customize-alist)
534   (let* ((shome-old (getenv "SHOME"))
535          (inferior-Sqpe+6-SHOME-name "ess-SHOME")
536          (inferior-Sqpe+6-program-name (concat "ess-SHOME" "/cmd/sqpe.exe")))
537     (setenv "SHOME" "ess-SHOME")
538     (ess-write-to-dribble-buffer
539      (format "\n(Sqpe+template): ess-dialect=%s, buf=%s\n" ess-dialect
540              (current-buffer)))
541     (setq ess-customize-alist    ; change inferior-ess-primary-prompt
542           (append ess-customize-alist
543                   '((inferior-ess-primary-prompt   . "^"))))
544     (inferior-ess)
545     (setq ess-customize-alist Sqpe+6-customize-alist) ; restore i-e-p-p in alist
546     (ess-setq-vars-local ess-customize-alist) ; restore i-e-p-p in buffer
547     (setq inferior-ess-prompt           ; define with correct i-e-p-p
548           ;; Do not anchor to bol with `^'       ; (copied from ess-inf.el)
549           (concat "\\("
550                   inferior-ess-primary-prompt
551                   "\\|"
552                   inferior-ess-secondary-prompt
553                   "\\)"))
554     (setq comint-prompt-regexp (concat "^" inferior-ess-prompt))
555                                         ; define with correct i-e-p-p
556     (setq comint-input-sender 'inferior-ess-input-sender)
557     (add-hook 'comint-output-filter-functions 'shell-strip-ctrl-m nil t)
558     (goto-char (point-max))
559     (insert "options(interactive=T)")
560     (inferior-ess-send-input)
561     (setq mode-name "iESS(Sqpe)")
562     ;;  (ess-eval-linewise inferior-S+6-editor-pager-command)
563     (if inferior-ess-language-start
564         (ess-eval-linewise inferior-ess-language-start))
565     (setenv "SHOME" shome-old)))
566
567
568 \f ; Provide package
569
570 (provide 'essd-sp6w)
571
572 \f ; Local variables section
573
574 ;;; This file is automatically placed in Outline minor mode.
575 ;;; The file is structured as follows:
576 ;;; Chapters:     ^L ;
577 ;;; Sections:    ;;*;;
578 ;;; Subsections: ;;;*;;;
579 ;;; Components:  defuns, defvars, defconsts
580 ;;;              Random code beginning with a ;;;;* comment
581
582 ;;; Local variables:
583 ;;; mode: emacs-lisp
584 ;;; outline-minor-mode: nil
585 ;;; mode: outline-minor
586 ;;; outline-regexp: "\^L\\|\\`;\\|;;\\*\\|;;;\\*\\|(def[cvu]\\|(setq\\|;;;;\\*"
587 ;;; End:
588
589 ;;; essd-sp6w.el ends here