home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / languages / elisp / packages / MouseAndMenuEmacs / Prolog.el < prev    next >
Encoding:
Text File  |  1990-05-31  |  15.3 KB  |  420 lines

  1. ;; Major mode for editing Prolog, and for running Prolog under Emacs
  2. ;; Copyright (C) 1986 Free Software Foundation, Inc.
  3. ;; Author Masanobu UMEDA (umerin@flab.fujitsu.junet)
  4.  
  5. ;; Modified, Fri Mar 4 16:29:47 1988, by Russell Ritchie, <russell@uk.ac.strath.hci>
  6. ;; to use the ``write-temp-file and load'' method now employed by lisp-mode
  7. ;; and to allow differing Prolog programs to be run.
  8.  
  9. ;; Modified, Thu Apr 21 14:15:06 1988, by Russell Ritchie, <russell@uk.ac.strath.hci>,
  10. ;; to allow multiple, differing Prolog processes (for using Quintus saved states).
  11. ;; Set inferior-prolog-program to the name of the saved state you want to run.
  12. ;; Do this either with a Local variables comment in Prolog source file, or in your
  13. ;; .emacs initialisation file. If you set it to nil in your .emacs file, you will be
  14. ;; prompted for the name of the prolog program you want to run every time you visit
  15. ;; a[nother] Prolog file.
  16.  
  17. ;; Added inferior-prolog-buffer, Wed Nov 9 11:57:33 1988, <russell@uk.ac.strath.hci>.
  18. ;; Added (provide 'Prolog), Wed Nov 9 11:58:44 1988, <russell@uk.ac.strath.hci>.
  19.  
  20. ;; This file is part of GNU Emacs.
  21.  
  22. ;; GNU Emacs is distributed in the hope that it will be useful,
  23. ;; but WITHOUT ANY WARRANTY.  No author or distributor
  24. ;; accepts responsibility to anyone for the consequences of using it
  25. ;; or for whether it serves any particular purpose or works at all,
  26. ;; unless he says so in writing.  Refer to the GNU Emacs General Public
  27. ;; License for full details.
  28.  
  29. ;; Everyone is granted permission to copy, modify and redistribute
  30. ;; GNU Emacs, but only under the conditions described in the
  31. ;; GNU Emacs General Public License.   A copy of this license is
  32. ;; supposed to have been given to you along with GNU Emacs so you
  33. ;; can know your rights and responsibilities.  It should be in a
  34. ;; file named COPYING.  Among other things, the copyright notice
  35. ;; and this notice must be preserved on all copies.
  36.  
  37. (require 'shell)
  38. (provide 'Prolog)
  39.  
  40. (defvar prolog-mode-syntax-table nil)
  41. (defvar prolog-mode-abbrev-table nil)
  42. (defvar prolog-mode-map nil)
  43.  
  44. (defvar inferior-prolog-program "prolog"
  45.   "*Program that is run by 'run-prolog' in the Prolog buffer.
  46. If this is set to nil a program to be executed will be prompted for.")
  47.  
  48. (defvar inferior-prolog-buffer nil
  49.   "The buffer the inferior Prolog process is running in.
  50. Do NOT set this variable, it is bound automatically after determination of which program to run.")
  51.  
  52. (defvar prolog-consult-string "reconsult('%s').\n"
  53.   "*(Re)Consult mode (for C-Prolog and Quintus Prolog). ")
  54.  
  55. (defvar prolog-compile-string "compile('%s').\n"
  56.   "*Compile mode (for Quintus Prolog).")
  57.  
  58. (defvar prolog-eof-string "end_of_file.\n"
  59.   "*String that represents end of file for prolog.
  60. nil means send actual operating system end of file.")
  61.  
  62. (defvar prolog-indent-width 4)
  63.  
  64. (if prolog-mode-syntax-table
  65.     ()
  66.   (let ((table (make-syntax-table)))
  67.     (modify-syntax-entry ?_ "w" table)
  68.     (modify-syntax-entry ?\\ "\\" table)
  69.     (modify-syntax-entry ?/ "." table)
  70.     (modify-syntax-entry ?* "." table)
  71.     (modify-syntax-entry ?+ "." table)
  72.     (modify-syntax-entry ?- "." table)
  73.     (modify-syntax-entry ?= "." table)
  74.     (modify-syntax-entry ?% "<" table)
  75.     (modify-syntax-entry ?< "." table)
  76.     (modify-syntax-entry ?> "." table)
  77.     (modify-syntax-entry ?\' "\"" table)
  78.     (setq prolog-mode-syntax-table table)))
  79.  
  80. (define-abbrev-table 'prolog-mode-abbrev-table ())
  81.  
  82. (defun prolog-mode-variables ()
  83.   (set-syntax-table prolog-mode-syntax-table)
  84.   (setq local-abbrev-table prolog-mode-abbrev-table)
  85.   (make-local-variable 'paragraph-start)
  86.   (setq paragraph-start (concat "^%%\\|^$\\|" page-delimiter)) ;'%%..'
  87.   (make-local-variable 'paragraph-separate)
  88.   (setq paragraph-separate paragraph-start)
  89.   (make-local-variable 'indent-line-function)
  90.   (setq indent-line-function 'prolog-indent-line)
  91.   (make-local-variable 'comment-start)
  92.   (setq comment-start "%")
  93.   (make-local-variable 'comment-start-skip)
  94.   (setq comment-start-skip "%+ *")
  95.   (make-local-variable 'comment-column)
  96.   (setq comment-column 48)
  97.   (make-local-variable 'comment-indent-hook)
  98.   (setq comment-indent-hook 'prolog-comment-indent))
  99.  
  100. (defun prolog-mode-commands (map)
  101.   (define-key map "\t" 'prolog-indent-line)
  102.   (define-key map "\C-c\C-p" 'prolog-consult-predicate-and-go)
  103.   (define-key map "\C-cp"    'prolog-consult-predicate)
  104.   (define-key map "\C-c\C-r" 'prolog-consult-region-and-go)
  105.   (define-key map "\C-cr"    'prolog-consult-region)
  106.   (define-key map "\C-c\C-b" 'prolog-consult-buffer-and-go)
  107.   (define-key map "\C-cb"    'prolog-consult-buffer))
  108.  
  109. (if prolog-mode-map
  110.     nil
  111.   (setq prolog-mode-map (make-sparse-keymap))
  112.   (prolog-mode-commands prolog-mode-map))
  113.  
  114. (defun prolog-mode ()
  115.   "Major mode for editing Prolog code for Prologs.
  116. Blank lines and `%%...' separate paragraphs.  `%'s start comments.
  117. Commands:
  118. \\{prolog-mode-map}
  119. Entry to this mode calls the value of prolog-mode-hook
  120. if that value is non-nil."
  121.   (interactive)
  122.   (kill-all-local-variables)
  123.   (use-local-map prolog-mode-map)
  124.   (setq major-mode 'prolog-mode)
  125.   (setq mode-name "Prolog")
  126.   (prolog-mode-variables)
  127.   (run-hooks 'prolog-mode-hook))
  128.  
  129. (defun c-prolog-mode ()
  130.   "Major mode for editing C-Prolog code.
  131. Commands:
  132. \\{prolog-mode-map}
  133. Entry to this mode calls the value of prolog-mode-hook then c-prolog-mode-hook."
  134.   (interactive)
  135.   (prolog-mode)
  136.   (setq mode-name "C-Prolog")
  137.   (make-local-variable 'inferior-prolog-program)
  138.   (setq inferior-prolog-program "c-prolog1.5")
  139.   (make-local-variable 'inferior-prolog-buffer)    ; Set by #'run-prolog when the buffer is created.
  140.   (run-hooks 'c-prolog-mode-hook))
  141.  
  142. (defun quintus-prolog-mode ()
  143.   "Major mode for editing Quintus Prolog code.
  144. Commands:
  145. \\{prolog-mode-map}
  146. Entry to this mode calls the value of prolog-mode-hook then quintus-prolog-mode-hook."
  147.   (interactive)
  148.   (prolog-mode)
  149.   (setq mode-name "Quintus Prolog")
  150.   (make-local-variable 'inferior-prolog-program)
  151.   (setq inferior-prolog-program "qprolog2.0")
  152.   (make-local-variable 'inferior-prolog-process-name)
  153.   (setq inferior-prolog-process-name inferior-prolog-program)
  154.   (make-local-variable 'inferior-prolog-buffer)    ; Set by #'run-prolog when the buffer is created.
  155.   (run-hooks 'quintus-prolog-mode-hook))
  156.  
  157. (defun prolog-indent-line (&optional whole-exp)
  158.   "Indent current line as Prolog code.
  159. With argument, indent any additional lines of the same clause
  160. rigidly along with this one (not yet)."
  161.   (interactive "p")
  162.   (let ((indent (prolog-indent-level))
  163.     (pos (- (point-max) (point))) beg)
  164.     (beginning-of-line)
  165.     (setq beg (point))
  166.     (skip-chars-forward " \t")
  167.     (if (zerop (- indent (current-column)))
  168.     nil
  169.       (delete-region beg (point))
  170.       (indent-to indent))
  171.     (if (> (- (point-max) pos) (point))
  172.     (goto-char (- (point-max) pos)))
  173.     ))
  174.  
  175. (defun prolog-indent-level ()
  176.   "Compute prolog indentation level."
  177.   (save-excursion
  178.     (beginning-of-line)
  179.     (skip-chars-forward " \t")
  180.     (cond
  181.      ((looking-at "%%%") 0)        ;Large comment starts
  182.      ((looking-at "%[^%]") comment-column) ;Small comment starts
  183.      ((bobp) 0)                ;Beginning of buffer
  184.      (t
  185.       (let ((empty t) ind more less)
  186.     (if (looking-at ")")
  187.         (setq less t)        ;Find close
  188.       (setq less nil))
  189.     ;; See previous indentation
  190.     (while empty
  191.       (forward-line -1)
  192.       (beginning-of-line)
  193.       (if (bobp) (setq empty nil))
  194.       (skip-chars-forward " \t")
  195.       (if (not (or (looking-at "%[^%]") (looking-at "\n")))
  196.           (setq empty nil)))
  197.     (setq ind (current-column))    ;Beginning of clause
  198.     ;; See its beginning
  199.     (if (looking-at "%%[^%]")
  200.         ind
  201.       ;; Real prolog code
  202.       (if (looking-at "(")
  203.           (setq more t)        ;Find open
  204.         (setq more nil))
  205.       ;; See its tail
  206.       (end-of-prolog-clause)
  207.       (or (bobp) (forward-char -1))
  208.       (cond ((looking-at "[,(;>]")
  209.          (if (and more (looking-at "[^,]"))
  210.              (+ ind prolog-indent-width) ;More indentation
  211.            (max tab-width ind))) ;Same indentation
  212.         ((looking-at "-") tab-width) ;TAB
  213.         ((or less (looking-at "[^.]"))
  214.          (max (- ind prolog-indent-width) 0)) ;Less indentation
  215.         (t 0))            ;No indentation
  216.       )))
  217.      )))
  218.  
  219. (defun end-of-prolog-clause ()
  220.   "Go to end of clause in this line."
  221.   (beginning-of-line 1)
  222.   (let* ((eolpos (save-excursion (end-of-line) (point))))
  223.     (if (re-search-forward comment-start-skip eolpos 'move)
  224.     (goto-char (match-beginning 0)))
  225.     (skip-chars-backward " \t")))
  226.  
  227. (defun prolog-comment-indent ()
  228.   "Compute prolog comment indentation."
  229.   (cond ((looking-at "%%%") 0)
  230.     ((looking-at "%%") (prolog-indent-level))
  231.     (t
  232.      (save-excursion
  233.            (skip-chars-backward " \t")
  234.            (max (1+ (current-column)) ;Insert one space at least
  235.             comment-column)))
  236.     ))
  237.  
  238.  
  239. ;;;
  240. ;;; Inferior prolog mode
  241. ;;;
  242. (defvar inferior-prolog-mode-map nil)
  243.  
  244. (defun inferior-prolog-mode ()
  245.   "Major mode for interacting with an inferior Prolog process.
  246.  
  247. Runs the value of inferior-prolog-program in the Prolog buffer.
  248.  
  249. The following commands are available:
  250. \\{inferior-prolog-mode-map}
  251.  
  252. Entry to this mode calls the value of prolog-mode-hook with no arguments,
  253. if that value is non-nil.  Likewise with the value of shell-mode-hook.
  254. prolog-mode-hook is called after shell-mode-hook.
  255.  
  256. You can send text to the inferior Prolog from other buffers
  257. using the commands send-region, send-string, \\[prolog-consult-predicate], 
  258. \\[prolog-consult-region and \\[prolog-consult-buffer].
  259.  
  260. Commands:
  261. Tab indents for Prolog; with argument, shifts rest
  262.  of expression rigidly with the current line.
  263. Paragraphs are separated only by blank lines and '%%'. '%'s start comments.
  264.  
  265. Return at end of buffer sends line as input.
  266. Return not at end copies rest of line to end and sends it.
  267. \\[shell-send-eof] sends end-of-file as input.
  268. \\[kill-shell-input] and \\[backward-kill-word] are kill commands, imitating normal Unix input editing.
  269. \\[interrupt-shell-subjob] interrupts the shell or its current subjob if any.
  270. \\[stop-shell-subjob] stops, likewise. \\[quit-shell-subjob] sends quit signal, likewise."
  271.   (interactive)
  272.   (kill-all-local-variables)
  273.   (setq major-mode 'inferior-prolog-mode)
  274.   (setq mode-name "Inferior Prolog")
  275.   (setq mode-line-process '(": %s"))
  276.   (prolog-mode-variables)
  277.   (require 'shell)
  278.   (if inferior-prolog-mode-map
  279.       nil
  280.     (setq inferior-prolog-mode-map (copy-alist shell-mode-map))
  281.     (prolog-mode-commands inferior-prolog-mode-map))
  282.   (use-local-map inferior-prolog-mode-map)
  283.   (make-local-variable 'last-input-start)
  284.   (setq last-input-start (make-marker))
  285.   (make-local-variable 'last-input-end)
  286.   (setq last-input-end (make-marker))
  287.   (make-variable-buffer-local 'shell-prompt-pattern)
  288.   (setq shell-prompt-pattern "^| [ ?][- ] *") ;Set prolog prompt pattern
  289.   (run-hooks 'shell-mode-hook 'prolog-mode-hook))
  290.  
  291. (defun run-prolog ()
  292.   "Run an inferior Prolog process, use 
  293. inferior-prolog-progam for the name of the Prolog buffer."
  294.   (interactive)
  295.   (let ((inferior-prolog-program
  296.      (or inferior-prolog-program (read-existing-program-name))))
  297.     (setq inferior-prolog-buffer
  298.       (make-shell (file-name-nondirectory inferior-prolog-program)
  299.               (if (string-match "~" inferior-prolog-program)
  300.               ;; User has specified a ~-relative program, so...
  301.               (expand-file-name inferior-prolog-program)
  302.             inferior-prolog-program)))
  303.     (switch-to-buffer inferior-prolog-buffer)
  304.     (inferior-prolog-mode)))
  305.  
  306. (defun prolog-consult-region (compile beg end)
  307.   "Send the region to the Prolog process made by M-x run-prolog.
  308.  If COMPILE (prefix arg) is not nil,
  309.  use compile mode rather than consult mode.
  310.  
  311. Bound to \\<prolog-mode-map>\\[prolog-consult-region]"
  312.   (interactive "P\nr")
  313.   (message "Sending region...")
  314.   (save-excursion
  315.     (let* ((inferior-prolog-program (file-name-nondirectory inferior-prolog-program))
  316.        (filename
  317.         (format
  318.          "/tmp/emPROLOG%d" (process-id (get-process inferior-prolog-program)))))
  319.       (write-region beg end filename nil 'nomessage)
  320.       (process-send-string
  321.     inferior-prolog-program
  322.     (format (if compile prolog-compile-string prolog-consult-string) filename))))
  323.   (message "Sent region!"))
  324.  
  325. (defun prolog-consult-region-and-go (compile beg end)
  326.   "Send the region to the inferior Prolog, and switch to Prolog buffer.
  327.  If COMPILE (prefix arg) is not nil,
  328.  use compile mode rather than consult mode.
  329.  
  330. Bound to \\<prolog-mode-map>\\[prolog-consult-region]"
  331.   (interactive "P\nr")
  332.   (prolog-consult-region compile beg end)
  333.   (switch-to-buffer-other-window inferior-prolog-buffer)
  334.   (end-of-buffer))
  335.  
  336. (defun start-of-prolog-predicate (predicate)
  337.   "Attempt to find the start of prolog PREDICATE.
  338. Simple minded: searches from start of buffer for PREDICATE at beginning of line."
  339.   (interactive "sWhich predicate?: ")
  340.   (goto-char (point-min))
  341.   (re-search-forward (concat "^" predicate))
  342.   (beginning-of-line))
  343.  
  344. (defun end-of-prolog-predicate (predicate)
  345.   "Attempt to find the end of prolog PREDICATE.
  346. Simple minded: searches from end of buffer for last PREDICATE clause at beginning of line, 
  347. then searches for \".\" at end of line."
  348.   (interactive "sWhich predicate?: ")
  349.   (goto-char (point-max))
  350.   (re-search-backward (concat "^" predicate))
  351.   (re-search-forward "\\.$"))
  352.  
  353. (defun prolog-consult-predicate (compile predicate)
  354.   "Send the prompted-for predicate to the PROLOG process made by M-x run-prolog.
  355. If interactive arg COMPILE is non-nil, then try to compile predicate using
  356. the value of prolog-compile-string, rather than 'reconsult'ing.
  357.  
  358. Bound to \\<prolog-mode-map>\\[prolog-consult-predicate]"
  359.   (interactive "P\nsWhich predicate?: ")
  360.   (save-excursion
  361.     (end-of-prolog-predicate predicate)
  362.     (let ((end (point)))
  363.       (start-of-prolog-predicate predicate)
  364.       (prolog-consult-region compile (point) end))))
  365.  
  366. (defun prolog-consult-predicate-and-go (compile predicate)
  367.   "Send the prompted-for predicate to Prolog, and switch to Prolog buffer.
  368. If interactive arg COMPILE is non-nil, then try to compile predicate using
  369. the value of prolog-compile-string, rather than 'reconsult'ing.
  370.  
  371. Bound to \\<prolog-mode-map>\\[prolog-consult-predicate-and-go]"
  372.   (interactive "P\nsWhich predicate?: ")
  373.   (prolog-consult-predicate compile predicate)
  374.   (switch-to-buffer-other-window inferior-prolog-buffer)
  375.   (end-of-buffer))
  376.  
  377. (defun prolog-consult-buffer (compile)
  378.   "Send the entire current buffer to the Prolog process.
  379.  If prefix arg COMPILE is non-nil then use
  380.  compile mode rather than consult mode.
  381.  
  382. Bound to \\<prolog-mode-map>\\[prolog-consult-buffer]."
  383.   (interactive "P")
  384.   (message (concat "Sending contents of " (buffer-name) "..."))
  385.   (save-excursion
  386.     (mark-whole-buffer)
  387.     (prolog-consult-region compile (point) (mark)))
  388.   (message (concat "Sent " (buffer-name) "!")))
  389.  
  390. (defun prolog-consult-buffer-and-go (compile)
  391.   "Send the entire current buffer to the Prolog buffer and go to it.
  392.  If prefix arg COMPILE is non-nil then use
  393.  compile mode rather than consult mode.
  394.  
  395. Bound to \\<prolog-mode-map>\\[prolog-consult-buffer-and-go]."
  396.   (interactive "P")
  397.   (prolog-consult-buffer compile)
  398.   (switch-to-buffer-other-window inferior-prolog-buffer)
  399.   (end-of-buffer))
  400.  
  401. (defun prolog-compile-region (start end)
  402.   "Compile PROLOG buffer from START of region to END."
  403.   (interactive "r")
  404.   (prolog-consult-region t start end))
  405.  
  406. (defun prolog-compile-buffer ()
  407.   "Compile all of current PROLOG buffer."
  408.   (interactive)
  409.   (prolog-consult-buffer t))
  410.  
  411. (defun start-prolog ()
  412.   "Called when a file ending in \".pl\" is visited. Starts a prolog process 
  413.  (using run-prolog) in another window and displays that and the file, leaving 
  414. the cursor at the top of the file buffer."
  415.   (interactive)
  416.   (let ((this (current-buffer)))
  417.     (prolog-mode)            ; Set prolog-mode in the ".pl" file.
  418.     (run-prolog)            ; Start up a prolog process.
  419.     (switch-to-buffer this)))
  420.