debray@sbcs.UUCP (Saumya Debray) (03/02/84)
The Prolog mode for emacs: ========================= I. Description: -------------- This is a set of mlisp functions that facilitates the writing and execution of Prolog programs within emacs. Text files with a '.P' suffix are automatically put into electric-prolog mode upon entry. II. Features: ------------ 1) When a right-paren ")" or right-bracket "]" is entered, the cursor flashes back to the corresponding left-paren or left-bracket. If there is a parenthesis mismatch, an error is signalled. 2) When a period "." is typed in at the end of a clause, the clause is checked for unbalanced "("s or "["s: if any are found, an error is signalled. 3) Prolog may be called directly from within emacs by typing "ESC-x prolog". This results in the spawning of a Prolog process which may be manipulated as follows: Stop Prolog ------------------------------------ ^z Continue (after stopping prolog with a ^z): ---- ^q Terminate Prolog ------------------------------- ^d Interrupt Prolog ------------------------------- ^c 4) During debugging, it often becomes necessary to reconsult files repeatedly. This is simply achieved in electric-prolog by putting the cursor in the buffer corresponding to the file to be reconsulted and typing "^Xr" (control-x followed by r); electric-prolog will then write the file out, construct the reconsult command for Prolog and position the user in the buffer corresponding to the Prolog process, whereupon, by simply hitting <return>, the file will be reconsulted. III. Bugs: ---------- 1) The "%" comment-starter is not recognized by electric-prolog (mainly because I never used it and never got around to putting it in). 2) When a character that is not a period, followed by a period ".", followed by a space, tab or newline is encountered, the end of a clause is assumed to have been reached. (The period at the end of a clause is required to be preceded by a character other than a period so that constructs like "p =.. [X|Y]" are not interpreted to be at the end of the clause.) This may lead to spurious error messages at times, if an operator is defined in a manner that confuses electric-prolog. IV. Installation: ---------------- (i) The following lines are to be added to ..../maclib/profile.ml (for the system) or the user's ".emacs_pro" file: ================================================== (autoload "electric-prolog-mode" "prolog.ml") (auto-execute "electric-prolog-mode" "*.P") (autoload "prolog" "prolog.ml") ================================================== (ii) The following is the source code for the electric-prolog functions: They should be placed in a file "prolog.ml" (or any other name that is consistent with the 3 lines above ((autoload ...), (auto-execute ...)) in .../maclib (for the system) or the user's home directory. (Note: in order that users can execute prolog in any directory, the complete path to the "prolog.ml" file should really be included in the autoload/auto- execute commands in the user's ".emacs_pro" file, above, e.g.: (autoload "electric-prolog-mode" "/ue/db2/debray/prolog.ml") (auto-execute "electric-prolog-mode" "*.P") (autoload "prolog" "/ue/db2/debray/prolog.ml") ). Please send mail regarding experienes/questions/bugs to: Saumya Debray, Dept. of Computer Science, SUNY at Stony Brook: (516)-246-7146 philabs!sbcs!debray debray@suny-sbcs@CSNet-Relay ================================================== ; "Electric-prolog mode" ; Author: Saumya K. Debray, Dept. of Computer Science, SUNY at Stony Brook. ; Date: Sept. 1983. ; ; "prolog-paren" flashes the cursor back to a balancing parenthesis within ; the same clause. ; (defun (prolog-paren currbuf (insert-character (last-key-struck)) (save-excursion (setq currbuf (current-buffer-name)) (clause-to-buffer "$0001$") (backward-paren) (if (bobp) (progn (erase-buffer) (switch-to-buffer currbuf) (error-message (concat "Too many " (concat (char-to-string (last-key-struck)) "s")))) (progn (erase-buffer) (switch-to-buffer currbuf) (backward-paren) (if (dot-is-visible) (sit-for 5) (progn (beginning-of-line) (set-mark) (end-of-line) (message (region-to-string))))) ) ) ) (erase-comment (set-mark) (forward-word) (if (in-comment) (progn (search-forward "*/") (delete-region-to-buffer "$0003$") (delete-white-space) 1) 0) ) (clause-to-buffer buffname (setq buffname (arg 1 "c-t-b buffname: ")) (set-mark)(back-to-end-of-clause) (exchange-dot-and-mark) (copy-region-to-buffer buffname) (temp-use-buffer buffname) (electric-prolog-mode) ) (prolog-reverse-paren currbuf ; (insert-character '.') (if (! (in-comment)) (progn (delete-white-space) (save-excursion (setq currbuf (current-buffer-name)) (backward-character)(clause-to-buffer "$0002$") (beginning-of-file) (if (looking-at '.') (delete-next-character)) (delete-white-space) (while (erase-comment)(novalue)) (end-of-file) (insert-character ')') (if (! (error-occured (backward-paren))) (if (! (bobp)) (error-message "There are unbalanced ('s in this clause"))) (end-of-file)(delete-previous-character)(insert-character ']') (backward-paren) (if (! (bobp)) (error-message "There are unbalanced ['s in this clause")) (erase-buffer) (switch-to-buffer currbuf) ) ) ) ) (check-clause char (insert-character (last-key-struck)) (setq char (get-tty-character)) (push-back-character char) (if (+ (+ (= char 9) ; tab = ^I (= char 10) ; newline = ^J ) (+ (= char 13) ; newline = ^M (= char 32) ; space )) (prolog-reverse-paren) ) ) ; "in-comment" returns true if dot is within a comment, false otherwise. (in-comment begin-com end-com curr-pos (save-excursion (setq curr-pos (dot)) (if (! (error-occured (search-reverse "/*"))) (progn (setq begin-com (dot)) (goto-character curr-pos) (if (error-occured (search-reverse "*/")) (setq end-com 0) (setq end-com (dot))) (> begin-com end-com))) ) ) ; "back-to-end-of-clause" moves the dot to the end of the previous clause. (back-to-end-of-clause (re-search-reverse "[^.]\\.$\\|[^.]\\.[ ]\\|\\`.") (while (in-comment) (re-search-reverse "[^.]\\.$\\|[^.]\\.[ ]\\|\\`.")) (novalue) ) (reconsult-file fname (if (= (active-process) "Prolog") (progn (write-current-file) (setq fname (concat "[-'" (concat (current-file-name) "']."))) (pop-to-buffer "Prolog") (insert-string fname) ) (error-message "Prolog process does not exist!") ) ) (prolog (message "prolog ...") (start-prolog) (local-bind-to-key "input-to-prolog" "\^M") (local-bind-to-key "stop-prolog" "\^Z") (local-bind-to-key "continue-prolog" "\^Q") (local-bind-to-key "eot-prolog" "\^D") (local-bind-to-key "interrupt-prolog" "\^C") (local-bind-to-key "reconsult-file" "\^Xr") (novalue) ) (start-prolog (if (= (active-process) "Prolog") (pop-to-buffer "Prolog") (start-process "prolog" "Prolog") ) ) (input-to-prolog (newline) (region-to-process "Prolog") ) (stop-prolog (stop-process "Prolog") (message "Prolog stopped") ) (continue-prolog (continue-process "Prolog") (message "continuing Prolog") (pop-to-buffer "Prolog") ) (eot-prolog (eot-process "Prolog") ) (interrupt-prolog (int-process "Prolog") ) ) (defun (electric-prolog-mode (remove-all-local-bindings) (local-bind-to-key "prolog-paren" ")") (local-bind-to-key "prolog-paren" "]") (local-bind-to-key "check-clause" ".") (local-bind-to-key "reconsult-file" "\^Xr") (setq mode-string "prolog") (use-syntax-table "prolog") (novalue) ) ) (use-syntax-table "prolog") (modify-syntax-entry "() (") (modify-syntax-entry ")( )") (modify-syntax-entry "(] [") (modify-syntax-entry ")[ ]") (modify-syntax-entry """ '") (modify-syntax-entry """ """) (modify-syntax-entry """ { /*") (modify-syntax-entry """ }*/") (modify-syntax-entry "w _a-zA-Z0-9") ; ============================= EOF ========================================= -- Saumya Debray, SUNY at Stony Brook uucp: {floyd, cbosgd, ihnp4, mcvax, cmcl2}!philabs \ {amd70, akgua, decwrl, utzoo}!allegra > !sbcs!debray {teklabs, hp-pcd, metheus}!ogcvax / CSNet: debray@suny-sbcs@CSNet-Relay