You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
189 lines
5.9 KiB
189 lines
5.9 KiB
;;; sage-build.el --- Build Sage |
|
|
|
;; Copyright (C) 2008 Nicholas Alexander |
|
|
|
;; Author: Nicholas Alexander <ncalexan@pv109055.reshsg.uci.edu> |
|
;; Keywords: sage build |
|
|
|
|
|
;;; Commentary: |
|
;; |
|
|
|
(require 'compile) |
|
(require 'sage-mode) |
|
|
|
;; History of sage-build commands. |
|
;;; Code: |
|
|
|
;;;###autoload |
|
(defvar sage-build-history nil) |
|
|
|
(defun sage-wait-until-dead (process seconds msg) |
|
"Wait SECONDS until PROCESS is dead, displaying MSG." |
|
(let ((killed nil)) |
|
(message "Trying %s..." msg) |
|
(accept-process-output) |
|
(if (with-timeout (seconds (not killed)) |
|
(while (not killed) |
|
(accept-process-output nil 1) |
|
(setq killed (not (memq (process-status process) '(open run stop)))) |
|
;; (setq killed (eq (process-status process) 'exit)) |
|
|
|
;; (goto-char (point-max)) |
|
;; (beginning-of-line) |
|
;; (setq killed (looking-at "Process Sage killed")) |
|
)) |
|
(progn |
|
(accept-process-output process 0 1) |
|
(message "Trying %s... failed!" msg) |
|
nil) |
|
(accept-process-output process 0 1) |
|
(message "Trying %s... done." msg) |
|
t |
|
))) |
|
|
|
(defun sage-rerun-internal (buffer) |
|
(accept-process-output nil 0 1) |
|
(sit-for 0) |
|
(with-current-buffer buffer |
|
(goto-char (point-max)) |
|
(insert "\nRestarting Sage...\n\n") |
|
(goto-char (point-max)) |
|
;; (call-interactively 'run-sage) ;; this causes new buffers to appear, not good |
|
(message "Restarting Sage...") |
|
(run-sage nil sage-rerun-command t) ;; restart (new command noshow) |
|
(message "Restarting Sage... done") |
|
(pop-to-buffer buffer) |
|
(goto-char (point-max)))) |
|
|
|
;;;###autoload |
|
(defalias 'restart-sage 'rerun-sage) |
|
;;;###autoload |
|
(defalias 'sage-restart 'rerun-sage) |
|
;;;###autoload |
|
(defalias 'sage-rerun 'rerun-sage) |
|
;;;###autoload |
|
(defun rerun-sage () |
|
"Kill a running sage and spawn a new sage in the same buffer. |
|
Use `sage-build' with a prefix argument to rebuild sage and then |
|
rerun the freshly built sage." |
|
(interactive) |
|
(let ((bufs (sage-all-inferior-sage-buffers)) |
|
(buffer nil)) |
|
(cond ((not bufs) |
|
(progn |
|
(message "Need a Sage buffer to rerun Sage in...") |
|
(call-interactively 'run-sage))) |
|
((= 1 (length bufs)) |
|
(setq buffer (car bufs))) |
|
(t (setq buffer |
|
(completing-read |
|
"Rerun Sage in buffer: " bufs nil nil |
|
(car bufs))))) |
|
;; (kill-buffer buffer) |
|
(with-current-buffer buffer |
|
;; (message (get-buffer-process buffer)) |
|
(let* ((sprocess (get-buffer-process (current-buffer)))) |
|
(when (and sprocess |
|
(not (eq (process-status sprocess) 'exit))) |
|
;; (set-process-sentinel sprocess nil) |
|
(sage-quit-debugger) |
|
|
|
(when (and sprocess |
|
(not (eq (process-status sprocess) 'exit))) ;; be a little cautious |
|
(comint-kill-input) |
|
(comint-send-eof) ;; and again to kill sage itself |
|
(accept-process-output nil 0 1) |
|
(sit-for 0)) |
|
|
|
(sage-wait-until-dead sprocess 2 "soft kill") |
|
|
|
(when (not (eq (process-status sprocess) 'exit)) |
|
(comint-kill-input) |
|
(comint-kill-subjob) |
|
(sage-wait-until-dead sprocess 3 "hard kill")))) |
|
|
|
;; (comint-mode) |
|
;; the idea here is to not respawn sage from within the compilation |
|
;; sentinel. it seems easy to deadlock emacs in this scenario. |
|
(run-with-idle-timer 0.3 nil 'sage-rerun-internal buffer) |
|
))) |
|
|
|
;;;###autoload |
|
(defun sage-build-process-setup () |
|
"Setup compilation variables and buffer for `sage-build'. |
|
Set up `compilation-exit-message-function' and run `sage-build-setup-hook'." |
|
(set (make-local-variable 'compilation-exit-message-function) |
|
(lambda (status code msg) |
|
(if (eq status 'exit) |
|
(cond ((zerop code) |
|
'("finished (build succeeded)\n" . "build succeeded")) |
|
((> code 0) |
|
'("finished (build failed)\n" . "build failed")) |
|
(t |
|
(cons msg code))) |
|
(cons msg code)))) |
|
(add-hook 'compilation-finish-functions |
|
(lambda (buffer msg) |
|
(when current-prefix-arg ;; XXX (and (string-match "succeed" msg) andrun) |
|
(rerun-sage) |
|
)) nil t) |
|
(run-hooks 'sage-build-setup-hook)) |
|
|
|
(defvar sage-build-regexp-alist |
|
'(("File \"\\(.*?\\)\", line \\([0-9]+\\):" |
|
1 2))) |
|
|
|
(define-compilation-mode sage-build-mode "sage-build" |
|
"Sets `grep-last-buffer' and `compilation-window-height'." |
|
;; (set (make-local-variable 'compilation-error-face) |
|
;; grep-hit-face) |
|
;; (set (make-local-variable 'compilation-disable-input) t) |
|
|
|
(set (make-local-variable 'compilation-error-regexp-alist) |
|
sage-build-regexp-alist) |
|
(set (make-local-variable 'compilation-process-setup-function) |
|
'sage-build-process-setup)) |
|
|
|
;;;###autoload |
|
(defun sage-default-build-command () |
|
"Compute the default sage build command for C-u M-x sage-build to offer." |
|
(format "%s -b" sage-command)) |
|
|
|
;;;###autoload |
|
(defalias 'build-sage 'sage-build) |
|
|
|
;;;###autoload |
|
(defun sage-build (command-args) |
|
"Build sage (like sage -b), with user-specified args, and collect output in a buffer. |
|
While sage-build runs asynchronously, you can use |
|
\\[next-error] (M-x next-error), or |
|
\\<sage-build-mode-map>\\[compile-goto-error] in the sage-build XXX |
|
output buffer, to go to the lines where sage-build found matches. |
|
|
|
With prefix arg (or andrun), act like sage -br: build sage and |
|
spawn a new sage on success. |
|
|
|
This command uses a special history list for its COMMAND-ARGS, so you can |
|
easily repeat a sage-build command." |
|
(interactive |
|
(progn |
|
(let ((default (sage-default-build-command))) |
|
(list (read-from-minibuffer (if current-prefix-arg |
|
"Build and run sage (like this): " |
|
"Build sage (like this): ") |
|
default |
|
nil nil 'sage-build-history |
|
(if current-prefix-arg nil default)))))) |
|
|
|
;; Setting process-setup-function makes exit-message-function work |
|
;; even when async processes aren't supported. |
|
(unless (hash-table-p compilation-locs) |
|
(compilation-minor-mode 1)) |
|
(compilation-forget-errors) |
|
(setq compilation-messages-start nil) |
|
(compilation-start command-args 'sage-build-mode)) |
|
|
|
(provide 'sage-build) |
|
|
|
;;; sage-build.el ends here
|
|
|