;; File unix-tex-mma.el
;; UNIX shell interface to TeX/Mathematica
;; Written 4/11/1991 by Dan Dill dan@chem.bu.edu

(defconst unix-tex-mma-version-string
  "TeX/Mathematica UNIX shell interface Version 1 <Thur 11 April 1991>"
  "String describing this version of TeX/Mathematica UNIX shell interface.")

;; Copyright (C) 1991 Dan Dill
;; This is part of TeX/Mathematica
;;
;; TeX/Mathematica is distributed in the hope that it will be useful, but
;; WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility to
;; anyone for the consequences of using it or for whether it serves any
;; particular purpose or works at all, unless he says so in writing.
;;
;; Everyone is granted permission to copy, modify and redistribute this
;; tex-mma package, provided:
;;  1.  All copies contain this copyright notice.
;;  2.  All modified copies shall carry a prominant notice stating who
;;      made the last modification and the date of such modification.
;;  3.  No charge is made for this software or works derived from it.  
;;      This clause shall not be construed as constraining other software
;;      distributed on the same medium as this software, nor is a
;;      distribution fee considered a charge.
;;
;; Portions of this package were adapted from GNU Emacs.
;;
;; Copyright (C) 1985, 1986, 1987, 1988 Free Software Foundation, Inc. 
;; 
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY.  No author or distributor
;; accepts responsibility to anyone for the consequences of using it
;; or for whether it serves any particular purpose or works at all,
;; unless he says so in writing.  Refer to the GNU Emacs General Public
;; License for full details.
;;
;; Everyone is granted permission to copy, modify and redistribute
;; GNU Emacs, but only under the conditions described in the
;; GNU Emacs General Public License.   A copy of this license is
;; supposed to have been given to you along with GNU Emacs so you
;; can know your rights and responsibilities.  It should be in a
;; file named COPYING.  Among other things, the copyright notice
;; and this notice must be preserved on all copies.


;; Developed with GNU Emacs version 18.55


(defun unix-tex-mma-hook ()
  "Hook for TeX/Mathematica."
  ; Put any setup processing you need to do here.  You don't have to
  ; do any, but this function must still be defined.
  )

(defconst unix-tex-mma-cell-alist
  '(
    ("buffer-go" . unix-buffer-go )
    ("recenter" . unix-recenter)
    ("replace" . unix-replace)
    ("send" . unix-send)
    ("send-cell" . unix-send-cell)
    ("show" . unix-show)
    ("update" . unix-update)
    ))

(defun unix-start ()
  "Start up UNIX shell mode, if necessary."
  (require 'shell)
  (if (unix-start-p)
      nil
    (let ((home-buffer (current-buffer)))
      (message "Starting UNIX shell...")
      (pop-to-buffer unix-process-buffer)
      (shell)
      ; Wait until startup is done
      (while (not (looking-at shell-prompt-pattern))
	(sit-for 1)
	(goto-char (point-max))
	(beginning-of-line))
      (goto-char (point-max))
      (pop-to-buffer home-buffer)
      (message "")
      )))

(defconst unix-process-name "shell"
  "The name of the inferior unix process.")
(defconst unix-process-buffer "*shell*"
  "The name of the shell-mode buffer running UNIX shell.")
(defconst unix-process-string "math" ; For now
  "String to pass to Unix exec fucntion to start UNIX shell.")

(defun unix-start-p ()
  (if (get-buffer-process unix-process-buffer)
      t
    nil
    ))

(defun unix-buffer-go ()
  "Go to UNIX shell buffer."
  (interactive)
  (unix-start)
  (unix-pop-to-buffer)
  )

(defun unix-recenter ()
  "Place UNIX shell input prompt at top of window."
  (interactive)
  (unix-start)
  (let ((home-buffer (current-buffer)))
    (unix-pop-to-buffer)
    (set-window-start (selected-window) last-input-end)
    (goto-char last-input-end)
    (pop-to-buffer home-buffer)
    ))

(defun unix-show ()
  "Make last UNIX shell output visible."
  (unix-start)
  (let ((home-buffer (current-buffer)))
    (unix-pop-to-buffer)
    (goto-char last-input-end)
    (recenter)
    (pop-to-buffer home-buffer)
    ))

(defun unix-pop-to-buffer ()
  (pop-to-buffer (process-buffer (get-process unix-process-name)))
  )

(defun unix-send ()
  "Send UNIX statements containing point to UNIX shell.
Statements are delimited by blank lines."
  (interactive)
  (unix-start)
  (let ((start (tex-mma-math-start))
	(end (tex-mma-math-end))
	(home-buffer (current-buffer)))
    (unix-pop-to-buffer)
    (goto-char (point-max))
    (insert-buffer-substring home-buffer start end)
    ))

(defun unix-send-cell ()
  "Send input to UNIX shell.  Point must be in a unix cell."
  (interactive)
  (if (not (tex-mma-cell-p "unix"))
      (error "Not in unix cell"))
  (unix-start)
  (let ((home-buffer (current-buffer))
	start end)
    (save-excursion
      (goto-char (tex-mma-cell-start "unix"))
      (setq start (point))
      (if (not (setq end (tex-mma-output-p "unix")))
	  (setq end (tex-mma-cell-end "unix"))))
    (unix-pop-to-buffer)
    (goto-char (point-max))
    (insert-buffer-substring home-buffer start end)
    (shell-send-input)
    (pop-to-buffer home-buffer)
    ))

(defun unix-replace ()
  "Replace output (if any) with last UNIX shell result.
Point must be in unix cell.
Output assumed to follow input, separated by a blank line."
  (interactive)
  (if (not (tex-mma-cell-p "unix"))
      (error "Not in UNIX cell"))
  (unix-start)
  (save-excursion
    (tex-mma-delete-output "unix")
    (unix-get)
    ))

(defun unix-update ()
  "Send input to UNIX shell and optionally replace output with result.
Point must be in unix cell.
Output assumed to follow input, separated by a blank line."
  (interactive)
  (if (not (tex-mma-cell-p "unix"))
      (error "Not in UNIX cell"))
  (unix-send-cell)
  ; We need to wait for UNIX output anyhow, so we might as well ask
  (if (y-or-n-p "Replace output? ")
      (unix-replace)
    t
    ))

(defun unix-get ()
  "Insert last output from UNIX shell.
Assumes point in cell.  Output inserted at end of cell."
  (unix-start)
  (let ((tex-mma-process (get-process unix-process-name)))
    (let ((tex-mma-buffer (process-buffer tex-mma-process))
	  (home-buffer (current-buffer))
	  out-start out-end)
      (pop-to-buffer tex-mma-buffer)
      (goto-char last-input-end) ; First line of UNIX output
      (setq out-start (point))	 ; ..
      (goto-char (point-max))	 ; Last line
      (beginning-of-line)	 ; .. exclude next prompt
      (setq out-end (point))
      (goto-char (point-max))	 ; Leave point at next prompt
      (pop-to-buffer home-buffer)
      (save-excursion ; Insert output before \end{mathematica}
	(goto-char (tex-mma-cell-end "unix"))
	(forward-line 1)	 ; Insert blank line before output
	(open-line 2)		 ; ..
	(forward-line 1)	 ; ..
	(insert-buffer-substring tex-mma-buffer out-start out-end)
	(kill-line 1) ; Delete blank lines at end of output
	))))
