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