Changes http://wiki.axiom-developer.org/AxiomEmacsMode/diff
--
??changed:
\begin{document}
-\title{\$SPAD/src/emacs/axiommode.el\\Version 19-06-2007}
+\title{\$SPAD/src/emacs/axiommode.el\\Version 30-09-2007}
\author{Jay Belanger, Fran\c{c}ois Maltey, Martin Rubey and Cliff Yapp}
\item[M-return] evaluates input and appends output at the end of the buffer.
++added:
+\item[C-return] writes the front item of the kill ring into a temporary file,
+ and then [[)re]]ads that file.
\end{description}
??changed:
(defvar axiom-after-output-wait 100) ;; time to wait for axiom to repond prompt
-
+(defvar axiom-mode-map (copy-keymap comint-mode-map)
+ "local key map for Axiom terminal mode")
@
++added:
+; from emacs 22
+(defun make-temp-file (prefix &optional dir-flag suffix)
+ "Create a temporary file.
+The returned file name (created by appending some random characters at the end
+of PREFIX, and expanding against `temporary-file-directory' if necessary),
+is guaranteed to point to a newly created empty file.
+You can then use `write-region' to write new data into the file.
+
+If DIR-FLAG is non-nil, create a new empty directory instead of a file.
+
+If SUFFIX is non-nil, add that at the end of the file name."
+ (let ((umask (default-file-modes))
+ file)
+ (unwind-protect
+ (progn
+ ;; Create temp files with strict access rights. It's easy to
+ ;; loosen them later, whereas it's impossible to close the
+ ;; time-window of loose permissions otherwise.
+ (set-default-file-modes ?\700)
+ (while (condition-case ()
+ (progn
+ (setq file
+ (make-temp-name
+ (expand-file-name prefix
temporary-file-directory)))
+ (if suffix
+ (setq file (concat file suffix)))
+ (if dir-flag
+ (make-directory file)
+ (write-region "" nil file nil 'silent nil 'excl))
+ nil)
+ (file-already-exists t))
+ ;; the file was somehow created by someone else between
+ ;; `make-temp-name' and `write-region', let's try again.
+ nil)
+ file)
+ ;; Reset the umask.
+ (set-default-file-modes umask))))
+
+(defun axiom-yank ()
+ "puts the front item of the kill ring into a temporary file and makes axiom
)read it"
+ (interactive)
+ (let* ((tmp-file (make-temp-file "axiom" nil ".input"))
+ (end (progn (goto-char (point-max))
+ (point))))
+ (write-region (car kill-ring-yank-pointer) nil tmp-file)
+ (delete-region (axiom-previous-prompt) end)
+ (comint-set-process-mark)
+ (insert (concat ")re " tmp-file))
+ (axiom-eval)
+ (delete-file tmp-file)))
+
+(define-key axiom-mode-map [(ctrl return)] 'axiom-yank)
+
(defun axiom-output? (position)
--removed:
<<axiom-mode-map>>=
-(defvar axiom-mode-map (copy-keymap comint-mode-map)
- "local key map for Axiom terminal mode")
-
(define-key axiom-mode-map [(meta up)] 'axiom-previous-input)
<<axiom-reset>>=
++added:
+(defun axiom-resync-directory ()
+ "Send )sys pwd to the axiom process, parse the result, cd to it and clean up
+ output. Assumes that we are just after a prompt."
+ (let ((inhibit-read-only t)
+ (begin (progn (forward-line 0) (point)))
+ (end (progn (end-of-line) (point)))
+ (dir))
+ (delete-region begin end)
+ (process-send-string (get-buffer-process (current-buffer)) ")sys pwd\n")
+ (axiom-wait-for-output)
+ (forward-line -1)
+ (end-of-line)
+ (sit-for 0)
+ (setq end (point))
+ (cd (buffer-substring-no-properties begin end))
+ (delete-region (1- begin) end)
+ (forward-line 1)
+ (end-of-line)))
+
+; (let ((inhibit-read-only t)
+; (inhibit-field-text-motion t)
+; dir begin end)
+; (delete-region (progn (forward-line 0) (point))
+; (progn (end-of-line) (point)))
+; (process-send-string (get-buffer-process (current-buffer)) ")sys pwd\n")
+; (axiom-wait-for-output)
+; (forward-line -1)
+; (setq begin (point))
+; (end-of-line)
+; (sit-for 0)
+; (setq end (point))
+; (cd (buffer-substring-no-properties begin end))
+; (delete-region (1- begin) end)
+; (forward-line 1)
+; (end-of-line)))
+
+
(defun axiom-reset ()
??changed:
"Remove read-only properties from everything after the last prompt. Set
-process-mark so we can continue."
+process-mark so we can continue. Resync directory."
(interactive)
??changed:
(axiom-make-prompt (re-search-backward axiom-prompt nil t) (point))
- (comint-goto-process-mark)))
+ (comint-goto-process-mark)
+ (axiom-resync-directory)))
??changed:
(interactive)
- (if axiom-system-command
- ;; we are responding to a system command.
- (progn
- (setq axiom-system-command nil
- axiom-end-of-input (copy-marker (axiom-end-of-input)))
- (comint-send-input)
- (axiom-wait-for-output)
-
- ;; If there is a prompt further down, we are overwriting old stuff.
- (when (re-search-forward axiom-prompt nil t)
- (re-search-backward axiom-prompt)
- (axiom-repair-prompts)
- (re-search-forward axiom-prompt nil t)
- (comint-set-process-mark)))
-
- ;; otherwise, we first check whether process-mark is at a prompt
- (when (axiom-prompt? (1- (process-mark axiom-process)))
-
- ;; do we have multiline input?
-[25 more lines...]
+ (let ((axiom-cd nil))
+ (if axiom-system-command
+ ;; we are responding to a system command.
+ (progn
+ (setq axiom-system-command nil
+ axiom-end-of-input (copy-marker (axiom-end-of-input)))
+ (comint-send-input)
+ (axiom-wait-for-output)
+ ;; If there is a prompt further down, we are overwriting old stuff.
+ (when (re-search-forward axiom-prompt nil t)
+ (re-search-backward axiom-prompt)
+ (axiom-repair-prompts)
+ (re-search-forward axiom-prompt nil t)
+ (comint-set-process-mark)))
+
+ ;; otherwise, we first check whether process-mark is at a prompt
+ (when (axiom-prompt? (1- (process-mark axiom-process)))
+
+ ;; do we have multiline input?
+ (beginning-of-line)
+ (if (looking-at ".*_ *$")
+ (progn (end-of-line)
+ (newline))
+
+ ;; move to the the end of the preceding prompt
+ (axiom-previous-prompt)
+ (comint-set-process-mark)
+ ;; is it a system command?
+ (setq axiom-system-command (looking-at " *)"))
+ (when axiom-system-command
+ (setq axiom-cd (looking-at " *)cd *")))
+
+ ;; If there is a prompt further down, we are overwriting old stuff.
+ (if (axiom-next-prompt)
+ (progn (axiom-overwrite-output-eval)
+ ;; if we are now looking at a prompt, we are certainly not
+ ;; answering a question posed by axiom.
+ (when (looking-backward-at axiom-prompt)
+ (when axiom-cd (axiom-resync-directory))
+ (setq axiom-system-command nil)
+ (axiom-repair-prompts)
+ (end-of-line) ;; this moves point to the end of the
prompt!
+ ;; it seems to work even if we type text
+ ;; during a computation.
+ (comint-set-process-mark)))
+ (axiom-normal-eval)
+ (when (looking-backward-at axiom-prompt)
+ (when axiom-cd (axiom-resync-directory))
+ (setq axiom-system-command nil))))))))
++added:
+\subsection{Command completion}
+
+It is not clear to what extend command completion would be useful in Axiom.
+For the moment, I just enable filename completion. I'd like to restrict to
+[[.input]], [[.spad]] and [[.as]] filenames, but I do not know how.
+
+<<axiom-command-completion>>=
+(define-key axiom-mode-map "\t" 'axiom-dynamic-complete)
+@
+
+I had [[(define-key axiom-mode-map [tab] 'axiom-dynamic-complete)]]
+here before, but that did not work entirely: hitting tab twice inserted a tab!
+
+<<axiom-command-completion>>=
+(defun axiom-file-name-all-completions (pathnondir directory)
+ "Returns all filenames relevant to axiom"
+ (save-match-data
+ (remove-if-not
+ (function (lambda (f)
+ (or (and (string-match "\\.[^.]*\\'" f)
+ (member (match-string 0 f)
+ (list ".input" ".spad" ".as")))
+ (string= (file-name-directory f) f))))
+ (file-name-all-completions pathnondir directory))))
+@
+
+We are not using [[file-name-extension]], since that would strip off trailing
+tildes.
+
+
+The following probably could be simplified a lot. In principle, I need to find
+the position of the first mismatch.
+
+<<axiom-command-completion>>=
+(defun axiom-file-name-completion (file directory)
+ "Returns the longest string common to all file names relevant to axiom in
+DIRECTORY that start with FILE. If there is only one and FILE matches it
+exactly, returns t. Returns nil if DIR contains no name starting with FILE."
+ (let* ((completions (axiom-file-name-all-completions file directory))
+ (frst (first completions))
+ (len (length frst))
+ (start 0)
+ (not-done t))
+ (cond ((consp (rest completions))
+ (while (and not-done
+ (> len start))
+ (let ((char (substring frst start (1+ start)))
+ (rst (rest completions)))
+ (while (and not-done
+ (consp rst))
+ (if (and (> (length (first rst)) start)
+ (string= (substring (first rst)
+ start (1+ start))
+ char))
+ (setq rst (rest rst))
+ (setq not-done nil))))
+ (when not-done
+ (setq start (1+ start))))
+ (substring frst 0 start))
+ ((string= frst file)
+ t)
+ (t
+ frst))))
+@
+
+This is stolen from [[comint.el]], I only changed [[file-name-all-completions]]
+to [[axiom-file-name-all-completions]].
+
+<<axiom-command-completion>>=
+(defun axiom-dynamic-list-filename-completions ()
+ "List in help buffer possible completions of the filename at point."
+ (interactive)
+ (let* ((completion-ignore-case (memq system-type '(ms-dos windows-nt)))
+ ;; If we bind this, it breaks remote directory tracking in rlogin.el.
+ ;; I think it was originally bound to solve file completion problems,
+ ;; but subsequent changes may have made this unnecessary. sm.
+ ;;(file-name-handler-alist nil)
+ (filename (or (comint-match-partial-filename) ""))
+ (pathdir (file-name-directory filename))
+ (pathnondir (file-name-nondirectory filename))
+ (directory (if pathdir (comint-directory pathdir) default-directory))
+ (completions (axiom-file-name-all-completions pathnondir directory)))
+ (if (not completions)
+ (message "No completions of %s" filename)
+ (comint-dynamic-list-completions
+ (mapcar 'comint-quote-filename completions)))))
+@
+
+Again, this is stolen from [[comint.el]]. I should specialise here, I think.
+Furthermore, directory tracking does not work yet.
+
+<<axiom-command-completion>>=
+(defun axiom-dynamic-complete ()
+ "Dynamically perform completion at point."
+ (interactive)
+ (when (save-excursion
+ (axiom-previous-prompt)
+ (looking-at " *)"))
+ (axiom-dynamic-complete-filename)))
+@
+
+Maybe the bit to detect whether we have a system command should go into a new
+function, since it's used in eval, too.
+
+<<axiom-command-completion>>=
+(defun axiom-dynamic-complete-filename ()
+ "Dynamically complete at point as a filename.
+See `comint-dynamic-complete-filename'. Returns t if successful."
+ (interactive)
+ (let* ((completion-ignore-case (memq system-type '(ms-dos windows-nt)))
+ (completion-ignored-extensions comint-completion-fignore)
+ ;; If we bind this, it breaks remote directory tracking in rlogin.el.
+ ;; I think it was originally bound to solve file completion problems,
+ ;; but subsequent changes may have made this unnecessary. sm.
+ ;;(file-name-handler-alist nil)
+ (minibuffer-p (window-minibuffer-p (selected-window)))
+ (success t)
+ (dirsuffix (cond ((not comint-completion-addsuffix)
+ "")
+ ((not (consp comint-completion-addsuffix))
+ (char-to-string directory-sep-char))
+ (t
+ (car comint-completion-addsuffix))))
+ (filesuffix (cond ((not comint-completion-addsuffix)
+ "")
+ ((not (consp comint-completion-addsuffix))
+ " ")
+ (t
+ (cdr comint-completion-addsuffix))))
+ (filename (or (comint-match-partial-filename) ""))
+ (pathdir (file-name-directory filename))
+ (pathnondir (file-name-nondirectory filename))
+ (directory (if pathdir (comint-directory pathdir) default-directory))
+ (completion (axiom-file-name-completion pathnondir directory)))
+ (cond ((null completion)
+ (message "No completions of %s" filename)
+ (setq success nil))
+ ((eq completion t) ; Means already completed "file".
+ (insert filesuffix)
+ (unless minibuffer-p
+ (message "Sole completion")))
+ ((string-equal completion "") ; Means completion on "directory/".
+ (axiom-dynamic-list-filename-completions))
+ (t ; Completion string returned.
+ (let ((file (concat (file-name-as-directory directory) completion)))
+ (insert (comint-quote-filename
+ (substring (directory-file-name completion)
+ (length pathnondir))))
+ (cond ((symbolp (axiom-file-name-completion completion directory))
+ ;; We inserted a unique completion.
+ (insert (if (file-directory-p file) dirsuffix filesuffix))
+ (unless minibuffer-p
+ (message "Completed")))
+ ((and comint-completion-recexact comint-completion-addsuffix
+ (string-equal pathnondir completion)
+ (file-exists-p file))
+ ;; It's not unique, but user wants shortest match.
+ (insert (if (file-directory-p file) dirsuffix filesuffix))
+ (unless minibuffer-p
+ (message "Completed shortest")))
+ ((or comint-completion-autolist
+ (string-equal pathnondir completion))
+ ;; It's not unique, list possible completions.
+ (axiom-dynamic-list-filename-completions))
+ (t
+ (unless minibuffer-p
+ (message "Partially completed")))))))
+ success))
+@
;;################### Terminal Mode ########################
++added:
+<<axiom-command-completion>>
<<axiommodekeyboardmap-axiom-previous-input>>
--
forwarded from http://wiki.axiom-developer.org/[EMAIL PROTECTED]