[net.sources] emacs prolog mode: mlisp source

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