Initial revision
[bpt/emacs.git] / lisp / progmodes / prolog.el
CommitLineData
d8025917 1;; Major mode for editing Prolog, and for running Prolog under Emacs
2;; Copyright (C) 1986, 1987 Free Software Foundation, Inc.
3;; Author Masanobu UMEDA (umerin@flab.flab.fujitsu.junet)
4
5;; This file is part of GNU Emacs.
6
7;; GNU Emacs is free software; you can redistribute it and/or modify
8;; it under the terms of the GNU General Public License as published by
9;; the Free Software Foundation; either version 1, or (at your option)
10;; any later version.
11
12;; GNU Emacs is distributed in the hope that it will be useful,
13;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15;; GNU General Public License for more details.
16
17;; You should have received a copy of the GNU General Public License
18;; along with GNU Emacs; see the file COPYING. If not, write to
19;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
20
21(defvar prolog-mode-syntax-table nil)
22(defvar prolog-mode-abbrev-table nil)
23(defvar prolog-mode-map nil)
24
25(defvar prolog-program-name "prolog"
26 "*Program name for invoking an inferior Prolog with `run-prolog'.")
27
28(defvar prolog-consult-string "reconsult(user).\n"
29 "*(Re)Consult mode (for C-Prolog and Quintus Prolog). ")
30
31(defvar prolog-compile-string "compile(user).\n"
32 "*Compile mode (for Quintus Prolog).")
33
34(defvar prolog-eof-string "end_of_file.\n"
35 "*String that represents end of file for prolog.
36nil means send actual operaing system end of file.")
37
38(defvar prolog-indent-width 4)
39
40(if prolog-mode-syntax-table
41 ()
42 (let ((table (make-syntax-table)))
43 (modify-syntax-entry ?_ "w" table)
44 (modify-syntax-entry ?\\ "\\" table)
45 (modify-syntax-entry ?/ "." table)
46 (modify-syntax-entry ?* "." table)
47 (modify-syntax-entry ?+ "." table)
48 (modify-syntax-entry ?- "." table)
49 (modify-syntax-entry ?= "." table)
50 (modify-syntax-entry ?% "<" table)
51 (modify-syntax-entry ?< "." table)
52 (modify-syntax-entry ?> "." table)
53 (modify-syntax-entry ?\' "\"" table)
54 (setq prolog-mode-syntax-table table)))
55
56(define-abbrev-table 'prolog-mode-abbrev-table ())
57
58(defun prolog-mode-variables ()
59 (set-syntax-table prolog-mode-syntax-table)
60 (setq local-abbrev-table prolog-mode-abbrev-table)
61 (make-local-variable 'paragraph-start)
62 (setq paragraph-start (concat "^%%\\|^$\\|" page-delimiter)) ;'%%..'
63 (make-local-variable 'paragraph-separate)
64 (setq paragraph-separate paragraph-start)
65 (make-local-variable 'paragraph-ignore-fill-prefix)
66 (setq paragraph-ignore-fill-prefix t)
67 (make-local-variable 'indent-line-function)
68 (setq indent-line-function 'prolog-indent-line)
69 (make-local-variable 'comment-start)
70 (setq comment-start "%")
71 (make-local-variable 'comment-start-skip)
72 (setq comment-start-skip "%+ *")
73 (make-local-variable 'comment-column)
74 (setq comment-column 48)
75 (make-local-variable 'comment-indent-hook)
76 (setq comment-indent-hook 'prolog-comment-indent))
77
78(defun prolog-mode-commands (map)
79 (define-key map "\t" 'prolog-indent-line)
80 (define-key map "\e\C-x" 'prolog-consult-region))
81
82(if prolog-mode-map
83 nil
84 (setq prolog-mode-map (make-sparse-keymap))
85 (prolog-mode-commands prolog-mode-map))
86
87(defun prolog-mode ()
88 "Major mode for editing Prolog code for Prologs.
89Blank lines and `%%...' separate paragraphs. `%'s start comments.
90Commands:
91\\{prolog-mode-map}
92Entry to this mode calls the value of prolog-mode-hook
93if that value is non-nil."
94 (interactive)
95 (kill-all-local-variables)
96 (use-local-map prolog-mode-map)
97 (setq major-mode 'prolog-mode)
98 (setq mode-name "Prolog")
99 (prolog-mode-variables)
100 (run-hooks 'prolog-mode-hook))
101
102(defun prolog-indent-line (&optional whole-exp)
103 "Indent current line as Prolog code.
104With argument, indent any additional lines of the same clause
105rigidly along with this one (not yet)."
106 (interactive "p")
107 (let ((indent (prolog-indent-level))
108 (pos (- (point-max) (point))) beg)
109 (beginning-of-line)
110 (setq beg (point))
111 (skip-chars-forward " \t")
112 (if (zerop (- indent (current-column)))
113 nil
114 (delete-region beg (point))
115 (indent-to indent))
116 (if (> (- (point-max) pos) (point))
117 (goto-char (- (point-max) pos)))
118 ))
119
120(defun prolog-indent-level ()
121 "Compute prolog indentation level."
122 (save-excursion
123 (beginning-of-line)
124 (skip-chars-forward " \t")
125 (cond
126 ((looking-at "%%%") 0) ;Large comment starts
127 ((looking-at "%[^%]") comment-column) ;Small comment starts
128 ((bobp) 0) ;Beginning of buffer
129 (t
130 (let ((empty t) ind more less)
131 (if (looking-at ")")
132 (setq less t) ;Find close
133 (setq less nil))
134 ;; See previous indentation
135 (while empty
136 (forward-line -1)
137 (beginning-of-line)
138 (if (bobp)
139 (setq empty nil)
140 (skip-chars-forward " \t")
141 (if (not (or (looking-at "%[^%]") (looking-at "\n")))
142 (setq empty nil))))
143 (if (bobp)
144 (setq ind 0) ;Beginning of buffer
145 (setq ind (current-column))) ;Beginning of clause
146 ;; See its beginning
147 (if (looking-at "%%[^%]")
148 ind
149 ;; Real prolog code
150 (if (looking-at "(")
151 (setq more t) ;Find open
152 (setq more nil))
153 ;; See its tail
154 (end-of-prolog-clause)
155 (or (bobp) (forward-char -1))
156 (cond ((looking-at "[,(;>]")
157 (if (and more (looking-at "[^,]"))
158 (+ ind prolog-indent-width) ;More indentation
159 (max tab-width ind))) ;Same indentation
160 ((looking-at "-") tab-width) ;TAB
161 ((or less (looking-at "[^.]"))
162 (max (- ind prolog-indent-width) 0)) ;Less indentation
163 (t 0)) ;No indentation
164 )))
165 )))
166
167(defun end-of-prolog-clause ()
168 "Go to end of clause in this line."
169 (beginning-of-line 1)
170 (let* ((eolpos (save-excursion (end-of-line) (point))))
171 (if (re-search-forward comment-start-skip eolpos 'move)
172 (goto-char (match-beginning 0)))
173 (skip-chars-backward " \t")))
174
175(defun prolog-comment-indent ()
176 "Compute prolog comment indentation."
177 (cond ((looking-at "%%%") 0)
178 ((looking-at "%%") (prolog-indent-level))
179 (t
180 (save-excursion
181 (skip-chars-backward " \t")
182 ;; Insert one space at least, except at left margin.
183 (max (+ (current-column) (if (bolp) 0 1))
184 comment-column)))
185 ))
186
187\f
188;;;
189;;; Inferior prolog mode
190;;;
191(defvar inferior-prolog-mode-map nil)
192
193(defun inferior-prolog-mode ()
194 "Major mode for interacting with an inferior Prolog process.
195
196The following commands are available:
197\\{inferior-prolog-mode-map}
198
199Entry to this mode calls the value of prolog-mode-hook with no arguments,
200if that value is non-nil. Likewise with the value of comint-mode-hook.
201prolog-mode-hook is called after comint-mode-hook.
202
203You can send text to the inferior Prolog from other buffers
204using the commands send-region, send-string and \\[prolog-consult-region].
205
206Commands:
207Tab indents for Prolog; with argument, shifts rest
208 of expression rigidly with the current line.
209Paragraphs are separated only by blank lines and '%%'. '%'s start comments.
210
211Return at end of buffer sends line as input.
212Return not at end copies rest of line to end and sends it.
213\\[comint-kill-input] and \\[backward-kill-word] are kill commands, imitating normal Unix input editing.
214\\[comint-interrupt-subjob] interrupts the shell or its current subjob if any.
215\\[comint-stop-subjob] stops. \\[comint-quit-subjob] sends quit signal."
216 (interactive)
217 (require 'comint)
218 (comint-mode)
219 (setq major-mode 'inferior-prolog-mode
220 mode-name "Inferior Prolog"
221 comint-prompt-regexp "^| [ ?][- ] *")
222 (prolog-mode-variables)
223 (if inferior-prolog-mode-map nil
224 (setq inferior-prolog-mode-map (copy-keymap comint-mode-map))
225 (prolog-mode-commands inferior-prolog-mode-map))
226 (use-local-map inferior-prolog-mode-map)
227 (run-hooks 'prolog-mode-hook))
228
229(defun run-prolog ()
230 "Run an inferior Prolog process, input and output via buffer *prolog*."
231 (interactive)
232 (require 'comint)
233 (switch-to-buffer (make-comint "prolog" prolog-program-name))
234 (inferior-prolog-mode))
235
236(defun prolog-consult-region (compile beg end)
237 "Send the region to the Prolog process made by M-x run-prolog.
238 If COMPILE (prefix arg) is not nil,
239 use compile mode rather than consult mode."
240 (interactive "P\nr")
241 (save-excursion
242 (if compile
243 (send-string "prolog" prolog-compile-string)
244 (send-string "prolog" prolog-consult-string))
245 (send-region "prolog" beg end)
246 (send-string "prolog" "\n") ;May be unnecessary
247 (if prolog-eof-string
248 (send-string "prolog" prolog-eof-string)
249 (process-send-eof "prolog")))) ;Send eof to prolog process.
250
251(defun prolog-consult-region-and-go (compile beg end)
252 "Send the region to the inferior Prolog, and switch to *prolog* buffer.
253 If COMPILE (prefix arg) is not nil,
254 use compile mode rather than consult mode."
255 (interactive "P\nr")
256 (prolog-consult-region compile beg end)
257 (switch-to-buffer "*prolog*"))