stiller@blaze.cs.jhu.edu writes:
Is there an emacs mode for gap ? I just built GAP 3.1 on SPARC and run
in shell mode from within emacs but the shell echoes each line I type.
How do I stop this?
The lines are no longer printed twice if you start GAP with option
'-n'. This will disable the command line editing.
Here is, however, a first version of 'gap.el' which defines a GAP mode
for GNU Emacs. It carries some of GAP's features to Emacs, such as
command completion and the help facility. Any suggestions to improve
and enhance 'gap.el' are welcome.
Goetz Pfeiffer.
--Cut here------------------------------------------------------------------- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;A gap.el GAP Filter Goetz Pfeiffer ;; ;A @(#)$Id: 1.html,v 1.2 2004/04/21 15:06:03 felsch Exp $ ;; ;Y Copyright 1992, Lehrstuhl D fuer Mathematik, RWTH Aachen, Germany ;; ;; This file contains the definition of a GAP mode for GNU Emacs. This mode ;; is based on the shell mode of GNU Emacs. ;; ;; GNU Emacs is free software; you can redistribute it and/or modify it ;; under the terms of the GNU General Public License as published by the ;; Free Software Foundation; either version 1, or (at your option) any later ;; version. ;; ;; GNU Emacs is distributed in the hope that it will be useful, but WITHOUT ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for ;; more details. ;; ;; You should have received a copy of the GNU General Public License along ;; with GNU Emacs; see the file COPYING. If not, write to the Free Software ;; Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. ;; ;; The GAP mode enables Emacs to run GAP in a buffer. Moreover it enables ;; editing GAP library files with command completion. Start a GAP process ;; in buffer '*gap*' with 'M-x gap'. Then 'TAB' will do command line ;; completion just like GAP does without Emacs. To get help about a topic ;; enter '?'. This is possible in any place of the command line. The topic ;; defaults to the symbol around point. Hitting <return> on a previous ;; input line in the GAP buffer will send that line again to the GAP ;; process. ;; ;; Editing a '*.g' file in GAP mode is possible but somehow dangerous. To ;; enter GAP mode type 'M-x gap-mode' in the buffer containing the '*.g' ;; file. Both the help facility ('?') and command completion are available. ;; They will refer to the GAP process running in the buffer '*gap*'. This ;; may cause big confusion if the GAP process is busy with other things. ;; ;H $Log: 1.html,v $ ;H Revision 1.2 2004/04/21 15:06:03 felsch ;H Corrected links in the Forum Archive pages. VF ;H ;H Revision 1.1.1.1 2004/04/20 13:39:30 felsch ;H The final GAP-Forum archive until 2003. ;H ;H Revision 1.4 2003/06/12 19:20:31 gap ;H Further update. AH ;H ;H Revision 1.3 1997/08/15 11:18:41 gap ;H New forum setup. AH ;H ;H Revision 1.2 1997/04/24 15:23:28 gap ;H These files were replaced by the versions in WWW. The content is basically the ;H same but the formatting has been much more friendly towards the HTML-Converter. ;H AH ;H ;H Revision 1.1 1996/10/30 13:06:31 gap ;H added forum archive and translation files. ;H ;H Revision 1.1 1992/04/15 15:45:15 goetz ;H Initial revision ;H ;;
(provide 'gap)
(require 'shell)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;V gap-process-string ;V gap-start-options ;V gap-process-buffer ;V gap-prompt-pattern ;; (defvar gap-process-string "/usd/gap/3.1/src/gap.ds" "*A string to pass to the unix 'exec' function to start GAP") (defvar gap-start-options (list "-l" "/usd/gap/3.1/lib/" "-m" "2m") "*The list of initial GAP options")
(defvar gap-process-buffer
"*gap*"
"The buffer normally running GAP.")
(defvar gap-prompt-pattern "\\(gap\\)?> "
"*Regexp used by Newline command in GAP mode to match prompt.")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;V gap-key-map . . . . . . . . . . . . . . . . . . . . . . . . key bindings. ;; ;; The 'gap-key-map' defines the key bindings in gap mode. ;; ;; The <return> key is bound to 'gap-send', '\t' is bound to ;; 'gap-complete' and the '?' key is bound to 'gap-help'. ;; (defvar gap-key-map nil) (if gap-key-map nil (setq gap-key-map (copy-keymap shell-mode-map)) (define-key gap-key-map "\C-m" 'gap-send) (define-key gap-key-map "\t" 'gap-complete) (define-key gap-key-map "?" 'gap-help)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;V gap-syntax-table . . . . . . . . . . . . . . . . . . . . . syntax table. ;; ;; The 'gap-syntax-table' describes the syntax of the GAP language. This ;; is used to determine an identifier, for example (see 'gap-complete'). ;; Defines '#' to be the beginning of a comment and '\n' to be the end. ;; (defvar gap-syntax-table nil "Syntax table used while in gap mode.")
(if gap-syntax-table ()
(setq gap-syntax-table (make-syntax-table))
(modify-syntax-entry ?# "<" gap-syntax-table)
(modify-syntax-entry ?\n ">" gap-syntax-table))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;F (gap-send) . . . . . . . . . . . . . . . . . . . . . . send input to GAP. ;; ;; 'gap-send' sends the prepared input to GAP. This function is bound to ;; the <return> key in gap mode. It has to decide whether the new input ;; has been typed after the last output or whether a previous line shall ;; be repeated. In the latter case it has to strip off an occasional ;; prompt. ;; (defun gap-send () "Send input to GAP." (interactive "*") (or (get-buffer-process (current-buffer)) (error "Current buffer has no process")) (end-of-line) (if (eobp) (progn (move-marker last-input-start (process-mark (get-buffer-process (current-buffer)))) (insert ?\n) (move-marker last-input-end (point))) (beginning-of-line) (re-search-forward gap-prompt-pattern (save-excursion (end-of-line) (point)) t) (let ((copy (buffer-substring (point) (progn (forward-line 1) (point))))) (goto-char (point-max)) (move-marker last-input-start (point)) (insert copy) (move-marker last-input-end (point)))) (let ((process (get-buffer-process (current-buffer)))) (process-send-region process last-input-start last-input-end) (set-marker (process-mark process) (point))) (setq gap-send-state 'echo)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;F (gap-mode) . . . . . . . . . . . . . . . . . . . . . . . Emacs' GAP mode. ;; (defun gap-mode () "Major mode for interacting with GAP and editing '*.g' files.
\\[gap] starts GAP.
\\[gap-send] sends input to GAP.
\\[gap-help] gives help on a GAP subject.
Most commands from the Emacs' shell mode are available as well.
Entry to this mode calls the value of gap-mode-hook with no args,
if that value is non-nil."
(interactive)
(kill-all-local-variables)
(setq major-mode 'gap-mode)
(setq mode-name "GAP")
(setq mode-line-process '(": %s"))
(use-local-map gap-key-map);; rebind RET if editing file
(or (get-buffer-process (current-buffer))
(local-set-key "\C-m" 'newline))(set-syntax-table gap-syntax-table)
(make-local-variable 'gap-send-state)
(setq gap-send-state 'normal)
(make-local-variable 'last-input-start)
(setq last-input-start (make-marker))
(make-local-variable 'last-input-end)
(setq last-input-end (make-marker))(run-hooks 'gap-mode-hook))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;F (gap-output-filter PROC STRING) . . . . . . . . . . . handle GAP output. ;; ;; The filter 'gap-output-filter' is used to process GAP output before ;; it is echoed in the buffer. It behaves according to its state ;; 'gap-send-state'. ;; ;; The possible states are: ;; ;; 'normal': just put the output in the buffer. ;; ;; 'echo': suppress GAP echo of the command, then return to 'normal'. ;; ;; 'completing': handle command line completion. ;; (defun gap-output-filter (proc string) (cond ((eq gap-send-state 'normal) (insert string) (set-marker (process-mark proc) (point))) ((eq gap-send-state 'echo) (if (string-equal string "\n") (setq gap-send-state 'normal))) ((eq gap-send-state 'completing) (if (string-equal string "\C-g") (beep) (if (not (or (string-equal string " ") (string-equal string "\C-h"))) (insert string))) ))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;F (gap-help-filter PROC STRING) . . . . . . . . . . . . handle help output. ;; ;; The 'gap-help-filter' takes care of GAP help output. The output of a ;; help request is put into the '*Help*' buffer. This filter deletes the ;; echo of the request. As GAP sends its help in pages we have to type ;; <space> at the end of each page. The prompt indicates that help is ;; complete. ;; (defun gap-help-filter (proc string) (let ((cbuf (current-buffer))) (set-buffer "*Help*") (goto-char (point-max)) (insert string) (beginning-of-line) (if (looking-at " -- <space> for more --") (progn (delete-region (point) (point-max)) (process-send-string proc " "))) (if (looking-at "\\( *[\C-h]+\\)\\|\\(\\?.*[\C-m]\\)") (progn (delete-region (point) (point-max)))) (if (looking-at "gap>") (progn (delete-region (point) (point-max)) (set-process-filter proc 'gap-output-filter))) (set-buffer cbuf))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;F (gap) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . runs GAP. ;; (defun gap () "Run GAP, input and output via buffer *gap*." (interactive) (pop-to-buffer (start-gap-process "*gap*" "gap" gap-process-string gap-start-options)) (if (not (eq major-mode 'gap-mode)) (gap-mode)) (setq gap-process-buffer (current-buffer)) (set-process-filter (get-buffer-process gap-process-buffer) 'gap-output-filter)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;F (gap-complete) . . . . . . . . . . . . . . . . . . . complete identifier. ;; ;; 'gap-complete' sends the partial identifier preceding point to the ;; running gap process and asks this via '\t' to complete the ;; identifier. We have to handle the gap output of the complete ;; identifier. Moreover we have to clear the GAP input line via '^X' ;; while the intended input is still prepared in the Emacs buffer. ;; (defun gap-complete () "Complete the partial identifier preceeding point." (interactive "*") (let ((process (get-buffer-process gap-process-buffer)) sent-successfully) (if (not (and process (memq (process-status process) '(run stop)))) (error "No GAP process running in buffer %s" gap-process-buffer)) (setq gap-completion-ident (gap-ident-around-point))
;; delete partial identifier from input line
(delete-backward-char (length gap-completion-ident));; ask for completion and clear input line
(setq gap-send-state 'completing)
(process-send-string process (concat gap-completion-ident "\t\C-x"))
))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;F (gap-ident-around-point) . . . . . . . . . . . . identifier around point. ;; (defun gap-ident-around-point () "Return the identifier around the point as a string." (save-excursion (let (beg) (if (not (eobp)) (forward-char 1)) (if (not (re-search-backward "\\w\\|\\s_" nil t)) "" (forward-char 1) (backward-sexp) (setq beg (point)) (forward-sexp) (buffer-substring beg (point)))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;F (gap-help TOPIC ARG) . . . . . . . . . . . . . . . . . . . . . . . help. ;; ;; 'gap-help' normally is invoked by pressing the '?' key in gap mode. ;; The minibuffer is used to ask for the help topic. Here the identifier ;; around point (see 'gap-ident-around-point') is used as a default. The ;; chosen topic is passed to the GAP help facility. The output is ;; displayed in the '*Help' buffer. ;; (defun gap-help (topic arg) "Display GAP help about TOPIC in the *Help* buffer." (interactive (let ((enable-recursive-minibuffers t) (try-word (gap-ident-around-point)) val) (if (string-equal try-word "gap>") (setq val (read-string "GAP topic: ")) (setq val (read-string (format "GAP topic (default %s): " try-word))) (if (string-equal val "") (setq val try-word))) (list val current-prefix-arg))) (let ((process (get-buffer-process gap-process-buffer)) sent-successfully) (if (not (and process (memq (process-status process) '(run stop)))) (error "No gap process running in buffer %s" gap-process-buffer)) (unwind-protect (progn (with-output-to-temp-buffer "*Help*" (print-help-return-message)) (set-process-filter process 'gap-help-filter) (process-send-string process (concat "?" topic "\n")))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;F (start-gap-process ... ) . . . . . . . . . . . . . . . . . . . start GAP. ;; (defun start-gap-process (bufferid name program switches) (let ((buffer (get-buffer-create bufferid)) (disp (getenv "DISPLAY")) proc proc-args proc-more-args status size) (setq proc (get-buffer-process buffer)) (if proc (setq status (process-status proc))) (save-excursion (set-buffer buffer) (if (memq status '(run stop)) nil (if proc (delete-process proc)) (message "Starting GAP...")
(setq proc (apply 'start-process name buffer (concat exec-directory "env") (format "TERMCAP=emacs:co#%d:tc=unknown:" (screen-width)) "TERM=emacs" "EMACS=t" "-" program switches))(setq procname (process-name proc)) (goto-char (point-max)) (set-marker (process-mark proc) (point)) (shell-mode))) buffer))
(run-hooks 'gap-mode-load-hook)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;E Emacs . . . . . . . . . . . . . . . . . . . . . . . local emacs variables ;; ;; Local Variables: ;; fill-column: 77 ;; fill-prefix: ";; " ;; End: ;;