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