Initial Commit
[packages] / xemacs-packages / ess / lisp / ess-trns.el
1 ;;; ess-trns.el --- Support for manipulating S transcript files
2
3 ;; Copyright (C) 1989--1994 Bates, Kademan, Ritter and Smith
4 ;; Copyright (C) 1997--2004 A.J. Rossini, Rich M. Heiberger, Martin
5 ;;      Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen.
6
7 ;; Original Author: David Smith <dsmith@stats.adelaide.edu.au>
8 ;; Maintainers: ESS-core <ESS-core@stat.math.ethz.ch>
9
10 ;; This file is part of ESS
11
12 ;; This file is free software; you can redistribute it and/or modify
13 ;; it under the terms of the GNU General Public License as published by
14 ;; the Free Software Foundation; either version 2, or (at your option)
15 ;; any later version.
16
17 ;; This file is distributed in the hope that it will be useful,
18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 ;; GNU General Public License for more details.
21
22 ;; You should have received a copy of the GNU General Public License
23 ;; along with GNU Emacs; see the file COPYING.  If not, write to
24 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
25
26 ;;; Commentary:
27
28 ;; Code for dealing with ESS transcripts.
29
30 ;;; Code:
31
32 \f ; Requires and autoloads
33
34 (require 'ess)
35
36 (eval-when-compile
37   (require 'comint)
38   (require 'ess-inf))
39
40 (autoload 'ess-eval-region              "ess-inf" "[autoload]" t)
41 (autoload 'ess-eval-region-and-go       "ess-inf" "[autoload]" t)
42 (autoload 'ess-eval-function            "ess-inf" "[autoload]" t)
43 (autoload 'ess-eval-function-and-go     "ess-inf" "[autoload]" t)
44 (autoload 'ess-eval-line                "ess-inf" "[autoload]" t)
45 (autoload 'ess-eval-line-and-go         "ess-inf" "[autoload]" t)
46 (autoload 'ess-eval-line-and-step       "ess-inf" "[autoload]" t)
47
48 (autoload 'comint-previous-prompt       "comint" "[autoload]" t)
49 (autoload 'comint-next-prompt           "comint" "[autoload]" t)
50
51 (autoload 'ess-load-file                "ess-inf" "[autoload]" t)
52 (autoload 'ess-request-a-process        "ess-inf" "(autoload)" nil)
53 (autoload 'get-ess-buffer               "ess-inf" "(autoload)" nil)
54 (autoload 'ess-switch-to-ESS            "ess-inf" "(autoload)" nil)
55 (autoload 'ess-switch-to-end-of-ESS     "ess-inf" "(autoload)" nil)
56 (autoload 'ess-eval-linewise            "ess-inf" "(autoload)" nil)
57 (autoload 'inferior-ess-get-old-input   "ess-inf" "(autoload)" nil)
58
59 \f ; ess-transcript-mode
60 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
61 ;;;; In this section:
62 ;;;;
63 ;;;; * The major mode ess-transcript-mode
64 ;;;; * Commands for ess-transcript-mode
65 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
66
67 ;;*;; Major mode definition
68 (defvar ess-transcript-mode-map nil "Keymap for `ess-transcript-mode'.")
69 (if ess-transcript-mode-map
70     nil
71
72   (cond ((featurep 'xemacs)
73          ;; Code for XEmacs
74          (setq ess-transcript-mode-map (make-keymap))
75          (set-keymap-parent ess-transcript-mode-map text-mode-map))
76         ((not (featurep 'xemacs))
77          ;; Code for GNU Emacs
78          (setq ess-transcript-mode-map (make-sparse-keymap))))
79
80   (define-key ess-transcript-mode-map "\C-c\C-s" 'ess-switch-process)
81   (define-key ess-transcript-mode-map "\C-c\C-r" 'ess-eval-region)
82   (define-key ess-transcript-mode-map "\C-c\M-r" 'ess-eval-region-and-go)
83 ;;  (define-key ess-transcript-mode-map "\M-\C-x"  'ess-eval-function)
84 ;;  (define-key ess-transcript-mode-map "\C-c\M-f" 'ess-eval-function-and-go)
85 ;;  (define-key ess-transcript-mode-map "\C-c\C-j" 'ess-eval-line)
86 ;;  (define-key ess-transcript-mode-map "\C-c\M-j" 'ess-eval-line-and-go)
87
88   (define-key ess-transcript-mode-map "\C-c\C-k"    'ess-force-buffer-current)
89   (define-key ess-transcript-mode-map "\C-c\C-q"    'ess-quit)
90
91   (define-key ess-transcript-mode-map "\C-c\C-j" 'ess-transcript-send-command)
92   (define-key ess-transcript-mode-map "\C-c\M-j" 'ess-transcript-send-command-and-move)
93   (define-key ess-transcript-mode-map "\M-\C-a"  'ess-beginning-of-function)
94   (define-key ess-transcript-mode-map "\M-\C-e"  'ess-end-of-function)
95   (define-key ess-transcript-mode-map "\C-c\C-y" 'ess-switch-to-ESS)
96   (define-key ess-transcript-mode-map "\C-c\C-z" 'ess-switch-to-end-of-ESS)
97   (define-key ess-transcript-mode-map "\C-c\C-v" 'ess-display-help-on-object)
98   (define-key ess-transcript-mode-map "\C-c\C-d" 'ess-dump-object-into-edit-buffer)
99   (define-key ess-transcript-mode-map "\C-c\C-t" 'ess-execute-in-tb)
100   (define-key ess-transcript-mode-map "\C-c\t"   'ess-complete-object-name)
101   (define-key ess-transcript-mode-map "\C-a"     'comint-bol)
102   (define-key ess-transcript-mode-map "\M-\t"    'comint-replace-by-expanded-filename)
103   (define-key ess-transcript-mode-map "\M-?"     'comint-dynamic-list-completions)
104   (define-key ess-transcript-mode-map "\C-c\C-k" 'ess-request-a-process)
105   (define-key ess-transcript-mode-map "{"        'ess-electric-brace)
106   (define-key ess-transcript-mode-map "}"        'ess-electric-brace)
107   (define-key ess-transcript-mode-map "\e\C-h"   'ess-mark-function)
108   (define-key ess-transcript-mode-map "\e\C-q"   'ess-indent-exp)
109   (define-key ess-transcript-mode-map "\177"     'backward-delete-char-untabify)
110   (define-key ess-transcript-mode-map "\t"       'ess-indent-command)
111
112   (define-key ess-transcript-mode-map "\C-c\C-p" 'comint-previous-prompt)
113   (define-key ess-transcript-mode-map "\C-c\C-n" 'comint-next-prompt)
114   ;; (define-key ess-transcript-mode-map "\C-c\C-n"    'ess-eval-line-and-step)
115
116   (define-key ess-transcript-mode-map "\r"       'ess-transcript-send-command-and-move)
117   (define-key ess-transcript-mode-map "\M-\r"    'ess-transcript-send-command)
118   (define-key ess-transcript-mode-map "\C-c\r"   'ess-transcript-copy-command)
119   (define-key ess-transcript-mode-map "\C-c\C-w" 'ess-transcript-clean-region))
120
121 (easy-menu-define
122  ess-transcript-mode-menu ess-transcript-mode-map
123  "Menu for use in S transcript mode."
124  '("ESS-trans"
125    ["What is this? (beta)" ess-mouse-me                  t]
126    ["Describe"         describe-mode                     t]
127    ["About"            (ess-goto-info "Transcript Mode") t]
128    ["Send bug report"  ess-submit-bug-report             t]
129    "------"
130    ["Mark cmd group"   mark-paragraph         t]
131    ["Previous prompt"  comint-previous-prompt t]
132    ["Next prompt"      comint-next-prompt     t]
133    "------"
134    ["Send and move"  ess-transcript-send-command-and-move t]
135    ["Copy command"   ess-transcript-copy-command          t]
136    ["Send command"   ess-transcript-send-command          t]
137    ["Clean Region"   ess-transcript-DO-clean-region       t]))
138
139
140
141 (if (not (string-match "XEmacs" emacs-version))
142     (progn
143        (if (featurep 'ess-trans)
144            (define-key ess-transcript-mode-map [menu-bar ess-trans]
145              (cons "ess-trans" ess-transcript-mode-menu))
146          (eval-after-load "ess-trans"
147                           '(define-key ess-transcript-mode-map
148                              [menu-bar ess-trans]
149                              (cons "ess-trans"
150                                    ess-transcript-mode-menu))))))
151
152 (defun ess-transcript-mode-xemacs-menu ()
153   "Hook to install `ess-transcript-mode' menu for XEmacs (w/ easymenu)."
154   (if 'ess-transcript-mode
155         (easy-menu-add ess-transcript-mode-menu)
156     (easy-menu-remove ess-transcript-mode-menu)))
157
158 (if (string-match "XEmacs" emacs-version)
159     (add-hook 'ess-transcript-mode-hook 'ess-transcript-mode-xemacs-menu))
160
161 (defun ess-transcript-mode (alist &optional proc)
162   "Major mode for manipulating {ESS} transcript files.
163
164 Type \\[ess-transcript-send-command] to send a command in the
165 transcript to the current S process. \\[ess-transcript-copy-command]
166 copies the command but does not execute it, allowing you to edit it in
167 the process buffer first.
168
169 Type \\[ess-transcript-clean-region] to delete all outputs and prompts
170 in the region, leaving only the S commands.  Other keybindings are:
171
172 \\{ess-transcript-mode-map}"
173   (interactive)
174   (require 'ess-inf)
175   (kill-all-local-variables)
176   (toggle-read-only t) ;; to protect the buffer.
177   (ess-setq-vars-local alist); (current-buffer))
178   (setq major-mode 'ess-transcript-mode)
179   (setq mode-name "ESS Transcript")
180   (use-local-map ess-transcript-mode-map)
181   (set-syntax-table ess-mode-syntax-table)
182   (setq mode-line-process
183         '(" [" ess-local-process-name "]"))
184   (make-local-variable 'ess-local-process-name)
185   (setq ess-local-process-name nil)
186   (make-local-variable 'paragraph-start)
187   (setq paragraph-start (concat "^" inferior-ess-primary-prompt "\\|^\^L"))
188   (make-local-variable 'paragraph-separate)
189   (setq paragraph-separate "^\^L")
190   (setq inferior-ess-prompt
191         ;; Do not anchor to bol with `^'       ; (copied from ess-inf.el)
192         (concat "\\("
193                 inferior-ess-primary-prompt
194                 "\\|"
195                 inferior-ess-secondary-prompt
196                 "\\)"))
197   (make-local-variable 'comint-prompt-regexp)
198   (setq comint-prompt-regexp (concat "^" inferior-ess-prompt))
199
200   ;; font-lock support
201   (make-local-variable 'font-lock-defaults)
202   (setq font-lock-defaults
203         '(inferior-ess-font-lock-keywords nil nil ((?' . "."))))
204
205   ;;; Keep <tabs> out of the code.
206   (make-local-variable 'indent-tabs-mode)
207   (setq indent-tabs-mode nil)
208
209   (run-hooks 'ess-transcript-mode-hook))
210
211 ;;*;; Commands used in S transcript mode
212
213 (defun ess-transcript-send-command ()
214   "Send the command at point in the transcript to the ESS process.
215 The line should begin with a prompt.  The ESS process buffer is displayed if it
216 is not already."
217   (interactive)
218   (let* ((proc (or ess-local-process-name
219                    (ess-request-a-process "Evaluate into which process? " t)))
220          (ess-buf (get-ess-buffer proc)))
221     (setq ess-local-process-name proc)
222     (if (get-buffer-window ess-buf) nil
223       (display-buffer ess-buf t))
224     (let ((input (inferior-ess-get-old-input)))
225       (save-excursion
226         (set-buffer ess-buf)
227         (goto-char (point-max))
228         (ess-eval-linewise input)))))
229
230 (defun ess-transcript-send-command-and-move ()
231   "Send the command on this line, and move point to the next command."
232   (interactive)
233   (ess-transcript-send-command)
234   (goto-char ess-temp-point)
235   (comint-next-prompt 1))
236
237 (defun ess-transcript-copy-command ()
238   "Copy the command at point to the command line of the ESS process."
239   (interactive)
240   (let* ((proc (or ess-local-process-name
241                    (ess-request-a-process "Evaluate into which process? " t)))
242          (ess-buf (process-buffer (get-process proc)))
243          (input (inferior-ess-get-old-input)))
244     (setq ess-local-process-name proc)
245     (if (get-buffer-window ess-buf) nil
246       (display-buffer ess-buf t))
247     (save-excursion
248       (set-buffer ess-buf)
249       (goto-char (point-max))
250       (insert input)))
251   (ess-switch-to-end-of-ESS))
252
253 (defun ess-transcript-clean-region (beg end even-if-read-only)
254   "Strip the transcript in the region, leaving only (R/S/Lsp/..) commands.
255 Deletes any lines not beginning with a prompt, and then removes the
256 prompt from those lines that remain.  Prefix argument means to use
257 \\[toggle-read-only] to clean even if the buffer is \\[read-only]."
258   (interactive "r\nP")
259   (let ((do-toggle (and buffer-read-only even-if-read-only)))
260     (save-excursion
261       (if do-toggle (toggle-read-only 0))
262       (save-restriction
263         (deactivate-mark)
264         (narrow-to-region beg end)
265         (goto-char (point-min))
266         (delete-non-matching-lines (concat "^" inferior-ess-prompt))
267         (goto-char (point-min))
268         (replace-regexp (concat "^" inferior-ess-prompt) ""))
269       (if do-toggle (toggle-read-only 1)))))
270
271 (defun ess-transcript-DO-clean-region (beg end)
272   "Clean the current via \\[ess-transcript-clean-region] even if the buffer is read-only."
273   (interactive "r")
274   (ess-transcript-clean-region beg end 'In-ANY-case))
275
276 \f ; Local variables section
277
278 ;;; This file is automatically placed in Outline minor mode.
279 ;;; The file is structured as follows:
280 ;;; Chapters:     ^L ;
281 ;;; Sections:    ;;*;;
282 ;;; Subsections: ;;;*;;;
283 ;;; Components:  defuns, defvars, defconsts
284 ;;;              Random code beginning with a ;;;;* comment
285
286 ;;; Local variables:
287 ;;; mode: emacs-lisp
288 ;;; mode: outline-minor
289 ;;; outline-regexp: "\^L\\|\\`;\\|;;\\*\\|;;;\\*\\|(def[cvu]\\|(setq\\|;;;;\\*"
290 ;;; End:
291
292 ;;; ess-trans.el ends here