Initial Commit
[packages] / xemacs-packages / prog-modes / prolog.el
1 ;;; prolog.el --- major mode for editing and running Prolog under Emacs
2
3 ;; Copyright (C) 1986, 1987, 1993 Free Software Foundation, Inc.
4
5 ;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
6 ;; Keywords: languages
7
8 ;; This file is part of XEmacs.
9
10 ;; XEmacs is free software; you can redistribute it and/or modify it
11 ;; under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 2, or (at your option)
13 ;; any later version.
14
15 ;; XEmacs is distributed in the hope that it will be useful, but
16 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 ;; General Public License for more details.
19
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with XEmacs; see the file COPYING.  If not, write to the 
22 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
24
25 ;;; Synched up with: Not synched with FSF, we appear to have a newer version
26
27 ;;; Commentary:
28
29 ;; This package provides a major mode for editing Prolog.  It knows
30 ;; about Prolog syntax and comments, and can send regions to an inferior
31 ;; Prolog interpreter process.
32
33 ;;; Code:
34
35 (defvar prolog-mode-syntax-table nil)
36 (defvar prolog-mode-abbrev-table nil)
37 (defvar prolog-mode-map nil)
38
39 (defgroup prolog nil
40   "Major mode for editing and running Prolog under Emacs"
41   :group 'languages)
42
43   
44 (defcustom prolog-program-name "prolog"
45   "*Program name for invoking an inferior Prolog with `run-prolog'."
46   :type 'string
47   :group 'prolog)
48
49 (defcustom prolog-consult-string "reconsult(user).\n"
50   "*(Re)Consult mode (for C-Prolog and Quintus Prolog). "
51   :type 'string
52   :group 'prolog)
53
54 (defcustom prolog-compile-string "compile(user).\n"
55   "*Compile mode (for Quintus Prolog)."
56   :type 'string
57   :group 'prolog)
58
59 (defcustom prolog-eof-string "end_of_file.\n"
60   "*String that represents end of file for prolog.
61 nil means send actual operating system end of file."
62   :type 'string
63   :group 'prolog)
64
65 (defcustom prolog-indent-width 4
66   "Level of indentation in Prolog buffers."
67   :type 'integer
68   :group 'prolog)
69
70 (defconst prolog-font-lock-keywords (purecopy
71   (list
72    (cons (concat
73           "[( \t]\\("
74           (mapconcat 'identity
75                      '("write" "writeq" "nl" "is" "call" "read" "get" "get0"
76                        "tell" "told" "open" "close" "format" "put"
77                        "assert" "asserta" "assertz"
78                        "retract" "retractall" "clause"
79                        "record" "recorda" "abolish"
80                        "setof" "bagof" "findall" "sort" "compare"
81                        "var" "nonvar" "integer" "float"  "number" "ground"
82                        "atom" "atomic" "simple" "callable" "compound"
83                        "functor" "arg" "copy_term" "numbervars"
84                        "atom_chars"  "number_chars" "atom_to_chars"
85                        "length" "unix" "halt"
86                        "op" "dynamic" "meta_predicate" "raise_exception"
87                        "module" "ensure_loaded" "use_module"
88                        "fail" "true"
89                        "module_interface" "begin_module" "define_struct"
90                        "import" "export" "global" "tool" "external"
91                        "define_macro" "local" "library" "from"
92                        )
93                      "\\|")
94           "\\)[ .,\t\n()]")
95          1)
96    '("^[a-z][a-zA-Z0-9_]+"   0 font-lock-function-name-face)
97 ;   '("[@!$#]"   0 font-lock-function-name-face)
98    '("!"   0 font-lock-function-name-face)
99    '("@"   0 font-lock-function-name-face)
100    '("<=>"   0 font-lock-function-name-face)
101    '("==>"   0 font-lock-function-name-face)
102    '(";"   0 font-lock-function-name-face)
103    '(":-" 0 font-lock-function-name-face)
104    '("\\[" 0 font-lock-keyword-face)
105    '("\\]" 0 font-lock-keyword-face)
106    '("|" 0 font-lock-keyword-face)
107    ))
108   "Additional expressions to highlight in Prolog mode.")
109
110 (if prolog-mode-syntax-table
111     ()
112   (let ((table (make-syntax-table)))
113     (modify-syntax-entry ?/  ". 14" table)
114     (modify-syntax-entry ?*  ". 23" table)
115     (modify-syntax-entry ?%  "< b"  table)
116     (modify-syntax-entry ?\n "> b"  table)
117     (modify-syntax-entry ?_  "w"  table)
118     (modify-syntax-entry ?\\ "\\" table)
119     (modify-syntax-entry ?\' "\"" table)
120     (modify-syntax-entry ?+  "." table)
121     (modify-syntax-entry ?-  "." table)
122     (modify-syntax-entry ?=  "." table)
123     (modify-syntax-entry ?<  "." table)
124     (modify-syntax-entry ?>  "." table)
125     (setq prolog-mode-syntax-table table)))
126
127 (define-abbrev-table 'prolog-mode-abbrev-table ())
128
129 (defun prolog-mode-variables ()
130   (set-syntax-table prolog-mode-syntax-table)
131   (setq local-abbrev-table prolog-mode-abbrev-table)
132   (make-local-variable 'paragraph-start)
133   (setq paragraph-start (concat "%%\\|$\\|" page-delimiter)) ;'%%..'
134   (make-local-variable 'paragraph-separate)
135   (setq paragraph-separate paragraph-start)
136   (make-local-variable 'paragraph-ignore-fill-prefix)
137   (setq paragraph-ignore-fill-prefix t)
138   (make-local-variable 'indent-line-function)
139   (setq indent-line-function 'prolog-indent-line)
140   (make-local-variable 'comment-start)
141   (setq comment-start "%")
142   (make-local-variable 'comment-start-skip)
143   (setq comment-start-skip "%+ *")
144   (make-local-variable 'comment-column)
145   (setq comment-column 48)
146   (make-local-variable 'comment-indent-function)
147   (setq comment-indent-function 'prolog-comment-indent))
148
149 (defun prolog-mode-commands (map)
150   (define-key map "\t" 'prolog-indent-line)
151   (define-key map "\e\C-x" 'prolog-consult-region))
152
153 (if prolog-mode-map
154     nil
155   (setq prolog-mode-map (make-sparse-keymap))
156   (prolog-mode-commands prolog-mode-map))
157
158 ;;;###autoload
159 (defun prolog-mode ()
160   "Major mode for editing Prolog code for Prologs.
161 Blank lines and `%%...' separate paragraphs.  `%'s start comments.
162 Commands:
163 \\{prolog-mode-map}
164 Entry to this mode calls the value of `prolog-mode-hook'
165 if that value is non-nil."
166   (interactive)
167   (kill-all-local-variables)
168   (use-local-map prolog-mode-map)
169   (setq major-mode 'prolog-mode)
170   (setq mode-name "Prolog")
171   (prolog-mode-variables)
172   (run-hooks 'prolog-mode-hook))
173
174 (defun prolog-indent-line (&optional whole-exp)
175   "Indent current line as Prolog code.
176 With argument, indent any additional lines of the same clause
177 rigidly along with this one (not yet)."
178   (interactive "p")
179   (let ((indent (prolog-indent-level))
180         (pos (- (point-max) (point))) beg)
181     (beginning-of-line)
182     (setq beg (point))
183     (skip-chars-forward " \t")
184     (if (zerop (- indent (current-column)))
185         nil
186       (delete-region beg (point))
187       (indent-to indent))
188     (if (> (- (point-max) pos) (point))
189         (goto-char (- (point-max) pos)))
190     ))
191
192 (defun prolog-indent-level ()
193   "Compute prolog indentation level."
194   (save-excursion
195     (beginning-of-line)
196     (skip-chars-forward " \t")
197     (cond
198      ((looking-at "%%%") 0)             ;Large comment starts
199      ((looking-at "%[^%]") comment-column) ;Small comment starts
200      ((bobp) 0)                         ;Beginning of buffer
201      (t
202       (let ((empty t) ind more less)
203         (if (looking-at ")")
204             (setq less t)               ;Find close
205           (setq less nil))
206         ;; See previous indentation
207         (while empty
208           (forward-line -1)
209           (beginning-of-line)
210           (if (bobp)
211               (setq empty nil)
212             (skip-chars-forward " \t")
213             (if (not (or (looking-at "%[^%]") (looking-at "\n")))
214                 (setq empty nil))))
215         (if (bobp)
216             (setq ind 0)                ;Beginning of buffer
217           (setq ind (current-column)))  ;Beginning of clause
218         ;; See its beginning
219         (if (looking-at "%%[^%]")
220             ind
221           ;; Real prolog code
222           (if (looking-at "(")
223               (setq more t)             ;Find open
224             (setq more nil))
225           ;; See its tail
226           (end-of-prolog-clause)
227           (or (bobp) (forward-char -1))
228           (cond ((looking-at "[,(;>]")
229                  (if (and more (looking-at "[^,]"))
230                      (+ ind prolog-indent-width) ;More indentation
231                    (max tab-width ind))) ;Same indentation
232                 ((looking-at "-") tab-width) ;TAB
233                 ((or less (looking-at "[^.]"))
234                  (max (- ind prolog-indent-width) 0)) ;Less indentation
235                 (t 0))                  ;No indentation
236           )))
237      )))
238
239 (defun end-of-prolog-clause ()
240   "Go to end of clause in this line."
241   (beginning-of-line 1)
242   (let* ((eolpos (save-excursion (end-of-line) (point))))
243     (if (re-search-forward comment-start-skip eolpos 'move)
244         (goto-char (match-beginning 0)))
245     (skip-chars-backward " \t")))
246
247 (defun prolog-comment-indent ()
248   "Compute prolog comment indentation."
249   (cond ((looking-at "%%%") 0)
250         ((looking-at "%%") (prolog-indent-level))
251         (t
252          (save-excursion
253                (skip-chars-backward " \t")
254                ;; Insert one space at least, except at left margin.
255                (max (+ (current-column) (if (bolp) 0 1))
256                     comment-column)))
257         ))
258
259 \f
260 ;;;
261 ;;; Inferior prolog mode
262 ;;;
263 (defvar inferior-prolog-mode-map nil)
264
265 ;;;###autoload
266 (defun inferior-prolog-mode ()
267   "Major mode for interacting with an inferior Prolog process.
268
269 The following commands are available:
270 \\{inferior-prolog-mode-map}
271
272 Entry to this mode calls the value of `prolog-mode-hook' with no arguments,
273 if that value is non-nil.  Likewise with the value of `comint-mode-hook'.
274 `prolog-mode-hook' is called after `comint-mode-hook'.
275
276 You can send text to the inferior Prolog from other buffers
277 using the commands `process-send-region', `process-send-string' and
278 \\[prolog-consult-region].
279
280 Commands:
281 Tab indents for Prolog; with argument, shifts rest
282  of expression rigidly with the current line.
283 Paragraphs are separated only by blank lines and '%%'.
284 '%'s start comments.
285
286 Return at end of buffer sends line as input.
287 Return not at end copies rest of line to end and sends it.
288 \\[comint-kill-input] and \\[backward-kill-word] are kill commands, imitating normal Unix input editing.
289 \\[comint-interrupt-subjob] interrupts the shell or its current subjob if any.
290 \\[comint-stop-subjob] stops. \\[comint-quit-subjob] sends quit signal."
291   (interactive)
292   (require 'comint)
293   (comint-mode)
294   (setq major-mode 'inferior-prolog-mode
295         mode-name "Inferior Prolog"
296         comint-prompt-regexp "^| [ ?][- ] *")
297   (prolog-mode-variables)
298   (if inferior-prolog-mode-map nil
299     (setq inferior-prolog-mode-map (copy-keymap comint-mode-map))
300     (prolog-mode-commands inferior-prolog-mode-map))
301   (use-local-map inferior-prolog-mode-map)
302   (run-hooks 'prolog-mode-hook))
303
304 ;;;###autoload
305 (defun run-prolog ()
306   "Run an inferior Prolog process, input and output via buffer *prolog*."
307   (interactive)
308   (require 'comint)
309   (switch-to-buffer (make-comint "prolog" prolog-program-name))
310   (inferior-prolog-mode))
311
312 (defun prolog-consult-region (compile beg end)
313   "Send the region to the Prolog process made by \"M-x run-prolog\".
314 If COMPILE (prefix arg) is not nil, use compile mode rather than consult mode."
315   (interactive "P\nr")
316   (save-excursion
317     (if compile
318         (process-send-string "prolog" prolog-compile-string)
319       (process-send-string "prolog" prolog-consult-string))
320     (process-send-region "prolog" beg end)
321     (process-send-string "prolog" "\n")         ;May be unnecessary
322     (if prolog-eof-string
323         (process-send-string "prolog" prolog-eof-string)
324       (process-send-eof "prolog")))) ;Send eof to prolog process.
325
326 (defun prolog-consult-region-and-go (compile beg end)
327   "Send the region to the inferior Prolog, and switch to *prolog* buffer.
328 If COMPILE (prefix arg) is not nil, use compile mode rather than consult mode."
329   (interactive "P\nr")
330   (prolog-consult-region compile beg end)
331   (switch-to-buffer "*prolog*"))
332
333 ;; XEmacs addition
334 ;;;###autoload(add-to-list 'auto-mode-alist '("\\.prolog\\'" . prolog-mode))
335
336 ;;; prolog.el ends here