home *** CD-ROM | disk | FTP | other *** search
- ;; This is the interface for pari under emacs
- ;; The main commands in this file are
- ;; M-x gp Opens a buffer for interaction with gp and then starts gp.
- ;; C-u M-x gp Like M-x gp, but prompts for command line arguments.
- ;; M-x gpman Displays the gp-pari manual using any dvi preview program.
-
- ;; All functions of gp are preserved.
-
- ;; This version by David Carlisle (JANET: carlisle@uk.ac.man.cs).
- ;; The original pari.el was written by Annette Hoffman.
-
-
- ;; Version 2.9 (16/12/91)
-
- ;; See pari.txt for more details.
-
-
- (provide 'gp)
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- ;; The following five constants (aka variables !) should be
- ;; set for each site.
-
- (defconst gp-chap3 "~pari/PARISOURCES/tex/usersch3.tex"
- "The TeX source for chapter 3 of the PARI-GP manual")
-
- (defconst gp-file-name "/usr/local/bin/gp"
- "The file name of the gp executable file")
-
- (defconst gp-man-dvi "~pari/SPARC/tex/users.dvi"
- "dvi version of the manual")
-
- (defconst gp-menu "~pari/PARISOURCES/pari.menu"
- "menu file")
-
- (defconst gp-dvi-preview "xdvi -s 3"
- ;; (defconst gp-dvi-preview "texsun"
- "dvi previewer (and options)")
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- ;; Individual users may want to re-set some of the variables in this section
- ;; in a gp-mode-hook in their .emacs file.
-
- ;; See pari.txt for an example of a gp-mode-hook.
-
- (defvar gp-stack-size "4000000"
- "Default stack size: passed to the progam gp.")
-
- (defvar gp-buffer-size "30000"
- "Default buffer size: passed to the progam gp.")
-
- (defvar gp-prime-limit "500000"
- "Default prime limit: passed to the progam gp.")
-
- (defvar gp-prompt-for-args nil
- "A non-nil value makes M-x gp act like C-u M-x gp,
- ie prompt for the command line arguments.")
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- (setq gp-temp-file (make-temp-name "/usr/tmp/gp_"))
-
- (defvar gp-prompt-pattern
- "---- (type return to continue) ----\\|\\?[\C-j\t ]*"
- "Regexp used to match gp prompts.
- can be set with gp-set-prompt (bound to M-\\ p)")
-
-
- (defvar gp-map (make-sparse-keymap)
- "Local keymap used in buffer *PARI*.")
-
- (define-key gp-map "\C-m" 'gp-send-input)
- (define-key gp-map "\M-\C-m" 'gp-copy-input)
- (define-key gp-map "\M-\\p" 'gp-set-prompt)
- (define-key gp-map "\M-\\t" 'gp-meta-t)
- (define-key gp-map "\M-\\d" 'gp-meta-d)
-
- (define-key gp-map "\M-\\r" 'gp-meta-r)
- (define-key gp-map "\M-\\w" 'gp-meta-w)
- (define-key gp-map "\M-\\v" 'gp-meta-v)
- (define-key gp-map "\M-\\x" 'gp-meta-x)
- (define-key gp-map "\M-\\s" 'gp-meta-s)
- (define-key gp-map "\M-\\a" 'gp-meta-a)
- (define-key gp-map "\M-\\b" 'gp-meta-b)
- (define-key gp-map "\M-\\m" 'gp-meta-m)
- (define-key gp-map "\M-\\k" 'gp-meta-k)
- (define-key gp-map "\M-\\q" 'gp-meta-q)
- (define-key gp-map "\M-?" 'gp-get-man-entry)
- (define-key gp-map "\M-\\c" 'gp-menu)
- (define-key gp-map "\M-\\\\" 'gp-break-long-line)
- (define-key gp-map "\C-c" 'gp-interrupt)
-
- (defvar gp-process nil "")
- (defvar gp-man-process nil "")
-
- (defun gp (flag)
- "
- Open a buffer and a window for the execution of gp.
-
- The following bindings are available:
- \\{gp-map}
-
- The variables
- gp-file-name gp-stack-size gp-buffer-size gp-prime-limit
- determine the command line that starts gp.
- To override the default settings, give gp a prefix argument.
- C-u M-x gp ."
- (interactive "P")
- ;; Create buffer *PARI* and make it become the current buffer.
- (switch-to-buffer "*PARI*")
- (goto-char (point-max))
- (if gp-process
- nil
- (kill-all-local-variables)
- (setq major-mode 'gp)
- (setq mode-name "GP")
- ;; Set up user preferences.
- (run-hooks 'gp-mode-hook)
-
- ;; Make gp-map the local map of buffer *PARI*.
- (use-local-map gp-map)
- (setq mode-line-process '(": %s"))
-
- ;; Form the command line string.
-
- (let* (
- (flag (or flag gp-prompt-for-args))
- (gp-command
- (concat
- (gp-read-input "Gp executable ?" gp-file-name "" flag)
- (gp-read-input "Stack size ?" gp-stack-size " -s " flag)
- (gp-read-input "Buffer size ?" gp-buffer-size " -b " flag)
- (gp-read-input "Prime limit ?" gp-prime-limit " -p " flag))))
- ;; Insert the command line string into the *PARI* buffer.
- ;; (This is just for reference.)
- (insert (concat "\n" gp-command "\n"))
- ;; Start gp.
-
- (setq gp-process
- (start-process
- "pari" "*PARI*" shell-file-name "-c"
- (concat "stty nl; exec " gp-command))))
- ;; Clean up when the gp process has finished.
- (set-process-sentinel gp-process 'gp-sentinel)))
-
- (defun gp-read-input (prompt default sep flag)
- " If flag is non-nil, reads string then if string is \"\" uses default.
- If flag is nil then string is the default.
- If resulting string is not \"\" prepends sep.
- As a special case, if string is a space, return \"\"."
- (let ((string
- (if flag
- ;; If flag is non-nil prompt for input from mini-buffer.
- (read-input
- (concat prompt " (Default "default") "))
- ;; Else use the default string.
- default)))
- (if (equal string "")
- (if (equal default "")
- ;; If sting and default both "":
- ""
- ;; If string "" and default is non empty:
- (concat sep default))
- (if (equal string " ")
- ;; If string is a space:
- ""
- ;; If string is non empty:
- (concat sep string)))))
-
- (defun gp-sentinel (proc msg)
- "Sentinel for the gp-process in buffer *PARI*."
- (if (get-buffer "*gp-help*") (kill-buffer "*gp-help*"))
- (let ((b (get-file-buffer gp-chap3))) (if b (kill-buffer b)))
- (let ((b (get-file-buffer gp-menu))) (if b (kill-buffer b)))
- (if (get-buffer "*PARI*")
- (progn
- (set-buffer "*PARI*")
- (goto-char (point-max))
- (insert msg)
- (delete-windows-on "*PARI*")))
- (if (file-exists-p gp-temp-file)
- ;; Let /bin/sh to the removing, as people may have aliased rm to rm -i,
- ;; and apparently -f does not override this on all systems.
- (let((shell-file-name "/bin/sh")
- (shell-command (concat "rm " gp-temp-file))
- (message "Removing %s" gp-temp-file ))))
- (setq gp-process nil))
-
- (defun gpman()
- "Start up xdvi with the gp manual."
- (interactive)
- ;; Run gp-mode-hook in case it specifies a different
- ;; version of the manual.
- (run-hooks 'gp-mode-hook)
- (set-buffer (get-buffer-create "*GP-MAN*"))
- (if gp-man-process
- nil
- ;; Start xdvi.
- (message (concat "Starting " gp-dvi-preview " " gp-man-dvi))
- (setq gp-man-process
- (start-process "gp-man" "*GP-MAN*"
- shell-file-name
- "-c" (concat "exec " gp-dvi-preview " " gp-man-dvi)))
- (set-process-sentinel gp-man-process 'gp-man-sentinel)))
-
- (defun gp-man-sentinel (proc msg)
- "Sentinel for the gp-man-process in buffer *GP-MAN*."
- (let ((buf (process-buffer proc)))
- (if buf (kill-buffer buf)))
- (message (concat "gpman: " msg))
- (setq gp-man-process nil))
-
- (defun gp-copy-input()
- "Copy expression around point to the end of the buffer.
- (Unless this is already the last expression.)"
- (interactive)
- ;; Go back to the end of prompt, and record that point.
- ;; If a line contains more than one prompt string, use the FIRST.
- ;; This is so that ? ?cos works. (ie gives the help for cos).
- ;; We can not insist on prompt at the beginning of a line (ie put
- ;; ^ in gp-prompt-pattern) because of the output from print1()
- (re-search-backward gp-prompt-pattern)
- (let ((p (match-end 0)))
- (beginning-of-line)
- (re-search-forward gp-prompt-pattern)
- (setq gp-input-start (point))
- ;; Go past the last prompt on this line before looking for end of expression.
- (goto-char p))
- ;; Check if we are already at the last expression.
- (let ((nlast (re-search-forward (concat "[\n ]*\\("
- gp-prompt-pattern
- "\\|^%[0-9]+ = \\|^ *\\*\\*\\*\\|^ *unused characters\\|^ *time[ r]\\)")
- (point-max) t)))
- ;; Find the limit of the expression.
- ;; This is the end of buffer,the prompt, or an error message.
- (let ((limit (if nlast (match-beginning 0) (point-max))))
- (goto-char gp-input-start)
- ;; End of expression is a line ending with } if it starts with {,
- ;; otherwise a line not ending with \.
- (let ((end-expression (if (looking-at " *{") "}$" "[^\\]$")))
- ;; Look for the end of expression, as far as the limit computed above.
- (setq gp-complete-expression (re-search-forward end-expression limit 1))
- (setq gp-input-end (point))
- ;; If not already the last expression copy to the end of the buffer.
- (if nlast
- (progn
- (goto-char (point-max))
- (insert (buffer-substring gp-input-start gp-input-end))
- (if gp-complete-expression
- nil
- (ding)
- (message "Incomplete expression."))))))))
-
-
- (defun gp-send-input ()
- "Send input to gp. Does not send incomplete expressions
- ie those starting with {, without a matching }, or those
- ending with \\ .
- Use a temporary file (and \\r )for large expressions"
- (interactive)
- ;; gp-copy-input does all the work!
- (gp-copy-input)
- (insert "\n")
- (if gp-complete-expression
- ;; If it is a complete expression do this:
- (progn
- (if (> (- gp-input-end gp-input-start) 255)
- ;; If large expression, use a temporary file.
- (progn
- (write-region gp-input-start gp-input-end gp-temp-file)
- (process-send-string gp-process (concat "\\r "gp-temp-file"\n")))
- ;; Else use process-send-region.
- (process-send-region gp-process gp-input-start gp-input-end)
- (process-send-string gp-process "\n"))
- (set-marker (process-mark gp-process) (point)))
- ;; Else do this:
- (message "Incomplete expression: Not sent to gp.")))
-
-
- (defun gp-interrupt ()
- "Interrupt gp.
- This is identical to interrupt-shell-subjob in shell-mode."
- (interactive)
- (interrupt-process nil t))
-
- (defun gp-set-prompt (p)
- "Set new gp prompt (and tell emacs that you have done so).
- Do not put spaces in the argument, or emacs and gp will
- have a different idea about what the prompt is."
- (interactive "sNew prompt: ")
- ;; gp-prompt-pattern matches:
- ;; (New prompt plus any following white space) OR (Old pattern).
- (setq gp-prompt-pattern
- (concat (regexp-quote p) "[\C-j\t ]*\\|" gp-prompt-pattern))
- (set-buffer "*PARI*")
- (goto-char (point-max))
- ;; Tell gp about the change too!
- (insert (concat "\\prompt="p))
- (gp-send-input))
-
- (defun gp-replace (a b)
- "Replace the regexp a by the string b everywhere in the current buffer"
- (goto-char (point-min))
- (while (re-search-forward a (point-max) t)
- (replace-match b t t)))
-
- (defun gp-get-man-entry (fn)
- "Obtains the description of fn from chapter 3 of the manual.
- Strips off some (not all) of the TeX syntax, and displays the result
- in a new window.
- If there is no entry for fn in the manual, sends ?fn to gp."
- (interactive "sFunction: ")
- ;; Stop TeX-mode being loaded for gp-chap3.
- (let ((auto-mode-alist nil))
- (set-buffer (find-file-noselect gp-chap3)))
- ;; Fix up one or two special cases, or
- ;; regexp-quote the argument.
- (let ((qfn (cond
- ((equal fn "\\" ) "\\\\backslash")
- ((equal fn "^" ) "\\\\hat{}")
- ((equal fn "!" ) "fact")
- ((equal fn "~" ) "trans")
- ((equal fn "_" ) "conj")
- ((equal fn "-" ) "\\+")
- ((equal fn "%" ) "\\\\%")
- ((equal fn "min" ) "max")
- ((equal fn "log" ) "ln")
- ((equal fn "det2" ) "det")
- ((or (equal fn "<=" )(equal fn "<" )(equal fn ">=" )
- (equal fn ">" )(equal fn "==" )(equal fn "!=" )
- (equal fn "||" )(equal fn "&&" ))
- "comparison and \\\\ref{boolean operators}")
- ((regexp-quote fn)))))
- ;; Find the entry.
- (goto-char (point-min))
- ;; Entry starts with \subsec ... fn
- (if (re-search-forward
- (concat "\\(subsec[\\\\{ref]*[\\${]\\)" qfn "[}\\$]") (point-max) t)
- ;; If There is an entry in the manual do this:
- (progn
- (goto-char (match-end 1))
- (let ((copy (buffer-substring (point)
- ;; Entry ends with "The library" or the next (sub-)section.
- (progn (re-search-forward "[tT]he library\\|\\\\[sub]*sec"
- (point-max) t)
- (match-beginning 0))))
- (wind (selected-window)))
- ;; Copy the entry to the help buffer.
- (switch-to-buffer-other-window (get-buffer-create "*gp-help*"))
- (erase-buffer)
- (insert copy)
- ;; Strip off some of the TeX. Note the idea is to leave enough
- ;; pseudo-TeX so that the entry is understandable. Thus want to
- ;; leave: a^2, x \over y, etc.
- (gp-replace "\\$-" "-")
- (gp-replace "\\$" " " )
- (gp-replace "\\\\backslash" "\\")
- (gp-replace "\\\\hat" "^")
- (gp-replace
- "\\\\smallskip\\|\\\\sref{[ a-z]*}\\|\\\\bf\\|\
- \\\\ref\\|\\\\Bbb\\|\\\\text\\|\\\\tt\\|{\\|}"
- "")
- (goto-char (point-min))
- (select-window wind)))
- ;; Else there is no entry in the manual. So send ?fn to gp.
- (set-buffer "*PARI*")
- (gp-meta-command (concat "?" fn)))))
-
- (defun gp-meta-command (command)
- "Send command to gp, and display output in help buffer"
- (goto-char (point-max))
- (let ((temp (point)) (wind (selected-window)))
- ;; Send the meta command to gp.
- (process-send-string gp-process (concat command "\n"))
- ;; Wait for the gp-prompt to be sent.
- (gp-wait-for-output)
- ;; Display the output in the help buffer.
- (let ((copy (buffer-substring temp (point-max))))
- (delete-region temp (point-max))
- (switch-to-buffer-other-window (get-buffer-create "*gp-help*"))
- (erase-buffer)
- (insert copy)
- (beginning-of-line)
- (delete-region (point) (point-max))
-
- (goto-char (point-min))
- (select-window wind))))
-
- (defun gp-wait-for-output ()
- "Hang around until the prompt appears."
- (setq ndone t)
- (while ndone
- (accept-process-output "*PARI*")
- (let ((p (point)))
- (beginning-of-line)
- (if (looking-at gp-prompt-pattern)
- (progn (message "done") (setq ndone nil))
- (message "Waiting for gp output ..."))
- (goto-char p))))
-
- (defun gp-meta-d ()
- "Sends \\d to gp, then displays output in the help buffer.
- Prints the gp defaults."
- (interactive)
- (gp-meta-command "\\d"))
-
- (defun gp-meta-t ()
- "Sends \\t to gp, then displays output in the help buffer.
- Prints the longword format of PARI types."
- (interactive)
- (gp-meta-command "\\t"))
-
- (defun gp-meta-r (file)
- "Sends a \\r <file name> comand to gp.
- Reads in gp commands from a file.
- See gp-meta-r"
- (interactive "fRead from file: ")
- (goto-char (point-max))
- (insert (concat "\\r " (expand-file-name file)))
- (gp-send-input))
-
- (defun gp-meta-w (file num)
- "Sends a \\w<num> <file name> comand to gp.
- Writes gp object %<num> to <file name>."
- (interactive "FWrite to file: \nsObject number %%")
- (goto-char (point-max))
- (insert (concat "\\w"num" " (expand-file-name file)))
- (gp-send-input))
-
- (defun gp-meta-x ()
- "Sends \\x to gp, then displays output in the help buffer.
- Prints tree of addresses and contents of last object."
- (interactive)
- (gp-meta-command "\\x"))
-
- (defun gp-meta-v ()
- "Sends \\v to gp, then displays output in the help buffer.
- Prints the version number of this implementation of pari-gp."
- (interactive)
- (gp-meta-command "\\v"))
-
- (defun gp-meta-s (num)
- "Sends \\s or \\s(num) to gp, then displays output in the help buffer.
- Prints the state of the pari stack."
- (interactive "sNumber of longwords (default 0) ")
- (if (equal num "")
- (gp-meta-command "\\s")
- (gp-meta-command (concat "\\s(" num ")" ))))
-
- (defun gp-meta-a (num)
- "Sends \\a or \\a<num> to gp, then displays output in the help buffer.
- Prints object %<num> in raw format."
- (interactive "sPrint object (default last) %%")
- (if (equal num "")
- (gp-meta-command "\\a")
- (gp-meta-command (concat "\\a" num))))
-
- (defun gp-meta-b (num)
- "Sends \\b or \\b<num> to gp, then displays output in the help buffer.
- Prints object %<num> in pretty format."
- (interactive "sPrint object (default last) %%")
- (if (equal num "")
- (gp-meta-command "\\b")
- (gp-meta-command (concat "\\b" num))))
-
- (defun gp-meta-m (num)
-
- "Sends \\m or \\m<num> to gp, then displays output in the help buffer.
- Prints object %<num> in prettymatrix format."
- (interactive "sPrint object (default last) %%")
- (if (equal num "")
- (gp-meta-command "\\m")
- (gp-meta-command (concat "\\m" num))))
-
- (defun gp-meta-k ()
- "Sends \\k to gp.
- Prompts for confirmation before
- re-initialising gp and clearing the buffer."
- (interactive)
- (if (y-or-n-p "Re-initialise gp ? ")
- (progn
- (set-buffer "*PARI*")
- (goto-char (point-max))
- (insert "\\k\n")
- (set-marker (process-mark gp-process) (point))
- (if (y-or-n-p "Clear *PARI* buffer ? ")
- (erase-buffer))
- (process-send-string gp-process "\\k\n")))
- (message ""))
-
- (defun gp-meta-q ()
-
- "Sends \\q to gp.
- Prompts for confirmation before quiting."
- (interactive)
- (if (y-or-n-p "Quit gp ? ")
- (progn
-
- (set-buffer "*PARI*")
- (goto-char (point-max))
- (process-send-string gp-process "\\q\n")))
- (message ""))
-
- (defun gp-break-long-line ()
- "gp will not accept lines longer than 256.
- gp-break-long-line breaks current line
- inserting \\ every (screen-width)-5 chars."
- (interactive)
- (let ((length (min (- (screen-width) 5) 250)))
- (move-to-column length)
- (while (not (looking-at "$"))
- (insert "\\\n")
- (move-to-column length))))
-
-
- ;;; The gp help mode.
-
- (defun gp-menu ()
- "Major-mode for the gp menu buffer.
- The available commands are
- \\{gp-menu-map}"
- (interactive)
- (find-file-other-window gp-menu)
- (setq buffer-read-only t)
- (kill-all-local-variables)
- (setq major-mode 'gp-menu)
- (setq mode-name "GP MENU")
- (use-local-map gp-menu-map)
- (gp-menu-main))
-
- (defun gp-menu-info ()
- (message "SPC=next DEL=previous RET=select m=main-menu q=quit s=scroll-help"))
-
- (defun gp-menu-next ()
- "Move down one line of the gp help menu. (Go to top if at the end.)"
- (interactive)
- (gp-menu-info)
- (forward-line 1)
- (if (eobp)
- (progn (ding) (goto-char (point-min)))))
-
- (defun gp-menu-previous ()
- "Move up one line of the gp help menu. (Go to bottom if at the top.)"
- (interactive)
- (gp-menu-info)
- (if (bobp)
- (progn (ding) (goto-char (point-max)) (beginning-of-line))
- (forward-line -1)))
-
- (defun gp-menu-quit ()
- "Switch the *PARI* buffer if it exists, or (other-buffer) if it does not."
- (interactive)
- (let ((w (get-buffer-window "*PARI*"))
- (b (get-buffer "*PARI*")) )
- (cond
- (w (progn (delete-window)(select-window w)))
- (b (switch-to-buffer b))
- (t (switch-to-buffer (other-buffer))))))
-
- (defun gp-menu-select ()
- "Select a subject from the main menu, or a manual entry from a subject menu."
- (interactive)
- (if main-menu
- ;; RET in main menu.
- (progn
- (setq main-menu nil)
- (widen)
- (beginning-of-line)
- (let ((sect (buffer-substring
- (point) (progn (end-of-line) (point)))))
- (narrow-to-region
- (progn
- (re-search-forward (concat "^###" sect))
-
- (forward-line 1) (point))
- (progn (re-search-forward "\C-j###" ) (match-beginning 0))))
- (goto-char (point-min)))
- ;; RET in subject menu.
- (beginning-of-line)
- (gp-get-man-entry (buffer-substring
- (point)
- (progn (end-of-line) (point)))))
- (gp-menu-info))
-
-
-
- (defun gp-menu-main ()
- "Display the main menu."
- (interactive)
- (gp-menu-info)
- (widen)
- (goto-char (point-min))
- (narrow-to-region (point)
- (progn (re-search-forward "\C-j###") (match-beginning 0)))
- (goto-char (point-min))
- (setq done nil)
- (setq main-menu t))
-
- (defun gp-menu-scroll ()
- "Scroll the gp help window if it is visible"
- (interactive)
- (gp-menu-info)
- (if (get-buffer-window "*gp-help*")
- (let ((wind (selected-window)))
- (switch-to-buffer-other-window "*gp-help*")
- (if (pos-visible-in-window-p (point-max))
- (goto-char (point-min))
- (scroll-up))
- (select-window wind))))
-
-
- (defvar gp-menu-map (make-sparse-keymap)
- "Local keymap used in gp menu buffer.")
-
-
- (define-key gp-menu-map " " 'gp-menu-next)
- (define-key gp-menu-map "\C-?" 'gp-menu-previous)
- (define-key gp-menu-map "\C-m" 'gp-menu-select)
- (define-key gp-menu-map "q" 'gp-menu-quit)
- (define-key gp-menu-map "m" 'gp-menu-main)
- (define-key gp-menu-map "s" 'gp-menu-scroll)
-
-
-